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.cpp
3 #include "StdAfx.h"
5 #include "MyXml.h"
7 static bool IsValidChar(char c)
8 {
9 return
10 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) const
57 {
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) const
65 {
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) const
73 {
74 return (IsTag && Name == tag);
75 }
77 int CXmlItem::FindSubTag(const AString &tag) const
78 {
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() const
86 {
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) const
97 {
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 }