void File::parse(const wstring& text) { clear(); wstring section_name; Section section; size_t begin_pos = 0; while (begin_pos < text.size()) { size_t end_pos = text.find(L'\n', begin_pos); if (end_pos == wstring::npos) end_pos = text.size(); else end_pos++; wstring line = strip(text.substr(begin_pos, end_pos - begin_pos)); if ((line.size() > 2) && (line[0] == L'[') && (line[line.size() - 1] == L']')) { // section header if (!section.empty()) { (*this)[section_name] = section; section.clear(); } section_name = strip(line.substr(1, line.size() - 2)); } if ((line.size() > 0) && (line[0] == L';')) { // comment } else { size_t delim_pos = line.find(L'='); if (delim_pos != wstring::npos) { // name = value pair wstring name = strip(line.substr(0, delim_pos)); wstring value = strip(line.substr(delim_pos + 1, line.size() - delim_pos - 1)); // remove quotes if needed if ((value.size() >= 2) && (value[0] == L'"') && (value[value.size() - 1] == L'"')) value = value.substr(1, value.size() - 2); if (!name.empty() && !value.empty()) section[name] = value; } } begin_pos = end_pos; } if (!section.empty()) { (*this)[section_name] = section; } }
void Section::_validate(Section & section, Section & result) { if(!this->has_key("__base_dir__")) { this->add_key("__base_dir__", configment::unrepr_key_validator("string(default=\"\")")); this->_lst.remove("__base_dir__"); this->_lst.push_front("__base_dir__"); } if(!this->has_key("__validate__")) { this->add_key("__validate__", configment::unrepr_key_validator("boolean(default=True)")); this->_lst.remove("__validate__"); this->_lst.push_front("__validate__"); } Str many_section_name("__many__"); typedef std::vector<Object> VEC_T; VEC_T sub_sections; bool has_many_section = false; section._default_values.clear(); for(Section::const_iterator i = this->cbegin(); i != this->cend(); ++i) { const Object & ps_key = i->first; const Object & ps_val = i->second; const Section * ps_sub_section = dynamic_cast<const Section *>(&ps_val.get_object()); if(ps_sub_section != 0) { // this is a section sub_sections.push_back(ps_key); if(ps_key.operator ==(many_section_name)) { has_many_section = true; } else { try { Object & pt_val = section.at(ps_key); if(! pt_val.is<Section>()) { _add_key_validation_error(result, ps_key, "it is a key, but it should a Section"); } } catch(KeyError) { // inserting section section[ps_key] = Section(); } } } else { //std::cout << "DBG: KEY_VALIDATOR: ps_key= " << ps_key << ", ps_val=" << ps_val << std::endl; KeyValidator key_validator = _make_KeyValidator(ps_val); //std::cout << "DBG: VAL: looking for key " << ps_key << std::endl; bool key_validator_has_default = key_validator.has_default(); if(key_validator_has_default) { // inserting default value //std::cout << "DBG: VAL: inserting default: " << ps_key.repr() << "=" << key_validator.get_default() << std::endl; //...section[ps_key] = key_validator.get_default(); section.add_default_key(ps_key, key_validator.get_default()); } try { Object & pt_val = section.at(ps_key); if(pt_val.is<Section>()) { _add_key_validation_error(result, ps_key, "is is a Section, but it should be a key"); } else { str_type key = ps_key; ValidationResult vr; key_validator.validate(pt_val, vr); if(vr) { std::ostringstream os; os << vr; _add_key_validation_error(result, key, os.str()); } } } catch(KeyError) { if(key_validator_has_default) { section.add_key(ps_key, key_validator.get_default(), true); } else { //std::cout << "DBG: VAL: don't have a default for " << ps_key.repr() << std::endl; //std::ostringstream os; //os << parents << "::" << ps_key << " does not have a (default) value"; //vr.add_error(os.str()); _add_key_validation_error(result, ps_key, "does not have a (default) value"); } } } } // validating sub_sections: for(Section::object_map_type::iterator i = section._map.begin(); i != section._map.end(); ++i) { const Object & pt_key = i->first; //const Object & pt_val = i->second; Section * pt_sub_section = dynamic_cast<Section *>(&i->second.get_object()); if(pt_sub_section != 0) { Object v_section_name; bool validate = false; if(std::find(sub_sections.begin(), sub_sections.end(), pt_key) != sub_sections.end()) { v_section_name = pt_key; validate = true; } else if(has_many_section) { v_section_name = many_section_name; validate = true; } if(validate) { //std::cout << "DBG: VAL: validating sub-section " << pt_key << " with " << v_section_name << std::endl; Section & v_section = dynamic_cast<Section &>(this->at(v_section_name).get_object()); Section sub_result; v_section._validate(*pt_sub_section, sub_result); if(sub_result) { Section & sub_section = dynamic_cast<Section &>(sub_result.get_object()); _add_section_validation_error(result, pt_key, sub_section); } } } } //std::cout << "DV: " << section._default_values << std::endl; // if validation is not enabled, clear result if(! section.is_validation_enabled()) { result.clear(); } str_type base_dir = section.at("__base_dir__"); if(base_dir.size() > 0) { section.set_base_dir(base_dir, false, true); } }