XMLStorage update to prepare for rbuild integration
Modified: trunk/reactos/base/shell/explorer/utility/xmlstorage.cpp
Modified: trunk/reactos/base/shell/explorer/utility/xmlstorage.h

Modified: trunk/reactos/base/shell/explorer/utility/xmlstorage.cpp
--- trunk/reactos/base/shell/explorer/utility/xmlstorage.cpp	2006-02-08 08:47:46 UTC (rev 106)
+++ trunk/reactos/base/shell/explorer/utility/xmlstorage.cpp	2006-02-12 10:35:41 UTC (rev 107)
@@ -4,7 +4,7 @@
  //
  // xmlstorage.cpp
  //
- // Copyright (c) 2004, 2005 Martin Fuchs <martin-fuchs@gmx.net>
+ // Copyright (c) 2004, 2005, 2006 Martin Fuchs <martin-fuchs@gmx.net>
  //
 
 
@@ -48,7 +48,8 @@
 #ifdef __GNUC__
 const LPCXSSTR XMLStorage::XS_TRUE = XS_TRUE_STR;
 const LPCXSSTR XMLStorage::XS_FALSE = XS_FALSE_STR;
-const LPCXSSTR XMLStorage::XS_NUMBERFMT = XS_NUMBERFMT_STR;
+const LPCXSSTR XMLStorage::XS_INTFMT = XS_INTFMT_STR;
+const LPCXSSTR XMLStorage::XS_FLOATFMT = XS_FLOATFMT_STR;
 #endif
 
 
@@ -143,7 +144,7 @@
 		if (slash == path)
 			return NULL;
 
-		int l = slash? slash-path: strlen(path);
+		size_t l = slash? slash-path: strlen(path);
 		std::string comp(path, l);
 		path += l;
 
@@ -265,201 +266,6 @@
 }
 
 
