ultimatepp/uppsrc/Core/XML.h
2024-08-23 08:35:19 +02:00

296 lines
No EOL
12 KiB
C++

String DeXml(const char *s, byte charset = CHARSET_DEFAULT, bool escapelf = false);
String DeXml(const char *s, const char *end, byte charset = CHARSET_DEFAULT, bool escapelf = false);
String DeXml(const String& s, byte charset = CHARSET_DEFAULT, bool escapelf = false);
String XmlPI(const char *text);
String XmlHeader(const char *encoding = "UTF-8", const char *version = "1.0", const char *standalone = NULL);
String XmlDecl(const char *text);
String XmlDocType(const char *text);
String XmlDoc(const char *name, const char *xmlbody);
String XmlComment(const char *text);
class XmlTag : Moveable<XmlTag> {
String tag;
String end;
public:
XmlTag& Tag(const char *s);
String operator()();
String operator()(const char *text);
String operator()(const String& text) { return operator()(~text); }
String Text(const char *s, byte charset = CHARSET_DEFAULT);
String Text(const String& s, byte charset = CHARSET_DEFAULT) { return Text(~s, charset); }
String PreservedText(const char *s, byte charset = CHARSET_DEFAULT);
String PreservedText(const String& s, byte charset = CHARSET_DEFAULT) { return PreservedText(~s, charset); }
String GetBegin() const { return tag + '>'; }
String GetEnd() const { return end; }
XmlTag& operator()(const char *attr, const char *val);
XmlTag& operator()(const char *attr, int q);
XmlTag& operator()(const char *attr, double q);
XmlTag& operator()(const char *attr, float q);
XmlTag() {}
XmlTag(const char *tag) { Tag(tag); }
};
enum { XML_DOC, XML_TAG, XML_END, XML_TEXT, XML_DECL, XML_PI, XML_COMMENT, XML_EOF };
struct XmlError : public Exc
{
XmlError(const char *s) : Exc(s) {}
};
class XmlParser {
enum {
#ifdef flagTEST_XML // This is for testing purposes only to increase boundary condition frequency
MCHARS = 128,
CHUNK = 256
#else
MCHARS = 256,
CHUNK = 16384
#endif
};
struct Nesting {
Nesting(String tag = Null, bool blanks = false) : tag(tag), preserve_blanks(blanks) {}
String tag;
bool preserve_blanks;
};
VectorMap<String, String> entity;
Stream *in;
Buffer<char> buffer;
int len;
int begincolumn;
const char *begin;
const char *term;
String attr1, attrval1;
VectorMap<String, String> attr;
Array<Nesting> stack;
int type;
String nattr1, nattrval1;
VectorMap<String, String> nattr;
String tagtext;
String cdata;
bool empty_tag;
bool npreserve, preserveall;
bool relaxed;
bool raw;
int line;
byte acharset;
byte scharset;
void Init();
void LoadMore0();
void LoadMore() { if(len - (term - begin) < MCHARS) LoadMore0(); }
bool More();
bool HasMore() { return *term || More(); }
void Ent(StringBuffer& out);
void Next();
void ReadAttr(StringBuffer& b, int c);
String ReadTag(bool next);
String ReadEnd(bool next);
String ReadDecl(bool next);
String ReadPI(bool next);
String ReadComment(bool next);
int GetColumn0() const;
String Convert(StringBuffer& b);
public:
void SkipWhites();
void RegisterEntity(const String& id, const String& text);
bool IsEof();
const char *GetPtr() const { return term; }
bool IsTag();
String PeekTag() { return ReadTag(false); }
String ReadTag() { return ReadTag(true); }
bool Tag(const char *tag);
bool Tag(const String& tag);
void PassTag(const char *tag);
void PassTag(const String& tag);
bool IsEnd();
String PeekEnd() { return ReadEnd(false); }
String ReadEnd() { return ReadEnd(true); }
bool End();
bool End(const char *tag);
bool End(const String& tag);
void PassEnd();
void PassEnd(const char *tag);
bool TagE(const char *tag);
void PassTagE(const char *tag);
bool TagElseSkip(const char *tag);
bool LoopTag(const char *tag);
int GetAttrCount() const { return attr.GetCount() + !IsNull(attr1); }
String GetAttr(int i) const { return i ? attr.GetKey(i - 1) : attr1; }
bool IsAttr(const char *id) const { return attr1 == id || attr.Find(id) >= 0; }
String operator[](int i) const { return i ? attr[i - 1] : attrval1; }
String operator[](const char *id) const { return attr1 == id ? attrval1 : attr.Get(id, Null); }
int Int(const char *id, int def = Null) const;
double Double(const char *id, double def = Null) const;
float Float(const char *id, float def = Null) const;
bool IsText();
String PeekText() { return cdata; }
String ReadText();
String ReadTextE();
bool IsDecl();
String PeekDecl() { return ReadDecl(false); }
String ReadDecl() { return ReadDecl(true); }
bool IsPI();
String PeekPI() { return ReadPI(false); }
String ReadPI() { return ReadPI(true); }
bool IsComment();
String PeekComment() { return ReadComment(false); }
String ReadComment() { return ReadComment(true); }
void Skip();
void SkipEnd();
VectorMap<String, String> PickAttrs();
int GetLine() const { return line; }
int GetColumn() const { return GetColumn0() + 1; }
void Relaxed(bool b = true) { relaxed = b; }
bool IsRelaxed() const { return relaxed; }
void PreserveAllWhiteSpaces(bool b = true) { preserveall = b; }
void Raw(bool b = true) { raw = b; }
XmlParser(const char *s);
XmlParser(Stream& in);
};
class XmlNode : Moveable<XmlNode>, DeepCopyOption<XmlNode> {
int type;
String text;
Array<XmlNode> node;
One< VectorMap<String, String> > attr;
public:
static const XmlNode& Void();
bool IsVoid() const { return this == &Void(); }
int GetType() const { return type; }
String GetText() const { return text; }
String GetTag() const { return text; }
bool IsTag() const { return type == XML_TAG; }
bool IsTag(const char *tag) const { return IsTag() && text == tag; }
bool IsText() const { return type == XML_TEXT; }
void Clear() { text.Clear(); attr.Clear(); node.Clear(); type = -1; }
void CreateTag(const char *tag) { type = XML_TAG; text = tag; }
void CreateText(const String& txt) { type = XML_TEXT; text = txt; }
void CreatePI(const String& pi) { type = XML_PI; text = pi; }
void CreateDecl(const String& decl) { type = XML_DECL; text = decl; }
void CreateComment(const String& comment) { type = XML_COMMENT; text = comment; }
void CreateDocument() { Clear(); }
bool IsEmpty() const { return type == XML_DOC && node.GetCount() == 0; }
operator bool() const { return !IsEmpty(); }
int GetCount() const { return node.GetCount(); }
XmlNode& At(int i) { return node.At(i); }
const XmlNode& Node(int i) const { return node[i]; }
const XmlNode& operator[](int i) const { return i >= 0 && i < node.GetCount() ? node[i] : Void(); }
const XmlNode& operator[](const char *tag) const;
XmlNode& Add() { return node.Add(); }
void Remove(int i);
void AddText(const String& txt) { Add().CreateText(txt); }
int FindTag(const char *tag) const;
XmlNode& Add(const char *tag);
XmlNode& GetAdd(const char *tag);
XmlNode& operator()(const char *tag) { return GetAdd(tag); }
void Remove(const char *tag);
String GatherText() const;
String operator~() const { return GatherText(); }
bool HasTags() const;
int GetAttrCount() const { return attr ? attr->GetCount() : 0; }
String AttrId(int i) const { return attr->GetKey(i); }
String Attr(int i) const { return (*attr)[i]; }
String Attr(const char *id) const { return attr ? attr->Get(id, Null) : String(); }
XmlNode& SetAttr(const char *id, const String& val);
int AttrInt(const char *id, int def = Null) const;
XmlNode& SetAttr(const char *id, int val);
void SetAttrs(VectorMap<String, String>&& a);
void Shrink();
rval_default(XmlNode);
XmlNode(const XmlNode& n, int);
XmlNode() { type = XML_DOC; }
typedef Array<XmlNode>::ConstIterator ConstIterator;
ConstIterator Begin() const { return node.Begin(); }
ConstIterator End() const { return node.End(); }
typedef XmlNode value_type;
typedef ConstIterator const_iterator;
typedef const XmlNode& const_reference;
typedef int size_type;
typedef int difference_type;
const_iterator begin() const { return Begin(); }
const_iterator end() const { return End(); }
};
enum {
XML_IGNORE_DECLS = 0x01,
XML_IGNORE_PIS = 0x02,
XML_IGNORE_COMMENTS = 0x04,
};
struct ParseXmlFilter {
virtual bool DoTag(const String& tag) = 0;
virtual void EndTag();
};
XmlNode ParseXML(XmlParser& p, dword style = XML_IGNORE_DECLS|XML_IGNORE_PIS|XML_IGNORE_COMMENTS);
XmlNode ParseXML(const char *s, dword style = XML_IGNORE_DECLS|XML_IGNORE_PIS|XML_IGNORE_COMMENTS);
XmlNode ParseXML(Stream& in, dword style = XML_IGNORE_DECLS|XML_IGNORE_PIS|XML_IGNORE_COMMENTS);
XmlNode ParseXMLFile(const char *path, dword style = XML_IGNORE_DECLS|XML_IGNORE_PIS|XML_IGNORE_COMMENTS);
XmlNode ParseXML(XmlParser& p, ParseXmlFilter& filter, dword style = XML_IGNORE_DECLS|XML_IGNORE_PIS|XML_IGNORE_COMMENTS);
XmlNode ParseXML(const char *s, ParseXmlFilter& filter, dword style = XML_IGNORE_DECLS|XML_IGNORE_PIS|XML_IGNORE_COMMENTS);
XmlNode ParseXML(Stream& in, ParseXmlFilter& filter, dword style = XML_IGNORE_DECLS|XML_IGNORE_PIS|XML_IGNORE_COMMENTS);
XmlNode ParseXMLFile(const char *path, ParseXmlFilter& filter, dword style = XML_IGNORE_DECLS|XML_IGNORE_PIS|XML_IGNORE_COMMENTS);
class IgnoreXmlPaths : public ParseXmlFilter {
public:
virtual bool DoTag(const String& id);
virtual void EndTag();
private:
Index<String> list;
Vector<String> path;
public:
IgnoreXmlPaths(const char *s);
};
enum {
XML_HEADER = 0x01,
XML_DOCTYPE = 0x02,
XML_PRETTY = 0x04,
XML_ESCAPELF = 0x08,
};
void AsXML(Stream& out, const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY);
String AsXML(const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY);
bool AsXMLFile(const char *path, const XmlNode& n, dword style = XML_HEADER|XML_DOCTYPE|XML_PRETTY);