7 // Track memory leaks on Windows to the line that new'd the memory
10 #define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
13 static char THIS_FILE
[] = __FILE__
;
17 bool XMLUtil::IsWhiteSpace(char cLetter
)
19 if ((cLetter
== ' ') ||
28 // See if a character is 0 - 9
29 bool XMLUtil::IsDigit(char cLetter
)
31 if ((cLetter
>= '0') && (cLetter
<= '9'))
36 // Strip the leading and trailing white space off a string.
37 string
XMLUtil::StripWhiteSpace(const string
& strText
)
39 string strResult
= "";
41 strResult
.reserve(strText
.length());
44 while ((iStart
< (int) strText
.length()) && (IsWhiteSpace(strText
[iStart
])))
47 int iEnd
= strText
.length() - 1;
48 while ((iEnd
> 0) && (IsWhiteSpace(strText
[iEnd
])))
51 strResult
= strText
.substr(iStart
, iEnd
- iStart
+ 1);
56 // Return a string containing the contents of a file
57 string
XMLUtil::LoadFile(const string
& strFilename
, unsigned int iSizeHint
)
59 string strResult
= "";
61 char szBuffer
[XML_UTIL_READ_BUFFER_SIZE
];
63 fp
= fopen(strFilename
.c_str(), "r");
69 result
= _stat64(strFilename
.c_str(), &buf
);
70 strResult
.reserve((unsigned long) buf
.st_size
+ 256);
72 // On unix, we default to 128,000 bytes or whatever the caller passed in as a hint
73 strResult
.reserve(iSizeHint
);
78 memset(szBuffer
, 0, XML_UTIL_READ_BUFFER_SIZE
);
79 fread(szBuffer
, 1, XML_UTIL_READ_BUFFER_SIZE
- 1, fp
);
80 strResult
+= szBuffer
;
91 // Returns what is between the given tag in the passed XML. We only return the first matching
92 // tag if there are multiple in the XML. Tags are case sensitive.
93 string
XMLUtil::GetElementString(const string
& strTag
, const string
& strXML
, bool bStripWhiteSpace
)
95 string strResult
= "";
107 int iPosStart
= strXML
.find(strStart
);
108 int iPosEnd
= strXML
.find(strEnd
);
110 if ((iPosStart
!= -1) && (iPosEnd
!= -1))
112 strResult
= strXML
.substr(iPosStart
+ strStart
.length(), iPosEnd
- (iPosStart
+ strStart
.length()));
115 if (bStripWhiteSpace
)
116 strResult
= StripWhiteSpace(strResult
);
121 // Return the integer representing an element
122 int XMLUtil::GetElementInt(const string
& strTag
, const string
& strXML
, bool* pFound
)
124 string strElement
= GetElementString(strTag
, strXML
);
127 for (i
= 0; i
< strElement
.size(); i
++)
131 if ((!IsDigit(strElement
[i
])) && ((strElement
[i
] != '-')))
135 if (!IsDigit(strElement
[i
]))
139 // Only try and convert something that is all digits
140 if (i
== strElement
.size())
144 return atoi(strElement
.c_str());
154 int64
XMLUtil::GetElementLongLong(const string
& strTag
, const string
& strXML
, bool* pFound
)
156 string strElement
= GetElementString(strTag
, strXML
);
159 for (i
= 0; i
< strElement
.size(); i
++)
163 if ((!IsDigit(strElement
[i
])) && ((strElement
[i
] != '-')))
167 if (!IsDigit(strElement
[i
]))
171 // Only try and convert something that is all digits
172 if ((i
> 0) && (i
== strElement
.size()))
177 return _atoi64(strElement
.c_str());
179 return atoll(strElement
.c_str());
190 // Optionally can pass back a bool that tell us if the tag was found
191 float XMLUtil::GetElementFloat(const string
& strTag
, const string
& strXML
, bool* pFound
)
193 string strElement
= GetElementString(strTag
, strXML
);
195 bool bFoundDot
= false;
198 for (i
= 0; i
< strElement
.size(); i
++)
202 if ((!IsDigit(strElement
[i
])) && ((strElement
[i
] != '-')))
207 if (!IsDigit(strElement
[i
]))
209 if ((strElement
[i
] == '.') && (!bFoundDot
))
217 // Only try and convert something that is all digits
218 if ((i
> 0) && (i
== strElement
.size()))
222 return (float) atof(strElement
.c_str());
232 // Return a vector containing all the text inside all tags matching the passed one
233 VECTOR_STRING
XMLUtil::GetElementStrings(const string
& strTag
, const string
& strXML
, bool bStripWhiteSpace
)
235 VECTOR_STRING vResult
;
236 vResult
.reserve(XML_UTIL_DEFAULT_VECTOR_SIZE
);
238 string strStart
= "";
240 string strResult
= "";
250 int iPosStart
= strXML
.find(strStart
);
251 int iPosEnd
= strXML
.find(strEnd
);
253 while ((iPosStart
!= string::npos
) && (iPosEnd
!= string::npos
))
255 // We want to be able to handle having the same tag emedded in itself.
256 // So between the start tag and the first instance of the end tag,
257 // we'll count any other instances of the start tag. If we find some
258 // then we require that we continue until we get that number more of
260 int iCurrentStart
= iPosStart
+ strStart
.length();
262 while ((iCurrentStart
!= string::npos
) && (iCurrentStart
< iPosEnd
))
264 iCurrentStart
= strXML
.find(strStart
, iCurrentStart
);
265 if ((iCurrentStart
!= string::npos
) && (iCurrentStart
< iPosEnd
))
268 iCurrentStart
+= strStart
.length();
271 // Now look for end tag to balance the start tags
272 for (int i
= 0; i
< iEmbedCount
; i
++)
274 iPosEnd
= strXML
.find(strEnd
, iPosEnd
+ strEnd
.length());
276 // Check to make sure we're still matching tags
277 if (iPosEnd
== string::npos
)
281 strResult
= strXML
.substr(iPosStart
+ strStart
.length(), iPosEnd
- (iPosStart
+ strStart
.length()));
283 if (bStripWhiteSpace
)
284 strResult
= StripWhiteSpace(strResult
);
286 iPosStart
= strXML
.find(strStart
, iPosEnd
+ strEnd
.length());
288 if (iPosStart
!= string::npos
)
289 iPosEnd
= strXML
.find(strEnd
, iPosStart
);
291 vResult
.push_back(strResult
);
297 VECTOR_NAME_VALUE_PAIR
XMLUtil::GetNameValuePairs(const string
& strXML
, bool bStripWhiteSpace
)
299 VECTOR_NAME_VALUE_PAIR vResult
;
300 vResult
.reserve(XML_UTIL_DEFAULT_VECTOR_SIZE
);
302 bool bInStartTag
= false;
304 string strValue
= "";
307 while (i
< strXML
.length())
309 if ((!bInStartTag
) && (strXML
[i
] == '<'))
311 // Starting a new tag
314 else if (bInStartTag
)
316 if (strXML
[i
] == '>')
318 // Hit the end of the start tag, get everything
319 // until we find the end tag.
321 string strFind
= "</";
326 iPos
= strXML
.find(strFind
, i
);
330 strValue
= strXML
.substr(i
+ 1, iPos
- i
- 1);
333 sPair
.strName
= strName
;
334 sPair
.strValue
= strValue
;
336 vResult
.push_back(sPair
);
338 i
= iPos
+ strFind
.length();
349 strName
+= strXML
[i
];