- /// read XML stream into XML tree below _pos
-XML_Status XMLReaderBase::read()
-{
-	XML_Status status = XML_STATUS_OK;
-
-	while(status == XML_STATUS_OK) {
-		char* buffer = (char*) XML_GetBuffer(_parser, BUFFER_LEN);
-
-		int l = read_buffer(buffer, BUFFER_LEN);
-		if (l < 0)
-			break;
-
-		status = XML_ParseBuffer(_parser, l, false);
-	}
-
-	if (status != XML_STATUS_ERROR)
-		status = XML_ParseBuffer(_parser, 0, true);
-
-	if (_pos->_children.empty())
-		_pos->_trailing.append(_content);
-	else
-		_pos->_children.back()->_trailing.append(_content);
-
-	_content.erase();
-
-	return status;
-}
-
-
- /// store XML version and encoding into XML reader
-void XMLCALL XMLReaderBase::XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone)
-{
-	XMLReaderBase* pReader = (XMLReaderBase*) userData;
-
-	if (version)
-		pReader->_xml_version = version;
-
-	if (encoding)
-		pReader->_encoding = encoding;
-}
-
- /// notifications about XML start tag
-void XMLCALL XMLReaderBase::XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts)
-{
-	XMLReaderBase* pReader = (XMLReaderBase*) userData;
-	XMLPos& pos = pReader->_pos;
-
-	 // search for end of first line
-	const char* s = pReader->_content.c_str();
-	const char* p = s;
-	const char* e = p + pReader->_content.length();
-
-	for(; p<e; ++p)
-		if (*p == '\n') {
-			++p;
-			break;
-		}
-
-	if (p != s)
-		if (pos->_children.empty()) {	// no children in last node?
-			if (pReader->_last_tag == TAG_START)
-				pos->_content.append(s, p-s);
-			else if (pReader->_last_tag == TAG_END)
-				pos->_trailing.append(s, p-s);
-			// else TAG_NONE -> don't store white space in root node
-		} else
-			pos->_children.back()->_trailing.append(s, p-s);
-
-	std::string leading;
-
-	if (p != e)
-		leading.assign(p, e-p);
-
-	XMLNode* node = new XMLNode(String_from_XML_Char(name), leading);
-
-	pos.add_down(node);
-
-	while(*atts) {
-		const XML_Char* attr_name = *atts++;
-		const XML_Char* attr_value = *atts++;
-
-		(*node)[String_from_XML_Char(attr_name)] = String_from_XML_Char(attr_value);
-	}
-
-	pReader->_last_tag = TAG_START;
-	pReader->_content.erase();
-}
-
- /// notifications about XML end tag
-void XMLCALL XMLReaderBase::XML_EndElementHandler(void* userData, const XML_Char* name)
-{
-	XMLReaderBase* pReader = (XMLReaderBase*) userData;
-	XMLPos& pos = pReader->_pos;
-
-	 // search for end of first line
-	const char* s = pReader->_content.c_str();
-	const char* p = s;
-	const char* e = p + pReader->_content.length();
-
-	for(; p<e; ++p)
-		if (*p == '\n') {
-			++p;
-			break;
-		}
-
-	if (p != s)
-		if (pos->_children.empty())	// no children in current node?
-			pos->_content.append(s, p-s);
-		else
-			if (pReader->_last_tag == TAG_START)
-				pos->_content.append(s, p-s);
-			else
-				pos->_children.back()->_trailing.append(s, p-s);
-
-	if (p != e)
-		pos->_end_leading.assign(p, e-p);
-
-	pos.back();
-
-	pReader->_last_tag = TAG_END;
-	pReader->_content.erase();
-}
-
- /// store content, white space and comments
-void XMLCALL XMLReaderBase::XML_DefaultHandler(void* userData, const XML_Char* s, int len)
-{
-	XMLReaderBase* pReader = (XMLReaderBase*) userData;
-
-	pReader->_content.append(s, len);
-}
-
-
- /// return error strings for Expat errors
-std::string XMLReaderBase::get_error_string() const
-{
-	XML_Error error = XML_GetErrorCode(_parser);
-
-	switch(error) {
-	  case XML_ERROR_NONE:								return "XML_ERROR_NONE";
-	  case XML_ERROR_NO_MEMORY:							return "XML_ERROR_NO_MEMORY";
-	  case XML_ERROR_SYNTAX:							return "XML_ERROR_SYNTAX";
-	  case XML_ERROR_NO_ELEMENTS:						return "XML_ERROR_NO_ELEMENTS";
-	  case XML_ERROR_INVALID_TOKEN:						return "XML_ERROR_INVALID_TOKEN";
-	  case XML_ERROR_UNCLOSED_TOKEN:					return "XML_ERROR_UNCLOSED_TOKEN";
-	  case XML_ERROR_PARTIAL_CHAR:						return "XML_ERROR_PARTIAL_CHAR";
-	  case XML_ERROR_TAG_MISMATCH:						return "XML_ERROR_TAG_MISMATCH";
-	  case XML_ERROR_DUPLICATE_ATTRIBUTE:				return "XML_ERROR_DUPLICATE_ATTRIBUTE";
-	  case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:			return "XML_ERROR_JUNK_AFTER_DOC_ELEMENT";
-	  case XML_ERROR_PARAM_ENTITY_REF:					return "XML_ERROR_PARAM_ENTITY_REF";
-	  case XML_ERROR_UNDEFINED_ENTITY:					return "XML_ERROR_UNDEFINED_ENTITY";
-	  case XML_ERROR_RECURSIVE_ENTITY_REF:				return "XML_ERROR_RECURSIVE_ENTITY_REF";
-	  case XML_ERROR_ASYNC_ENTITY:						return "XML_ERROR_ASYNC_ENTITY";
-	  case XML_ERROR_BAD_CHAR_REF:						return "XML_ERROR_BAD_CHAR_REF";
-	  case XML_ERROR_BINARY_ENTITY_REF:					return "XML_ERROR_BINARY_ENTITY_REF";
-	  case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:		return "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF";
-	  case XML_ERROR_MISPLACED_XML_PI:					return "XML_ERROR_MISPLACED_XML_PI";
-	  case XML_ERROR_UNKNOWN_ENCODING:					return "XML_ERROR_UNKNOWN_ENCODING";
-	  case XML_ERROR_INCORRECT_ENCODING:				return "XML_ERROR_INCORRECT_ENCODING";
-	  case XML_ERROR_UNCLOSED_CDATA_SECTION:			return "XML_ERROR_UNCLOSED_CDATA_SECTION";
-	  case XML_ERROR_EXTERNAL_ENTITY_HANDLING:			return "XML_ERROR_EXTERNAL_ENTITY_HANDLING";
-	  case XML_ERROR_NOT_STANDALONE:					return "XML_ERROR_NOT_STANDALONE";
-	  case XML_ERROR_UNEXPECTED_STATE:					return "XML_ERROR_UNEXPECTED_STATE";
-	  case XML_ERROR_ENTITY_DECLARED_IN_PE:				return "XML_ERROR_ENTITY_DECLARED_IN_PE";
-	  case XML_ERROR_FEATURE_REQUIRES_XML_DTD:			return "XML_ERROR_FEATURE_REQUIRES_XML_DTD";
-	  case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:	return "XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING";
-	  case XML_ERROR_UNBOUND_PREFIX:					return "XML_ERROR_UNBOUND_PREFIX";
- // EXPAT version >= 1.95.8
-#if XML_MAJOR_VERSION>1 || (XML_MAJOR_VERSION==1 && XML_MINOR_VERSION>95) || (XML_MAJOR_VERSION==1 && XML_MINOR_VERSION==95 && XML_MICRO_VERSION>7)
-	  case XML_ERROR_UNDECLARING_PREFIX:				return "XML_ERROR_UNDECLARING_PREFIX";
-	  case XML_ERROR_INCOMPLETE_PE:						return "XML_ERROR_INCOMPLETE_PE";
-	  case XML_ERROR_XML_DECL:							return "XML_ERROR_XML_DECL";
-	  case XML_ERROR_TEXT_DECL:							return "XML_ERROR_TEXT_DECL";
-	  case XML_ERROR_PUBLICID:							return "XML_ERROR_PUBLICID";
-	  case XML_ERROR_SUSPENDED:							return "XML_ERROR_SUSPENDED";
-	  case XML_ERROR_NOT_SUSPENDED:						return "XML_ERROR_NOT_SUSPENDED";
-	  case XML_ERROR_ABORTED:							return "XML_ERROR_ABORTED";
-	  case XML_ERROR_FINISHED:							return "XML_ERROR_FINISHED";
-	  case XML_ERROR_SUSPEND_PE:						return "XML_ERROR_SUSPEND_PE";
-#endif
-#if XML_MAJOR_VERSION>=2
-		/* Added in 2.0. */
-	  case XML_ERROR_RESERVED_PREFIX_XML:				return "XML_ERROR_RESERVED_PREFIX_XML";
-	  case XML_ERROR_RESERVED_PREFIX_XMLNS:				return "XML_ERROR_RESERVED_PREFIX_XMLNS";
-	  case XML_ERROR_RESERVED_NAMESPACE_URI:			return "XML_ERROR_RESERVED_NAMESPACE_URI";
-#endif
-	}
-
-	std::ostringstream out;
-
-	out << "XML parser error #" << error;
-
-	return out.str();
-}
-
-
  /// encode XML string literals
 std::string EncodeXMLString(const XS_String& str)
 {
@@ -635,4 +441,284 @@
 }
 
 
