#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <cassert>
#include <cmath>
#include <memory>

#include "sdc_common.hpp"
#include "sdc_error.hpp"

namespace sdcparse {

/*
 * Functions for create_clock
 */
void sdc_create_clock_set_period(Callback& callback, const Lexer& lexer, CreateClock& sdc_create_clock, double period) {
    if(!std::isnan(sdc_create_clock.period)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Can only define a single clock period.\n"); 
    } else {
        sdc_create_clock.period = period;
    }
}

void sdc_create_clock_set_name(Callback& callback, const Lexer& lexer, CreateClock& sdc_create_clock, const std::string& name) {
    if(!sdc_create_clock.name.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Can only define a single clock name.\n");
    } else {
        sdc_create_clock.name = name;
    }
}

void sdc_create_clock_set_waveform(Callback& callback, const Lexer& lexer, CreateClock& sdc_create_clock, double rise_edge, double fall_edge) {
    if(!std::isnan(sdc_create_clock.rise_edge) || !std::isnan(sdc_create_clock.fall_edge)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Can only define a single waveform.\n"); 
    } else {
        sdc_create_clock.rise_edge = rise_edge;
        sdc_create_clock.fall_edge = fall_edge;
    }
}

void sdc_create_clock_add_targets(Callback& callback, const Lexer& lexer, CreateClock& sdc_create_clock, StringGroup target_group) {
    assert(target_group.type == StringGroupType::STRING);

    if(!sdc_create_clock.targets.strings.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Can only define a single set of targets for clock creation. "
                  "If you want to define multiple targets specify them as a list (e.g. \"{target1 target2}\").\n");
    }

    sdc_create_clock.targets = target_group;
}

void add_sdc_create_clock(Callback& callback, const Lexer& lexer, CreateClock& sdc_create_clock) {
    /*
     * Error Checking
     */

    //Must have a clock period
    if(std::isnan(sdc_create_clock.period)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must define clock period.\n");
    }

    //Must have either a target (if a netlist clock), or a name (if a virtual clock) 
    if(sdc_create_clock.targets.strings.size() == 0 && sdc_create_clock.name.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must define either a target (for netlist clock) or a name (for virtual clock).\n");
    }

    //Currently we do not support defining clock names that differ from the netlist target name
    if(sdc_create_clock.targets.strings.size() != 0 && !sdc_create_clock.name.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Currently custom names for netlist clocks are unsupported, remove '-name' option or create a virtual clock.\n");
    }

    /*
     * Set defaults
     */
    //Determine default rise/fall time for waveform
    if(std::isnan(sdc_create_clock.rise_edge) && std::isnan(sdc_create_clock.fall_edge)) {
        sdc_create_clock.rise_edge = 0.0;
        sdc_create_clock.fall_edge = sdc_create_clock.period / 2;
    }
    assert(!std::isnan(sdc_create_clock.rise_edge));
    assert(!std::isnan(sdc_create_clock.fall_edge));
    
    //Determine if clock is virtual or not
    if(sdc_create_clock.targets.strings.size() == 0 && !sdc_create_clock.name.empty()) {
        //Have a virtual target if there is a name AND no target strings
        sdc_create_clock.is_virtual = true;
    } else {
        assert(sdc_create_clock.targets.strings.size() > 0);
        //Have a real target so this is not a virtual clock
        sdc_create_clock.is_virtual = false;
    }

    /*
     * Add command
     */
    callback.create_clock(sdc_create_clock);

}

/*
 * Functions for set_input_delay/set_output_delay
 */
void sdc_set_io_delay_set_clock(Callback& callback, const Lexer& lexer, SetIoDelay& sdc_set_io_delay, const std::string& clock_name) {
    if(!sdc_set_io_delay.clock_name.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Can only specify a single clock\n"); 
    }

    sdc_set_io_delay.clock_name = clock_name;
}

void sdc_set_io_delay_set_max_value(Callback& callback, const Lexer& lexer, SetIoDelay& sdc_set_io_delay, double max_value) {
    if(!std::isnan(sdc_set_io_delay.max_delay)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Max delay value can only specified once.\n"); 
    }

    sdc_set_io_delay.max_delay = max_value;
}

void sdc_set_io_delay_set_ports(Callback& callback, const Lexer& lexer, SetIoDelay& sdc_set_io_delay, StringGroup ports) {
    assert(ports.type == StringGroupType::PORT);

    if(!sdc_set_io_delay.target_ports.strings.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Currently only a single get_ports command is supported.\n"); 
    }

    sdc_set_io_delay.target_ports = ports;
}

