#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_EXPATPARSER_H #define NUCLEX_STORAGE_XML_EXPATPARSER_H #include "Nuclex/Storage/Config.h" #include "ExpatApi.h" #include #include namespace Nuclex { namespace Storage { namespace Xml { // ------------------------------------------------------------------------------------------- // /// Wraps the eXpat XML parser API class ExpatParser { /// Initializes a new eXpat parser public: ExpatParser(const std::string &charset = "UTF-8"); /// Retrieves the wrapped eXpat parser instance /// The wrapped eXpat parser instance public: XML_Parser Get() const { return this->parser.get(); } /// Builds a string describing the first encountered error /// A string descrbing the first encountered error public: std::string BuildErrorDescription() const; /// Checks whether the parser has encountered an error /// True if the parser has encountered an error public: bool ErrorEncountered() const { return (this->errorCode != XML_ERROR_NONE); } /// Throws an exception if the parser has encountered an error public: void ThrowIfErrorRecorded() const; /// Sets the user data that will be passed to all callbacks /// User data that will be passed to all callbacks public: void SetUserData(void *userData) { ::XML_SetUserData(this->parser.get(), userData); } /// /// Sets the callbacks that will be invoked when XML elements are encountered /// /// /// Callback that will be invoked when an opening XML element is encountered /// /// /// Callback that will be invoked when a closing XML element is encountered /// public: void SetElementHandler(XML_StartElementHandler start, XML_EndElementHandler end) { ::XML_SetElementHandler(this->parser.get(), start, end); } /// /// Sets the callback that will be invoked when text is encountered in the XML input /// /// Callback that will be invoked when encountering text public: void SetCharacterDataHandler(XML_CharacterDataHandler handler) { ::XML_SetCharacterDataHandler(this->parser.get(), handler); } /// Pauses or aborts the parser /// Whether the parser can be resumed later /// The status reported by the eXpat parser public: XML_Status StopParser(bool resumable = true) { XML_Status status = ::XML_StopParser( this->parser.get(), resumable ? XML_TRUE : XML_FALSE ); if(status == XML_STATUS_ERROR) { recordError(); } return status; } /// Resumes parsing after the parser was paused /// The status reported by the eXpat parser public: XML_Status ResumeParser() { XML_Status status = ::XML_ResumeParser(this->parser.get()); if(status == XML_STATUS_ERROR) { recordError(); } return status; } /// Allocates an internal buffer the parser will use /// Length of the buffer in bytes public: void *GetBuffer(std::size_t length); /// /// Parses the contents of eXpat's current buffer () /// /// Amount of data the buffer has been filled with /// Whether this call provides the final chunk of data /// The status reported by the eXpat parser public: XML_Status ParseBuffer(std::size_t length, bool isFinal); /// Records the first error the parser has encountered private: void recordError() { if(this->errorCode == XML_ERROR_NONE) { // Only record the first error this->errorCode = ::XML_GetErrorCode(this->parser.get()); this->errorLineNumber = ::XML_GetErrorLineNumber(this->parser.get()); this->errorColumnIndex = ::XML_GetErrorColumnNumber(this->parser.get()); } } /// The expat parser used to walk through the XML elements private: std::unique_ptr parser; /// Code of the last error that has occurred private: XML_Error errorCode; /// Line number at which the error has occurred, if any private: XML_Size errorLineNumber; /// Column index at which the error has occurred, if any private: XML_Size errorColumnIndex; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Storage::Xml #endif // NUCLEX_STORAGE_XML_EXPATPARSER_H