#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_STORAGE_XML_XMLBLOBREADER_IMPL_H #define NUCLEX_STORAGE_XML_XMLBLOBREADER_IMPL_H #include "Nuclex/Storage/Xml/XmlBlobReader.h" #include "ExpatParser.h" #include namespace Nuclex { namespace Storage { namespace Xml { // ------------------------------------------------------------------------------------------- // /// Reads data using the XML format class XmlBlobReader::Impl { /// Amount of data handed to the parser at once private: static const std::size_t BufferSize; /// Initializes a new XML blob reader implementation /// Blob of plaintext XML the XML blog reader will parse public: Impl(const Blob &blob); /// Destroys the XML blob reader implementation public: ~Impl(); /// Reads from XML plaintext up until the next event is encountered /// The type of event encountered when parsing public: XmlReadEvent Read(); /// Retrieves the name of the last element that was entered or exited /// The name of the last element entered or exited public: const std::string &GetElementName() const { return this->name; } /// Counts the number of attributes in the current element /// The number of attributes present in the current element public: std::size_t CountAttributes() const { return this->attributes.size(); } /// Retrieves the text in the element currently entered /// The text in the element currently entered public: const std::string &GetElementText() const { return this->text; } /// Retrieves the value if the attribute with the specified name /// Name of the attribute whose value will be retrieved /// The value of the requested attribute or null if it doesn't exist public: const std::string *GetAttributeValue(const std::string &attributeName) const { for(std::size_t index = 0; index < this->attributes.size(); ++index) { if(this->attributes[index].first == attributeName) { return &this->attributes[index].second; } } return nullptr; } /// Retrieves the name of the attribue with the specified index /// Index of the attribue whose name will be retrieved /// The name of the attribue with the specified index public: const std::string &GetAttributeName(std::size_t index) const { return this->attributes.at(index).first; } /// Reads the next chunk of data from the blob and parses it /// The status of the XML parser private: XML_Status parseNextChunk(); /// Called when eXpat encounters the start of an element /// Name of the elment whose start eXpat has encountered /// Start of the array containing the attribute names /// Number of attributes in the array private: void elementStartEncountered( const char *name, const char **firstAttribute, std::size_t attributeCount ); /// Called when eXpat encounters the end of an element /// Name of the element whose end eXpat has encountered private: void elementEndEncountered(const char *name); /// Calback for when eXpat encounters text between nodes /// Text that eXpat has encountered in the XML stream /// Lenght of the encountered text private: void textEncountered(const char *text, int length); /// Callback for when eXpat encounters the start of an element /// this pointer of the implementation details instance /// Name of the element whose start eXpat encountered /// /// The element's attribues in a null-terminated array of name/value pairs /// private: static void elementStartEncountered( void *impl, const char *name, const char **attributes ); /// Callback for when eXpat encounters the end of an element /// this pointer of the implementation details instance /// Name of the element whose end eXpat encountered private: static void elementEndEncountered(void *impl, const char *name); /// Calback for when eXpat encounters text between nodes /// this pointer of the implementation details instance /// Text that eXpat has encountered in the XML stream /// Lenght of the encountered text private: static void textEncountered(void *impl, const char *text, int length); /// Combines a name with a value stored as a string typedef std::pair NameValuePair; /// The expat parser used to walk through the XML elements private: ExpatParser parser; /// Whether the parser has been suspended private: bool isSuspended; /// From which which the parser reads and processes XML plaintext private: const Blob &blob; /// Length of the blob being parsed private: std::uint64_t blobLength; /// Position of the parser within the blob private: std::uint64_t position; /// Lastmost read event that was encountered private: XmlReadEvent lastReadEvent; /// Whether the parser reported an element end after being suspended private: bool elementEndOutstanding; /// Name of the current element private: std::string name; /// Attributes in the current element private: std::vector attributes; /// Name of the current element private: std::string text; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Storage::Xml #endif // NUCLEX_STORAGE_XML_XMLBLOBREADER_IMPL_H