void add_sdc_set_io_delay(Callback& callback, const Lexer& lexer, SetIoDelay& sdc_set_io_delay) {
    /*
     * Error checks
     */
    if(sdc_set_io_delay.clock_name.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify clock name.\n"); 
    }

    if(std::isnan(sdc_set_io_delay.max_delay)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify max delay value.\n"); 
    }

    if(sdc_set_io_delay.target_ports.strings.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify target ports using get_ports.\n"); 
    }

    /*
     * Add command
     */
    callback.set_io_delay(sdc_set_io_delay);
}

/*
 * Functions for set_clock_groups
 */
void sdc_set_clock_groups_set_type(Callback& callback, const Lexer& lexer, SetClockGroups& sdc_set_clock_groups, ClockGroupsType type) {
    if(sdc_set_clock_groups.type != ClockGroupsType::NONE) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Can only specify a single clock groups relation type (e.g. '-exclusive')\n"); 
    }

    sdc_set_clock_groups.type = type;
}

void sdc_set_clock_groups_add_group(Callback& /*callback*/, const Lexer& /*lexer*/, SetClockGroups& sdc_set_clock_groups, StringGroup clock_group) {
    assert(clock_group.type == StringGroupType::CLOCK || clock_group.type == StringGroupType::STRING);

    //Duplicate and insert the clock group
    sdc_set_clock_groups.clock_groups.push_back(clock_group);
}

void add_sdc_set_clock_groups(Callback& callback, const Lexer& lexer, SetClockGroups& sdc_set_clock_groups) {
    /*
     * Error checks
     */
    if(sdc_set_clock_groups.type == ClockGroupsType::NONE) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify clock relation type as '-exclusive'.\n"); 
    }

    if(sdc_set_clock_groups.clock_groups.size() < 2) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify at least 2 clock groups.\n"); 
    }

    /*
     * Add command
     */
    callback.set_clock_groups(sdc_set_clock_groups);
}

/*
 * Functions for set_false_path
 */
void sdc_set_false_path_add_to_from_group(Callback& callback, const Lexer& lexer, 
                                                            SetFalsePath& sdc_set_false_path, 
                                                            StringGroup group, 
                                                            FromToType to_from_dir) {
    assert(group.type == StringGroupType::CLOCK || group.type == StringGroupType::STRING);

    //Error checking
    if(to_from_dir == FromToType::FROM) {
        //Check that we haven't already defined the from path    
        if(!sdc_set_false_path.from.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-from' option is supported.\n"); 
        }
    } else {
        assert(to_from_dir == FromToType::TO);
        //Check that we haven't already defined the from path    
        if(!sdc_set_false_path.to.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-to' option is supported.\n"); 
        }
    }

    //Add the clock group
    if(to_from_dir == FromToType::FROM) {
        sdc_set_false_path.from = group;
    } else {
        assert(to_from_dir == FromToType::TO);
        sdc_set_false_path.to = group;
    }
}

void add_sdc_set_false_path(Callback& callback, const Lexer& /*lexer*/, SetFalsePath& sdc_set_false_path) {
    /*
     * Error checks
     */

    /*
     * Add command
     */
    callback.set_false_path(sdc_set_false_path);

}

/*
 * Functions for set_max_delay/set_min_delay
 */
void sdc_set_min_max_delay_set_value(Callback& callback, const Lexer& lexer, SetMinMaxDelay& sdc_set_min_max_delay, double min_max_delay) {
    if(!std::isnan(sdc_set_min_max_delay.value)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify max delay value only once.\n"); 
    }
    sdc_set_min_max_delay.value = min_max_delay;
}

void sdc_set_min_max_delay_add_to_from_group(Callback& callback, const Lexer& lexer, SetMinMaxDelay& sdc_set_min_max_delay, StringGroup group, FromToType to_from_dir) {
    assert(group.type == StringGroupType::CLOCK || group.type == StringGroupType::STRING);

    //Error checking
    if(to_from_dir == FromToType::FROM) {
        //Check that we haven't already defined the from path    
        if(!sdc_set_min_max_delay.from.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-from' option is supported.\n"); 
        }
    } else {
        assert(to_from_dir == FromToType::TO);
        //Check that we haven't already defined the from path    
        if(!sdc_set_min_max_delay.to.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-to' option is supported.\n"); 
        }
    }

    //Add the clock group
    if(to_from_dir == FromToType::FROM) {
        sdc_set_min_max_delay.from = group;
    } else {
        assert(to_from_dir == FromToType::TO);
        sdc_set_min_max_delay.to = group;
    }
}