+ /// read XML stream into XML tree below _pos
+XML_Status XMLReaderBase::read()
+{
+	XML_Status status = XML_STATUS_OK;
+
+	while(status == XML_STATUS_OK) {
+		char* buffer = (char*) XML_GetBuffer(_parser, BUFFER_LEN);
+
+		size_t l = read_buffer(buffer, BUFFER_LEN);
+		if ((int)l < 0)
+			break;
+
+		status = XML_ParseBuffer(_parser, l, false);
+	}
+
+	if (status != XML_STATUS_ERROR)
+		status = XML_ParseBuffer(_parser, 0, true);
+
+	finish_read();
+
+	return status;
+}
+
+
+ /// return current parser position as string
+std::string XMLReaderBase::get_position() const
+{
+	int line = XML_GetCurrentLineNumber(_parser);
+	int column = XML_GetCurrentColumnNumber(_parser);
+
+	std::ostringstream out;
+	out << "(" << line << ") : [column " << column << "]";
+
+	return out.str();
+}
+
+
+#ifdef XMLNODE_LOCATION
+
+XMLLocation XMLReaderBase::get_location() const
+{
+	int line = XML_GetCurrentLineNumber(_parser);
+	int column = XML_GetCurrentColumnNumber(_parser);
+
+	return XMLLocation(_display_path, line, column);
+}
+
+std::string XMLLocation::str() const
+{
+	std::ostringstream out;
+
+	if (_pdisplay_path)
+		out << _pdisplay_path;
+
+	out << "(" << _line << ") : [column " << _column << "]";
+
+	return out.str();
+}
+
+#endif
+
+
+ /// return current error code from Expat
+XML_Error XMLReaderBase::get_error_code() const
+{
+	return XML_GetErrorCode(_parser);
+}
+
+
+ /// store XML version and encoding into XML reader
+void XMLCALL XMLReaderBase::XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone)
+{
+	XMLReaderBase* pReader = (XMLReaderBase*) userData;
+
+	pReader->XmlDeclHandler(version, encoding, standalone);
+}
+
+ /// notifications about XML start tag
+void XMLCALL XMLReaderBase::XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts)
+{
+	XMLReaderBase* pReader = (XMLReaderBase*) userData;
+
+	XMLNode::AttributeMap attributes;
+
+	while(*atts) {
+		const XML_Char* attr_name = *atts++;
+		const XML_Char* attr_value = *atts++;
+
+		attributes[String_from_XML_Char(attr_name)] = String_from_XML_Char(attr_value);
+	}
+
+	pReader->StartElementHandler(String_from_XML_Char(name), attributes);
+}
+
+ /// notifications about XML end tag
+void XMLCALL XMLReaderBase::XML_EndElementHandler(void* userData, const XML_Char* name)
+{
+	XMLReaderBase* pReader = (XMLReaderBase*) userData;
+
+	pReader->EndElementHandler();
+}
+
+ /// store content, white space and comments
+void XMLCALL XMLReaderBase::XML_DefaultHandler(void* userData, const XML_Char* s, int len)
+{
+	XMLReaderBase* pReader = (XMLReaderBase*) userData;
+
+	pReader->DefaultHandler(s, len);
+}
+
+
+ /// return error strings for Expat errors
+std::string XMLReaderBase::get_error_string() const
+{
+	XML_Error error = XML_GetErrorCode(_parser);
+
+	switch(error) {
+	  case XML_ERROR_NONE:								return "XML_ERROR_NONE";
+	  case XML_ERROR_NO_MEMORY:							return "XML_ERROR_NO_MEMORY";
+	  case XML_ERROR_SYNTAX:							return "XML_ERROR_SYNTAX";
+	  case XML_ERROR_NO_ELEMENTS:						return "XML_ERROR_NO_ELEMENTS";
+	  case XML_ERROR_INVALID_TOKEN:						return "XML_ERROR_INVALID_TOKEN";
+	  case XML_ERROR_UNCLOSED_TOKEN:					return "XML_ERROR_UNCLOSED_TOKEN";
+	  case XML_ERROR_PARTIAL_CHAR:						return "XML_ERROR_PARTIAL_CHAR";
+	  case XML_ERROR_TAG_MISMATCH:						return "XML_ERROR_TAG_MISMATCH";
+	  case XML_ERROR_DUPLICATE_ATTRIBUTE:				return "XML_ERROR_DUPLICATE_ATTRIBUTE";
+	  case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:			return "XML_ERROR_JUNK_AFTER_DOC_ELEMENT";
+	  case XML_ERROR_PARAM_ENTITY_REF:					return "XML_ERROR_PARAM_ENTITY_REF";
+	  case XML_ERROR_UNDEFINED_ENTITY:					return "XML_ERROR_UNDEFINED_ENTITY";
+	  case XML_ERROR_RECURSIVE_ENTITY_REF:				return "XML_ERROR_RECURSIVE_ENTITY_REF";
+	  case XML_ERROR_ASYNC_ENTITY:						return "XML_ERROR_ASYNC_ENTITY";
+	  case XML_ERROR_BAD_CHAR_REF:						return "XML_ERROR_BAD_CHAR_REF";
+	  case XML_ERROR_BINARY_ENTITY_REF:					return "XML_ERROR_BINARY_ENTITY_REF";
+	  case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:		return "XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF";
+	  case XML_ERROR_MISPLACED_XML_PI:					return "XML_ERROR_MISPLACED_XML_PI";
+	  case XML_ERROR_UNKNOWN_ENCODING:					return "XML_ERROR_UNKNOWN_ENCODING";
+	  case XML_ERROR_INCORRECT_ENCODING:				return "XML_ERROR_INCORRECT_ENCODING";
+	  case XML_ERROR_UNCLOSED_CDATA_SECTION:			return "XML_ERROR_UNCLOSED_CDATA_SECTION";
+	  case XML_ERROR_EXTERNAL_ENTITY_HANDLING:			return "XML_ERROR_EXTERNAL_ENTITY_HANDLING";
+	  case XML_ERROR_NOT_STANDALONE:					return "XML_ERROR_NOT_STANDALONE";
+	  case XML_ERROR_UNEXPECTED_STATE:					return "XML_ERROR_UNEXPECTED_STATE";
+	  case XML_ERROR_ENTITY_DECLARED_IN_PE:				return "XML_ERROR_ENTITY_DECLARED_IN_PE";
+	  case XML_ERROR_FEATURE_REQUIRES_XML_DTD:			return "XML_ERROR_FEATURE_REQUIRES_XML_DTD";
+	  case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:	return "XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING";
+	  case XML_ERROR_UNBOUND_PREFIX:					return "XML_ERROR_UNBOUND_PREFIX";
+ // EXPAT version >= 1.95.8
+#if XML_MAJOR_VERSION>1 || (XML_MAJOR_VERSION==1 && XML_MINOR_VERSION>95) || (XML_MAJOR_VERSION==1 && XML_MINOR_VERSION==95 && XML_MICRO_VERSION>7)
+	  case XML_ERROR_UNDECLARING_PREFIX:				return "XML_ERROR_UNDECLARING_PREFIX";
+	  case XML_ERROR_INCOMPLETE_PE:						return "XML_ERROR_INCOMPLETE_PE";
+	  case XML_ERROR_XML_DECL:							return "XML_ERROR_XML_DECL";
+	  case XML_ERROR_TEXT_DECL:							return "XML_ERROR_TEXT_DECL";
+	  case XML_ERROR_PUBLICID:							return "XML_ERROR_PUBLICID";
+	  case XML_ERROR_SUSPENDED:							return "XML_ERROR_SUSPENDED";
+	  case XML_ERROR_NOT_SUSPENDED:						return "XML_ERROR_NOT_SUSPENDED";
+	  case XML_ERROR_ABORTED:							return "XML_ERROR_ABORTED";
+	  case XML_ERROR_FINISHED:							return "XML_ERROR_FINISHED";
+	  case XML_ERROR_SUSPEND_PE:						return "XML_ERROR_SUSPEND_PE";
+#endif
+#if XML_MAJOR_VERSION>=2
+		/* Added in 2.0. */
+	  case XML_ERROR_RESERVED_PREFIX_XML:				return "XML_ERROR_RESERVED_PREFIX_XML";
+	  case XML_ERROR_RESERVED_PREFIX_XMLNS:				return "XML_ERROR_RESERVED_PREFIX_XMLNS";
+	  case XML_ERROR_RESERVED_NAMESPACE_URI:			return "XML_ERROR_RESERVED_NAMESPACE_URI";
+#endif
+	}
+
+	std::ostringstream out;
+
+	out << "XML parser error #" << error;
+
+	return out.str();
+}
+
+
+void XMLReaderBase::finish_read()
+{
+	if (_pos->_children.empty())
+		_pos->_trailing.append(_content);
+	else
+		_pos->_children.back()->_trailing.append(_content);
+
+	_content.erase();
+}
+
+
+ /// store XML version and encoding into XML reader
+void XMLReaderBase::XmlDeclHandler(const XML_Char* version, const XML_Char* encoding, int standalone)
+{
+	if (version)
+		_xml_version = version;
+
+	if (encoding)
+		_encoding = encoding;
+}
+
+
+ /// notifications about XML start tag
+void XMLReaderBase::StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes)
+{
+	 // search for end of first line
+	const char* s = _content.c_str();
+	const char* p = s;
+	const char* e = p + _content.length();
+
+	for(; p<e; ++p)
+		if (*p == '\n') {
+			++p;
+			break;
+		}
+
+	if (p != s)
+		if (_pos->_children.empty()) {	// no children in last node?
+			if (_last_tag == TAG_START)
+				_pos->_content.append(s, p-s);
+			else if (_last_tag == TAG_END)
+				_pos->_trailing.append(s, p-s);
+			// else TAG_NONE -> don't store white space in root node
+		} else
+			_pos->_children.back()->_trailing.append(s, p-s);
+
+	std::string leading;
+
+	if (p != e)
+		leading.assign(p, e-p);
+
+	XMLNode* node = new XMLNode(name, leading);
+
+	_pos.add_down(node);
+
+#ifdef XMLNODE_LOCATION
+	node->_location = get_location();
+#endif
+
+	node->_attributes = attributes;
+
+	_last_tag = TAG_START;
+	_content.erase();
+}
+
+ /// notifications about XML end tag
+void XMLReaderBase::EndElementHandler()
+{
+	 // search for end of first line
+	const char* s = _content.c_str();
+	const char* p = s;
+	const char* e = p + _content.length();
+
+	for(; p<e; ++p)
+		if (*p == '\n') {
+			++p;
+			break;
+		}
+
+	if (p != s)
+		if (_pos->_children.empty())	// no children in current node?
+			_pos->_content.append(s, p-s);
+		else
+			if (_last_tag == TAG_START)
+				_pos->_content.append(s, p-s);
+			else
+				_pos->_children.back()->_trailing.append(s, p-s);
+
+	if (p != e)
+		_pos->_end_leading.assign(p, e-p);
+
+	_pos.back();
+
+	_last_tag = TAG_END;
+	_content.erase();
+}
+
+ /// store content, white space and comments
+void XMLReaderBase::DefaultHandler(const XML_Char* s, int len)
+{
+	_content.append(s, len);
+}
+
+
+XS_String XMLWriter::s_empty_attr;
+
 }	// namespace XMLStorage

