1 /*
2 * OpenBOR - http://www.LavaLit.com
3 * -----------------------------------------------------------------------
4 * Licensed under the BSD license, see LICENSE in OpenBOR root for details.
5 *
6 * Copyright (c) 2004 - 2011 OpenBOR Team
7 */
8
9 // XmlDocument.cpp: implementation of the CXmlDocument class.
10 //
11 //////////////////////////////////////////////////////////////////////
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15
16 #include "XmlDocument.h"
17 #include <xtl.h>
18
19 //////////////////////////////////////////////////////////////////////
20 // Construction/Destruction
21 //////////////////////////////////////////////////////////////////////
22
CXmlDocument()23 CXmlDocument::CXmlDocument()
24 {
25 m_doc = 0;
26 m_size = 0;
27 m_nodes = 0;
28
29 m_szTag[0] = 0;
30 m_szText[0] = 0;
31 }
32
Create(char * szString)33 void CXmlDocument::Create(char* szString)
34 {
35 m_doc = szString;
36 m_size = strlen(m_doc);
37 }
38
~CXmlDocument()39 CXmlDocument::~CXmlDocument()
40 {
41 }
42
43
44
45 //////////////////////////////////////////////////////////////////////////////////
46 // Function: xml_load_doc
47 // Opens an XML document and loads it into memory.
48 //
Load(char * szFile)49 int CXmlDocument::Load(char* szFile)
50 {
51 FILE* hFile;
52
53 hFile = fopen(szFile,"rb");
54 if (hFile==NULL)
55 {
56 OutputDebugString("No such file: ");
57 OutputDebugString(szFile);
58 OutputDebugString("\n");
59 return -1;
60 }
61
62 fseek(hFile,0,SEEK_END);
63 m_size = ftell(hFile);
64
65 fseek(hFile,0,SEEK_SET);
66
67 m_doc = (char*) malloc(m_size);
68 if (!m_doc)
69 {
70 m_size = 0;
71 fclose(hFile);
72 return -2;
73 }
74
75 if (fread(m_doc, m_size, 1, hFile)<=0)
76 {
77 delete m_doc;
78 m_doc = 0;
79 m_size = 0;
80 fclose(hFile);
81 return -3;
82 }
83
84 fclose(hFile);
85 return 0;
86 }
87
88
89
90
91
92
93
94
95 //////////////////////////////////////////////////////////////////////////////////
96 // Function: xml_close_doc
97 // Closes XML document freeing up resources.
98 //
Close()99 void CXmlDocument::Close()
100 {
101 if (m_doc!=NULL)
102 {
103 delete m_doc;
104 m_doc =0;
105 }
106
107 m_size =0;
108 m_nodes = 0;
109 m_szTag[0] = 0;
110 m_szText[0] = 0;
111 }
112
113
114
115
GetNodeCount(char * szTag)116 int CXmlDocument::GetNodeCount(char* szTag)
117 {
118 m_nodes = 0;
119
120 char* szCurrentTag;
121 XmlNode node;
122
123 node = GetNextNode(XML_ROOT_NODE);
124 while (node>0)
125 {
126 szCurrentTag = GetNodeTag(node);
127 if ( !strcmpi(szCurrentTag,szTag) )
128 m_nodes++;
129
130 node = GetNextNode(node);
131 }
132
133 return m_nodes;
134 }
135
136
137
138 //////////////////////////////////////////////////////////////////////////////////
139 // Function: xml_next_tag
140 // Moves the current position to the next tag.
141 //
GetNextNode(XmlNode node)142 XmlNode CXmlDocument::GetNextNode(XmlNode node)
143 {
144 int openBracket = -1;
145 int closeBracket = -1;
146 int i;
147 char c;
148
149 for (i=node; i<m_size; i++)
150 {
151 c=m_doc[i];
152
153 if (openBracket<0)
154 {
155 if (c=='<')
156 openBracket=i;
157 continue;
158 }
159
160 if (closeBracket<0)
161 {
162 if (c=='>')
163 {
164 closeBracket=i;
165 break;
166 }
167 }
168 }
169
170 if ((openBracket>=0) && (closeBracket>=0))
171 {
172 return openBracket+1;
173 }
174
175 return 0;
176 }
177
178
179 //////////////////////////////////////////////////////////////////////////////////
180 // Function: xml_get_tag_name
181 // Gets the tag name at the current position (max 32 chars!).
182 //
GetNodeTag(XmlNode node)183 char* CXmlDocument::GetNodeTag(XmlNode node)
184 {
185 int i;
186 char c;
187
188 for (i=node; i<m_size; i++)
189 {
190 c=m_doc[i];
191
192 if ( (c==' ') || (c=='\n') || (c=='\r') || (c=='\t') || (c=='>') )
193 {
194 memcpy(m_szTag,&m_doc[node],i-node);
195 m_szTag[i-node]=0;
196 return m_szTag;
197 }
198 }
199
200 return 0;
201 }
202
203
204 //////////////////////////////////////////////////////////////////////////////////
205 // Function: xml_get_child_tag
206 // Gets the position of the child tag.
207 //
GetChildNode(XmlNode node,char * szTag)208 XmlNode CXmlDocument::GetChildNode(XmlNode node, char* szTag)
209 {
210 char szCurrentTag[32];
211 char* szChildTag;
212
213 // get parent node tag
214 strcpy(szCurrentTag,GetNodeTag(node));
215
216 // get child node
217 node = GetNextNode(node);
218 while (node>0)
219 {
220 // get child node tag
221 szChildTag = GetNodeTag(node);
222
223 // does the child's tag match the one we're looking for
224 if ( !strcmpi(szChildTag,szTag) )
225 return node;
226
227 // is this actually the parent's closing tag?
228 else if ( !strcmpi(&szChildTag[1],szCurrentTag) )
229 return 0;
230
231 node = GetNextNode(node);
232 }
233
234 return 0;
235 }
236
237
238
239 //////////////////////////////////////////////////////////////////////////////////
240 // Function: xml_get_tag_text
241 // Gets the text of a given tag (max limit 128 chars!!).
242 //
GetNodeText(XmlNode node)243 char* CXmlDocument::GetNodeText(XmlNode node)
244 {
245 int i,text=0;
246 int opens=1;
247 int elements=0;
248 char c;
249 for (i=node;i<(m_size-1);i++)
250 {
251 c = m_doc[i];
252
253 switch (c)
254 {
255 case '<':
256 opens++;
257 if (m_doc[i+1]!='/')
258 elements++;
259 else
260 elements--;
261 break;
262 case '>' :
263 opens--;
264 break;
265 case ' ' :
266 case '\n':
267 case '\r':
268 case '\t':
269 break;
270 default:
271 if ((opens==0) && (elements==0))
272 text = i;
273 break;
274 }
275
276 if (text)
277 break;
278 }
279
280 if (!text)
281 return 0;
282
283 for (i=text;i<m_size;i++)
284 {
285 c = m_doc[i];
286 if (c=='<')
287 {
288 memcpy(m_szText,&m_doc[text],i-text);
289 m_szText[i-text]=0;
290 return m_szText;
291 }
292 }
293
294 m_szText[0]=0;
295 return m_szText;
296 }
297
298
299
300
EnumerateNodes(char * szTag,XmlNodeCallback pFunc)301 void CXmlDocument::EnumerateNodes(char* szTag, XmlNodeCallback pFunc)
302 {
303 char* szCurrentTag;
304 XmlNode node;
305
306 node = GetNextNode(XML_ROOT_NODE);
307 while (node>0)
308 {
309 szCurrentTag = GetNodeTag(node);
310 if ( !strcmpi(szCurrentTag,szTag) )
311 pFunc(szTag,node);
312
313 node = GetNextNode(node);
314 }
315 }
316