void add_sdc_set_min_max_delay(Callback& callback, const Lexer& lexer, SetMinMaxDelay& sdc_set_min_max_delay) {
    /*
     * Error checks
     */
    if(std::isnan(sdc_set_min_max_delay.value)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify the max delay value.\n"); 
    }

    /*
     * Add command
     */
    callback.set_min_max_delay(sdc_set_min_max_delay);

}

/*
 * Functions for set_multicycle_path
 */
void sdc_set_multicycle_path_set_type(Callback& callback, const Lexer& lexer, SetMulticyclePath& sdc_set_multicycle_path, SetupHoldType type) {
    if(sdc_set_multicycle_path.type != SetupHoldType::NONE) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify the type (e.g. '-setup' or '-hold') only once.\n"); 
    }
    sdc_set_multicycle_path.type = type;
}

void sdc_set_multicycle_path_set_mcp_value(Callback& callback, const Lexer& lexer, SetMulticyclePath& sdc_set_multicycle_path, int mcp_value) {
    if(sdc_set_multicycle_path.mcp_value != UNINITIALIZED_INT) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify multicycle path value only once.\n"); 
    }
    sdc_set_multicycle_path.mcp_value = mcp_value;
}

void sdc_set_multicycle_path_add_to_from_group(Callback& callback, const Lexer& lexer, SetMulticyclePath& sdc_set_multicycle_path, 
                                                                     StringGroup group, 
                                                                     FromToType to_from_dir) {
    assert(group.type == StringGroupType::CLOCK || group.type == StringGroupType::STRING);

    //Error checking
    if(to_from_dir == FromToType::FROM) {
        //Check that we haven't already defined the from path    
        if(!sdc_set_multicycle_path.from.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-from' option is supported.\n"); 
        }
    } else {
        assert(to_from_dir == FromToType::TO);
        //Check that we haven't already defined the from path    
        if(!sdc_set_multicycle_path.to.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-to' option is supported.\n"); 
        }
    }

    //Add the clock group
    if(to_from_dir == FromToType::FROM) {
        sdc_set_multicycle_path.from = group;
    } else {
        assert(to_from_dir == FromToType::TO);
        sdc_set_multicycle_path.to = group;
    }
}

void add_sdc_set_multicycle_path(Callback& callback, const Lexer& lexer, SetMulticyclePath& sdc_set_multicycle_path) {
    /*
     * Error checks
     */
    if(sdc_set_multicycle_path.mcp_value == UNINITIALIZED_INT) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify the multicycle path value.\n"); 
    }

    /*
     * Add command
     */
    callback.set_multicycle_path(sdc_set_multicycle_path);

}

/*
 * Functions for set_clock_uncertainty
 */
void sdc_set_clock_uncertainty_set_type(Callback& callback, const Lexer& lexer, SetClockUncertainty& sdc_set_clock_uncertainty, SetupHoldType type) {
    if(sdc_set_clock_uncertainty.type != SetupHoldType::NONE) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify the type (e.g. '-setup' or '-hold') only once.\n"); 
    }
    sdc_set_clock_uncertainty.type = type;
}

void sdc_set_clock_uncertainty_set_value(Callback& callback, const Lexer& lexer, SetClockUncertainty& sdc_set_clock_uncertainty, float value) {
    if(!std::isnan(sdc_set_clock_uncertainty.value)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify clock uncertainty value only once.\n"); 
    }
    sdc_set_clock_uncertainty.value = value;
}

void sdc_set_clock_uncertainty_add_to_from_group(Callback& callback, const Lexer& lexer, SetClockUncertainty& sdc_set_clock_uncertainty, 
                                                                     StringGroup group, 
                                                                     FromToType to_from_dir) {
    assert(group.type == StringGroupType::CLOCK || group.type == StringGroupType::STRING);

    //Error checking
    if(to_from_dir == FromToType::FROM) {
        //Check that we haven't already defined the from path    
        if(!sdc_set_clock_uncertainty.from.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-from' option is supported.\n"); 
        }
    } else {
        assert(to_from_dir == FromToType::TO);
        //Check that we haven't already defined the from path    
        if(!sdc_set_clock_uncertainty.to.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-to' option is supported.\n"); 
        }
    }

    //Add the clock group
    if(to_from_dir == FromToType::FROM) {
        sdc_set_clock_uncertainty.from = group;
    } else {
        assert(to_from_dir == FromToType::TO);
        sdc_set_clock_uncertainty.to = group;
    }
}

