Updated German translation
[dasher.git] / Src / DasherCore / XMLUtil.cpp
blobf7a7f73c6fcaf627a1400d80da2d32de05fe77b4
2 #include "../Common/Common.h"
4 #include <cstring>
6 #include "XMLUtil.h"
8 #include <sys/types.h>
9 #include <sys/stat.h>
11 // Track memory leaks on Windows to the line that new'd the memory
12 #ifdef _WIN32
13 #ifdef _DEBUG
14 #define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
15 #define new DEBUG_NEW
16 #undef THIS_FILE
17 static char THIS_FILE[] = __FILE__;
18 #endif
19 #endif
21 bool XMLUtil::IsWhiteSpace(char cLetter)
23 if ((cLetter == ' ') ||
24 (cLetter == '\n') ||
25 (cLetter == '\r') ||
26 (cLetter == '\t'))
27 return true;
29 return false;
32 // See if a character is 0 - 9
33 bool XMLUtil::IsDigit(char cLetter)
35 if ((cLetter >= '0') && (cLetter <= '9'))
36 return true;
37 return false;
40 // Strip the leading and trailing white space off a string.
41 string XMLUtil::StripWhiteSpace(const string& strText)
43 string strResult = "";
45 strResult.reserve(strText.length());
47 int iStart = 0;
48 while ((iStart < (int) strText.length()) && (IsWhiteSpace(strText[iStart])))
49 iStart++;
51 int iEnd = strText.length() - 1;
52 while ((iEnd > 0) && (IsWhiteSpace(strText[iEnd])))
53 iEnd--;
55 strResult = strText.substr(iStart, iEnd - iStart + 1);
57 return strResult;
60 // Return a string containing the contents of a file
61 string XMLUtil::LoadFile(const string& strFilename, unsigned int iSizeHint)
63 string strResult = "";
65 char szBuffer[XML_UTIL_READ_BUFFER_SIZE];
66 FILE* fp = NULL;
67 fp = fopen(strFilename.c_str(), "r");
68 if (fp != NULL)
70 #ifdef _WIN32
71 struct __stat64 buf;
72 int result;
73 result = _stat64(strFilename.c_str(), &buf);
74 strResult.reserve((unsigned long) buf.st_size + 256);
75 #else
76 // On unix, we default to 128,000 bytes or whatever the caller passed in as a hint
77 strResult.reserve(iSizeHint);
78 #endif
80 while (!feof(fp))
82 memset(szBuffer, 0, XML_UTIL_READ_BUFFER_SIZE);
83 fread(szBuffer, 1, XML_UTIL_READ_BUFFER_SIZE - 1, fp);
84 strResult += szBuffer;
87 fclose(fp);
88 fp = NULL;
91 return strResult;
95 // Returns what is between the given tag in the passed XML. We only return the first matching
96 // tag if there are multiple in the XML. Tags are case sensitive.
97 string XMLUtil::GetElementString(const string& strTag, const string& strXML, bool bStripWhiteSpace)
99 string strResult = "";
100 string strStart = "";
101 string strEnd = "";
103 strStart += "<";
104 strStart += strTag;
105 strStart += ">";
107 strEnd += "</";
108 strEnd += strTag;
109 strEnd += ">";
111 int iPosStart = strXML.find(strStart);
112 int iPosEnd = strXML.find(strEnd);
114 if ((iPosStart != -1) && (iPosEnd != -1))
116 strResult = strXML.substr(iPosStart + strStart.length(), iPosEnd - (iPosStart + strStart.length()));
119 if (bStripWhiteSpace)
120 strResult = StripWhiteSpace(strResult);
122 return strResult;
125 // Return the integer representing an element
126 int XMLUtil::GetElementInt(const string& strTag, const string& strXML, bool* pFound)
128 string strElement = GetElementString(strTag, strXML);
130 unsigned int i = 0;
131 for (i = 0; i < strElement.size(); i++)
133 if (i == 0)
135 if ((!IsDigit(strElement[i])) && ((strElement[i] != '-')))
136 break;
138 else
139 if (!IsDigit(strElement[i]))
140 break;
143 // Only try and convert something that is all digits
144 if (i == strElement.size())
146 if (pFound != NULL)
147 *pFound = true;
148 return atoi(strElement.c_str());
150 else
152 if (pFound != NULL)
153 *pFound = false;
154 return -1;
158 int64 XMLUtil::GetElementLongLong(const string& strTag, const string& strXML, bool* pFound)
160 string strElement = GetElementString(strTag, strXML);
162 unsigned int i = 0;
163 for (i = 0; i < strElement.size(); i++)
165 if (i == 0)
167 if ((!IsDigit(strElement[i])) && ((strElement[i] != '-')))
168 break;
170 else
171 if (!IsDigit(strElement[i]))
172 break;
175 // Only try and convert something that is all digits
176 if ((i > 0) && (i == strElement.size()))
178 if (pFound != NULL)
179 *pFound = true;
180 #ifdef _WIN32
181 return _atoi64(strElement.c_str());
182 #else
183 return atoll(strElement.c_str());
184 #endif
186 else
188 if (pFound != NULL)
189 *pFound = false;
190 return -1;
194 // Optionally can pass back a bool that tell us if the tag was found
195 float XMLUtil::GetElementFloat(const string& strTag, const string& strXML, bool* pFound)
197 string strElement = GetElementString(strTag, strXML);
199 bool bFoundDot = false;
201 unsigned int i = 0;
202 for (i = 0; i < strElement.size(); i++)
204 if (i == 0)
206 if ((!IsDigit(strElement[i])) && ((strElement[i] != '-')))
207 break;
209 else
211 if (!IsDigit(strElement[i]))
213 if ((strElement[i] == '.') && (!bFoundDot))
214 bFoundDot = true;
215 else
216 break;
221 // Only try and convert something that is all digits
222 if ((i > 0) && (i == strElement.size()))
224 if (pFound != NULL)
225 *pFound = true;
226 return (float) atof(strElement.c_str());
228 else
230 if (pFound != NULL)
231 *pFound = false;
232 return (float) 0.0;
236 // Return a vector containing all the text inside all tags matching the passed one
237 VECTOR_STRING XMLUtil::GetElementStrings(const string& strTag, const string& strXML, bool bStripWhiteSpace)
239 VECTOR_STRING vResult;
240 vResult.reserve(XML_UTIL_DEFAULT_VECTOR_SIZE);
242 string strStart = "";
243 string strEnd = "";
244 string strResult = "";
246 strStart += "<";
247 strStart += strTag;
248 strStart += ">";
250 strEnd += "</";
251 strEnd += strTag;
252 strEnd += ">";
254 size_t iPosStart = strXML.find(strStart);
255 size_t iPosEnd = strXML.find(strEnd);
257 while ((iPosStart != string::npos) && (iPosEnd != string::npos))
259 // We want to be able to handle having the same tag emedded in itself.
260 // So between the start tag and the first instance of the end tag,
261 // we'll count any other instances of the start tag. If we find some
262 // then we require that we continue until we get that number more of
263 // close tags.
264 size_t iCurrentStart = iPosStart + strStart.length();
265 size_t iEmbedCount = 0;
266 while ((iCurrentStart != string::npos) && (iCurrentStart < iPosEnd))
268 iCurrentStart = strXML.find(strStart, iCurrentStart);
269 if ((iCurrentStart != string::npos) && (iCurrentStart < iPosEnd))
271 iEmbedCount++;
272 iCurrentStart += strStart.length();
275 // Now look for end tag to balance the start tags
276 for (size_t i = 0; i < iEmbedCount; i++)
278 iPosEnd = strXML.find(strEnd, iPosEnd + strEnd.length());
280 // Check to make sure we're still matching tags
281 if (iPosEnd == string::npos)
282 break;
285 strResult = strXML.substr(iPosStart + strStart.length(), iPosEnd - (iPosStart + strStart.length()));
287 if (bStripWhiteSpace)
288 strResult = StripWhiteSpace(strResult);
290 iPosStart = strXML.find(strStart, iPosEnd + strEnd.length());
292 if (iPosStart != string::npos)
293 iPosEnd = strXML.find(strEnd, iPosStart);
295 vResult.push_back(strResult);
298 return vResult;
301 VECTOR_NAME_VALUE_PAIR XMLUtil::GetNameValuePairs(const string& strXML, bool bStripWhiteSpace)
303 VECTOR_NAME_VALUE_PAIR vResult;
304 vResult.reserve(XML_UTIL_DEFAULT_VECTOR_SIZE);
306 bool bInStartTag = false;
307 string strName = "";
308 string strValue = "";
310 size_t i = 0;
311 while (i < strXML.length())
313 if ((!bInStartTag) && (strXML[i] == '<'))
315 // Starting a new tag
316 bInStartTag = true;
318 else if (bInStartTag)
320 if (strXML[i] == '>')
322 // Hit the end of the start tag, get everything
323 // until we find the end tag.
325 string strFind = "</";
326 strFind += strName;
327 strFind += ">";
329 size_t iPos = string::npos;
330 iPos = strXML.find(strFind, i);
332 if (iPos != string::npos)
334 strValue = strXML.substr(i + 1, iPos - i - 1);
336 NameValuePair sPair;
337 sPair.strName = strName;
338 sPair.strValue = strValue;
340 vResult.push_back(sPair);
342 i = iPos + strFind.length();
345 else
346 break;
348 bInStartTag = false;
349 strName = "";
350 strValue = "";
352 else
353 strName += strXML[i];
356 i++;
359 return vResult;