Modified: trunk/reactos/base/shell/explorer/utility/xmlstorage.h
--- trunk/reactos/base/shell/explorer/utility/xmlstorage.h	2006-02-08 08:47:46 UTC (rev 106)
+++ trunk/reactos/base/shell/explorer/utility/xmlstorage.h	2006-02-12 10:35:41 UTC (rev 107)
@@ -4,7 +4,7 @@
  //
  // xmlstorage.h
  //
- // Copyright (c) 2004, 2005 Martin Fuchs <martin-fuchs@gmx.net>
+ // Copyright (c) 2004, 2005, 2006 Martin Fuchs <martin-fuchs@gmx.net>
  //
 
 
@@ -38,19 +38,91 @@
 
 #ifndef _XMLSTORAGE_H
 
+
+#if _MSC_VER>=1400
+#ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES			1
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT	1
+#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES			1
+#endif
+#endif
+
+
+#ifndef _NO_EXPAT
+
+//#include "expat.h"
 #include <expat/expat.h>
 
+#else
+
+typedef char XML_Char;
+
+enum XML_Status {
+	XML_STATUS_ERROR = 0,
+	XML_STATUS_OK = 1
+};
+
+enum XML_Error {
+	XML_ERROR_NONE,
+	XML_ERROR_FAILURE
+};
+
+#endif
+
+
 #ifdef _MSC_VER
