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