void add_sdc_set_clock_uncertainty(Callback& callback, const Lexer& lexer, SetClockUncertainty& sdc_set_clock_uncertainty) {
    /*
     * Error checks
     */
    if(std::isnan(sdc_set_clock_uncertainty.value)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify the clock uncertainty value.\n"); 
    }

    /*
     * Add command
     */
    callback.set_clock_uncertainty(sdc_set_clock_uncertainty);

}

/*
 * Functions for set_clock_latency
 */
void sdc_set_clock_latency_set_type(Callback& callback, const Lexer& lexer, SetClockLatency& sdc_set_clock_latency, ClockLatencyType type) {
    //Error checking
    if(sdc_set_clock_latency.type != ClockLatencyType::NONE) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "The latency type (e.g. '-source') can only be specified once.\n"); 
    }

    sdc_set_clock_latency.type = type;
}

void sdc_set_clock_latency_early_late(Callback& callback, const Lexer& lexer, SetClockLatency& sdc_set_clock_latency, EarlyLateType early_late) {
    //Error checking
    if(sdc_set_clock_latency.early_late != EarlyLateType::NONE) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "The '-early' and/or '-late' options can only be specified once.\n"); 
    }

    sdc_set_clock_latency.early_late = early_late;
}

void sdc_set_clock_latency_set_value(Callback& callback, const Lexer& lexer, SetClockLatency& sdc_set_clock_latency, float value) {
    if(!std::isnan(sdc_set_clock_latency.value)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "The clock latency value can only be specified once.\n"); 
    }
    
    sdc_set_clock_latency.value = value;
}

void sdc_set_clock_latency_set_clocks(Callback& callback, const Lexer& lexer, SetClockLatency& sdc_set_clock_latency, StringGroup target_clocks) {
    if(target_clocks.type != StringGroupType::CLOCK) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Target clocks must be specified with 'get_clocks'.\n"); 
    }

    sdc_set_clock_latency.target_clocks = target_clocks;
}

void add_sdc_set_clock_latency(Callback& callback, const Lexer& lexer, SetClockLatency& sdc_set_clock_latency) {
    /*
     * Error checks
     */
    if(sdc_set_clock_latency.type != ClockLatencyType::SOURCE) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify the clock latency type (e.g. '-source').\n"); 
    }

    if(std::isnan(sdc_set_clock_latency.value)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify the clock latency value.\n"); 
    }

    if(sdc_set_clock_latency.target_clocks.strings.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify target clocks.\n"); 
    }

    /*
     * Add command
     */
    callback.set_clock_latency(sdc_set_clock_latency);
}

/*
 * Functions for set_disable_timing
 */
void sdc_set_disable_timing_add_to_from_group(Callback& callback, const Lexer& lexer, 
                                                            SetDisableTiming& sdc_set_disable_timing, 
                                                            StringGroup group, 
                                                            FromToType to_from_dir) {

    //Error checking
    if (group.type != StringGroupType::PIN && group.type != StringGroupType::STRING) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only get_pins supported with set_disable_timing.\n"); 
    }

    if(to_from_dir == FromToType::FROM) {
        //Check that we haven't already defined the from path    
        if(!sdc_set_disable_timing.from.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-from' option is supported.\n"); 
        }
    } else {
        assert(to_from_dir == FromToType::TO);
        //Check that we haven't already defined the from path    
        if(!sdc_set_disable_timing.to.strings.empty()) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-to' option is supported.\n"); 
        }
    }

    //Add the clock group
    if(to_from_dir == FromToType::FROM) {
        sdc_set_disable_timing.from = group;
    } else {
        assert(to_from_dir == FromToType::TO);
        sdc_set_disable_timing.to = group;
    }
}

void add_sdc_set_disable_timing(Callback& callback, const Lexer& /*lexer*/, SetDisableTiming& sdc_set_disable_timing) {
    /*
     * Error checks
     */

    /*
     * Add command
     */
    callback.set_disable_timing(sdc_set_disable_timing);
}

/*
 * Functions for set_timing_derate
 */
