Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* Copyright (C) 2022 by Andreas Theofilu <andreas@theosys.at>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __TEXPATPP_H__
#define __TEXPATPP_H__
#include <string>
#include <vector>
#include <expat.h>
#include "tvalidatefile.h"
namespace Expat
{
/**
* @enum _ETYPE_t
* @brief Internal used type identifier for elements.
*/
typedef enum _ETYPE_t
{
_ET_START, //!< Element is a start element. Other elements with a bigger depth follow.
_ET_END, //!< Element is an end element. Other elements with a bigger depth are before.
_ET_ATOMIC //!< Element is a single one which starts and stop in one line.
}_ETYPE_t;
typedef struct _ATTRIBUTE_t
{
std::string name;
std::string content;
}_ATTRIBUTE_t;
typedef _ATTRIBUTE_t ATTRIBUTE_t;
typedef struct _ELEMENT_t
{
std::string name;
int depth;
std::string content;
std::vector<_ATTRIBUTE_t> attrs;
_ETYPE_t eType;
}_ELEMENT_t;
/**
* @enum TENCODING_t
* @brief Defines the possible integrated encodings.
* If the encoding is not ENC_UTF8 it must be set before the parser is
* started. The encoding defines the character set used for the XML file.
* If the XML file is encoded in a different character set than defined,
* it may lead into parsing errors.
*/
typedef enum TENCODING_t
{
ENC_UNKNOWN, //!< Unknown encoding. This is equal with ENC_UTF8
ENC_UTF8, //!< Default encoding if not defined elsewhere
ENC_UTF16, //!< UTF16 encoding.
ENC_ISO_8859_1, //!< ISO-8859-1 encoding.
ENC_CP1250, //!< CP1250 (Windows) character set.
ENC_US_ASCII //!< US-ASCII encoding.
}TENCODING_t;
/**
* @class TExpat
* @brief C++ wrapper class for the XML parser expat.
*
* This class is a small C++ wrapper for the XML parser expat. Expat is part of
* *NIX system and also in the NDK of Android. Therefor it is used in this
* project.
*/
class TExpat : public TValidateFile
{
public:
/**
* Constructor.
*/
TExpat();
/**
* Constructor.
*
* @param file The file name of a file containing the XML code to parse.
*/
TExpat(const std::string& file);
/**
* Destructor.
*/
~TExpat();
/**
* @brief Sets the file to parse.
* This method does not check the file. If it is invalid, the parser
* will fail.
*
* @param file The file to parse.
*/
void setFile(const std::string& file) { mFile = file; }
/**
* @brief Set the encoding of the XML file.
* By default UTF8 encoding is assumed if not explicitely defined
* in the XML file. If there is an encoding defination in the XML
* file like:
*
* <?xml version="1.0" encoding="ISO-8859-2"?>
*
* for example, than this encoding is used by default.
*
* This method sets the encoding to one of the supported encodings.
* If the XML file is encoded in another character set as defined,
* than it may come to errors during parsing!
*
* @param enc Encoding to be used for parsing the XML file.
*/
void setEncoding(TENCODING_t enc);
/**
* @brief Starts the XML parser.
* This method invoke the XML parser. If any error occure and error
* message is logged and the error handler is set.
*
* @return On success it returns TRUE and FALSE otherwise.
*/
bool parse(bool debug=false);
/**
* Retrieves the first element with the name \p name at the depth
* \p depth.
*
* @param name The name of the wanted element. This is case
* sensitive!
* @param depth The depth where the element is.
*
* @return On success the content of the element is returned.
* Otherwise an empty string is returned.
*/
std::string getElement(const std::string& name, int depth, bool *valid=nullptr);
/**
* Retrieves the first element with the name \p name at the depth
* \p depth.
*
* @param name The name of the wanted element. This is case
* sensitive!
* @param depth The depth where the element is.
* @param valid An optional pointer retrieving the state of the
* search. On success it returns TRUE, otherwise FALSE.
* @return On success the content of the element is returned as an
* integer. Otherwise 0 is returned and \p valid is set to FALSE.
*/
int getElementInt(const std::string& name, int depth, bool *valid=nullptr);
/**
* Retrieves the first element with the name \p name at the depth
* \p depth.
*
* @param name The name of the wanted element. This is case
* sensitive!
* @param depth The depth where the element is.
* @param valid An optional pointer retrieving the state of the
* search. On success it returns TRUE, otherwise FALSE.
* @return On success the content of the element is returned as a
* long integer. Otherwise 0 is returned and \p valid is set to FALSE.
*/
long getElementLong(const std::string& name, int depth, bool *valid=nullptr);
/**
* Retrieves the first element with the name \p name at the depth
* \p depth.
*
* @param name The name of the wanted element. This is case
* sensitive!
* @param depth The depth where the element is.
* @param valid An optional pointer retrieving the state of the
* search. On success it returns TRUE, otherwise FALSE.
* @return On success the content of the element is returned as a
* floating value. Otherwise 0 is returned and \p valid is set to FALSE.
*/
float getElementFloat(const std::string& name, int depth, bool *valid=nullptr);
/**
* Retrieves the first element with the name \p name at the depth
* \p depth.
*
* @param name The name of the wanted element. This is case
* sensitive!
* @param depth The depth where the element is.
* @param valid An optional pointer retrieving the state of the
* search. On success it returns TRUE, otherwise FALSE.
* @return On success the content of the element is returned as a
* double value. Otherwise 0 is returned and \p valid is set to FALSE.
*/
double getElementDouble(const std::string& name, int depth, bool *valid=nullptr);
/**
* Retrieves the first element with the name \p name at the depth
* \p depth.
*
* @param name The name of the wanted element. This is case
* sensitive!
* @param depth The depth where the element is.
*
* @return On success returns the index of the element found.
* Otherwise TExpat::npos is returned.
*/
size_t getElementIndex(const std::string& name, int depth);
/**
* @brief Retrieves the first element with the name \p name.
* This method saves the found position internally. If no matching
* entity was found, the internal position is set to an invalid
* position.
*
* @param name The name of the wanted element. This is case
* sensitive!
* @param depth This parameter is optional and can be NULL. If it is
* present, the method returns the depth of the found element with
* this parameter. If the element was not found, this parameter
* will contain -1.
*
* @return On success returns the index of the element found.
* Otherwise TExpat::npos is returned.
*/
size_t getElementIndex(const std::string& name, int *depth);
/**
* Retrieves the \p name, the \p content and the attributes of the
* element. If the element has no attributes, an empty attribute
* list is returned.
*
* This method does not set the internal position. This means that
* a method depending on the internal position like getNextElement()
* will not succeed or return the content of another entity!
*
* @param index The index of the element. This value may be
* retrieved by calling previously the method getElementIndex().
* @param name This parameter can be NULL. If it is present, the
* name of the element is returned.
* @param content This parameter can be NULL. If it is present,
* the content of the element is returned. If there was no content,
* an empty string is returned.
* @param attrs This parameter can be NULL. If it is present and if
* the element contains at least 1 attribute, the attributes are
* returned in the vector.
*
* @return If a valid element was found, the index is returned.
* Otherwise TExpat::npos will be returned.
*/
size_t getElementFromIndex(size_t index, std::string *name, std::string *content, std::vector<ATTRIBUTE_t> *attrs);
/**
* @brief Retrieves the next element from the given index \p index.
* The method succeeds if the next element is not an end tag or if
* \p index is less than the number of total elements. The method
* increases the index by 1 and returns this entity.
*
* This method does not set the internal position. This means that
* a method depending on the internal position like getNextElement()
* will not succeed or return the content of another entity!
*
* @param index The index of the element. This value may be
* retrieved by calling previously the method getElementIndex().
* @param name This parameter can be NULL. If it is present, the
* name of the element is returned.
* @param content This parameter can be NULL. If it is present,
* the content of the element is returned. If there was no content,
* an empty string is returned.
* @param attrs This parameter can be NULL. If it is present and if
* the element contains at least 1 attribute, the attributes are
* returned in the vector.
*
* @return If a valid element was found, the index is returned.
* Otherwise TExpat::npos will be returned.
*/
size_t getNextElementFromIndex(size_t index, std::string *name, std::string *content, std::vector<ATTRIBUTE_t> *attrs);
/**
* @brief Retrieves the first element with the name \p name.
*
* This method saves the found position internally. If no matching
* entity was found, the internal position is set to an invalid
* position.
*
* @param name The name of the wanted element.
* @param depth A pointer to an integer. The method returns the
* depth of the found element in this parameter.
*
* @return On success the content of the element is returned, if
* any. Otherwise an error is logged and an empty string is returned.
* The parameter \p depth is set to -1 on error.
*/
std::string getFirstElement(const std::string& name, int *depth);
/**
* Retrieves the next element in the list. This method depends on
* the method getFirstElement(), which must be called previous.
*
* This method saves the found position internally. If no matching
* entity was found, the internal position is set to an invalid
* position.
*
* @param name The name of the element to search for. This
* parameter is optional and may be NULL.
* @param depth The depth of the element to return. If there are
* no more elements with the name \p name and the depth \p depth
* than an empty string is returned.
*
* @return On success the content of the element is returned. If
* an error occurs an error message is logged and the error is set.
*/
std::string getNextElement(const std::string& name, int depth, bool *valid=nullptr);
/**
* Retrieves the next element in the list. This method depends on
* the method getFirstElement(), which must be called previous.
*
* This method saves the found position internally. If no matching
* entity was found, the internal position is set to an invalid
* position.
*
* @param name The name of the element to search for. This
* parameter is optional and may be NULL.
* @param depth The depth of the element to return. If there are
* no more elements with the name \p name and the depth \p depth
* than an empty string is returned.
*
* @return On success the index of the element is returned. If
* an error occurs an error message is logged and the error is set.
*/
size_t getNextElementIndex(const std::string& name, int depth);
/**
* Searches in the attribute list of an attribute called \p name
* and returns the content.
*
* @param name The name of the wanted attribute.
* @param attrs A vector list of attributes.
*
* @return On success returns the content of the attribute \p name.
* Otherwise an empty string is returned.
*/
std::string getAttribute(const std::string& name, std::vector<ATTRIBUTE_t>& attrs);
/**
* Searches in the attribute list of an attribute called \p name
* and returns the content.
*
* @param name The name of the wanted attribute.
* @param attrs A vector list of attributes.
*
* @return On success returns the content of the attribute \p name
* as an integer value.
* Otherwise an error text is set (TError) and 0 is returned.
*/
int getAttributeInt(const std::string& name, std::vector<ATTRIBUTE_t>& attrs);
/**
* Searches in the attribute list of an attribute called \p name
* and returns the content.
*
* @param name The name of the wanted attribute.
* @param attrs A vector list of attributes.
*
* @return On success returns the content of the attribute \p name
* as a long value.
* Otherwise an error text is set (TError) and 0 is returned.
*/
long getAttributeLong(const std::string& name, std::vector<ATTRIBUTE_t>& attrs);
/**
* Searches in the attribute list of an attribute called \p name
* and returns the content.
*
* @param name The name of the wanted attribute.
* @param attrs A vector list of attributes.
*
* @return On success returns the content of the attribute \p name
* as a floating value.
* Otherwise an error text is set (TError) and 0 is returned.
*/
float getAttributeFloat(const std::string& name, std::vector<ATTRIBUTE_t>& attrs);
/**
* Searches in the attribute list of an attribute called \p name
* and returns the content.
*
* @param name The name of the wanted attribute.
* @param attrs A vector list of attributes.
*
* @return On success returns the content of the attribute \p name
* as a double precission floating value.
* Otherwise an error text is set (TError) and 0 is returned.
*/
double getAttributeDouble(const std::string& name, std::vector<ATTRIBUTE_t>& attrs);
/**
* Converts a string into an integer value.
*
* @param content A string containing numbers.
* @return On success returns the value representation of the
* \p content. If not convertable, TError is set and 0 is returned.
*/
int convertElementToInt(const std::string& content);
/**
* Converts a string into a long integer value.
*
* @param content A string containing numbers.
* @return On success returns the value representation of the
* \p content. If not convertable, TError is set and 0 is returned.
*/
long convertElementToLong(const std::string& content);
/**
* Converts a string into a floating value.
*
* @param content A string containing numbers.
* @return On success returns the value representation of the
* \p content. If not convertable, TError is set and 0 is returned.
*/
float convertElementToFloat(const std::string& content);
/**
* Converts a string into a double floating value.
*
* @param content A string containing numbers.
* @return On success returns the value representation of the
* \p content. If not convertable, TError is set and 0 is returned.
*/
double convertElementToDouble(const std::string& content);
/**
* Sets the internal pointer to the \p index. If this points to an
* invalid index, the method sets an error and returns FALSE.
*
* @param index The index into the internal XML list.
* @return On success it returns TRUE.
*/
bool setIndex(size_t index);
/**
* Retrieves the attribute list from the current position.
*
* @return On success the attributes of the current position are
* returned. If the current position is at the end or doesn't
* has attributes, an empty list is returned.
*/
std::vector<ATTRIBUTE_t> getAttributes();
/**
* Retrieves the attribute list from the \p index.
*
* @return On success the attributes of the position \p index are
* returned. If the position \p index is at the end or doesn't
* has attributes, an empty list is returned.
*/
std::vector<ATTRIBUTE_t> getAttributes(size_t index);
/**
* Checks whether the internal pointer points to a valid entry or
* not. If the internal pointer is valid it returns the name of the
* entity the pointer points to.
*
* @param valid This is an optional parameter. If this is set, then
* it is set to TRUE when the method succeeds and to FALSE
* otherwise.
*
* @return On success it returns the name of the entity and set the
* parameter \p valid to TRUE. On error it returns an empty string
* and sets the parameter \p valid to FALSE.
*/
std::string getElementName(bool *valid=nullptr);
/**
* Checks whether the internal pointer points to a valid entry or
* not. If the internal pointer is valid it returns the content of
* the entity the pointer points to.
*
* @param valid This is an optional parameter. If this is set, then
* it is set to TRUE when the method succeeds and to FALSE
* otherwise.
*
* @return On success it returns the content of the entity and set
* the parameter \p valid to TRUE. On error it returns an empty
* string and sets the parameter \p valid to FALSE.
*/
std::string getElementContent(bool *valid=nullptr);
/**
* Checks whether the internal pointer points to a valid entry or
* not. If the internal pointer is valid it returns the content of
* the entity converted to an integer.
*
* @param valid This is an optional parameter. If this is set, then
* it is set to TRUE when the method succeeds and to FALSE
* otherwise.
*
* @return On success it returns the content of the entity converted
* to an integer and set the parameter \p valid to TRUE. On error
* it returns an empty string and sets the parameter \p valid to
* FALSE.
*/
int getElementContentInt(bool *valid=nullptr);
/**
* Checks whether the internal pointer points to a valid entry or
* not. If the internal pointer is valid it returns the content of
* the entity converted to a long.
*
* @param valid This is an optional parameter. If this is set, then
* it is set to TRUE when the method succeeds and to FALSE
* otherwise.
*
* @return On success it returns the content of the entity converted
* to a long and set the parameter \p valid to TRUE. On error
* it returns an empty string and sets the parameter \p valid to
* FALSE.
*/
long getElementContentLong(bool *valid=nullptr);
/**
* Checks whether the internal pointer points to a valid entry or
* not. If the internal pointer is valid it returns the content of
* the entity converted to a floating value.
*
* @param valid This is an optional parameter. If this is set, then
* it is set to TRUE when the method succeeds and to FALSE
* otherwise.
*
* @return On success it returns the content of the entity converted
* to a float and set the parameter \p valid to TRUE. On error
* it returns an empty string and sets the parameter \p valid to
* FALSE.
*/
float getElementContentFloat(bool *valid=nullptr);
/**
* Checks whether the internal pointer points to a valid entry or
* not. If the internal pointer is valid it returns the content of
* the entity converted to a double.
*
* @param valid This is an optional parameter. If this is set, then
* it is set to TRUE when the method succeeds and to FALSE
* otherwise.
*
* @return On success it returns the content of the entity converted
* to a double and set the parameter \p valid to TRUE. On error
* it returns an empty string and sets the parameter \p valid to
* FALSE.
*/
double getElementContentDouble(bool *valid=nullptr);
static const size_t npos = static_cast<size_t>(-1); //!< Marks an invalid index
protected:
static void startElement(void* userData, const XML_Char* name, const XML_Char** attrs);
static void XMLCALL endElement(void *userData, const XML_Char *name);
static void XMLCALL CharacterDataHandler(void *, const XML_Char *s, int len);
static int cp1250_encoding_handler(void*, const XML_Char* encoding, XML_Encoding* info);
private:
static void createCP1250Encoding(XML_Encoding *enc); //!< Internal handler to handle CP1250 encoded files.
std::string mFile; //!< The name of a file containing the XML code to parse
std::vector<_ELEMENT_t> mElements; //!< The list of elemets in the order they appeared
std::vector<_ELEMENT_t>::iterator mLastIter{mElements.end()}; //!< The pointer to the last iterator
std::string mEncoding{"UTF-8"}; //!< Encoding of the XML file. UTF-8 is default encoding.
TENCODING_t mSetEncoding{ENC_UTF8}; //!< Encoding of the XML file. UTF-8 is default encoding.
// int mLastDepth{0}; //!< The depth of the last found element.
// Variables used for the static methods
static int mDepth;
static std::string mContent;
static std::string mLastName;
static std::vector<_ATTRIBUTE_t> mAttributes;
};
}
#endif