-#pragma comment(lib, "libexpat.lib")
 #pragma warning(disable: 4786)
+
+#ifndef	_NO_COMMENT
+#ifndef _NO_EXPAT
+#ifdef XML_STATIC
+#ifndef _DEBUG
+#pragma comment(lib, "libexpatMT")
 #endif
+#else
+#pragma comment(lib, "libexpat")
+#endif
+#endif
 
+#ifndef _STRING_DEFINED	// _STRING_DEFINED only allowed if using xmlstorage.cpp embedded in the project
+#if defined(_DEBUG) && defined(_DLL)	// DEBUG version only supported with MSVCRTD
+#if _MSC_VER==1400
+#pragma comment(lib, "xmlstorage-vc8d")
+#else
+#pragma comment(lib, "xmlstorage-vc6d")
+#endif
+#else
+#ifdef _DLL
+#if _MSC_VER==1400
+#pragma comment(lib, "xmlstorage-vc8")
+#else
+#pragma comment(lib, "xmlstorage-vc6")
+#endif
+#elif defined(_MT)
+#if _MSC_VER==1400
+#pragma comment(lib, "xmlstorage-vc8t")
+#else
+#pragma comment(lib, "xmlstorage-vc6t")
+#endif
+#else
+ // -ML is no more supported by VS2005.
+#pragma comment(lib, "xmlstorage-vc6l")
+#endif
+#endif
+#endif // _STRING_DEFINED
 
