diff --git a/src/IO/configuration_JSON.cpp b/src/IO/configuration_JSON.cpp index 50e34ad4d8..12625d9aca 100644 --- a/src/IO/configuration_JSON.cpp +++ b/src/IO/configuration_JSON.cpp @@ -264,13 +264,13 @@ void writeNode(const Config *config, rapidjson::Value &rootJSONData, rapidjson:: { // Write the options for (const auto &entry : config->getOptions()) { - const std::string &configKey = entry.first; - const std::string &configValue = entry.second; + const std::string &key = entry.first; + const Config::Option &option = entry.second; rapidjson::Value jsonKey; - jsonKey.SetString(configKey, allocator); + jsonKey.SetString(key, allocator); - rapidjson::Value jsonValue = encodeValue(configValue, allocator); + rapidjson::Value jsonValue = encodeValue(option.value, allocator); rootJSONData.AddMember(jsonKey, jsonValue, allocator); } diff --git a/src/IO/configuration_XML.cpp b/src/IO/configuration_XML.cpp index a709292e69..4d35d0a2dd 100644 --- a/src/IO/configuration_XML.cpp +++ b/src/IO/configuration_XML.cpp @@ -66,10 +66,22 @@ void readNode(xmlNodePtr root, Config *config) } readNode(node->children, section); } else { + Config::Option option; + xmlChar *nodeContent = xmlNodeGetContent(node); - std::string value(reinterpret_cast(nodeContent)); - config->set(key, value); + option.value = reinterpret_cast(nodeContent); xmlFree(nodeContent); + + xmlAttr *attribute = node->properties; + while (attribute) { + xmlChar* attributeValue = xmlNodeListGetString(node->doc, attribute->children, 1); + option.attributes[reinterpret_cast(attribute->name)] = reinterpret_cast(attributeValue); + xmlFree(attributeValue); + + attribute = attribute->next; + } + + config->addOption(key, std::move(option)); } } } @@ -87,20 +99,49 @@ void writeNode(xmlTextWriterPtr writer, const Config *config, const std::string // Write the options for (const auto &entry : config->getOptions()) { - const std::string &key = entry.first; - const std::string &value = entry.second; + const std::string &key = entry.first; + const Config::Option &option = entry.second; + // Start option xmlChar *elementName = encodeString(key, encoding); - xmlChar *elementText = encodeString(value, encoding); - int status = xmlTextWriterWriteFormatElement(writer, BAD_CAST elementName, "%s", elementText); + status = xmlTextWriterStartElement(writer, BAD_CAST elementName); + if (elementName) { + xmlFree(elementName); + } + if (status < 0) { + throw std::runtime_error("Error at xmlTextWriterStartElement"); + } + + // Write option attributes + for (const auto &attributeEntry : option.attributes) { + xmlChar *attributeName = encodeString(attributeEntry.first, encoding); + xmlChar *attributeValue = encodeString(attributeEntry.second, encoding); + status = xmlTextWriterWriteAttribute(writer, BAD_CAST attributeName, BAD_CAST attributeValue); + if (attributeValue) { + xmlFree(attributeValue); + } + if (attributeName) { + xmlFree(attributeName); + } + if (status < 0) { + throw std::runtime_error("Error at xmlTextWriterWriteAttribute"); + } + } + + // Write option value + xmlChar *elementText = encodeString(option.value, encoding); + status = xmlTextWriterWriteFormatString(writer, "%s", BAD_CAST elementText); if (elementText) { xmlFree(elementText); } - if (elementName) { - xmlFree(elementName); + if (status < 0) { + throw std::runtime_error("Error at xmlTextWriterStartElement"); } + + // End option + status = xmlTextWriterEndElement(writer); if (status < 0) { - throw std::runtime_error("Error at xmlTextWriterWriteFormatElement"); + throw std::runtime_error("Error at xmlTextWriterEndElement"); } } diff --git a/src/IO/configuration_config.cpp b/src/IO/configuration_config.cpp index 44a6cf3683..f4922672f7 100644 --- a/src/IO/configuration_config.cpp +++ b/src/IO/configuration_config.cpp @@ -133,58 +133,226 @@ const Config::Options & Config::getOptions() const } /*! - Checks if the specified option exists. + Gets a reference to the specified option. \param key is the name of the option - \result True is the option exists, false otherwise. + \result A reference to the specified option. */ -bool Config::hasOption(const std::string &key) const +Config::Option & Config::getOption(const std::string &key) { - return (m_options->count(key) > 0); + return const_cast