Mercurial > vba-clojure
view src/win32/7zip/7z/CPP/Common/MyXml.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line source
1 // MyXml.cpp3 #include "StdAfx.h"5 #include "MyXml.h"7 static bool IsValidChar(char c)8 {9 return10 c >= 'a' && c <= 'z' ||11 c >= 'A' && c <= 'Z' ||12 c >= '0' && c <= '9' ||13 c == '-';14 }16 static bool IsSpaceChar(char c)17 {18 return (c == ' ' || c == '\t' || c == 0x0D || c == 0x0A);19 }21 #define SKEEP_SPACES(s, pos) while (IsSpaceChar(s[pos])) pos++;23 static bool ReadProperty(const AString &s, int &pos, CXmlProp &prop)24 {25 prop.Name.Empty();26 prop.Value.Empty();27 for (; pos < s.Length(); pos++)28 {29 char c = s[pos];30 if (!IsValidChar(c))31 break;32 prop.Name += c;33 }35 if (prop.Name.IsEmpty())36 return false;38 SKEEP_SPACES(s, pos);39 if (s[pos++] != '=')40 return false;42 SKEEP_SPACES(s, pos);43 if (s[pos++] != '\"')44 return false;46 while (pos < s.Length())47 {48 char c = s[pos++];49 if (c == '\"')50 return true;51 prop.Value += c;52 }53 return false;54 }56 int CXmlItem::FindProperty(const AString &propName) const57 {58 for (int i = 0; i < Props.Size(); i++)59 if (Props[i].Name == propName)60 return i;61 return -1;62 }64 AString CXmlItem::GetPropertyValue(const AString &propName) const65 {66 int index = FindProperty(propName);67 if (index >= 0)68 return Props[index].Value;69 return AString();70 }72 bool CXmlItem::IsTagged(const AString &tag) const73 {74 return (IsTag && Name == tag);75 }77 int CXmlItem::FindSubTag(const AString &tag) const78 {79 for (int i = 0; i < SubItems.Size(); i++)80 if (SubItems[i].IsTagged(tag))81 return i;82 return -1;83 }85 AString CXmlItem::GetSubString() const86 {87 if (SubItems.Size() == 1)88 {89 const CXmlItem &item = SubItems[0];90 if (!item.IsTag)91 return item.Name;92 }93 return AString();94 }96 AString CXmlItem::GetSubStringForTag(const AString &tag) const97 {98 int index = FindSubTag(tag);99 if (index >= 0)100 return SubItems[index].GetSubString();101 return AString();102 }104 bool CXmlItem::ParseItems(const AString &s, int &pos, int numAllowedLevels)105 {106 if (numAllowedLevels == 0)107 return false;108 SubItems.Clear();109 AString finishString = "</";110 for (;;)111 {112 SKEEP_SPACES(s, pos);114 if (s.Mid(pos, finishString.Length()) == finishString)115 return true;117 CXmlItem item;118 if (!item.ParseItem(s, pos, numAllowedLevels - 1))119 return false;120 SubItems.Add(item);121 }122 }124 bool CXmlItem::ParseItem(const AString &s, int &pos, int numAllowedLevels)125 {126 SKEEP_SPACES(s, pos);128 int pos2 = s.Find('<', pos);129 if (pos2 < 0)130 return false;131 if (pos2 != pos)132 {133 IsTag = false;134 Name += s.Mid(pos, pos2 - pos);135 pos = pos2;136 return true;137 }138 IsTag = true;140 pos++;141 SKEEP_SPACES(s, pos);143 for (; pos < s.Length(); pos++)144 {145 char c = s[pos];146 if (!IsValidChar(c))147 break;148 Name += c;149 }150 if (Name.IsEmpty() || pos == s.Length())151 return false;153 int posTemp = pos;154 for (;;)155 {156 SKEEP_SPACES(s, pos);157 if (s[pos] == '/')158 {159 pos++;160 // SKEEP_SPACES(s, pos);161 return (s[pos++] == '>');162 }163 if (s[pos] == '>')164 {165 if (!ParseItems(s, ++pos, numAllowedLevels))166 return false;167 AString finishString = AString("</") + Name + AString(">");168 if (s.Mid(pos, finishString.Length()) != finishString)169 return false;170 pos += finishString.Length();171 return true;172 }173 if (posTemp == pos)174 return false;176 CXmlProp prop;177 if (!ReadProperty(s, pos, prop))178 return false;179 Props.Add(prop);180 posTemp = pos;181 }182 }184 bool SkeepHeader(const AString &s, int &pos, const AString &startString, const AString &endString)185 {186 SKEEP_SPACES(s, pos);187 if (s.Mid(pos, startString.Length()) == startString)188 {189 pos = s.Find(endString, pos);190 if (pos < 0)191 return false;192 pos += endString.Length();193 SKEEP_SPACES(s, pos);194 }195 return true;196 }198 bool CXml::Parse(const AString &s)199 {200 int pos = 0;201 if (!SkeepHeader(s, pos, "<?xml", "?>"))202 return false;203 if (!SkeepHeader(s, pos, "<!DOCTYPE", ">"))204 return false;205 if (!Root.ParseItem(s, pos, 1000))206 return false;207 SKEEP_SPACES(s, pos);208 return (pos == s.Length() && Root.IsTag);209 }