+#endif // _NO_COMMENT
+
+#endif // _MSC_VER
+
+
 #include <windows.h>	// for LPCTSTR
 
 #ifdef UNICODE
+#ifndef _UNICODE
 #define _UNICODE
 #endif
+#endif
 
 #include <tchar.h>
 #include <malloc.h>
@@ -81,6 +153,7 @@
 #define	XS_icmp stricmp
 #define	XS_nicmp strnicmp
 #define	XS_toi atoi
+#define	XS_tod strtod
 #define	XS_len strlen
 #define	XS_snprintf snprintf
 #define	XS_vsnprintf vsnprintf
@@ -92,14 +165,19 @@
 #define	XS_icmp _tcsicmp
 #define	XS_nicmp _tcsnicmp
 #define	XS_toi _ttoi
+#define	XS_tod _tcstod
 #define	XS_len _tcslen
 #define	XS_snprintf _sntprintf
 #define	XS_vsnprintf _vsntprintf
 #endif
 
 #ifndef COUNTOF
+#if _MSC_VER>=1400
+#define COUNTOF _countof
+#else
 #define COUNTOF(b) (sizeof(b)/sizeof(b[0]))
 #endif
+#endif
 
 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
 
@@ -269,7 +347,6 @@
 typedef std::filebuf STDIO_FILEBUF;
 #endif
 