void sdc_set_timing_derate_type(Callback& callback, const Lexer& lexer, SetTimingDerate& sdc_set_timing_derate, EarlyLateType type) {
    if(sdc_set_timing_derate.type != EarlyLateType::NONE) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single '-early' or '-late' option is supported.\n"); 
    }

    sdc_set_timing_derate.type = type; 
}

void sdc_set_timing_derate_target_type(Callback& callback, const Lexer& lexer, SetTimingDerate& sdc_set_timing_derate, TimingDerateTargetType target_type) {
    if(target_type == TimingDerateTargetType::NET) {
        if(sdc_set_timing_derate.derate_nets) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "-net_delay should only be specified once.\n"); 
        } else {
            sdc_set_timing_derate.derate_nets = true;
        }
    } else if (target_type == TimingDerateTargetType::CELL) {
        if(sdc_set_timing_derate.derate_cells) {
            sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "-cell_delay should only be specified once.\n"); 
        } else {
            sdc_set_timing_derate.derate_cells = true;
        }
    }
}

void sdc_set_timing_derate_value(Callback& callback, const Lexer& lexer, SetTimingDerate& sdc_set_timing_derate, float value) {
    if(!std::isnan(sdc_set_timing_derate.value)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single derate value per set_timing_derate command is allowed.\n"); 
    }

    if(sdc_set_timing_derate.value < 0) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Timing derate values must be positive.\n"); 
    }

    sdc_set_timing_derate.value = value;
}

void sdc_set_timing_derate_targets(Callback& callback, const Lexer& lexer, SetTimingDerate& sdc_set_timing_derate, StringGroup targets) {
    if(targets.type != StringGroupType::CELL) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only get_cells is supported with set_timing_derate.\n"); 
    }

    if(!sdc_set_timing_derate.cell_targets.strings.empty()) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Only a single get_cells call is supported with set_timing_derate.\n"); 
    }

    sdc_set_timing_derate.cell_targets = targets;
}

void add_sdc_set_timing_derate(Callback& callback, const Lexer& lexer, SetTimingDerate& sdc_set_timing_derate) {
    /*
     * Error checks
     */
    if(sdc_set_timing_derate.type == EarlyLateType::NONE) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify timing derate as '-early' or '-late'\n"); 
    }

    if(std::isnan(sdc_set_timing_derate.value)) {
        sdc_error_wrap(callback, lexer.lineno(), lexer.text(), "Must specify timing derate value\n"); 
    }

    /*
     * Defaults
     */
    if(!sdc_set_timing_derate.derate_nets && !sdc_set_timing_derate.derate_cells) {
        //If unspecified, both cells and nets are derated
        sdc_set_timing_derate.derate_nets = true;
        sdc_set_timing_derate.derate_cells = true;
    }

    /*
     * Add command
     */
    callback.set_timing_derate(sdc_set_timing_derate);
}

/*
 * Functions for string_group
 */
StringGroup make_sdc_string_group(StringGroupType type, const std::string& string) {
    //Convenience function for converting a single string into a group
    StringGroup sdc_string_group(type);
    sdc_string_group.strings.push_back(string);

    return sdc_string_group;
}

void sdc_string_group_add_string(StringGroup& sdc_string_group, const std::string& string) {
    //Insert the new string
    sdc_string_group.strings.push_back(string);
}

void sdc_string_group_add_strings(StringGroup& sdc_string_group, const StringGroup& string_group_to_add) {
    for(const auto& string : string_group_to_add.strings) {
        sdc_string_group_add_string(sdc_string_group, string);
    }
}

char* strdup(const char* src) {
    if(src == NULL) {
        return NULL;
    }

    size_t len = std::strlen(src); //Number of char's excluding null terminator

    //Space for [0..len] chars
    char* new_str = (char*) std::malloc((len+1)*sizeof(*src));
    assert(new_str != NULL);

    //Copy chars from [0..len], i.e. src[len] should be null terminator
    std::memcpy(new_str, src, len+1);
    
    return new_str;
}

char* strndup(const char* src, size_t len) {
    if(src == NULL) {
        return NULL;
    }

    //Space for [0..len] chars
    char* new_str = (char*) std::malloc((len+1)*sizeof(*src));
    assert(new_str != NULL);

    //Copy chars from [0..len-1]
    std::memcpy(new_str, src, len);
    
    //Add the null terminator
    new_str[len] = '\0';

    return new_str;
}

} //namespace
