/////////////////////////////////////////////////
// Xml-Object-Serialization
class TXmlObjSer{
private:
static TStrStrH TypeNmToTagNmH;
public:
static TStr GetTagNm(const TStr& TypeNm);
static void AssertXmlHd(
const PXmlTok& XmlTok, const TStr& Nm, const TStr& TypeNm);
static bool GetBoolArg(const PXmlTok& XmlTok, const TStr& Nm);
static int GetIntArg(const PXmlTok& XmlTok, const TStr& Nm);
static int64 GetInt64Arg(const PXmlTok& XmlTok, const TStr& Nm);
static double GetFltArg(const PXmlTok& XmlTok, const TStr& Nm);
};
/////////////////////////////////////////////////
// Xml-Object-Serialization-Tag-Name
class TXmlObjSerTagNm{
private:
TStr TagNm;
TSOut* SOut;
UndefDefaultCopyAssign(TXmlObjSerTagNm);
public:
TXmlObjSerTagNm(
TSOut& _SOut, const bool& ETagP,
const TStr& Nm, const TStr& TypeNm,
const TStr& ArgNm="", const TStr& ArgVal="");
TXmlObjSerTagNm(
TSOut& _SOut, const bool& ETagP,
const TStr& Nm, const TStr& TypeNm,
const TStr& ArgNm1, const TStr& ArgVal1,
const TStr& ArgNm2, const TStr& ArgVal2,
const TStr& ArgNm3="", const TStr& ArgVal3="",
const TStr& ArgNm4="", const TStr& ArgVal4="");
~TXmlObjSerTagNm();
};
/////////////////////////////////////////////////
// Xml-Char-Definition
ClassTP(TXmlChDef, PXmlChDef)//{
private:
TInt Chs;
TBSet CharChSet, CombChSet, ExtChSet;
TBSet LetterChSet, DigitChSet, NameChSet, PubidChSet;
TStrStrH EntityNmToValH;
void SetChTy(TBSet& ChSet, const int& MnCh, const int& MxCh=-1);
void SetChTy(TBSet& ChSet, const TStr& Str);
void SetEntityVal(const TStr& Nm, const TStr& Val);
public:
TXmlChDef();
TXmlChDef(TSIn& SIn):
Chs(SIn),
CharChSet(SIn), CombChSet(SIn), ExtChSet(SIn),
LetterChSet(SIn), DigitChSet(SIn), NameChSet(SIn), PubidChSet(SIn),
EntityNmToValH(SIn){}
static PXmlChDef Load(TSIn& SIn){return new TXmlChDef(SIn);}
void Save(TSOut& SOut){
Chs.Save(SOut);
CharChSet.Save(SOut); CombChSet.Save(SOut); ExtChSet.Save(SOut);
LetterChSet.Save(SOut); DigitChSet.Save(SOut); NameChSet.Save(SOut);
PubidChSet.Save(SOut);
EntityNmToValH.Save(SOut);}
TXmlChDef& operator=(const TXmlChDef&){Fail; return *this;}
bool IsChar(const uchar& Ch) const {return CharChSet.GetBit(Ch);}
bool IsComb(const uchar& Ch) const {return CombChSet.GetBit(Ch);}
bool IsExt(const uchar& Ch) const {return ExtChSet.GetBit(Ch);}
bool IsLetter(const uchar& Ch) const {return LetterChSet.GetBit(Ch);}
bool IsDigit(const uchar& Ch) const {return DigitChSet.GetBit(Ch);}
bool IsName(const uchar& Ch) const {return NameChSet.GetBit(Ch);}
bool IsPubid(const uchar& Ch) const {return PubidChSet.GetBit(Ch);}
bool IsWs(const uchar& Ch) const {
return (Ch==' ')||(Ch==TCh::CrCh)||(Ch==TCh::LfCh)||(Ch==TCh::TabCh);}
bool IsFirstNameCh(const uchar& Ch) const {
return IsLetter(Ch)||(Ch=='_')||(Ch==':');}
bool IsEoln(const uchar& Ch) const {
return (Ch==TCh::CrCh)||(Ch==TCh::LfCh);}
bool IsEntityNm(const TStr& EntityNm, TStr& EntityVal) const {
return EntityNmToValH.IsKeyGetDat(EntityNm, EntityVal);}
};
/////////////////////////////////////////////////
// Xml-Lexical
typedef enum {
xsyUndef, xsyWs, xsyComment,
xsyXmlDecl, xsyPI,
xsyDocTypeDecl, xsyElement, xsyAttList, xsyEntity, xsyNotation,
xsyTag, xsySTag, xsyETag, xsySETag, xsyStr, xsyQStr,
xsyEof} TXmlLxSym;
typedef enum {xspIntact, xspPreserve, xspSeparate, xspTruncate} TXmlSpacing;
class TXmlLx{
private: // character level functions
static TXmlChDef ChDef;
PSIn SIn;
TSIn& RSIn;
TChA ChStack;
uchar PrevCh, Ch;
int LnN, LnChN, ChN;
TXmlSpacing Spacing;
uchar GetCh();
void PutCh(const uchar& _Ch){ChStack.Push(Ch); Ch=_Ch;}
void PutStr(const TStr& Str){
for (int ChN=Str.Len()-1; ChN>=0; ChN--){PutCh(Str[ChN]);}}
void ToNrSpacing();
private: // part-of-symbol level functions
TStrStrH EntityNmToValH, PEntityNmToValH;
void GetWs(const bool& IsRq);
TStr GetReference();
void GetEq();
TStr GetName();
TStr GetName(const TStr& RqNm);
void GetComment();
TStr GetAttValue();
TStr GetVersionNum();
TStr GetEncName();
TStr GetStalVal();
void GetXmlDecl();
void GetPI();
TStr GetSystemLiteral();
TStr GetPubidLiteral();
TStr GetPEReference();
void GetExternalId();
void GetNData();
void GetDocTypeDecl();
void GetElement();
void GetAttList();
TStr GetEntityValue();
void GetEntity();
void GetNotation();
void GetCDSect();
public: // symbol state
TXmlLxSym Sym;
TChA TxtChA;
TStr TagNm;
TStrKdV ArgNmValKdV;
void SkipWs();
public:
TXmlLx(const PSIn& _SIn, const TXmlSpacing& _Spacing=xspIntact):
SIn(_SIn), RSIn(*SIn),
ChStack(), PrevCh(' '), Ch(' '),
LnN(1), LnChN(0), ChN(0), Spacing(_Spacing),
EntityNmToValH(100), PEntityNmToValH(100),
Sym(xsyUndef), TxtChA(), TagNm(), ArgNmValKdV(10){GetCh();}
TXmlLx& operator=(const TXmlLx&){Fail; return *this;}
TXmlLxSym GetSym();
TStr GetSymStr() const;
void EThrow(const TStr& MsgStr) const;
TStr GetFPosStr() const;
// tag arguments
void ClrArgV(){ArgNmValKdV.Clr();}
void AddArg(const TStr& ArgNm, const TStr& ArgVal){
ArgNmValKdV.Add(TStrKd(ArgNm, ArgVal));}
bool IsArgNm(const TStr& ArgNm) const {
return ArgNmValKdV.IsIn(TStrKd(ArgNm));}
int GetArgs() const {return ArgNmValKdV.Len();}
void GetArg(const int& ArgN, TStr& ArgNm, TStr& ArgVal) const {
ArgNm=ArgNmValKdV[ArgN].Key; ArgVal=ArgNmValKdV[ArgN].Dat;}
TStr GetArgVal(const TStr& ArgNm, const TStr& DfVal=TStr()) const {
int ArgN=ArgNmValKdV.SearchForw(TStrKd(ArgNm));
if (ArgN==-1){return DfVal;} else {return ArgNmValKdV[ArgN].Dat;}}
static char GetArgValQCh(const TStr& ArgVal){
if (ArgVal.IsChIn('\"')){return '\'';} else {return '\"';}}
// entities
bool IsEntityNm(const TStr& EntityNm, TStr& EntityVal) const {
return EntityNmToValH.IsKeyGetDat(EntityNm, EntityVal);}
void PutEntityVal(const TStr& Nm, const TStr& Val){
EntityNmToValH.AddDat(Nm, Val);}
bool IsPEntityNm(const TStr& EntityNm, TStr& EntityVal) const {
return PEntityNmToValH.IsKeyGetDat(EntityNm, EntityVal);}
void PutPEntityVal(const TStr& Nm, const TStr& Val){
PEntityNmToValH.AddDat(Nm, Val);}
// symbol to string conversion
static TStr GetXmlLxSymStr(const TXmlLxSym& XmlLxSym);
// string conversion
static bool IsTagNm(const TStr& Str);
static TStr GetXmlStrFromPlainMem(const TMem& PlainMem);
static TStr GetXmlStrFromPlainStr(const TChA& PlainChA);
static TStr GetPlainStrFromXmlStr(const TStr& XmlStr);
static TStr GetUsAsciiStrFromXmlStr(const TStr& EntRefStr);
static TStr GetChRefFromYuEntRef(const TStr& YuEntRefStr);
};
/////////////////////////////////////////////////
// Xml-Token
ClassTPV(TXmlTok, PXmlTok, TXmlTokV)//{
private:
TXmlLxSym Sym;
TStr Str;
TStrKdV ArgNmValV;
TXmlTokV SubTokV;
public:
TXmlTok(): Sym(xsyUndef), Str(), ArgNmValV(), SubTokV(){}
TXmlTok(const TXmlLxSym& _Sym):
Sym(_Sym), Str(), ArgNmValV(), SubTokV(){}
TXmlTok(const TXmlLxSym& _Sym, const TStr& _Str):
Sym(_Sym), Str(_Str), ArgNmValV(), SubTokV(){}
TXmlTok(const TXmlLxSym& _Sym, const TStr& _Str, const TStrKdV& _ArgNmValV):
Sym(_Sym), Str(_Str), ArgNmValV(_ArgNmValV){}
static PXmlTok New(){return PXmlTok(new TXmlTok());}
static PXmlTok New(const TXmlLxSym& Sym){return PXmlTok(new TXmlTok(Sym));}
static PXmlTok New(const TXmlLxSym& Sym, const TStr& Str){
return PXmlTok(new TXmlTok(Sym, Str));}
static PXmlTok New(
const TXmlLxSym& Sym, const TStr& Str, const TStrKdV& ArgNmValV){
return PXmlTok(new TXmlTok(Sym, Str, ArgNmValV));}
static PXmlTok New(const TStr& TagNm){
return PXmlTok(new TXmlTok(xsyTag, TagNm));}
static PXmlTok New(const TStr& TagNm, const TStr& ValStr){
PXmlTok TagXmlTok=PXmlTok(new TXmlTok(xsyTag, TagNm));
PXmlTok StrXmlTok=PXmlTok(new TXmlTok(xsyStr, ValStr));
TagXmlTok->AddSubTok(StrXmlTok); return TagXmlTok;}
static PXmlTok New(const TStr& TagNm,
const PXmlTok& XmlTok1, const PXmlTok& XmlTok2=NULL){
PXmlTok TagXmlTok=PXmlTok(new TXmlTok(xsyTag, TagNm));
if (!XmlTok1.Empty()){TagXmlTok->AddSubTok(XmlTok1);}
if (!XmlTok2.Empty()){TagXmlTok->AddSubTok(XmlTok2);}
return TagXmlTok;}
TXmlTok(TSIn&){Fail;}
static PXmlTok Load(TSIn&){Fail; return NULL;}
void Save(TSOut&){Fail;}
TXmlTok& operator=(const TXmlTok&){Fail; return *this;}
// type-of-token and text value (xsyWs, xsyStr, xsyQStr, xsyTag)
TXmlLxSym GetSym() const {return Sym;}
TStr GetSymStr() const {return TXmlLx::GetXmlLxSymStr(Sym);}
void PutStr(const TStr& _Str){Str=_Str;}
TStr GetStr() const {return Str;}
// tags
bool IsTag() const {return (Sym==xsyTag);}
bool IsTag(const TStr& TagNm) const {return (Sym==xsyTag)&&(Str==TagNm);}
TStr GetTagNm() const {IAssert(Sym==xsyTag); return Str;}
// tag argument
void AddArg(const TStr& ArgNm, const bool& ArgVal){
ArgNmValV.Add(TStrKd(ArgNm, TBool::GetStr(ArgVal)));}
void AddArg(const TStr& ArgNm, const int& ArgVal){
ArgNmValV.Add(TStrKd(ArgNm, TInt::GetStr(ArgVal)));}
void AddArg(const TStr& ArgNm, const double& ArgVal){
ArgNmValV.Add(TStrKd(ArgNm, TFlt::GetStr(ArgVal)));}
void AddArg(const TStr& ArgNm, const TStr& ArgVal){
ArgNmValV.Add(TStrKd(ArgNm, ArgVal));}
int GetArgs() const {return ArgNmValV.Len();}
void GetArg(const int& ArgN, TStr& ArgNm, TStr& ArgVal) const {
ArgNm=ArgNmValV[ArgN].Key; ArgVal=ArgNmValV[ArgN].Dat;}
bool IsArg(const TStr& ArgNm) const {
return ArgNmValV.SearchForw(TStrKd(ArgNm))!=-1;}
bool IsArg(const TStr& ArgNm, TStr& ArgVal) const {
int ArgN=ArgNmValV.SearchForw(TStrKd(ArgNm));
if (ArgN!=-1){ArgVal=ArgNmValV[ArgN].Dat;}
return ArgN!=-1;}
void PutArgVal(const TStr& ArgNm, const TStr& ArgVal){
ArgNmValV[ArgNmValV.SearchForw(TStrKd(ArgNm))].Dat=ArgVal;}
TStr GetArgVal(const TStr& ArgNm) const {
return ArgNmValV[ArgNmValV.SearchForw(TStrKd(ArgNm))].Dat;}
TStr GetArgVal(const TStr& ArgNm, const TStr& DfArgVal) const {
int ArgN=ArgNmValV.SearchForw(TStrKd(ArgNm));
return (ArgN==-1) ? DfArgVal : ArgNmValV[ArgN].Dat;}
bool GetBoolArgVal(const TStr& ArgNm, const bool& DfVal=false) const;
bool GetBoolArgVal(
const TStr& ArgNm, const TStr& TrueVal, const bool& DfVal=false) const;
bool GetBoolArgVal(const TStr& ArgNm,
const TStr& TrueVal, const TStr& FalseVal, const bool& DfVal=false) const;
int GetIntArgVal(const TStr& ArgNm, const int& DfVal=0) const;
double GetFltArgVal(const TStr& ArgNm, const double& DfVal=0) const;
TStr GetStrArgVal(const TStr& ArgNm, const TStr& DfVal=TStr()) const;
// sub tokens
bool IsSubTag(const TStr& TagNm) const {
return !GetTagTok(TagNm).Empty();}
bool IsSubTag(const TStr& TagNm, PXmlTok& Tok) const {
Tok=GetTagTok(TagNm); return !Tok.Empty();}
void AddSubTok(const PXmlTok& Tok){SubTokV.Add(Tok);}
int GetSubToks() const {return SubTokV.Len();}
PXmlTok GetSubTok(const int& SubTokN) const {return SubTokV[SubTokN];}
void ClrSubTok(){SubTokV.Clr();}
void PutSubTok(const PXmlTok& Tok, const int& SubTokN=-1);
// value retrieval
bool IsTagTok(const TStr& TagPath, PXmlTok& TagTok) const {
TagTok=GetTagTok(TagPath); return !TagTok.Empty();}
bool IsTagTok(const TStr& TagPath) const {
PXmlTok TagTok; return IsTagTok(TagPath, TagTok);}
PXmlTok GetTagTok(const TStr& TagPath) const;
void GetTagTokV(const TStr& TagPath, TXmlTokV& XmlTokV) const;
void GetTagValV(const TStr& TagNm, const bool& XmlP, TStrV& ValV) const;
TStr GetTagVal(const TStr& TagNm, const bool& XmlP) const;
TStr GetTagTokStr(const TStr& TagPath) const {
return GetTagTok(TagPath)->GetTokStr(false);}
TStr GetTagTokStrOrDf(const TStr& TagPath, const TStr& DfVal=TStr()) const {
PXmlTok TagTok;
if (IsTagTok(TagPath, TagTok)){return TagTok->GetTokStr(false);}
else {return DfVal;}}
// string representation for the token
void AddTokToChA(const bool& XmlP, TChA& ChA) const;
TStr GetTokStr(const bool& XmlP=true) const {
TChA ChA; AddTokToChA(XmlP, ChA); return ChA;}
static TStr GetTokVStr(const TXmlTokV& TokV, const bool& XmlP=true);
// convert current lexical symbol to token
static PXmlTok GetTok(TXmlLx& Lx);
};
/////////////////////////////////////////////////
// Xml-Document
ClassTPV(TXmlDoc, PXmlDoc, TXmlDocV)//{
private:
bool Ok;
TStr MsgStr;
PXmlTok Tok;
static void LoadTxtMiscStar(TXmlLx& Lx);
static PXmlTok LoadTxtElement(TXmlLx& Lx);
public:
TXmlDoc(): Ok(false), MsgStr(), Tok(){}
static PXmlDoc New(){return PXmlDoc(new TXmlDoc());}
TXmlDoc(const PXmlTok& _Tok): Ok(!_Tok.Empty()), MsgStr(), Tok(_Tok){}
static PXmlDoc New(const PXmlTok& Tok){return PXmlDoc(new TXmlDoc(Tok));}
TXmlDoc(TSIn&){Fail;}
static PXmlDoc Load(TSIn& SIn){return new TXmlDoc(SIn);}
void Save(TSOut&){Fail;}
TXmlDoc& operator=(const TXmlDoc&){Fail; return *this;}
// component retrieval
bool IsOk() const {return Ok;}
TStr GetMsgStr() const {return MsgStr;}
PXmlTok GetTok() const {IAssert(Ok); return Tok;}
// value retrieval
bool IsTagTok(const TStr& TagPath, PXmlTok& TagTok) const {
IAssert(Ok); TagTok=GetTagTok(TagPath); return !TagTok.Empty();}
bool IsTagTok(const TStr& TagPath) const {
PXmlTok TagTok; return IsTagTok(TagPath, TagTok);}
PXmlTok GetTagTok(const TStr& TagPath) const;
void PutTagTokStr(const TStr& TagPath, const TStr& TokStr) const;
TStr GetTagTokStr(const TStr& TagPath) const {
return GetTagTok(TagPath)->GetTokStr(false);}
void GetTagTokV(const TStr& TagPath, TXmlTokV& XmlTokV) const;
void GetTagValV(const TStr& TagNm, const bool& XmlP, TStrV& ValV) const {
IAssert(Ok); Tok->GetTagValV(TagNm, XmlP, ValV);}
TStr GetTagVal(const TStr& TagNm, const bool& XmlP) const {
TStrV ValV; GetTagValV(TagNm, XmlP, ValV);
if (ValV.Len()>0){return ValV[0];} else {return "";}}
bool GetTagTokBoolArgVal(
const TStr& TagPath, const TStr& ArgNm, const bool& DfVal=false) const;
int GetTagTokIntArgVal(
const TStr& TagPath, const TStr& ArgNm, const int& DfVal=0) const;
double GetTagTokFltArgVal(
const TStr& TagPath, const TStr& ArgNm, const double& DfVal=0) const;
TStr GetTagTokStrArgVal(
const TStr& TagPath, const TStr& ArgNm, const TStr& DfVal=TStr()) const;
// string representation
static TStr GetXmlStr(const TStr& Str);
// loading/saving document
static bool SkipTopTag(const PSIn& SIn);
static PXmlDoc LoadTxt(TXmlLx& Lx);
static PXmlDoc LoadTxt(const PSIn& SIn, const TXmlSpacing& Spacing=xspIntact);
static PXmlDoc LoadTxt(const TStr& FNm, const TXmlSpacing& Spacing=xspIntact);
static void LoadTxt(
const TStr& FNm, TXmlDocV& XmlDocV, const TXmlSpacing& Spacing=xspIntact);
void SaveTxt(const PSOut& SOut){
SOut->PutStr(GetTok()->GetTokStr());}
void SaveTxt(const TStr& FNm, const bool& Append=false){
PSOut SOut=TFOut::New(FNm, Append); SaveTxt(SOut);}
static PXmlDoc LoadStr(const TStr& Str);
void SaveStr(TStr& Str);
};
/////////////////////////////////////////////////
// Fast and dirty XML parser
// very basic it does only - string
, no comments, no arguments
class TXmlParser;
typedef TPt PXmlParser;
class TXmlParser { //J:
private:
TCRef CRef;
PSIn SIn;
TSIn& RSIn;
TChA _SymStr;
public:
TXmlLxSym Sym, NextSym;
TChA SymStr, NextSymStr;
private:
char GetCh() { return (! RSIn.Eof()) ? RSIn.GetCh() : TCh::EofCh; }
public:
TXmlParser(const PSIn& _SIn) : SIn(_SIn), RSIn(*SIn), Sym(xsyUndef), NextSym(xsyUndef) { }
static PXmlParser New(const PSIn& SIn) { return new TXmlParser(SIn); }
TXmlLxSym GetSym();
TXmlLxSym GetSym(TChA& _SymStr);
TXmlLxSym PeekSym();
TXmlLxSym PeekSym(TChA& _SymStr);
void SkipTillTag(const TChA& _SymStr);
TXmlLxSym GetTag(const TChA& TagStr);
void GetTagVal(const TChA& TagStr, TChA& TagVal);
static void GetPlainStrFromXmlStr(const TChA& XmlStr, TChA& PlainChA);
friend class TPt;
};