-
 struct FileHolder
 {
 	FileHolder(LPCTSTR path, LPCTSTR mode)
@@ -382,6 +459,34 @@
 #endif
 
 
+#ifdef XMLNODE_LOCATION
+ /// location of XML Node including XML file name
+struct XMLLocation
+{
+	XMLLocation()
+	 :	_pdisplay_path(NULL),
+		_line(0),
+		_column(0)
+	{
+	}
+
+	XMLLocation(const char* display_path, int line, int column)
+	 :	_pdisplay_path(display_path),
+		_line(line),
+		_column(column)
+	{
+	}
+
+	std::string str() const;
+
+protected:
+	const char*	_pdisplay_path;	// character pointer for fast reference
+	int	_line;
+	int	_column;
+};
+#endif
+
+
  /// in memory representation of an XML node
 struct XMLNode : public XS_String
 {
@@ -454,7 +559,8 @@
 	}
 
 	XMLNode(const XMLNode& other)
-	 :	_attributes(other._attributes),
+	 :	XS_String(other),
+		_attributes(other._attributes),
 		_leading(other._leading),
 		_content(other._content),
 		_end_leading(other._end_leading),
@@ -462,6 +568,10 @@
 	{
 		for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
 			_children.push_back(new XMLNode(**it));
+
+#ifdef XMLNODE_LOCATION
+		_location = other._location;
+#endif
 	}
 
 	~XMLNode()
@@ -588,6 +698,16 @@
 		return _children;
 	}
 
+	const AttributeMap& get_attributes() const
+	{
+		return _attributes;
+	}
+
+	AttributeMap& get_attributes()
+	{
+		return _attributes;
+	}
+
 	XS_String get_content() const
 	{
 #ifdef XS_STRING_UTF8
@@ -605,6 +725,10 @@
 		_content.assign(EncodeXMLString(s.c_str()));
 	}
 
+#ifdef XMLNODE_LOCATION
+	const XMLLocation& get_location() const {return _location;}
+#endif
+
 	enum WRITE_MODE {
 		FORMAT_SMART	= 0,	/// preserve original white space and comments if present; pretty print otherwise
 		FORMAT_ORIGINAL = 1,	/// write XML stream preserving original white space and comments
@@ -639,6 +763,10 @@
 	std::string _end_leading;
 	std::string _trailing;
 
+#ifdef XMLNODE_LOCATION
+	XMLLocation	_location;
+#endif
+
 	XMLNode* get_first_child() const
 	{
 		if (!_children.empty())
@@ -706,9 +834,9 @@
 	 /// relative XPath create function
 	XMLNode* create_relative(const char* path);
 
-	void write_worker(std::ostream& out, int indent) const;
-	void pretty_write_worker(std::ostream& out, int indent) const;
-	void smart_write_worker(std::ostream& out, int indent) const;
+	void	write_worker(std::ostream& out, int indent) const;
+	void	pretty_write_worker(std::ostream& out, int indent) const;
+	void	smart_write_worker(std::ostream& out, int indent) const;
 };
 
 
@@ -1242,17 +1370,20 @@
 
 #define	XS_TRUE_STR XS_TEXT("true")
 #define	XS_FALSE_STR XS_TEXT("false")
-#define	XS_NUMBERFMT_STR XS_TEXT("%d")
+#define	XS_INTFMT_STR XS_TEXT("%d")
+#define	XS_FLOATFMT_STR XS_TEXT("%f")
 
  // work around GCC's wide string constant bug
 #ifdef __GNUC__
 extern const LPCXSSTR XS_TRUE;
 extern const LPCXSSTR XS_FALSE;
-extern const LPCXSSTR XS_NUMBERFMT;
+extern const LPCXSSTR XS_INTFMT;
+extern const LPCXSSTR XS_FLOATFMT;
 #else
 #define	XS_TRUE XS_TRUE_STR
 #define	XS_FALSE XS_FALSE_STR
-#define	XS_NUMBERFMT XS_NUMBERFMT_STR
+#define	XS_INTFMT XS_INTFMT_STR
+#define	XS_FLOATFMT XS_FLOATFMT_STR
 #endif
 
 
@@ -1380,7 +1511,7 @@
 	operator XS_String() const
 	{
 		XS_CHAR buffer[32];
-		XS_snprintf(buffer, COUNTOF(buffer), XS_NUMBERFMT, _value);
+		XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, _value);
 		return buffer;
 	}
 
@@ -1416,7 +1547,7 @@
 	void assign(int value)
 	{
 		XS_CHAR buffer[32];
-		XS_snprintf(buffer, COUNTOF(buffer), XS_NUMBERFMT, value);
+		XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, value);
 		_ref.assign(buffer);
 	}
 
@@ -1425,6 +1556,89 @@
 };
 
 
