Created
November 14, 2019 21:19
-
-
Save duck2/758b6de52187def4d82c1d376e3a6de2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[...] | |
/* Internal loading functions, which validate and load a PugiXML DOM tree into memory. */ | |
inline int load_int(const char *in){ | |
int out; | |
out = std::strtol(in, NULL, 10); | |
if(errno != 0) | |
throw std::runtime_error("Invalid value `" + std::string(in) + "` when loading into a int."); return out; | |
} | |
inline unsigned int load_unsignedInt(const char *in){ | |
unsigned int out; | |
out = std::strtoul(in, NULL, 10); | |
if(errno != 0) | |
throw std::runtime_error("Invalid value `" + std::string(in) + "` when loading into a unsigned int."); return out; | |
} | |
inline float load_float(const char *in){ | |
float out; | |
out = std::strtof(in, NULL); | |
if(errno != 0) | |
throw std::runtime_error("Invalid value `" + std::string(in) + "` when loading into a float."); return out; | |
} | |
template<class T> | |
void load_channel(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <channel>."); | |
std::bitset<5> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_channel in = lex_attr_t_channel(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <channel>."); | |
switch(in){ | |
case atok_t_channel::CHAN_WIDTH_MAX: | |
out.set_channel_chan_width_max(load_int(attr.value())); | |
break; | |
case atok_t_channel::X_MAX: | |
out.set_channel_x_max(load_int(attr.value())); | |
break; | |
case atok_t_channel::X_MIN: | |
out.set_channel_x_min(load_int(attr.value())); | |
break; | |
case atok_t_channel::Y_MAX: | |
out.set_channel_y_max(load_int(attr.value())); | |
break; | |
case atok_t_channel::Y_MIN: | |
out.set_channel_y_min(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<5> test_astate = astate | std::bitset<5>(0b00000); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_channel); | |
} | |
template<class T> | |
void load_x_list(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <x_list>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_x_list in = lex_attr_t_x_list(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <x_list>."); | |
switch(in){ | |
case atok_t_x_list::INDEX: | |
out.set_x_list_index(load_unsignedInt(attr.value())); | |
break; | |
case atok_t_x_list::INFO: | |
out.set_x_list_info(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<2> test_astate = astate | std::bitset<2>(0b00); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_x_list); | |
} | |
template<class T> | |
void load_y_list(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <y_list>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_y_list in = lex_attr_t_y_list(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <y_list>."); | |
switch(in){ | |
case atok_t_y_list::INDEX: | |
out.set_y_list_index(load_unsignedInt(attr.value())); | |
break; | |
case atok_t_y_list::INFO: | |
out.set_y_list_info(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<2> test_astate = astate | std::bitset<2>(0b00); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_y_list); | |
} | |
template<class T> | |
void load_timing(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <timing>."); | |
std::bitset<5> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_timing in = lex_attr_t_timing(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <timing>."); | |
switch(in){ | |
case atok_t_timing::CIN: | |
out.set_timing_Cin(load_float(attr.value())); | |
break; | |
case atok_t_timing::CINTERNAL: | |
out.set_timing_Cinternal(load_float(attr.value())); | |
break; | |
case atok_t_timing::COUT: | |
out.set_timing_Cout(load_float(attr.value())); | |
break; | |
case atok_t_timing::R: | |
out.set_timing_R(load_float(attr.value())); | |
break; | |
case atok_t_timing::TDEL: | |
out.set_timing_Tdel(load_float(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<5> test_astate = astate | std::bitset<5>(0b00000); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_timing); | |
} | |
template<class T> | |
void load_sizing(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <sizing>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_sizing in = lex_attr_t_sizing(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <sizing>."); | |
switch(in){ | |
case atok_t_sizing::BUF_SIZE: | |
out.set_sizing_buf_size(load_float(attr.value())); | |
break; | |
case atok_t_sizing::MUX_TRANS_SIZE: | |
out.set_sizing_mux_trans_size(load_float(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<2> test_astate = astate | std::bitset<2>(0b00); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_sizing); | |
} | |
template<class T> | |
void load_switch(const pugi::xml_node &root, T &out){ | |
std::bitset<2> gstate = 0; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_switch in = lex_node_t_switch(node.name()); | |
if(gstate[(int)in] == 0) gstate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <switch>."); | |
switch(in){ | |
case gtok_t_switch::TIMING: | |
out.init_switch_timing(); | |
load_timing(node, out); | |
break; | |
case gtok_t_switch::SIZING: | |
out.init_switch_sizing(); | |
load_sizing(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<2> test_gstate = gstate | std::bitset<2>(0b01); | |
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_switch); | |
std::bitset<3> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_switch in = lex_attr_t_switch(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <switch>."); | |
switch(in){ | |
case atok_t_switch::ID: | |
out.set_switch_id(load_int(attr.value())); | |
break; | |
case atok_t_switch::NAME: | |
out.set_switch_name(attr.value()); | |
break; | |
case atok_t_switch::TYPE: | |
out.set_switch_type(lex_switch_type(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<3> test_astate = astate | std::bitset<3>(0b100); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_switch); | |
} | |
template<class T> | |
void load_segment_timing(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <segment_timing>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_segment_timing in = lex_attr_t_segment_timing(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <segment_timing>."); | |
switch(in){ | |
case atok_t_segment_timing::C_PER_METER: | |
out.set_segment_timing_C_per_meter(load_float(attr.value())); | |
break; | |
case atok_t_segment_timing::R_PER_METER: | |
out.set_segment_timing_R_per_meter(load_float(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<2> test_astate = astate | std::bitset<2>(0b11); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_segment_timing); | |
} | |
template<class T> | |
void load_segment(const pugi::xml_node &root, T &out){ | |
std::bitset<1> gstate = 0; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_segment in = lex_node_t_segment(node.name()); | |
if(gstate[(int)in] == 0) gstate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <segment>."); | |
switch(in){ | |
case gtok_t_segment::TIMING: | |
out.init_segment_timing(); | |
load_segment_timing(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<1> test_gstate = gstate | std::bitset<1>(0b1); | |
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_segment); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_segment in = lex_attr_t_segment(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <segment>."); | |
switch(in){ | |
case atok_t_segment::ID: | |
out.set_segment_id(load_int(attr.value())); | |
break; | |
case atok_t_segment::NAME: | |
out.set_segment_name(attr.value()); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<2> test_astate = astate | std::bitset<2>(0b00); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_segment); | |
} | |
template<class T> | |
void load_pin(const pugi::xml_node &root, T &out){ | |
out.set_pin_value(node.child_value()); | |
std::bitset<1> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_pin in = lex_attr_t_pin(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <pin>."); | |
switch(in){ | |
case atok_t_pin::PTC: | |
out.set_pin_ptc(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<1> test_astate = astate | std::bitset<1>(0b0); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_pin); | |
} | |
static const int NUM_T_PIN_CLASS_STATES = 2; | |
static const int NUM_T_PIN_CLASS_INPUTS = 1; | |
int gstate_t_pin_class[NUM_T_PIN_CLASS_STATES][NUM_T_PIN_CLASS_INPUTS] = { | |
{0}, | |
{0}, | |
}; | |
template<class T> | |
void load_pin_class(const pugi::xml_node &root, T &out){ | |
int next, state=1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_pin_class in = lex_node_t_pin_class(node.name()); | |
next = gstate_t_pin_class[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_pin_class[(int)in], gstate_t_pin_class[state], gtok_lookup_t_pin_class, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_pin_class::PIN: | |
out.add_pin_class_pin(); | |
load_pin(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_pin_class[state], gtok_lookup_t_pin_class, 1); | |
std::bitset<1> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_pin_class in = lex_attr_t_pin_class(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <pin_class>."); | |
switch(in){ | |
case atok_t_pin_class::TYPE: | |
out.set_pin_class_type(lex_pin_type(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<1> test_astate = astate | std::bitset<1>(0b0); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_pin_class); | |
} | |
template<class T> | |
void load_meta(const pugi::xml_node &root, T &out){ | |
out.set_meta_value(node.child_value()); | |
std::bitset<1> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_meta in = lex_attr_t_meta(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <meta>."); | |
switch(in){ | |
case atok_t_meta::NAME: | |
out.set_meta_name(attr.value()); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<1> test_astate = astate | std::bitset<1>(0b0); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_meta); | |
} | |
static const int NUM_T_METADATA_STATES = 2; | |
static const int NUM_T_METADATA_INPUTS = 1; | |
int gstate_t_metadata[NUM_T_METADATA_STATES][NUM_T_METADATA_INPUTS] = { | |
{0}, | |
{0}, | |
}; | |
template<class T> | |
void load_metadata(const pugi::xml_node &root, T &out){ | |
int next, state=1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_metadata in = lex_node_t_metadata(node.name()); | |
next = gstate_t_metadata[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_metadata[(int)in], gstate_t_metadata[state], gtok_lookup_t_metadata, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_metadata::META: | |
out.add_metadata_meta(); | |
load_meta(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_metadata[state], gtok_lookup_t_metadata, 1); | |
if(root.first_attribute()) | |
throw std::runtime_error("Unexpected attribute in <metadata>."); | |
} | |
static const int NUM_T_BLOCK_TYPE_STATES = 1; | |
static const int NUM_T_BLOCK_TYPE_INPUTS = 1; | |
int gstate_t_block_type[NUM_T_BLOCK_TYPE_STATES][NUM_T_BLOCK_TYPE_INPUTS] = { | |
{0}, | |
}; | |
template<class T> | |
void load_block_type(const pugi::xml_node &root, T &out){ | |
int next, state=0; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_block_type in = lex_node_t_block_type(node.name()); | |
next = gstate_t_block_type[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_block_type[(int)in], gstate_t_block_type[state], gtok_lookup_t_block_type, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_block_type::PIN_CLASS: | |
out.add_block_type_pin_class(); | |
load_pin_class(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_block_type[state], gtok_lookup_t_block_type, 1); | |
std::bitset<4> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_block_type in = lex_attr_t_block_type(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <block_type>."); | |
switch(in){ | |
case atok_t_block_type::HEIGHT: | |
out.set_block_type_height(load_int(attr.value())); | |
break; | |
case atok_t_block_type::ID: | |
out.set_block_type_id(load_int(attr.value())); | |
break; | |
case atok_t_block_type::NAME: | |
out.set_block_type_name(attr.value()); | |
break; | |
case atok_t_block_type::WIDTH: | |
out.set_block_type_width(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<4> test_astate = astate | std::bitset<4>(0b0000); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_block_type); | |
} | |
template<class T> | |
void load_grid_loc(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <grid_loc>."); | |
std::bitset<5> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_grid_loc in = lex_attr_t_grid_loc(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <grid_loc>."); | |
switch(in){ | |
case atok_t_grid_loc::BLOCK_TYPE_ID: | |
out.set_grid_loc_block_type_id(load_int(attr.value())); | |
break; | |
case atok_t_grid_loc::HEIGHT_OFFSET: | |
out.set_grid_loc_height_offset(load_int(attr.value())); | |
break; | |
case atok_t_grid_loc::WIDTH_OFFSET: | |
out.set_grid_loc_width_offset(load_int(attr.value())); | |
break; | |
case atok_t_grid_loc::X: | |
out.set_grid_loc_x(load_int(attr.value())); | |
break; | |
case atok_t_grid_loc::Y: | |
out.set_grid_loc_y(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<5> test_astate = astate | std::bitset<5>(0b00000); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_grid_loc); | |
} | |
template<class T> | |
void load_node_loc(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <node_loc>."); | |
std::bitset<6> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node_loc in = lex_attr_t_node_loc(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node_loc>."); | |
switch(in){ | |
case atok_t_node_loc::PTC: | |
out.set_node_loc_ptc(load_int(attr.value())); | |
break; | |
case atok_t_node_loc::SIDE: | |
out.set_node_loc_side(lex_loc_side(attr.value())); | |
break; | |
case atok_t_node_loc::XHIGH: | |
out.set_node_loc_xhigh(load_int(attr.value())); | |
break; | |
case atok_t_node_loc::XLOW: | |
out.set_node_loc_xlow(load_int(attr.value())); | |
break; | |
case atok_t_node_loc::YHIGH: | |
out.set_node_loc_yhigh(load_int(attr.value())); | |
break; | |
case atok_t_node_loc::YLOW: | |
out.set_node_loc_ylow(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<6> test_astate = astate | std::bitset<6>(0b000010); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_loc); | |
} | |
template<class T> | |
void load_node_timing(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <node_timing>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node_timing in = lex_attr_t_node_timing(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node_timing>."); | |
switch(in){ | |
case atok_t_node_timing::C: | |
out.set_node_timing_C(load_float(attr.value())); | |
break; | |
case atok_t_node_timing::R: | |
out.set_node_timing_R(load_float(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<2> test_astate = astate | std::bitset<2>(0b00); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_timing); | |
} | |
template<class T> | |
void load_node_segment(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <node_segment>."); | |
std::bitset<1> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node_segment in = lex_attr_t_node_segment(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node_segment>."); | |
switch(in){ | |
case atok_t_node_segment::SEGMENT_ID: | |
out.set_node_segment_segment_id(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<1> test_astate = astate | std::bitset<1>(0b0); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_segment); | |
} | |
template<class T> | |
void load_node_connection_box(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <node_connection_box>."); | |
std::bitset<3> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node_connection_box in = lex_attr_t_node_connection_box(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node_connection_box>."); | |
switch(in){ | |
case atok_t_node_connection_box::ID: | |
out.set_node_connection_box_id(load_int(attr.value())); | |
break; | |
case atok_t_node_connection_box::X: | |
out.set_node_connection_box_x(load_int(attr.value())); | |
break; | |
case atok_t_node_connection_box::Y: | |
out.set_node_connection_box_y(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<3> test_astate = astate | std::bitset<3>(0b000); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_connection_box); | |
} | |
template<class T> | |
void load_node_canonical_loc(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <node_canonical_loc>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node_canonical_loc in = lex_attr_t_node_canonical_loc(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node_canonical_loc>."); | |
switch(in){ | |
case atok_t_node_canonical_loc::X: | |
out.set_node_canonical_loc_x(load_int(attr.value())); | |
break; | |
case atok_t_node_canonical_loc::Y: | |
out.set_node_canonical_loc_y(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<2> test_astate = astate | std::bitset<2>(0b00); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node_canonical_loc); | |
} | |
template<class T> | |
void load_node(const pugi::xml_node &root, T &out){ | |
std::bitset<6> gstate = 0; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_node in = lex_node_t_node(node.name()); | |
if(gstate[(int)in] == 0) gstate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <node>."); | |
switch(in){ | |
case gtok_t_node::LOC: | |
out.init_node_loc(); | |
load_node_loc(node, out); | |
break; | |
case gtok_t_node::TIMING: | |
out.init_node_timing(); | |
load_node_timing(node, out); | |
break; | |
case gtok_t_node::SEGMENT: | |
out.init_node_segment(); | |
load_node_segment(node, out); | |
break; | |
case gtok_t_node::CONNECTION_BOX: | |
out.init_node_connection_box(); | |
load_node_connection_box(node, out); | |
break; | |
case gtok_t_node::CANONICAL_LOC: | |
out.init_node_canonical_loc(); | |
load_node_canonical_loc(node, out); | |
break; | |
case gtok_t_node::METADATA: | |
out.init_node_metadata(); | |
load_metadata(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<6> test_gstate = gstate | std::bitset<6>(0b111110); | |
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_node); | |
std::bitset<4> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_node in = lex_attr_t_node(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <node>."); | |
switch(in){ | |
case atok_t_node::CAPACITY: | |
out.set_node_capacity(load_unsignedInt(attr.value())); | |
break; | |
case atok_t_node::DIRECTION: | |
out.set_node_direction(lex_node_direction(attr.value())); | |
break; | |
case atok_t_node::ID: | |
out.set_node_id(load_unsignedInt(attr.value())); | |
break; | |
case atok_t_node::TYPE: | |
out.set_node_type(lex_node_type(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<4> test_astate = astate | std::bitset<4>(0b0010); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_node); | |
} | |
template<class T> | |
void load_edge(const pugi::xml_node &root, T &out){ | |
std::bitset<1> gstate = 0; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_edge in = lex_node_t_edge(node.name()); | |
if(gstate[(int)in] == 0) gstate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <edge>."); | |
switch(in){ | |
case gtok_t_edge::METADATA: | |
out.init_edge_metadata(); | |
load_metadata(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<1> test_gstate = gstate | std::bitset<1>(0b1); | |
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_edge); | |
std::bitset<4> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_edge in = lex_attr_t_edge(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <edge>."); | |
switch(in){ | |
case atok_t_edge::ID: | |
out.set_edge_id(load_unsignedInt(attr.value())); | |
break; | |
case atok_t_edge::SINK_NODE: | |
out.set_edge_sink_node(load_unsignedInt(attr.value())); | |
break; | |
case atok_t_edge::SRC_NODE: | |
out.set_edge_src_node(load_unsignedInt(attr.value())); | |
break; | |
case atok_t_edge::SWITCH_ID: | |
out.set_edge_switch_id(load_unsignedInt(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<4> test_astate = astate | std::bitset<4>(0b0001); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_edge); | |
} | |
static const int NUM_T_CHANNELS_STATES = 4; | |
static const int NUM_T_CHANNELS_INPUTS = 3; | |
int gstate_t_channels[NUM_T_CHANNELS_STATES][NUM_T_CHANNELS_INPUTS] = { | |
{-1, -1, 0}, | |
{-1, 1, 0}, | |
{-1, 1, -1}, | |
{2, -1, -1}, | |
}; | |
template<class T> | |
void load_channels(const pugi::xml_node &root, T &out){ | |
int next, state=3; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_channels in = lex_node_t_channels(node.name()); | |
next = gstate_t_channels[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_channels[(int)in], gstate_t_channels[state], gtok_lookup_t_channels, 3); | |
state = next; | |
switch(in){ | |
case gtok_t_channels::CHANNEL: | |
out.init_channels_channel(); | |
load_channel(node, out); | |
break; | |
case gtok_t_channels::X_LIST: | |
out.add_channels_x_list(); | |
load_x_list(node, out); | |
break; | |
case gtok_t_channels::Y_LIST: | |
out.add_channels_y_list(); | |
load_y_list(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_channels[state], gtok_lookup_t_channels, 3); | |
if(root.first_attribute()) | |
throw std::runtime_error("Unexpected attribute in <channels>."); | |
} | |
static const int NUM_T_SWITCHES_STATES = 2; | |
static const int NUM_T_SWITCHES_INPUTS = 1; | |
int gstate_t_switches[NUM_T_SWITCHES_STATES][NUM_T_SWITCHES_INPUTS] = { | |
{0}, | |
{0}, | |
}; | |
template<class T> | |
void load_switches(const pugi::xml_node &root, T &out){ | |
int next, state=1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_switches in = lex_node_t_switches(node.name()); | |
next = gstate_t_switches[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_switches[(int)in], gstate_t_switches[state], gtok_lookup_t_switches, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_switches::SWITCH: | |
out.add_switches_switch(); | |
load_switch(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_switches[state], gtok_lookup_t_switches, 1); | |
if(root.first_attribute()) | |
throw std::runtime_error("Unexpected attribute in <switches>."); | |
} | |
static const int NUM_T_SEGMENTS_STATES = 2; | |
static const int NUM_T_SEGMENTS_INPUTS = 1; | |
int gstate_t_segments[NUM_T_SEGMENTS_STATES][NUM_T_SEGMENTS_INPUTS] = { | |
{0}, | |
{0}, | |
}; | |
template<class T> | |
void load_segments(const pugi::xml_node &root, T &out){ | |
int next, state=1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_segments in = lex_node_t_segments(node.name()); | |
next = gstate_t_segments[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_segments[(int)in], gstate_t_segments[state], gtok_lookup_t_segments, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_segments::SEGMENT: | |
out.add_segments_segment(); | |
load_segment(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_segments[state], gtok_lookup_t_segments, 1); | |
if(root.first_attribute()) | |
throw std::runtime_error("Unexpected attribute in <segments>."); | |
} | |
static const int NUM_T_BLOCK_TYPES_STATES = 2; | |
static const int NUM_T_BLOCK_TYPES_INPUTS = 1; | |
int gstate_t_block_types[NUM_T_BLOCK_TYPES_STATES][NUM_T_BLOCK_TYPES_INPUTS] = { | |
{0}, | |
{0}, | |
}; | |
template<class T> | |
void load_block_types(const pugi::xml_node &root, T &out){ | |
int next, state=1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_block_types in = lex_node_t_block_types(node.name()); | |
next = gstate_t_block_types[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_block_types[(int)in], gstate_t_block_types[state], gtok_lookup_t_block_types, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_block_types::BLOCK_TYPE: | |
out.add_block_types_block_type(); | |
load_block_type(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_block_types[state], gtok_lookup_t_block_types, 1); | |
if(root.first_attribute()) | |
throw std::runtime_error("Unexpected attribute in <block_types>."); | |
} | |
static const int NUM_T_GRID_LOCS_STATES = 2; | |
static const int NUM_T_GRID_LOCS_INPUTS = 1; | |
int gstate_t_grid_locs[NUM_T_GRID_LOCS_STATES][NUM_T_GRID_LOCS_INPUTS] = { | |
{0}, | |
{0}, | |
}; | |
template<class T> | |
void load_grid_locs(const pugi::xml_node &root, T &out){ | |
int next, state=1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_grid_locs in = lex_node_t_grid_locs(node.name()); | |
next = gstate_t_grid_locs[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_grid_locs[(int)in], gstate_t_grid_locs[state], gtok_lookup_t_grid_locs, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_grid_locs::GRID_LOC: | |
out.add_grid_locs_grid_loc(); | |
load_grid_loc(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_grid_locs[state], gtok_lookup_t_grid_locs, 1); | |
if(root.first_attribute()) | |
throw std::runtime_error("Unexpected attribute in <grid_locs>."); | |
} | |
static const int NUM_T_RR_NODES_STATES = 2; | |
static const int NUM_T_RR_NODES_INPUTS = 1; | |
int gstate_t_rr_nodes[NUM_T_RR_NODES_STATES][NUM_T_RR_NODES_INPUTS] = { | |
{0}, | |
{0}, | |
}; | |
template<class T> | |
void load_rr_nodes(const pugi::xml_node &root, T &out){ | |
int next, state=1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_rr_nodes in = lex_node_t_rr_nodes(node.name()); | |
next = gstate_t_rr_nodes[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_rr_nodes[(int)in], gstate_t_rr_nodes[state], gtok_lookup_t_rr_nodes, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_rr_nodes::NODE: | |
out.add_rr_nodes_node(); | |
load_node(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_rr_nodes[state], gtok_lookup_t_rr_nodes, 1); | |
if(root.first_attribute()) | |
throw std::runtime_error("Unexpected attribute in <rr_nodes>."); | |
} | |
static const int NUM_T_RR_EDGES_STATES = 2; | |
static const int NUM_T_RR_EDGES_INPUTS = 1; | |
int gstate_t_rr_edges[NUM_T_RR_EDGES_STATES][NUM_T_RR_EDGES_INPUTS] = { | |
{0}, | |
{0}, | |
}; | |
template<class T> | |
void load_rr_edges(const pugi::xml_node &root, T &out){ | |
int next, state=1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_rr_edges in = lex_node_t_rr_edges(node.name()); | |
next = gstate_t_rr_edges[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_rr_edges[(int)in], gstate_t_rr_edges[state], gtok_lookup_t_rr_edges, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_rr_edges::EDGE: | |
out.add_rr_edges_edge(); | |
load_edge(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_rr_edges[state], gtok_lookup_t_rr_edges, 1); | |
if(root.first_attribute()) | |
throw std::runtime_error("Unexpected attribute in <rr_edges>."); | |
} | |
template<class T> | |
void load_bin_nodes(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <bin_nodes>."); | |
std::bitset<1> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_bin_nodes in = lex_attr_t_bin_nodes(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <bin_nodes>."); | |
switch(in){ | |
case atok_t_bin_nodes::FILE: | |
out.set_bin_nodes_file(attr.value()); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<1> test_astate = astate | std::bitset<1>(0b1); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_bin_nodes); | |
} | |
template<class T> | |
void load_connection_box(const pugi::xml_node &root, T &out){ | |
if(root.first_child().type() == pugi::node_element) | |
throw std::runtime_error("Unexpected child element in <connection_box>."); | |
std::bitset<2> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_connection_box in = lex_attr_t_connection_box(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <connection_box>."); | |
switch(in){ | |
case atok_t_connection_box::ID: | |
out.set_connection_box_id(load_unsignedInt(attr.value())); | |
break; | |
case atok_t_connection_box::NAME: | |
out.set_connection_box_name(attr.value()); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<2> test_astate = astate | std::bitset<2>(0b00); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_connection_box); | |
} | |
static const int NUM_T_CONNECTION_BOXES_STATES = 2; | |
static const int NUM_T_CONNECTION_BOXES_INPUTS = 1; | |
int gstate_t_connection_boxes[NUM_T_CONNECTION_BOXES_STATES][NUM_T_CONNECTION_BOXES_INPUTS] = { | |
{0}, | |
{0}, | |
}; | |
template<class T> | |
void load_connection_boxes(const pugi::xml_node &root, T &out){ | |
int next, state=1; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_connection_boxes in = lex_node_t_connection_boxes(node.name()); | |
next = gstate_t_connection_boxes[state][(int)in]; | |
if(next == -1) | |
dfa_error(gtok_lookup_t_connection_boxes[(int)in], gstate_t_connection_boxes[state], gtok_lookup_t_connection_boxes, 1); | |
state = next; | |
switch(in){ | |
case gtok_t_connection_boxes::CONNECTION_BOX: | |
out.add_connection_boxes_connection_box(); | |
load_connection_box(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
if(state != 0) dfa_error("end of input", gstate_t_connection_boxes[state], gtok_lookup_t_connection_boxes, 1); | |
std::bitset<3> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_connection_boxes in = lex_attr_t_connection_boxes(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <connection_boxes>."); | |
switch(in){ | |
case atok_t_connection_boxes::NUM_BOXES: | |
out.set_connection_boxes_num_boxes(load_unsignedInt(attr.value())); | |
break; | |
case atok_t_connection_boxes::X_DIM: | |
out.set_connection_boxes_x_dim(load_int(attr.value())); | |
break; | |
case atok_t_connection_boxes::Y_DIM: | |
out.set_connection_boxes_y_dim(load_int(attr.value())); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<3> test_astate = astate | std::bitset<3>(0b000); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_connection_boxes); | |
} | |
template<class T> | |
void load_rr_graph(const pugi::xml_node &root, T &out){ | |
std::bitset<9> gstate = 0; | |
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling()){ | |
gtok_t_rr_graph in = lex_node_t_rr_graph(node.name()); | |
if(gstate[(int)in] == 0) gstate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate element " + std::string(node.name()) + " in <rr_graph>."); | |
switch(in){ | |
case gtok_t_rr_graph::BINARY_NODES_AND_EDGES: | |
out.init_rr_graph_binary_nodes_and_edges(); | |
load_bin_nodes(node, out); | |
break; | |
case gtok_t_rr_graph::CONNECTION_BOXES: | |
out.init_rr_graph_connection_boxes(); | |
load_connection_boxes(node, out); | |
break; | |
case gtok_t_rr_graph::CHANNELS: | |
out.init_rr_graph_channels(); | |
load_channels(node, out); | |
break; | |
case gtok_t_rr_graph::SWITCHES: | |
out.init_rr_graph_switches(); | |
load_switches(node, out); | |
break; | |
case gtok_t_rr_graph::SEGMENTS: | |
out.init_rr_graph_segments(); | |
load_segments(node, out); | |
break; | |
case gtok_t_rr_graph::BLOCK_TYPES: | |
out.init_rr_graph_block_types(); | |
load_block_types(node, out); | |
break; | |
case gtok_t_rr_graph::GRID: | |
out.init_rr_graph_grid(); | |
load_grid_locs(node, out); | |
break; | |
case gtok_t_rr_graph::RR_NODES: | |
out.init_rr_graph_rr_nodes(); | |
load_rr_nodes(node, out); | |
break; | |
case gtok_t_rr_graph::RR_EDGES: | |
out.init_rr_graph_rr_edges(); | |
load_rr_edges(node, out); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<9> test_gstate = gstate | std::bitset<9>(0b000000011); | |
if(!test_gstate.all()) all_error(test_gstate, gtok_lookup_t_rr_graph); | |
std::bitset<3> astate = 0; | |
for(pugi::xml_attribute attr = root.first_attribute(); attr; attr = attr.next_attribute()){ | |
atok_t_rr_graph in = lex_attr_t_rr_graph(attr.name()); | |
if(astate[(int)in] == 0) astate[(int)in] = 1; | |
else throw std::runtime_error("Duplicate attribute " + std::string(attr.name()) + " in <rr_graph>."); | |
switch(in){ | |
case atok_t_rr_graph::TOOL_COMMENT: | |
out.set_rr_graph_tool_comment(attr.value()); | |
break; | |
case atok_t_rr_graph::TOOL_NAME: | |
out.set_rr_graph_tool_name(attr.value()); | |
break; | |
case atok_t_rr_graph::TOOL_VERSION: | |
out.set_rr_graph_tool_version(attr.value()); | |
break; | |
default: break; /* Not possible. */ | |
} | |
} | |
std::bitset<3> test_astate = astate | std::bitset<3>(0b111); | |
if(!test_astate.all()) attr_error(test_astate, atok_lookup_t_rr_graph); | |
} | |
void dfa_error(const char *wrong, int *states, const char **lookup, int len){ | |
std::vector<std::string> expected; | |
for(int i=0; i<len; i++){ | |
if(states[i] != -1) expected.push_back(lookup[i]); | |
} | |
std::string expected_or = expected[0]; | |
for(unsigned int i=1; i<expected.size(); i++) | |
expected_or += std::string(" or ") + expected[i]; | |
throw std::runtime_error("Expected " + expected_or + ", found " + std::string(wrong)); | |
} | |
template<std::size_t N> | |
void all_error(std::bitset<N> gstate, const char **lookup){ | |
std::vector<std::string> missing; | |
for(unsigned int i=0; i<N; i++){ | |
if(gstate[i] == 0) missing.push_back(lookup[i]); | |
} | |
std::string missing_and = missing[0]; | |
for(unsigned int i=1; i<missing.size(); i++) | |
missing_and += std::string(", ") + missing[i]; | |
throw std::runtime_error("Didn't find required elements " + missing_and + "."); | |
} | |
template<std::size_t N> | |
void attr_error(std::bitset<N> astate, const char **lookup){ | |
std::vector<std::string> missing; | |
for(unsigned int i=0; i<N; i++){ | |
if(astate[i] == 0) missing.push_back(lookup[i]); | |
} | |
std::string missing_and = missing[0]; | |
for(unsigned int i=1; i<missing.size(); i++) | |
missing_and += std::string(", ") + missing[i]; | |
throw std::runtime_error("Didn't find required attributes " + missing_and + "."); | |
} | |
} /* namespace uxsd */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment