/********************************************************************************
* *
* X M L R e a d e r & W r i t e r *
* *
*********************************************************************************
* Copyright (C) 2016,2024 by Jeroen van der Zijp. All Rights Reserved. *
*********************************************************************************
* This library is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 3 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 *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program. If not, see *
********************************************************************************/
#ifndef FXXML_H
#define FXXML_H
#ifndef FXPARSEBUFFER_H
#include "FXParseBuffer.h"
#endif
namespace FX {
/**
* The XML serializer loads or saves data to xml text file.
*/
class FXAPI FXXML : public FXParseBuffer {
public:
enum Error {
ErrOK, /// No errors
ErrEmpty, /// No data loaded
ErrSave, /// Unable to save
ErrLoad, /// Unable to load
ErrSpace, /// Expected space
ErrEquals, /// Expected equals sign '='
ErrName, /// Expected name
ErrString, /// Expected string
ErrToken, /// Illegal token
ErrDigit, /// Expected digit
ErrHexDigit, /// Expected hex digit
ErrSemiColon, /// Expected semicolon
ErrReference, /// Unknown reference
ErrNoMatch, /// Start and end tag not matching
ErrEof /// Unexpected end of file
};
enum {
CRLF = 0x0001, /// CRLF, LFCR, CR, LF map to LF
REFS = 0x0002, /// Character references processed
};
enum {
UTF8 = 1, /// UTF8 encoded
UTF16LE = 2, /// Little endian UTF16 encoded
UTF16BE = 3, /// Big endian UTF16 encoded
UTF32LE = 4, /// Little endian UTF32 encoded
UTF32BE = 5 /// Big endian UTF32 encoded
};
protected:
class Element; // Element info
protected:
FXlong offset; // Position from start
Element *current; // Current element instance
FXint column; // Column number
FXint line; // Line number
FXString vers; // Version
FXuint enc; // Encoding
private:
FXuint guess();
void spaces();
FXbool name();
FXbool match(FXchar ch);
FXbool match(const FXchar* str,FXint len);
Error parsestring(FXString& str);
Error parsexml();
Error parseversion();
Error parseencoding();
Error parsestandalone();
Error parseelementdecl();
Error parseexternalid();
Error parseinternalsubset();
Error parsedeclarations();
Error parseprocessing();
Error parsecomment();
Error parseattribute(Element& elm);
Error parsestarttag(Element& elm);
Error parseendtag(Element& elm);
Error parsecdata(Element& elm);
Error parsecontents(Element& elm);
Error parseelement();
private:
static const FXchar *const errors[];
private:
FXXML(const FXXML&);
FXXML& operator=(const FXXML&);
public:
/// Called when start of document is recognized.
FXCallback startDocumentCB;
/// Called when start of element is recognized.
FXCallback startElementCB;
/// Called to pass batch of decoded characters.
FXCallback charactersCB;
/// Called to pass comment string.
FXCallback commentCB;
/// Called to pass processing instruction.
FXCallback processingCB;
/// Called when end of element is recognized.
FXCallback endElementCB;
/// Called when end of document is recognized.
FXCallback endDocumentCB;
public:
/**
* Construct XML serializer.
*/
FXXML();
/**
* Construct XML serializer and open for direction d.
* Use given buffer data of size sz, or allocate a local buffer.
*/
FXXML(FXchar* buffer,FXuval sz=4096,Direction d=Load);
/**
* Open XML stream for given direction d.
* Use given buffer data of size sz, or allocate a local buffer.
*/
FXbool open(FXchar* buffer=nullptr,FXuval sz=4096,Direction d=Load);
/**
* Return size of parse buffer.
*/
FXuval size() const { return endptr-begptr; }
/**
* Return direction in effect.
*/
Direction direction() const { return dir; }
/**
* Return current line number.
*/
FXint getLine() const { return line; }
/**
* Return current column number.
*/
FXint getColumn() const { return column; }
/**
* Return offset from begin of file.
*/
FXlong getOffset() const { return offset; }
/**
* Parse the file, return error code to indicate success or
* failure.
*/
Error parse();
/// Document start
Error startDocument();
/// Element start w/no attributes
Error startElement(const FXString& tag);
/// Element start w/attributes
Error startElement(const FXString& tag,const FXStringDictionary& atts);
/// Characters
Error characters(const FXString& text);
/// Comment
Error comment(const FXString& text);
/// Processing instruction
Error processing(const FXString& target,const FXString& text);
/// Element end
Error endElement(const FXString& tag);
/// Document end
Error endDocument();
/// Returns error code for given error
static const FXchar* getError(Error err){ return errors[err]; }
/**
* Close stream and delete buffer, if owned.
*/
FXbool close();
/**
* Decode escaped special characters from XML stream.
*/
static FXbool decode(FXString& dst,const FXString& src,FXuint flags=CRLF|REFS);
/**
* Encode special characters for inclusion into XML stream.
*/
static FXbool encode(FXString& dst,const FXString& src,FXuint flags=CRLF|REFS);
/**
* Close XML stream and clean up.
*/
virtual ~FXXML();
};
}
#endif