+ /// type converter for numeric data
+struct XMLDouble
+{
+	XMLDouble(double value)
+	 :	_value(value)
+	{
+	}
+
+	XMLDouble(LPCXSSTR value, double def=0.)
+	{
+		LPTSTR end;
+
+		if (value && *value)
+			_value = XS_tod(value, &end);
+		else
+			_value = def;
+	}
+
+	XMLDouble(const XMLNode* node, const XS_String& attr_name, double def=0.)
+	{
+		LPTSTR end;
+		const XS_String& value = node->get(attr_name);
+
+		if (!value.empty())
+			_value = XS_tod(value.c_str(), &end);
+		else
+			_value = def;
+	}
+
+	operator double() const
+	{
+		return _value;
+	}
+
+	operator XS_String() const
+	{
+		XS_CHAR buffer[32];
+		XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, _value);
+		return buffer;
+	}
+
+protected:
+	double _value;
+
+private:
+	void operator=(const XMLDouble&); // disallow assignment operations
+};
+
+ /// type converter for numeric data with write access
+struct XMLDoubleRef
+{
+	XMLDoubleRef(XMLNode* node, const XS_String& attr_name, double def=0.)
+	 :	_ref((*node)[attr_name])
+	{
+		if (_ref.empty())
+			assign(def);
+	}
+
+	XMLDoubleRef& operator=(double value)
+	{
+		assign(value);
+
+		return *this;
+	}
+
+	operator double() const
+	{
+		LPTSTR end;
+		return XS_tod(_ref.c_str(), &end);
+	}
+
+	void assign(double value)
+	{
+		XS_CHAR buffer[32];
+		XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, value);
+		_ref.assign(buffer);
+	}
+
+protected:
+	XS_String& _ref;
+};
+
+
  /// type converter for string data
 struct XMLString
 {
@@ -1552,24 +1766,20 @@
 
 	XML_Status read();
 
-	virtual int read_buffer(char* buffer, int len) = 0;
+	std::string	get_position() const;
+	std::string	get_instructions() const {return _instructions;}
 
-	std::string get_position() const
-	{
-		int line = XML_GetCurrentLineNumber(_parser);
-		int column = XML_GetCurrentColumnNumber(_parser);
+	XML_Error	get_error_code() const;
+	std::string	get_error_string() const;
 
-		std::ostringstream out;
-		out << "(" << line << ") : [column " << column << "]";
+#ifdef XMLNODE_LOCATION
+	const char* _display_path;	// character pointer for fast reference in XMLLocation
 
-		return out.str();
-	}
+	XMLLocation get_location() const;
+#endif
 
-	std::string get_instructions() const {return _instructions;}
+	virtual int read_buffer(char* buffer, int len) = 0;
 
-	XML_Error	get_error_code() {return XML_GetErrorCode(_parser);}
-	std::string get_error_string() const;
-
 protected:
 	XMLPos		_pos;
 	XML_Parser	_parser;
@@ -1580,6 +1790,13 @@
 	std::string _content;
 	enum {TAG_NONE, TAG_START, TAG_END} _last_tag;
 
+	void	finish_read();
+
+	virtual void XmlDeclHandler(const XML_Char* version, const XML_Char* encoding, int standalone);
+	virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes);
+	virtual void EndElementHandler();
+	virtual void DefaultHandler(const XML_Char* s, int len);
+
 	static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone);
 	static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts);
 	static void XMLCALL XML_EndElementHandler(void* userData, const XML_Char* name);
@@ -1612,7 +1829,7 @@
 };
 
 
- /// management of XML file headers
+ /// Management of XML file headers
 struct XMLHeader
 {
 	XMLHeader(const std::string& xml_version="1.0", const std::string& encoding="UTF-8", const std::string& doctype="")
@@ -1659,13 +1876,11 @@
 		read(path);
 	}
 
-	std::istream& read(std::istream& in)
+	bool read(std::istream& in)
 	{
 		XMLReader reader(this, in);
 
-		read(reader);
-
-		return in;
+		return read(reader);
 	}
 
 	bool read(LPCTSTR path)
@@ -1700,6 +1915,11 @@
 
 	bool read(XMLReaderBase& reader, const std::string& display_path)
 	{
+#ifdef XMLNODE_LOCATION
+		 // make a string copy to handle temporary string objects
+		_display_path = display_path;
+		reader._display_path = _display_path.c_str();
+#endif
 		XML_Status status = reader.read();
 
 		_header._additional = reader.get_instructions();
@@ -1750,6 +1970,10 @@
 	XMLHeader	_header;
 	XML_Error	_last_error;
 	std::string _last_error_msg;
+
+#ifdef XMLNODE_LOCATION
+	std::string	_display_path;
+#endif
 };
 
 
@@ -1848,7 +2072,7 @@
 	void set_content(const XS_String& s)
 	{
[truncated at 1000 lines; 24 more skipped]