rlm@1: // MyXml.cpp rlm@1: rlm@1: #include "StdAfx.h" rlm@1: rlm@1: #include "MyXml.h" rlm@1: rlm@1: static bool IsValidChar(char c) rlm@1: { rlm@1: return rlm@1: c >= 'a' && c <= 'z' || rlm@1: c >= 'A' && c <= 'Z' || rlm@1: c >= '0' && c <= '9' || rlm@1: c == '-'; rlm@1: } rlm@1: rlm@1: static bool IsSpaceChar(char c) rlm@1: { rlm@1: return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A); rlm@1: } rlm@1: rlm@1: #define SKEEP_SPACES(s, pos) while (IsSpaceChar(s[pos])) pos++; rlm@1: rlm@1: static bool ReadProperty(const AString &s, int &pos, CXmlProp &prop) rlm@1: { rlm@1: prop.Name.Empty(); rlm@1: prop.Value.Empty(); rlm@1: for (; pos < s.Length(); pos++) rlm@1: { rlm@1: char c = s[pos]; rlm@1: if (!IsValidChar(c)) rlm@1: break; rlm@1: prop.Name += c; rlm@1: } rlm@1: rlm@1: if (prop.Name.IsEmpty()) rlm@1: return false; rlm@1: rlm@1: SKEEP_SPACES(s, pos); rlm@1: if (s[pos++] != '=') rlm@1: return false; rlm@1: rlm@1: SKEEP_SPACES(s, pos); rlm@1: if (s[pos++] != '\"') rlm@1: return false; rlm@1: rlm@1: while (pos < s.Length()) rlm@1: { rlm@1: char c = s[pos++]; rlm@1: if (c == '\"') rlm@1: return true; rlm@1: prop.Value += c; rlm@1: } rlm@1: return false; rlm@1: } rlm@1: rlm@1: int CXmlItem::FindProperty(const AString &propName) const rlm@1: { rlm@1: for (int i = 0; i < Props.Size(); i++) rlm@1: if (Props[i].Name == propName) rlm@1: return i; rlm@1: return -1; rlm@1: } rlm@1: rlm@1: AString CXmlItem::GetPropertyValue(const AString &propName) const rlm@1: { rlm@1: int index = FindProperty(propName); rlm@1: if (index >= 0) rlm@1: return Props[index].Value; rlm@1: return AString(); rlm@1: } rlm@1: rlm@1: bool CXmlItem::IsTagged(const AString &tag) const rlm@1: { rlm@1: return (IsTag && Name == tag); rlm@1: } rlm@1: rlm@1: int CXmlItem::FindSubTag(const AString &tag) const rlm@1: { rlm@1: for (int i = 0; i < SubItems.Size(); i++) rlm@1: if (SubItems[i].IsTagged(tag)) rlm@1: return i; rlm@1: return -1; rlm@1: } rlm@1: rlm@1: AString CXmlItem::GetSubString() const rlm@1: { rlm@1: if (SubItems.Size() == 1) rlm@1: { rlm@1: const CXmlItem &item = SubItems[0]; rlm@1: if (!item.IsTag) rlm@1: return item.Name; rlm@1: } rlm@1: return AString(); rlm@1: } rlm@1: rlm@1: AString CXmlItem::GetSubStringForTag(const AString &tag) const rlm@1: { rlm@1: int index = FindSubTag(tag); rlm@1: if (index >= 0) rlm@1: return SubItems[index].GetSubString(); rlm@1: return AString(); rlm@1: } rlm@1: rlm@1: bool CXmlItem::ParseItems(const AString &s, int &pos, int numAllowedLevels) rlm@1: { rlm@1: if (numAllowedLevels == 0) rlm@1: return false; rlm@1: SubItems.Clear(); rlm@1: AString finishString = "'); rlm@1: } rlm@1: if (s[pos] == '>') rlm@1: { rlm@1: if (!ParseItems(s, ++pos, numAllowedLevels)) rlm@1: return false; rlm@1: AString finishString = AString(""); rlm@1: if (s.Mid(pos, finishString.Length()) != finishString) rlm@1: return false; rlm@1: pos += finishString.Length(); rlm@1: return true; rlm@1: } rlm@1: if (posTemp == pos) rlm@1: return false; rlm@1: rlm@1: CXmlProp prop; rlm@1: if (!ReadProperty(s, pos, prop)) rlm@1: return false; rlm@1: Props.Add(prop); rlm@1: posTemp = pos; rlm@1: } rlm@1: } rlm@1: rlm@1: bool SkeepHeader(const AString &s, int &pos, const AString &startString, const AString &endString) rlm@1: { rlm@1: SKEEP_SPACES(s, pos); rlm@1: if (s.Mid(pos, startString.Length()) == startString) rlm@1: { rlm@1: pos = s.Find(endString, pos); rlm@1: if (pos < 0) rlm@1: return false; rlm@1: pos += endString.Length(); rlm@1: SKEEP_SPACES(s, pos); rlm@1: } rlm@1: return true; rlm@1: } rlm@1: rlm@1: bool CXml::Parse(const AString &s) rlm@1: { rlm@1: int pos = 0; rlm@1: if (!SkeepHeader(s, pos, "")) rlm@1: return false; rlm@1: if (!SkeepHeader(s, pos, "")) rlm@1: return false; rlm@1: if (!Root.ParseItem(s, pos, 1000)) rlm@1: return false; rlm@1: SKEEP_SPACES(s, pos); rlm@1: return (pos == s.Length() && Root.IsTag); rlm@1: }