const node dereference(void) const { if (ended_()) { throw xml_compiler_logic_error("extracted_ptree_iterator::dereference is called with invalid iterator."); } auto& top = extracted_ptree_.stack_.top(); if (top.it == top.end) { throw xml_compiler_logic_error("it == end in extracted_ptree_iterator::dereference."); } return node(*(top.it), extracted_ptree_, top.parent_replacement); }
void collapse_(void) const { for (;;) { if (ended_()) break; const auto& top = extracted_ptree_.stack_.top(); if (top.it != top.end) { break; } if (top.extracted()) { if (extracted_ptree_.included_files_.empty()) { throw xml_compiler_logic_error("included_files_.empty() in extracted_ptree_iterator::collapse_."); } extracted_ptree_.included_files_.pop_back(); } extracted_ptree_.stack_.pop(); } }
bool equal(const extracted_ptree_iterator const& other) const { if (is_end_() && other.is_end_()) { return true; } if (! is_end_() && ! other.is_end_()) { throw xml_compiler_logic_error("extracted_ptree_iterator::equal supports only it == end()."); } // ---------------------------------------- if (is_end_()) { other.equal(*this); } // ---------------------------------------- if (ended_()) { return true; } return false; }
void extract_include_(void) const { if (ended_()) return; const auto& xml_compiler = extracted_ptree_.xml_compiler_; auto& top = extracted_ptree_.stack_.top(); const auto& it = *(top.it); if (it.first != "include") return; // ---------------------------------------- // replacement std::tr1::shared_ptr<pqrs::string::replacement> replacement_ptr(new pqrs::string::replacement); if (! it.second.empty()) { replacement_loader loader(xml_compiler, *replacement_ptr); loader.traverse(extracted_ptree(extracted_ptree_, top.parent_replacement, it.second)); } auto end = replacement_ptr->end(); for (const auto& i : top.parent_replacement) { if (replacement_ptr->find(i.first) == end) { (*replacement_ptr)[i.first] = i.second; } } // ---------------------------------------- std::string xml_file_path; { auto path = it.second.get_optional<std::string>("<xmlattr>.path"); if (path) { if (extracted_ptree_.included_files_.empty()) { throw xml_compiler_logic_error("included_files_.empty() in extracted_ptree_iterator::extract_include_."); } xml_file_path = xml_compiler.make_file_path(pqrs::file_path::dirname(extracted_ptree_.included_files_.back()), *path); } } if (! xml_file_path.empty()) { for (const auto& i : extracted_ptree_.included_files_) { if (i == xml_file_path) { xml_compiler.error_information_.set("An infinite include loop is detected:\n" + xml_file_path); return; } } ptree_ptr pt_ptr; xml_compiler.read_xml_(pt_ptr, xml_file_path, *replacement_ptr); if (pt_ptr) { // Skip <include> next time. ++(top.it); // Do not call collapse_ here. // (Keep included_files_ to detect an infinite include loop.) if (! pt_ptr->empty()) { auto root_node = pt_ptr->begin(); const auto& root_children = root_node->second; if (! root_children.empty()) { extracted_ptree_.stack_.push(stack_data(pt_ptr, replacement_ptr, root_children)); extracted_ptree_.included_files_.push_back(xml_file_path); extract_include_(); } } collapse_(); } } }
const node& dereference(void) const { if (! node_) { throw xml_compiler_logic_error("node_ == nullptr in extracted_ptree_iterator::dereference."); } return *node_; }
void xml_compiler::traverse_devicedef_(const boost::property_tree::ptree& pt) { for (auto& it : pt) { if (it.first != "devicevendordef" && it.first != "deviceproductdef") { traverse_devicedef_(it.second); } else { std::string type; const char* name_tag_name = NULL; const char* value_tag_name = NULL; boost::optional<std::string> name; boost::optional<std::string> value; // ---------------------------------------- if (it.first == "devicevendordef") { type = "DeviceVendor"; name_tag_name = "vendorname"; value_tag_name = "vendorid"; } else if (it.first == "deviceproductdef") { type = "DeviceProduct"; name_tag_name = "productname"; value_tag_name = "productid"; } else { throw xml_compiler_logic_error("unknown type in traverse_devicedef_"); } // ---------------------------------------- for (auto& child : it.second) { if (child.first == name_tag_name) { name = boost::trim_copy(child.second.data()); } else if (child.first == value_tag_name) { value = boost::trim_copy(child.second.data()); } } // ---------------------------------------- // Validation if (! name) { set_error_message_(std::string("No <") + name_tag_name + "> within <" + it.first + ">."); continue; } if (name->empty()) { set_error_message_(std::string("Empty <") + name_tag_name + "> within <" + it.first + ">."); continue; } if (! value) { set_error_message_(std::string("No <") + value_tag_name + "> within <" + it.first + ">."); continue; } if (value->empty()) { set_error_message_(std::string("Empty <") + value_tag_name + "> within <" + it.first + ">."); continue; } auto v = pqrs::string::to_uint32_t(value); if (! v) { set_error_message_(std::string("Invalid <") + value_tag_name + "> within <" + it.first + ">:\n\n<" + value_tag_name + ">" + *value + "</" + value_tag_name + ">"); continue; } // ---------------------------------------- symbol_map_.add(type, *name, *v); } } }