-
Notifications
You must be signed in to change notification settings - Fork 36
IO/config: parse from XML/JSON formatted string #309
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ | |
| #include <libxml/parser.h> | ||
| #include <stdexcept> | ||
| #include <string> | ||
| #include <cstring> | ||
|
|
||
| #include "configuration_XML.hpp" | ||
|
|
||
|
|
@@ -216,6 +217,41 @@ void readConfiguration(const std::string &filename, const std::string &rootname, | |
| xmlCleanupParser(); | ||
| } | ||
|
|
||
| /*! | ||
| Read xml information from a plain xml-formatted std::string and fill the Config tree. | ||
| The method is meant for general-purpose xml info absorbing. So no version checking | ||
| is done in this context, nor rootname one. | ||
| \param source string containing all the info formatted in XML style. | ||
| \param rootConfig pointer to Config tree to store data parsed from the string. | ||
| */ | ||
| void readBufferConfiguration(const std::string &source, Config *rootConfig) | ||
| { | ||
| if (!rootConfig) { | ||
| throw std::runtime_error("XML::readConfiguration Null Config tree structure passed"); | ||
| } | ||
|
|
||
| // Macro to check API for match with the DLL we are using | ||
| LIBXML_TEST_VERSION | ||
|
|
||
| // Read the XML string | ||
| const char * cstr = source.c_str(); | ||
| xmlDoc *doc = xmlParseMemory(cstr, strlen(cstr)); | ||
| if (doc == nullptr) { | ||
| throw std::runtime_error("Could not parse XML configuration string: \"" + source + "\""); | ||
| } | ||
|
|
||
| // Get the root element | ||
| xmlNode * rootElement = xmlDocGetRootElement(doc); | ||
|
|
||
| //read it as usual | ||
| readNode(rootElement->children, rootConfig); | ||
|
|
||
| // Clean-up | ||
| xmlFreeDoc(doc); | ||
| xmlCleanupParser(); | ||
| } | ||
|
|
||
|
|
||
| /*! | ||
| Write the configuration to the specified file. | ||
|
|
||
|
|
@@ -283,6 +319,75 @@ void writeConfiguration(const std::string &filename, const std::string &rootname | |
| xmlFreeTextWriter(writer); | ||
| } | ||
|
|
||
| /*! | ||
| Write the Config Tree to a c++ string (xml-stringfication). All contents will | ||
| be appended to the target source string. | ||
| The method is meant for general-purpose xml info flushing. | ||
| \param source string to write to | ||
| \param rootConfig pointer to the Config tree to be stringfied. | ||
| \param rootname (optional) name of the root section. Default is "root". | ||
| */ | ||
| void writeBufferConfiguration(std::string &source, const Config *rootConfig, const std::string &rootname) | ||
|
||
| { | ||
| if (!rootConfig) { | ||
| throw std::runtime_error("XML::writeConfiguration Null Config tree structure passed"); | ||
| } | ||
|
|
||
| int status; | ||
|
|
||
| xmlBufferPtr buffer = xmlBufferCreate(); | ||
| if (buffer == NULL) { | ||
| throw std::runtime_error("Error creating the writing buffer"); | ||
| } | ||
| // Create a new XmlWriter for DOM tree acting on memory buffer, with no compression | ||
| xmlTextWriterPtr writer = xmlNewTextWriterMemory(buffer, 0); | ||
| if (writer == NULL) { | ||
| throw std::runtime_error("Error creating the xml buffer writer"); | ||
| } | ||
| //no indent. | ||
| xmlTextWriterSetIndent(writer, 0); | ||
|
|
||
| // Start the document | ||
| status = xmlTextWriterStartDocument(writer, NULL, DEFAULT_ENCODING.c_str(), NULL); | ||
| if (status < 0) { | ||
| throw std::runtime_error("Error at xmlTextWriterStartDocument"); | ||
| } | ||
|
|
||
| // Start the root element | ||
| xmlChar *elementName = encodeString(rootname, DEFAULT_ENCODING); | ||
| status = xmlTextWriterStartElement(writer, BAD_CAST elementName); | ||
| if (status < 0) { | ||
| throw std::runtime_error("Error at xmlTextWriterStartElement"); | ||
| } | ||
|
|
||
| // Attribute version is not relevant in this context. | ||
|
|
||
| // Write the configuration | ||
| writeNode(writer, rootConfig, DEFAULT_ENCODING); | ||
|
|
||
| // End section | ||
| status = xmlTextWriterEndElement(writer); | ||
| if (status < 0) { | ||
| throw std::runtime_error("Error at xmlTextWriterEndElement"); | ||
| } | ||
|
|
||
| // Close the document | ||
| status = xmlTextWriterEndDocument(writer); | ||
| if (status < 0) { | ||
| throw std::runtime_error("Error at xmlTextWriterEndDocument"); | ||
| } | ||
|
|
||
| // free the XML writer | ||
| xmlFreeTextWriter(writer); | ||
|
|
||
| //buffer is still hanging on, append its contents to the output string | ||
| //xmlChar (aka unsigned char) simple casting to char should be enough | ||
| source += std::string(reinterpret_cast<char*>(buffer->content)); | ||
|
|
||
| //free the buffer | ||
| xmlBufferFree(buffer); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this new class really needed? Can we just add an overload to the read/write functions of ConfigParser, this overloads will take in input the string and the format?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Introducing a class of its own, without overhead of filesystem checks, version control, propagation to static utilities and whatsover was faster and simpler. As I mention earlier, introducing rapidXML instead of libxml2 can straightforward the I/O part a lot.