Author: martinf Date: Tue Aug 1 03:23:19 2006 New Revision: 23398
URL: http://svn.reactos.org/svn/reactos?rev=23398&view=rev Log: IBrowser: update XMLStorage library and remove Expat dependency
Added: trunk/reactos/base/applications/ibrowser/utility/xs-native.cpp (with props) Removed: trunk/reactos/base/applications/ibrowser/expat-license.txt Modified: trunk/reactos/base/applications/ibrowser/Makefile-MinGW trunk/reactos/base/applications/ibrowser/Makefile-precomp trunk/reactos/base/applications/ibrowser/favorites.cpp trunk/reactos/base/applications/ibrowser/ibrowser.dsp trunk/reactos/base/applications/ibrowser/ibrowser.rbuild trunk/reactos/base/applications/ibrowser/make_ibrowser.dsp trunk/reactos/base/applications/ibrowser/utility/xmlstorage.cpp trunk/reactos/base/applications/ibrowser/utility/xmlstorage.h
Modified: trunk/reactos/base/applications/ibrowser/Makefile-MinGW URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/Makefile-MinGW (original) +++ trunk/reactos/base/applications/ibrowser/Makefile-MinGW Tue Aug 1 03:23:19 2006 @@ -50,13 +50,14 @@ webchild.o \ mainframe.o \ favorites.o \ + xs-native.o \ xmlstorage.o
LIBS = gdi32 comctl32 shell32 ole32 uuid oleaut32
all: $(TARGET)
-$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) libexpat.dll +$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) $(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS))
ibrowser$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico
Modified: trunk/reactos/base/applications/ibrowser/Makefile-precomp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/Makefile-precomp (original) +++ trunk/reactos/base/applications/ibrowser/Makefile-precomp Tue Aug 1 03:23:19 2006 @@ -52,6 +52,7 @@ webchild.o \ mainframe.o \ favorites.o \ + xs-native.o \ xmlstorage.o
LIBS = gdi32 comctl32 shell32 ole32 oleaut32 uuid @@ -61,7 +62,7 @@ precomp.h.gch: *.h utility/*.h $(CXX) $(CFLAGS) precomp.h
-$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) libexpat.dll +$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) $(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS))
ibrowser$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico
Removed: trunk/reactos/base/applications/ibrowser/expat-license.txt URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/expat-license.txt (original) +++ trunk/reactos/base/applications/ibrowser/expat-license.txt (removed) @@ -1,22 +1,0 @@ -Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd - and Clark Cooper -Copyright (c) 2001, 2002, 2003 Expat maintainers. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Modified: trunk/reactos/base/applications/ibrowser/favorites.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/favorites.cpp (original) +++ trunk/reactos/base/applications/ibrowser/favorites.cpp Tue Aug 1 03:23:19 2006 @@ -429,10 +429,10 @@ XMLDoc xbel;
if (!xbel.read(path)) - if (xbel._last_error == XML_ERROR_NO_ELEMENTS) +/*@@ if (xbel._last_error == XML_ERROR_NO_ELEMENTS) return false; - else - MessageBox(0/*@@g_Globals._hwndDesktop*/, String(xbel._last_error_msg.c_str()), + else */ + MessageBox(0/*@@g_Globals._hwndDesktop*/, xbel._errors.str(), TEXT("ROS Explorer - reading bookmark file"), MB_OK);
const_XMLPos pos(&xbel); @@ -457,9 +457,9 @@ super::write(pos); pos.back();
- xbel._header._doctype = "<!DOCTYPE xbel" - " PUBLIC \"+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML\"\n" - " \"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">"; + xbel._format._doctype._name = "xbel"; + xbel._format._doctype._public = "//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML"; + xbel._format._doctype._system = "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd";
xbel.write(path); }
Modified: trunk/reactos/base/applications/ibrowser/ibrowser.dsp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/ibrowser.dsp (original) +++ trunk/reactos/base/applications/ibrowser/ibrowser.dsp Tue Aug 1 03:23:19 2006 @@ -28,7 +28,7 @@ # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" -CPP=cl.exe +CPP=cl.cmd RSC=rc.exe
!IF "$(CFG)" == "ibrowser - Win32 Release" @@ -199,6 +199,10 @@
SOURCE=.\utility\xmlstorage.h # End Source File +# Begin Source File + +SOURCE=".\utility\xs-native.cpp" +# End Source File # End Group # Begin Group "resources"
Modified: trunk/reactos/base/applications/ibrowser/ibrowser.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/ibrowser.rbuild (original) +++ trunk/reactos/base/applications/ibrowser/ibrowser.rbuild Tue Aug 1 03:23:19 2006 @@ -3,7 +3,6 @@ <module name="ibrowser" type="win32gui" installbase="system32" installname="ibrowser.exe" allowwarnings ="true"> <linkerflag>-fexceptions</linkerflag> <include base="ibrowser">.</include> - <include base="ReactOS">include/expat</include> <define name="__USE_W32API" /> <define name="UNICODE" /> <define name="WIN32" /> @@ -18,12 +17,12 @@ <library>ole32</library> <library>oleaut32</library> <library>shell32</library> - <library>expat</library> <pch>precomp.h</pch> <directory name="utility"> <file>utility.cpp</file> <file>window.cpp</file> <file>xmlstorage.cpp</file> + <file>xs-native.cpp</file> </directory> <file>ibrowser.cpp</file> <file>favorites.cpp</file>
Modified: trunk/reactos/base/applications/ibrowser/make_ibrowser.dsp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/make_ibrowser.dsp (original) +++ trunk/reactos/base/applications/ibrowser/make_ibrowser.dsp Tue Aug 1 03:23:19 2006 @@ -4,7 +4,7 @@
# TARGTYPE "Win32 (x86) External Target" 0x0106
-CFG=make_ibrowser - Win32 bjam +CFG=make_ibrowser - Win32 Release !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE @@ -13,7 +13,7 @@ !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE -!MESSAGE NMAKE /f "make_ibrowser.mak" CFG="make_ibrowser - Win32 bjam" +!MESSAGE NMAKE /f "make_ibrowser.mak" CFG="make_ibrowser - Win32 Release" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE @@ -43,7 +43,7 @@ # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" -# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile-precomp UNICODE=0" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" mingw32-make -f Makefile-precomp UNICODE=0" # PROP Rebuild_Opt "clean all" # PROP Target_File "ibrowser.exe" # PROP Bsc_Name "" @@ -64,7 +64,7 @@ # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" -# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile-precomp UNICODE=0 DEBUG=1" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" mingw32-make -f Makefile-precomp UNICODE=0 DEBUG=1" # PROP Rebuild_Opt "clean all" # PROP Target_File "ibrowser.exe" # PROP Bsc_Name "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=0 DEBUG=1" @@ -85,7 +85,7 @@ # PROP Use_Debug_Libraries 1 # PROP Output_Dir "UDebug" # PROP Intermediate_Dir "UDebug" -# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=1 DEBUG=1" +# PROP Cmd_Line "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" mingw32-make -f Makefile.MinGW UNICODE=1 DEBUG=1" # PROP Rebuild_Opt "clean all" # PROP Target_File "ibrowser.exe" # PROP Bsc_Name "" @@ -106,7 +106,7 @@ # PROP Use_Debug_Libraries 0 # PROP Output_Dir "URelease" # PROP Intermediate_Dir "URelease" -# PROP Cmd_Line "msdevfilt -gcc make -f Makefile-precomp UNICODE=1" +# PROP Cmd_Line "msdevfilt -gcc mingw32-make -f Makefile-precomp UNICODE=1" # PROP Rebuild_Opt "clean all" # PROP Target_File "ibrowser.exe" # PROP Bsc_Name ""
Modified: trunk/reactos/base/applications/ibrowser/utility/xmlstorage.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/utility/xmlstorage.cpp (original) +++ trunk/reactos/base/applications/ibrowser/utility/xmlstorage.cpp Tue Aug 1 03:23:19 2006 @@ -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 //
@@ -36,22 +36,29 @@
*/
+#ifndef XS_NO_COMMENT +#define XS_NO_COMMENT // no #pragma comment(lib, ...) statements in .lib files +#endif + //#include "xmlstorage.h" #include <precomp.h>
// work around GCC's wide string constant bug #ifdef __GNUC__ -const LPCXSSTR XMLStorage::XS_TRUE = XS_TEXT("true"); -const LPCXSSTR XMLStorage::XS_FALSE = XS_TEXT("false"); -const LPCXSSTR XMLStorage::XS_NUMBERFMT = XS_TEXT("%d"); +const LPCXSSTR XMLStorage::XS_EMPTY = XS_EMPTY_STR; +const LPCXSSTR XMLStorage::XS_TRUE = XS_TRUE_STR; +const LPCXSSTR XMLStorage::XS_FALSE = XS_FALSE_STR; +const LPCXSSTR XMLStorage::XS_INTFMT = XS_INTFMT_STR; +const LPCXSSTR XMLStorage::XS_FLOATFMT = XS_FLOATFMT_STR; #endif
namespace XMLStorage {
-static std::string unescape(const char* s, char b='"', char e='"') + /// remove escape characters from zero terminated string +static std::string unescape(const char* s, char b, char e) { const char* end = s + strlen(s);
@@ -68,7 +75,13 @@ return std::string(s, end-s); }
-static std::string unescape(const char* s, int l, char b='"', char e='"') +inline std::string unescape(const char* s) +{ + return unescape(s, '"', '"'); +} + + /// remove escape characters from string with specified length +static std::string unescape(const char* s, size_t l, char b, char e) { const char* end = s + l;
@@ -85,6 +98,11 @@ return std::string(s, end-s); }
+inline std::string unescape(const char* s, size_t l) +{ + return unescape(s, l, '"', '"'); +} +
/// move XPath like to position in XML tree bool XMLPos::go(const char* path) @@ -137,7 +155,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;
@@ -198,7 +216,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;
@@ -259,239 +277,113 @@ }
- /// 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); + /// encode XML string literals +std::string EncodeXMLString(const XS_String& str) +{ + LPCXSSTR s = str.c_str(); + size_t l = XS_len(s); + + if (l <= BUFFER_LEN) { + LPXSSTR buffer = (LPXSSTR)alloca(6*sizeof(XS_CHAR)*XS_len(s)); // worst case """ / "'" + LPXSSTR o = buffer; + + for(LPCXSSTR p=s; *p; ++p) + switch(*p) { + case '&': + *o++ = '&'; *o++ = 'a'; *o++ = 'm'; *o++ = 'p'; *o++ = ';'; + break; + + case '<': + *o++ = '&'; *o++ = 'l'; *o++ = 't'; *o++ = ';'; + break; + + case '>': + *o++ = '&'; *o++ = 'g'; *o++ = 't'; *o++ = ';'; + break; + + case '"': + *o++ = '&'; *o++ = 'q'; *o++ = 'u'; *o++ = 'o'; *o++ = 't'; *o++ = ';'; + break; + + case ''': + *o++ = '&'; *o++ = 'a'; *o++ = 'p'; *o++ = 'o'; *o++ = 's'; *o++ = ';'; + break; + + default: + if ((unsigned)*p<20 && *p!='\t' && *p!='\r' && *p!='\n') { + char b[16]; + sprintf(b, "&%d;", (unsigned)*p); + for(const char*q=b; *q; ) + *o++ = *q++; + } else + *o++ = *p; + } + +#ifdef XS_STRING_UTF8 + return XS_String(buffer, o-buffer); +#else + return get_utf8(buffer, o-buffer); +#endif + } else { // l > BUFFER_LEN + // encode the whole string in a CDATA section + std::string ret = "<![CDATA["; + +#ifdef XS_STRING_UTF8 + ret += str; +#else + ret += get_utf8(str); +#endif + + ret += "]]>"; + + return ret; + +/* alternative code using ostringstream (beware: quite slow) +#include <sstream> + + std::ostringstream out; + + LPCXSSTR s = str.c_str(); + + for(LPCXSSTR p=s; *p; ++p) + switch(*p) { + case '&': + out << "&"; + break; + + case '<': + out << "<"; + break; + + case '>': + out << ">"; + break; + + case '"': + out << """; + break; + + case ''': + out << "'"; + break; + + default: + if ((unsigned)*p<20 && *p!='\t' *p!='\r' && *p!='\n') + out << "&" << (unsigned)*p << ";"; + else + out << *p; + } + +#ifdef XS_STRING_UTF8 + return XS_String(out.str()); +#else + return get_utf8(out.str()); +#endif + */ } - - 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); -} - - -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(); -} - - -std::string EncodeXMLString(const XS_String& str) -{ - LPCXSSTR s = str.c_str(); - LPXSSTR buffer = (LPXSSTR)alloca(5*sizeof(XS_CHAR)*XS_len(s)); // worst case. "&" - LPXSSTR o = buffer; - - for(LPCXSSTR p=s; *p; ++p) - switch(*p) { - case '&': - *o++ = '&'; *o++ = 'a'; *o++ = 'm'; *o++ = 'p'; *o++ = ';'; - break; - - case '<': - *o++ = '&'; *o++ = 'l'; *o++ = 't'; *o++ = ';'; - break; - - case '>': - *o++ = '&'; *o++ = 'g'; *o++ = 't'; *o++ = ';'; - break; - - case '"': - *o++ = '&'; *o++ = 'q'; *o++ = 'u'; *o++ = 'o'; *o++ = 't'; *o++ = ';'; - break; - - case ''': - *o++ = '&'; *o++ = 'a'; *o++ = 'p'; *o++ = 'o'; *o++ = 's'; *o++ = ';'; - break; - - default: - *o++ = *p; - } - -#ifdef XS_STRING_UTF8 - return XS_String(buffer, o-buffer); -#else - return get_utf8(buffer, o-buffer); -#endif -} - +} + + /// decode XML string literals XS_String DecodeXMLString(const XS_String& str) { LPCXSSTR s = str.c_str(); @@ -517,6 +409,16 @@ p += 5; } else *o++ = *p; + } else if (*p=='<' && !XS_nicmp(p+1,XS_TEXT("!CDATA["),7)) { + p += 9; + LPCXSSTR e = XS_strstr(p, XS_TEXT("]]>")); + if (e) { + size_t l = e - p; + memcpy(o, p, l); + o += l; + p += 3; + } else + *o++ = *p; } else *o++ = *p;
@@ -546,8 +448,28 @@ }
+ /// print node without any white space +void XMLNode::plain_write_worker(std::ostream& out) const +{ + out << '<' << EncodeXMLString(*this); + + for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it) + out << ' ' << EncodeXMLString(it->first) << "="" << EncodeXMLString(it->second) << """; + + if (!_children.empty()/*@@ || !_content.empty()*/) { + out << ">"; + + for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) + (*it)->plain_write_worker(out); + + out << "</" << EncodeXMLString(*this) << ">"; + } else + out << "/>"; +} + + /// pretty print node with children tree to output stream -void XMLNode::pretty_write_worker(std::ostream& out, int indent) const +void XMLNode::pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const { for(int i=indent; i--; ) out << XML_INDENT_SPACE; @@ -557,23 +479,23 @@ for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it) out << ' ' << EncodeXMLString(it->first) << "="" << EncodeXMLString(it->second) << """;
- if (!_children.empty() || !_content.empty()) { - out << ">\n"; + if (!_children.empty()/*@@ || !_content.empty()*/) { + out << '>' << format._endl;
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) - (*it)->pretty_write_worker(out, indent+1); + (*it)->pretty_write_worker(out, format, indent+1);
for(int i=indent; i--; ) out << XML_INDENT_SPACE;
- out << "</" << EncodeXMLString(*this) << ">\n"; + out << "</" << EncodeXMLString(*this) << '>' << format._endl; } else - out << "/>\n"; + out << "/>" << format._endl; }
/// write node with children tree to output stream using smart formating -void XMLNode::smart_write_worker(std::ostream& out, int indent) const +void XMLNode::smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const { if (_leading.empty()) for(int i=indent; i--; ) @@ -592,7 +514,7 @@ out << '>';
if (_content.empty()) - out << '\n'; + out << format._endl; else out << _content;
@@ -600,7 +522,7 @@
if (it != _children.end()) { for(; it!=_children.end(); ++it) - (*it)->smart_write_worker(out, indent+1); + (*it)->smart_write_worker(out, format, indent+1);
if (_end_leading.empty()) for(int i=indent; i--; ) @@ -614,10 +536,269 @@ }
if (_trailing.empty()) - out << '\n'; + out << format._endl; else out << _trailing; }
+std::ostream& operator<<(std::ostream& out, const XMLError& err) +{ + out << err._systemId << "(" << err._line << ") [column " << err._column << "] : " + << err._message; + + return out; +} + + +void DocType::parse(const char* p) +{ + while(isspace((unsigned char)*p)) ++p; + + const char* start = p; + while(isxmlsym(*p)) ++p; + _name.assign(start, p-start); + + while(isspace((unsigned char)*p)) ++p; + + start = p; + while(isxmlsym(*p)) ++p; + std::string keyword(p, p-start); // "PUBLIC" or "SYSTEM" + + while(isspace((unsigned char)*p)) ++p; + + if (*p=='"' || *p==''') { + char delim = *p; + + start = ++p; + while(*p && *p!=delim) ++p; + + if (*p == delim) + _public.assign(start, p++-start); + } else + _public.erase(); + + while(isspace((unsigned char)*p)) ++p; + + if (*p=='"' || *p==''') { + char delim = *p; + + start = ++p; + while(*p && *p!=delim) ++p; + + if (*p == delim) + _system.assign(start, p++-start); + } else + _system.erase(); +} + + + +void XMLFormat::print_header(std::ostream& out, bool lf) const +{ + out << "<?xml version=\"" << _version << "\" encoding=\"" << _encoding << "\""; + + if (_standalone != -1) + out << " standalone=\"yes\""; + + out << "?>"; + + if (lf) + out << _endl; + + if (!_doctype.empty()) { + out << "<!DOCTYPE " << _doctype._name; + + if (!_doctype._public.empty()) { + out << " PUBLIC " << _doctype._public; + + if (lf) + out << _endl; + + out << " " << _doctype._system; + } else if (!_doctype._system.empty()) + out << " SYSTEM " << _doctype._system; + + out << "?>"; + + if (lf) + out << _endl; + } + + for(StyleSheetList::const_iterator it=_stylesheets.begin(); it!=_stylesheets.end(); ++it) { + it->print(out); + + if (lf) + out << _endl; + } + +/* if (!_additional.empty()) { + out << _additional; + + if (lf) + out << _endl; + } */ +} + +void StyleSheet::print(std::ostream& out) const +{ + out << "<?xml-stylesheet" + " href=\"" << _href << "\"" + " type=\"" << _type << "\""; + + if (!_title.empty()) + out << " title=\"" << _title << "\""; + + if (!_media.empty()) + out << " media=\"" << _media << "\""; + + if (!_charset.empty()) + out << " charset=\"" << _charset << "\""; + + if (_alternate) + out << " alternate=\"yes\""; + + out << "?>"; +} + + + /// return formated error message +std::string XMLError::str() const +{ + std::ostringstream out; + + out << *this; + + return out.str(); +} + + + /// return merged error strings +XS_String XMLErrorList::str() const +{ + std::ostringstream out; + + for(const_iterator it=begin(); it!=end(); ++it) + out << *it << std::endl; + + 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 char* version, const char* encoding, int standalone) +{ + if (version) + _format._version = version; + + if (encoding) + _format._encoding = encoding; + + _format._standalone = standalone; +} + + + /// 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 at root node + p = s; + } 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(); +} + +#if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT) + /// store content, white space and comments +void XMLReaderBase::DefaultHandler(const XML_Char* s, int len) +{ +#if defined(XML_UNICODE) || defined(XS_USE_XERCES) + _content.append(String_from_XML_Char(s, len)); +#else + _content.append(s, len); +#endif +} +#endif + + +XS_String XMLWriter::s_empty_attr; + + } // namespace XMLStorage
Modified: trunk/reactos/base/applications/ibrowser/utility/xmlstorage.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/utility/xmlstorage.h (original) +++ trunk/reactos/base/applications/ibrowser/utility/xmlstorage.h Tue Aug 1 03:23:19 2006 @@ -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,107 @@
#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 + + +#ifdef XS_USE_XERCES + +#ifndef UNICODE +#ifndef XS_STRING_UTF8 +#define XS_STRING_UTF8 +#endif +#endif + +#include <xercesc/parsers/SAXParser.hpp> +#include <xercesc/sax/HandlerBase.hpp> + +using XERCES_CPP_NAMESPACE_QUALIFIER Locator; +using XERCES_CPP_NAMESPACE_QUALIFIER SAXParser; +using XERCES_CPP_NAMESPACE_QUALIFIER HandlerBase; +using XERCES_CPP_NAMESPACE_QUALIFIER InputSource; +using XERCES_CPP_NAMESPACE_QUALIFIER AttributeList; +using XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException; + +typedef XMLCh XML_Char; + +#elif defined(XS_USE_EXPAT) + #include <expat/expat.h>
+#endif + + #ifdef _MSC_VER -#pragma comment(lib, "libexpat.lib") #pragma warning(disable: 4786) -#endif - + +#ifndef XS_NO_COMMENT + +#ifdef XS_USE_XERCES +#ifdef _DEBUG +#pragma comment(lib, "xerces-c_2D") +#else +#pragma comment(lib, "xerces-c_2") +#endif +#elif defined(XS_USE_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 // XS_NO_COMMENT + +#endif // _MSC_VER + + +#ifdef UNICODE +#ifndef _UNICODE +#define _UNICODE +#endif +#else +#ifdef _UNICODE +#define UNICODE +#endif +#endif
#include <windows.h> // for LPCTSTR - -#ifdef UNICODE -#define _UNICODE -#endif
#include <tchar.h> #include <malloc.h> @@ -78,24 +166,47 @@ #define XS_TEXT(x) x #define LPXSSTR LPSTR #define LPCXSSTR LPCSTR +#define XS_cmp strcmp #define XS_icmp stricmp +#define XS_ncmp strncmp #define XS_nicmp strnicmp #define XS_toi atoi +#define XS_tod strtod #define XS_len strlen -#define XS_sprintf sprintf -#define XS_vsprintf vsprintf +#define XS_snprintf _snprintf +#define XS_vsnprintf _vsnprintf +#define XS_strstr strstr #else #define XS_CHAR TCHAR #define XS_TEXT(x) TEXT(x) #define LPXSSTR LPTSTR #define LPCXSSTR LPCTSTR +#define XS_cmp _tcscmp #define XS_icmp _tcsicmp +#define XS_ncmp _tcsncmp #define XS_nicmp _tcsnicmp #define XS_toi _ttoi +#define XS_tod _tcstod #define XS_len _tcslen -#define XS_sprintf _stprintf -#define XS_vsprintf _vstprintf -#endif +#define XS_snprintf _sntprintf +#define XS_vsnprintf _vsntprintf +#define XS_strstr _tcsstr +#endif + +#ifndef COUNTOF +#if _MSC_VER>=1400 +#define COUNTOF _countof +#else +#define COUNTOF(b) (sizeof(b)/sizeof(b[0])) +#endif +#endif + + +int inline isxmlsym(unsigned char c) +{ + return isalnum(c) || c=='_' || c=='-'; +} +
#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
@@ -121,46 +232,46 @@ XS_String() {}
XS_String(LPCXSSTR s) {if (s) super::assign(s);} - XS_String(LPCXSSTR s, int l) : super(s, l) {} + XS_String(LPCXSSTR s, size_t l) : super(s, l) {}
XS_String(const super& other) : super(other) {} XS_String(const XS_String& other) : super(other) {}
#if defined(UNICODE) && !defined(XS_STRING_UTF8) XS_String(LPCSTR s) {assign(s);} - XS_String(LPCSTR s, int l) {assign(s, l);} + XS_String(LPCSTR s, size_t l) {assign(s, l);} XS_String(const std::string& other) {assign(other.c_str());} XS_String& operator=(LPCSTR s) {assign(s); return *this;} - void assign(LPCSTR s) {if (s) {int bl=strlen(s); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, bl, b, bl));} else erase();} - void assign(LPCSTR s, int l) {if (s) {int bl=l; LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, bl));} else erase();} + void assign(LPCSTR s) {if (s) {size_t bl=strlen(s); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, bl, b, bl));} else erase();} + void assign(LPCSTR s, size_t l) {if (s) {size_t bl=l; LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, bl));} else erase();} #else XS_String(LPCWSTR s) {assign(s);} - XS_String(LPCWSTR s, int l) {assign(s, l);} + XS_String(LPCWSTR s, size_t l) {assign(s, l);} XS_String(const std::wstring& other) {assign(other.c_str());} XS_String& operator=(LPCWSTR s) {assign(s); return *this;} #ifdef XS_STRING_UTF8 void assign(const XS_String& s) {assign(s.c_str());} - void assign(LPCWSTR s) {if (s) {int bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, bl, b, bl, 0, 0));} else erase();} - void assign(LPCWSTR s, int l) {int bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, l, b, bl, 0, 0));} else erase();} + void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();} + void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();} #else // if !UNICODE && !XS_STRING_UTF8 - void assign(LPCWSTR s) {if (s) {int bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, bl, b, bl, 0, 0));} else erase();} - void assign(LPCWSTR s, int l) {int bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, bl, 0, 0));} else erase();} + void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();} + void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();} #endif #endif
XS_String& operator=(LPCXSSTR s) {if (s) super::assign(s); else erase(); return *this;} XS_String& operator=(const super& s) {super::assign(s); return *this;} void assign(LPCXSSTR s) {super::assign(s);} - void assign(LPCXSSTR s, int l) {super::assign(s, l);} + void assign(LPCXSSTR s, size_t l) {super::assign(s, l);}
operator LPCXSSTR() const {return c_str();}
#ifdef XS_STRING_UTF8 - operator std::wstring() const {int bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_UTF8, 0, c_str(), bl, b, bl));} + operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_UTF8, 0, c_str(), bl, b, bl));} #elif defined(UNICODE) - operator std::string() const {int bl=length(); LPSTR b=(LPSTR)alloca(bl); return std::string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), bl, b, bl, 0, 0));} -#else - operator std::wstring() const {int bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), bl, b, bl));} + operator std::string() const {size_t bl=length(); LPSTR b=(LPSTR)alloca(bl); return std::string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), bl, b, bl, 0, 0));} +#else + operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), (int)bl, b, (int)bl));} #endif
XS_String& printf(LPCXSSTR fmt, ...) @@ -169,7 +280,7 @@ XS_CHAR b[BUFFER_LEN];
va_start(l, fmt); - super::assign(b, XS_vsprintf(b, fmt, l)); + super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l)); va_end(l);
return *this; @@ -179,7 +290,7 @@ { XS_CHAR b[BUFFER_LEN];
- super::assign(b, XS_vsprintf(b, fmt, l)); + super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
return *this; } @@ -190,7 +301,7 @@ XS_CHAR b[BUFFER_LEN];
va_start(l, fmt); - super::append(b, XS_vsprintf(b, fmt, l)); + super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l)); va_end(l);
return *this; @@ -200,7 +311,7 @@ { XS_CHAR b[BUFFER_LEN];
- super::append(b, XS_vsprintf(b, fmt, l)); + super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
return *this; } @@ -211,12 +322,33 @@ #endif // XS_String
+#define XS_EMPTY_STR XS_TEXT("") +#define XS_TRUE_STR XS_TEXT("true") +#define XS_FALSE_STR XS_TEXT("false") +#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_EMPTY; +extern const LPCXSSTR XS_TRUE; +extern const LPCXSSTR XS_FALSE; +extern const LPCXSSTR XS_INTFMT; +extern const LPCXSSTR XS_FLOATFMT; +#else +#define XS_EMPTY XS_EMPTY_STR +#define XS_TRUE XS_TRUE_STR +#define XS_FALSE XS_FALSE_STR +#define XS_INTFMT XS_INTFMT_STR +#define XS_FLOATFMT XS_FLOATFMT_STR +#endif + + #ifndef XS_STRING_UTF8
-inline void assign_utf8(XS_String& s, const char* str) -{ - int lutf8 = strlen(str); - + // from UTF-8 to XS internal string encoding +inline void assign_utf8(XS_String& s, const char* str, int lutf8) +{ #ifdef UNICODE LPTSTR buffer = (LPTSTR)alloca(sizeof(TCHAR)*lutf8); int l = MultiByteToWideChar(CP_UTF8, 0, str, lutf8, buffer, lutf8); @@ -231,22 +363,44 @@ s.assign(buffer, l); }
-inline std::string get_utf8(LPCTSTR s, int l) + // from UTF-8 to XS internal string encoding +inline void assign_utf8(XS_String& s, const char* str) +{ + assign_utf8(s, str, strlen(str)); +} + + // from XS internal string encoding to UTF-8 +inline std::string get_utf8(LPCTSTR s, size_t l) { #ifdef UNICODE - int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl); - l = WideCharToMultiByte(CP_UTF8, 0, s, l, buffer, bl, 0, 0); + size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl); + l = WideCharToMultiByte(CP_UTF8, 0, s, (int)l, buffer, (int)bl, 0, 0); #else LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l); - l = MultiByteToWideChar(CP_ACP, 0, s, l, wbuffer, l); - - int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl); - l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, l, buffer, bl, 0, 0); + l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l); + + size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl); + l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0); #endif
return std::string(buffer, l); }
+#ifdef UNICODE + // from XS internal string encoding to UTF-8 +inline std::string get_utf8(const char* s, size_t l) +{ + LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l); + l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l); + + size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl); + l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0); + + return std::string(buffer, l); +} +#endif + + // from XS internal string encoding to UTF-8 inline std::string get_utf8(const XS_String& s) { return get_utf8(s.c_str(), s.length()); @@ -265,43 +419,58 @@ typedef std::filebuf STDIO_FILEBUF; #endif
+struct FileHolder +{ + FileHolder(LPCTSTR path, LPCTSTR mode) + { +#ifdef __STDC_WANT_SECURE_LIB__ // secure CRT functions using VS 2005 + if (_tfopen_s(&_pfile, path, mode) != 0) + _pfile = NULL; +#else + _pfile = _tfopen(path, mode); +#endif + } + + ~FileHolder() + { + if (_pfile) + fclose(_pfile); + } + +protected: + FILE* _pfile; +}; + /// input file stream with ANSI/UNICODE file names -struct tifstream : public std::istream +struct tifstream : public std::istream, FileHolder { typedef std::istream super;
tifstream(LPCTSTR path) : super(&_buf), - _pfile(_tfopen(path, TEXT("r"))), + FileHolder(path, TEXT("rb")), // binary mode is important for XMLReader::read_buffer() with MinGW libraries #ifdef __GNUC__ - _buf(_pfile, ios::in) + _buf(_pfile, std::ios::in) #else _buf(_pfile) #endif { }
- ~tifstream() - { - if (_pfile) - fclose(_pfile); - } - protected: - FILE* _pfile; STDIO_FILEBUF _buf; };
/// output file stream with ANSI/UNICODE file names -struct tofstream : public std::ostream +struct tofstream : public std::ostream, FileHolder { typedef std::ostream super;
tofstream(LPCTSTR path) : super(&_buf), - _pfile(_tfopen(path, TEXT("w"))), + FileHolder(path, TEXT("wb")), #ifdef __GNUC__ - _buf(_pfile, ios::out) + _buf(_pfile, std::ios::out) #else _buf(_pfile) #endif @@ -311,13 +480,9 @@ ~tofstream() { flush(); - - if (_pfile) - fclose(_pfile); }
protected: - FILE* _pfile; STDIO_FILEBUF _buf; };
@@ -326,16 +491,17 @@ #define XML_INDENT_SPACE " "
-#ifdef XML_UNICODE // Are XML_Char strings UTF-16 encoded? - +#if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT) + +#if defined(XML_UNICODE)/*Expat*/ || defined(XS_USE_XERCES)/*Xerces*/ // Are Expat/Xerces XML strings UTF-16 encoded? typedef XS_String String_from_XML_Char;
#elif defined(XS_STRING_UTF8) - typedef XS_String String_from_XML_Char;
#else
+ /// converter from Expat/Xerces strings to XMLStorage internal strings struct String_from_XML_Char : public XS_String { String_from_XML_Char(const XML_Char* str) @@ -345,6 +511,8 @@ };
#endif + +#endif // defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
#if defined(UNICODE) && !defined(XS_STRING_UTF8) @@ -363,6 +531,152 @@ };
#endif + + + /// XML Error with message and location +struct XMLError +{ + XMLError() + : _line(0), + _column(0), + _error_code(0) + { + } + + std::string str() const; + friend std::ostream& operator<<(std::ostream&, const XMLError& err); + + XS_String _message; + XS_String _systemId; + int _line; + int _column; + int _error_code; +}; + +struct XMLErrorList : public std::list<XMLError> +{ + XS_String str() const; +}; + + +#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 + + +enum PRETTY_FLAGS { + PRETTY_PLAIN = 0, + PRETTY_LINEFEED = 1, + PRETTY_INDENT = 2 +}; + + +struct StyleSheet +{ + std::string _href; // CDATA #REQUIRED + std::string _type; // CDATA #REQUIRED + std::string _title; // CDATA #IMPLIED + std::string _media; // CDATA #IMPLIED + std::string _charset; // CDATA #IMPLIED + bool _alternate; // (yes|no) "no" + + StyleSheet() : _alternate(false) {} + + StyleSheet(const std::string& href, const std::string& type="text/xsl", bool alternate=false) + : _href(href), + _type(type), + _alternate(alternate) + { + } + + bool empty() const {return _href.empty();} + void print(std::ostream& out) const; +}; + +struct StyleSheetList : public std::list<StyleSheet> +{ + void set(const StyleSheet& stylesheet) + { + clear(); + push_back(stylesheet); + } +}; + + +struct DocType +{ + std::string _name; + + // External Document Types are noted, but not parsed. + std::string _public; + std::string _system; + + // Internal DTDs are not supported. + + void parse(const char* str); + bool empty() const {return _name.empty();} +}; + + /// Management of XML file headers and formating +struct XMLFormat +{ + XMLFormat(PRETTY_FLAGS pretty=PRETTY_INDENT, const std::string& xml_version="1.0", const std::string& encoding="utf-8", const DocType& doctype=DocType()) + : _pretty(pretty), + _endl("\n"), + _version(xml_version), + _encoding(encoding), + _doctype(doctype), + _standalone(-1) + { + } + + void print_header(std::ostream& out, bool lf=true) const; + + PRETTY_FLAGS _pretty; + const char* _endl; // line ending string: "\n" or "\r\n" + + std::string _version; + std::string _encoding; + + DocType _doctype; + + StyleSheetList _stylesheets; + +// std::string _additional; + + int _standalone; +}; + + +enum WRITE_MODE { + FORMAT_PLAIN, /// write XML without any white space + FORMAT_SMART, /// preserve original white space and comments if present; pretty print otherwise + FORMAT_ORIGINAL, /// write XML stream preserving original white space and comments + FORMAT_PRETTY /// pretty print node to stream without preserving original white space +};
/// in memory representation of an XML node @@ -392,11 +706,33 @@ { return super::find(x); } + + XS_String get(const char* x, LPXSSTR def=XS_EMPTY_STR) const + { + const_iterator found = find(x); + + if (found != end()) + return found->second; + else + return def; + } }; #else - typedef std::map<XS_String, XS_String> AttributeMap; -#endif - + struct AttributeMap : public std::map<XS_String, XS_String> + { + XS_String get(const char* x, LPXSSTR def=XS_EMPTY_STR) const + { + const_iterator found = find(x); + + if (found != end()) + return found->second; + else + return def; + } + }; +#endif + + /// internal children node list struct Children : public std::list<XMLNode*> { void assign(const Children& other) @@ -436,17 +772,21 @@ }
XMLNode(const XMLNode& other) - : _attributes(other._attributes), + : XS_String(other), + _attributes(other._attributes), _leading(other._leading), _content(other._content), _end_leading(other._end_leading), _trailing(other._trailing) +#ifdef XMLNODE_LOCATION + , _location(other._location) +#endif { for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it) _children.push_back(new XMLNode(**it)); }
- ~XMLNode() + virtual ~XMLNode() { while(!_children.empty()) { delete _children.back(); @@ -500,14 +840,14 @@ }
/// read only access to an attribute - template<typename T> XS_String get(const T& attr_name) const + template<typename T> XS_String get(const T& attr_name, LPXSSTR def=XS_EMPTY_STR) const { AttributeMap::const_iterator found = _attributes.find(attr_name);
if (found != _attributes.end()) return found->second; else - return XS_String(); + return def; }
/// convenient value access in children node @@ -570,13 +910,23 @@ return _children; }
+ const AttributeMap& get_attributes() const + { + return _attributes; + } + + AttributeMap& get_attributes() + { + return _attributes; + } + XS_String get_content() const { #ifdef XS_STRING_UTF8 const XS_String& ret = _content; #else XS_String ret; - assign_utf8(ret, _content.c_str()); + assign_utf8(ret, _content.c_str(), _content.length()); #endif
return DecodeXMLString(ret.c_str()); @@ -587,18 +937,20 @@ _content.assign(EncodeXMLString(s.c_str())); }
- 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 - FORMAT_PRETTY = 2 /// pretty print node to stream without preserving original white space - }; +#ifdef XMLNODE_LOCATION + const XMLLocation& get_location() const {return _location;} +#endif
/// write node with children tree to output stream - std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART, int indent=0) const + std::ostream& write(std::ostream& out, const XMLFormat& format, WRITE_MODE mode=FORMAT_SMART, int indent=0) const { switch(mode) { + case FORMAT_PLAIN: + plain_write_worker(out); + break; + case FORMAT_PRETTY: - pretty_write_worker(out, indent); + pretty_write_worker(out, format, indent); break;
case FORMAT_ORIGINAL: @@ -606,7 +958,7 @@ break;
default: // FORMAT_SMART - smart_write_worker(out, indent); + smart_write_worker(out, format, indent); }
return out; @@ -616,10 +968,14 @@ Children _children; AttributeMap _attributes;
- std::string _leading; - std::string _content; - std::string _end_leading; - std::string _trailing; + std::string _leading; // UTF-8 encoded + std::string _content; // UTF-8 and entity encoded, may contain CDATA sections; decode with DecodeXMLString() + std::string _end_leading; // UTF-8 encoded + std::string _trailing; // UTF-8 encoded + +#ifdef XMLNODE_LOCATION + XMLLocation _location; +#endif
XMLNode* get_first_child() const { @@ -678,18 +1034,20 @@ } #endif
- /// XPath find functions + /// XPath find function (const) const XMLNode* find_relative(const char* path) const;
+ /// XPath find function XMLNode* find_relative(const char* path) {return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->find_relative(path));}
/// 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 plain_write_worker(std::ostream& out) const; + void pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const; + void smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const; };
@@ -708,6 +1066,7 @@ { }
+ /// internal iterator class struct iterator { typedef XMLNode::Children::iterator BaseIterator; @@ -806,6 +1165,7 @@ { }
+ /// internal iterator class struct const_iterator { typedef XMLNode::Children::const_iterator BaseIterator; @@ -954,6 +1314,7 @@ return _cur->get(attr_name); }
+ /// attribute setting void put(const XS_String& attr_name, const XS_String& value) { _cur->put(attr_name, value); @@ -1218,18 +1579,7 @@ };
- // 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; -#else -#define XS_TRUE XS_TEXT("true") -#define XS_FALSE XS_TEXT("false") -#define XS_NUMBERFMT XS_TEXT("%d") -#endif - - + /// type converter for boolean data struct XMLBool { XMLBool(bool value=false) @@ -1277,6 +1627,7 @@ void operator=(const XMLBool&); // disallow assignment operations };
+ /// type converter for boolean data with write access struct XMLBoolRef { XMLBoolRef(XMLNode* node, const XS_String& attr_name, bool def=false) @@ -1318,6 +1669,7 @@ };
+ /// type converter for integer data struct XMLInt { XMLInt(int value) @@ -1351,7 +1703,7 @@ operator XS_String() const { XS_CHAR buffer[32]; - XS_sprintf(buffer, XS_NUMBERFMT, _value); + XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, _value); return buffer; }
@@ -1362,6 +1714,7 @@ void operator=(const XMLInt&); // disallow assignment operations };
+ /// type converter for integer data with write access struct XMLIntRef { XMLIntRef(XMLNode* node, const XS_String& attr_name, int def=0) @@ -1386,7 +1739,7 @@ void assign(int value) { XS_CHAR buffer[32]; - XS_sprintf(buffer, XS_NUMBERFMT, value); + XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, value); _ref.assign(buffer); }
@@ -1395,6 +1748,90 @@ };
+ /// 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 { XMLString(const XS_String& value) @@ -1402,7 +1839,7 @@ { }
- XMLString(LPCXSSTR value, LPCXSSTR def=XS_TEXT("")) + XMLString(LPCXSSTR value, LPCXSSTR def=XS_EMPTY) { if (value && *value) _value = value; @@ -1410,7 +1847,7 @@ _value = def; }
- XMLString(const XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_TEXT("")) + XMLString(const XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY) { const XS_String& value = node->get(attr_name);
@@ -1437,16 +1874,17 @@ void operator=(const XMLString&); // disallow assignment operations };
+ /// type converter for string data with write access struct XMStringRef { - XMStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_TEXT("")) + XMStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY) : _ref((*node)[attr_name]) { if (_ref.empty()) assign(def); }
- XMStringRef(XMLNode* node, const XS_String& node_name, const XS_String& attr_name, LPCXSSTR def=XS_TEXT("")) + XMStringRef(XMLNode* node, const XS_String& node_name, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY) : _ref(node->subvalue(node_name, attr_name)) { if (_ref.empty()) @@ -1500,62 +1938,175 @@
/// XML reader base class struct XMLReaderBase -{ - XMLReaderBase(XMLNode* node) - : _pos(node), - _parser(XML_ParserCreate(NULL)) - { - XML_SetUserData(_parser, this); - XML_SetXmlDeclHandler(_parser, XML_XmlDeclHandler); - XML_SetElementHandler(_parser, XML_StartElementHandler, XML_EndElementHandler); - XML_SetDefaultHandler(_parser, XML_DefaultHandler); - - _last_tag = TAG_NONE; - } - - virtual ~XMLReaderBase() - { - XML_ParserFree(_parser); - } - - XML_Status read(); - - virtual int read_buffer(char* buffer, int len) = 0; - - std::string get_position() const - { - int line = XML_GetCurrentLineNumber(_parser); - int column = XML_GetCurrentColumnNumber(_parser); - - std::ostringstream out; - out << "(" << line << ") : [column " << column << "]"; - - return out.str(); - } - - std::string get_instructions() const {return _instructions;} - - XML_Error get_error_code() {return XML_GetErrorCode(_parser);} - std::string get_error_string() const; +#ifdef XS_USE_XERCES + : public HandlerBase +#endif +{ +#ifdef XS_USE_XERCES + + XMLReaderBase(XMLNode* node, InputSource* source, bool adoptSource=false); + virtual ~XMLReaderBase(); + + void read();
protected: - XMLPos _pos; + SAXParser* _parser; + InputSource* _source; + bool _deleteSource; + + virtual void XMLDecl(const XMLCh* const versionStr, const XMLCh* const encodingStr, + const XMLCh* const standaloneStr, const XMLCh* const actualEncodingStr); + + // Handlers for the SAX DocumentHandler interface + virtual void setDocumentLocator(const Locator* const locator); + virtual void startElement(const XMLCh* const name, AttributeList& attributes); + virtual void endElement(const XMLCh* const name); + virtual void characters(const XMLCh* const chars, const unsigned int length); + virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length); + + // Handlers for the SAX ErrorHandler interface + virtual void error(const SAXParseException& e); + virtual void fatalError(const SAXParseException& e); + virtual void warning(const SAXParseException& e); + virtual void resetErrors(); + +#elif defined(XS_USE_EXPAT) // !XS_USE_XERCES + + XMLReaderBase(XMLNode* node); + virtual ~XMLReaderBase(); + +protected: XML_Parser _parser; - std::string _xml_version; - std::string _encoding; - std::string _instructions; - - std::string _content; - enum {TAG_NONE, TAG_START, TAG_END} _last_tag; - - static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone); + + static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone=-1); 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); static void XMLCALL XML_DefaultHandler(void* userData, const XML_Char* s, int len); + + static std::string get_expat_error_string(XML_Error error_code); + +#else // XS_USE_EXPAT + + XMLReaderBase(XMLNode* node) + : _pos(node), + _endl_defined(false), + _utf8(false) + { + _last_tag = TAG_NONE; + } + + virtual ~XMLReaderBase(); + + bool parse(); + +#endif + +public: +#ifndef XS_USE_XERCES + void read(); + + std::string get_position() const; +#endif + const XMLFormat& get_format() const {return _format;} + const char* get_endl() const {return _endl_defined? _format._endl: "\n";} + + const XMLErrorList& get_errors() const {return _errors;} + const XMLErrorList& get_warnings() const {return _warnings;} + + void clear_errors() {_errors.clear(); _warnings.clear();} + +#ifdef XMLNODE_LOCATION + const char* _display_path; // character pointer for fast reference in XMLLocation + +#ifdef XS_USE_XERCES + const Locator* _locator; +#endif + + XMLLocation get_location() const; +#endif + +protected: + XMLPos _pos; + + std::string _content; // UTF-8 encoded + enum {TAG_NONE, TAG_START, TAG_END} _last_tag; + + XMLErrorList _errors; + XMLErrorList _warnings; + + XMLFormat _format; + bool _endl_defined; + +#ifdef XS_USE_XERCES + //@@ +#elif defined(XS_USE_EXPAT) + virtual int read_buffer(char* buffer, int len) = 0; +#else + virtual int get() = 0; + int eat_endl(); + + bool _utf8; +#endif + + void finish_read(); + + virtual void XmlDeclHandler(const char* version, const char* encoding, int standalone); + virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes); + virtual void EndElementHandler(); +#if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT) + virtual void DefaultHandler(const XML_Char* s, int len); +#else + virtual void DefaultHandler(const std::string& s); +#endif };
/// XML file reader + +#ifdef XS_USE_XERCES + +struct XercesXMLReader : public XMLReaderBase +{ + XercesXMLReader(XMLNode* node, InputSource* source, bool adoptSource=false) + : XMLReaderBase(node, source, adoptSource) + { + } + + XercesXMLReader(XMLNode* node, LPCTSTR path); + XercesXMLReader(XMLNode* node, const XMLByte* buffer, size_t bytes, const std::string& system_id=std::string()); +}; + +#define XMLReader XercesXMLReader + +#elif defined(XS_USE_EXPAT) + +struct ExpatXMLReader : public XMLReaderBase +{ + ExpatXMLReader(XMLNode* node, std::istream& in) + : XMLReaderBase(node), + _in(in) + { + } + + /// read XML stream into XML tree below _pos + int read_buffer(char* buffer, int len) + { + if (!_in.good()) + return -1; + + _in.read(buffer, len); + + return _in.gcount(); + } + +protected: + std::istream& _in; +}; + +#define XMLReader ExpatXMLReader + +#else // XS_USE_XERCES, XS_USE_EXPAT + struct XMLReader : public XMLReaderBase { XMLReader(XMLNode* node, std::istream& in) @@ -1564,127 +2115,110 @@ { }
- /// read XML stream into XML tree below _pos - int read_buffer(char* buffer, int len) - { - if (!_in.good()) - return -1; - - _in.read(buffer, len); - - return _in.gcount(); + /// read one character from XML stream + int get() + { + return _in.get(); }
protected: std::istream& _in; };
- -struct XMLHeader -{ - XMLHeader(const std::string& xml_version="1.0", const std::string& encoding="UTF-8", const std::string& doctype="") - : _version(xml_version), - _encoding(encoding), - _doctype(doctype) - { - } - - void print(std::ostream& out) const - { - out << "<?xml version=\"" << _version << "\" encoding=\"" << _encoding << "\"?>\n"; - - if (!_doctype.empty()) - out << _doctype << '\n'; - if (!_additional.empty()) - out << _additional << '\n'; - } - - std::string _version; - std::string _encoding; - std::string _doctype; - std::string _additional; -}; - - +#endif // XS_USE_XERCES + + + /// XML document holder struct XMLDoc : public XMLNode { XMLDoc() - : XMLNode(""), - _last_error(XML_ERROR_NONE) + : XMLNode("") { }
XMLDoc(LPCTSTR path) - : XMLNode(""), - _last_error(XML_ERROR_NONE) + : XMLNode("") { read(path); }
- std::istream& read(std::istream& in) - { - XMLReader reader(this, in); - - read(reader); - - return in; - } +#ifdef XS_USE_XERCES + bool read(LPCTSTR path) + { + XMLReader reader(this, path); + +#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8) + return read(reader, std::string(ANS(path))); +#else + return read(reader, XS_String(path)); +#endif + } + + bool read(const char* buffer, size_t len, const std::string& system_id=std::string()) + { + XMLReader reader(this, (const XMLByte*)buffer, len, system_id); + + return read(reader, system_id); + } + +#else // XS_USE_XERCES
bool read(LPCTSTR path) { tifstream in(path); XMLReader reader(this, in);
-//#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8) -// return read(reader, std::string(ANS(path))); -//#else +#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8) + return read(reader, std::string(ANS(path))); +#else return read(reader, XS_String(path)); -//#endif - } - - bool read(XMLReaderBase& reader) - { - XML_Status status = reader.read(); - - _header._additional = reader.get_instructions(); - - if (status == XML_STATUS_ERROR) { - std::ostringstream out; - - out << "input stream" << reader.get_position() << " " << reader.get_error_string(); - - _last_error = reader.get_error_code(); - _last_error_msg = out.str(); - } - - return status != XML_STATUS_ERROR; - } +#endif + } + + bool read(const char* buffer, size_t len, const std::string& system_id=std::string()) + { + std::istringstream in(std::string(buffer, len)); + + return read(in, system_id); + } + + bool read(std::istream& in, const std::string& system_id=std::string()) + { + XMLReader reader(this, in); + + return read(reader, system_id); + } +#endif // XS_USE_XERCES
bool read(XMLReaderBase& reader, const std::string& display_path) { - XML_Status status = reader.read(); - - _header._additional = reader.get_instructions(); - - if (status == XML_STATUS_ERROR) { - std::ostringstream out; - - out << display_path << reader.get_position() << " " << reader.get_error_string(); - - _last_error = reader.get_error_code(); - _last_error_msg = out.str(); - } - - return status != XML_STATUS_ERROR; +#ifdef XMLNODE_LOCATION + // make a string copy to handle temporary string objects + _display_path = display_path; + reader._display_path = _display_path.c_str(); +#endif + + reader.clear_errors(); + reader.read(); + + _format = reader.get_format(); + _format._endl = reader.get_endl(); + + if (!reader.get_errors().empty()) { + _errors = reader.get_errors(); + return false; + } + + return true; }
/// write XML stream preserving previous white space and comments std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART) const { - _header.print(out); + _format.print_header(out, mode!=FORMAT_PLAIN);
if (!_children.empty()) - _children.front()->write(out); + _children.front()->write(out, _format, mode);
return out; } @@ -1695,26 +2229,30 @@ return write(out, FORMAT_PRETTY); }
- void write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const + bool write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const { tofstream out(path);
- write(out, mode); - } - - void write_formating(LPCTSTR path) const + return write(out, mode).good(); + } + + bool write_formating(LPCTSTR path) const { tofstream out(path);
- write_formating(out); - } - - XMLHeader _header; - XML_Error _last_error; - std::string _last_error_msg; -}; - - + return write_formating(out).good(); + } + + XMLFormat _format; + XMLErrorList _errors; + +#ifdef XMLNODE_LOCATION + std::string _display_path; +#endif +}; + + + /// XML message wrapper struct XMLMessage : public XMLDoc { XMLMessage(const char* name) @@ -1723,7 +2261,212 @@ _pos.create(name); }
+ std::string toString() const + { + std::ostringstream out; + + write(out); + + return out.str(); + } + XMLPos _pos; + +protected: + XMLMessage() + : _pos(this) + { + } +}; + + +struct XMLMessageFromString : public XMLMessage +{ + XMLMessageFromString(const std::string& xml_str, const std::string& system_id=std::string()) + { + read(xml_str.c_str(), xml_str.length(), system_id); + } +}; + + + /// Reader for XML Messages +struct XMLMessageReader : public XMLPos +{ + XMLMessageReader(const std::string& xml_str, const std::string& system_id=std::string()) + : XMLPos(&_msg) + { + _msg.read(xml_str.c_str(), xml_str.length(), system_id); + } + + const XMLDoc& get_document() + { + return _msg; + } + +protected: + XMLDoc _msg; +}; + + +struct XMLWriter +{ + XMLWriter(std::ostream& out, const XMLFormat& format=XMLFormat()) + : _pofstream(NULL), + _out(out), + _format(format) + { + format.print_header(_out, false); // _format._endl is printed in write_pre() + } + + XMLWriter(LPCTSTR path, const XMLFormat& format=XMLFormat()) + : _pofstream(new tofstream(path)), + _out(*_pofstream), + _format(format) + { + format.print_header(_out, false); // _format._endl is printed in write_pre() + } + + ~XMLWriter() + { + _out << _format._endl; + delete _pofstream; + } + + /// create node and move to it + void create(const XS_String& name) + { + if (!_stack.empty()) { + StackEntry& last = _stack.top(); + + if (last._state < PRE_CLOSED) { + write_attributes(last); + close_pre(last); + } + + ++last._children; + } + + StackEntry entry; + entry._node_name = name; + _stack.push(entry); + + write_pre(entry); + } + + /// go back to previous position + bool back() + { + if (!_stack.empty()) { + write_post(_stack.top()); + + _stack.pop(); + return true; + } else + return false; + } + + /// attribute setting + void put(const XS_String& attr_name, const XS_String& value) + { + if (!_stack.empty()) + _stack.top()._attributes[attr_name] = value; + } + + /// C++ write access to an attribute + XS_String& operator[](const XS_String& attr_name) + { + if (_stack.empty()) + return s_empty_attr; + + return _stack.top()._attributes[attr_name]; + } + + void set_content(const XS_String& s) + { + if (!_stack.empty()) + _stack.top()._content = EncodeXMLString(s.c_str()); + } + + // public for access in StackEntry + enum WRITESTATE { + NOTHING, /*PRE,*/ ATTRIBUTES, PRE_CLOSED, /*CONTENT,*/ POST + }; + +protected: + tofstream* _pofstream; + std::ostream& _out; + const XMLFormat&_format; + + typedef XMLNode::AttributeMap AttrMap; + + struct StackEntry { + XS_String _node_name; + AttrMap _attributes; + std::string _content; + WRITESTATE _state; + bool _children; + + StackEntry() : _state(NOTHING), _children(false) {} + }; + + std::stack<StackEntry> _stack; + + static XS_String s_empty_attr; + + void close_pre(StackEntry& entry) + { + _out << '>'; + + entry._state = PRE_CLOSED; + } + + void write_pre(StackEntry& entry) + { + if (_format._pretty >= PRETTY_LINEFEED) + _out << _format._endl; + + if (_format._pretty == PRETTY_INDENT) + for(size_t i=_stack.size(); --i>0; ) + _out << XML_INDENT_SPACE; + + _out << '<' << EncodeXMLString(entry._node_name); + //entry._state = PRE; + } + + void write_attributes(StackEntry& entry) + { + for(AttrMap::const_iterator it=entry._attributes.begin(); it!=entry._attributes.end(); ++it) + _out << ' ' << EncodeXMLString(it->first) << "="" << EncodeXMLString(it->second) << """; + + entry._state = ATTRIBUTES; + } + + void write_post(StackEntry& entry) + { + if (entry._state < ATTRIBUTES) + write_attributes(entry); + + if (entry._children || !entry._content.empty()) { + if (entry._state < PRE_CLOSED) + close_pre(entry); + + _out << entry._content; + //entry._state = CONTENT; + + if (_format._pretty>=PRETTY_LINEFEED && entry._content.empty()) + _out << _format._endl; + + if (_format._pretty==PRETTY_INDENT && entry._content.empty()) + for(size_t i=_stack.size(); --i>0; ) + _out << XML_INDENT_SPACE; + + _out << "</" << EncodeXMLString(entry._node_name) << ">"; + } else { + _out << "/>"; + } + + entry._state = POST; + } };
Added: trunk/reactos/base/applications/ibrowser/utility/xs-native.cpp URL: http://svn.reactos.org/svn/reactos/trunk/reactos/base/applications/ibrowser/... ============================================================================== --- trunk/reactos/base/applications/ibrowser/utility/xs-native.cpp (added) +++ trunk/reactos/base/applications/ibrowser/utility/xs-native.cpp Tue Aug 1 03:23:19 2006 @@ -1,0 +1,438 @@ + + // + // XML storage classes + // + // xs-native.cpp + // + // Copyright (c) 2006 Martin Fuchs martin-fuchs@gmx.net + // + + +/* + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef XS_NO_COMMENT +#define XS_NO_COMMENT // no #pragma comment(lib, ...) statements in .lib files to enable static linking +#endif + +//#include "xmlstorage.h" +#include <precomp.h> + + +#if !defined(XS_USE_EXPAT) && !defined(XS_USE_XERCES) + +namespace XMLStorage { + + +XMLReaderBase::~XMLReaderBase() +{ +} + + /// read XML stream into XML tree below _pos +void XMLReaderBase::read() +{ + if (!parse()) { + XMLError error; + + error._message = "XML parsing error"; + //error._line = ; + //error._column = ; + + _errors.push_back(error); + } + + finish_read(); +} + + +struct Buffer +{ + Buffer() + { + _buffer = (char*) malloc(BUFFER_LEN); + _len = BUFFER_LEN; + + reset(); + } + + ~Buffer() + { + free(_buffer); + } + + void reset() + { + _wptr = _buffer; + _buffer_str.erase(); + } + + void append(char c) + { + size_t wpos = _wptr-_buffer; + + if (wpos >= _len) { + _len <<= 1; + _buffer = (char*) realloc(_buffer, _len); + _wptr = _buffer + wpos; + } + + *_wptr++ = c; + } + + const std::string& str(bool utf8) // returns UTF-8 encoded buffer content + { + if (utf8) + _buffer_str.assign(_buffer, _wptr-_buffer); + else + _buffer_str = get_utf8(_buffer, _wptr-_buffer); + + return _buffer_str; + } + + size_t len() const + { + return _wptr - _buffer; + } + + bool has_CDEnd() const + { + //if (_wptr-_buffer < 3) + // return false; + + return !strncmp(_wptr-3, "]]>", 3); + } + + XS_String get_tag() const + { + const char* p = _buffer_str.c_str(); + + if (*p == '<') + ++p; + + if (*p == '/') + ++p; + + const char* q = p; + + if (*q == '?') + ++q; + + while(isxmlsym(*q)) + ++q; + +#ifdef XS_STRING_UTF8 + return XS_String(p, q-p); +#else + XS_String tag; + assign_utf8(tag, p, q-p); + return tag; +#endif + } + + /// read attributes and values + void get_attributes(XMLNode::AttributeMap& attributes) const + { + const char* p = _buffer_str.c_str(); + + // find end of tag name + if (*p == '<') + ++p; + + if (*p == '/') + ++p; + else if (*p == '?') + ++p; + + while(isxmlsym(*p)) + ++p; + + // read attributes from buffer + while(*p && *p!='>' && *p!='/') { + while(isspace((unsigned char)*p)) + ++p; + + const char* attr_name = p; + + while(isxmlsym(*p)) + ++p; + + if (*p != '=') + break; //@TODO error handling + + size_t attr_len = p - attr_name; + + if (*++p!='"' && *p!=''') + break; //@TODO error handling + + char delim = *p; + const char* value = ++p; + + while(*p && *p!=delim) + ++p; + + size_t value_len = p - value; + + if (*p) + ++p; // '"' + +#ifdef XS_STRING_UTF8 + XS_String name_str(attr_name, attr_len); + XS_String value_str(value, value_len); +#else + XS_String name_str, value_str; + assign_utf8(name_str, attr_name, attr_len); + assign_utf8(value_str, value, value_len); +#endif + + attributes[name_str] = DecodeXMLString(value_str); + } + } + +protected: + char* _buffer; + char* _wptr; + size_t _len; + std::string _buffer_str; // UF-8 encoded +}; + +bool XMLReaderBase::parse() +{ + Buffer buffer; + int c = get(); + bool in_comment = false; + + while(c != EOF) { + if (in_comment || c=='<') { + buffer.append(c); + + // read start or end tag + for(;;) { + c = get(); + + if (c == EOF) + break; + + buffer.append(c); + + if (c == '>') + break; + } + + const std::string& b = buffer.str(_utf8); + const char* str = b.c_str(); + + if (in_comment || !strncmp(str+1, "!--", 3)) { + // XML comment + DefaultHandler(b); + + if (strcmp(str+b.length()-3, "-->")) + in_comment = true; + else + in_comment = false; + + c = get(); + } else if (str[1] == '/') { + // end tag + + /*@TODO error handling + const XS_String& tag = buffer.get_tag(); + + if (tag != last_opened_tag) { + ERROR + } + */ + + EndElementHandler(); + + c = get(); + } else if (str[1] == '?') { + // XML declaration + const XS_String& tag = buffer.get_tag(); + + if (tag == "?xml") { + XMLNode::AttributeMap attributes; + buffer.get_attributes(attributes); + + const std::string& version = attributes.get("version"); + const std::string& encoding = attributes.get("encoding"); + + int standalone; + XMLNode::AttributeMap::const_iterator found = // const_cast for ISO C++ compatibility error of GCC + const_cast<const XMLNode::AttributeMap&>(attributes).find("standalone"); + if (found != attributes.end()) + standalone = !XS_icmp(found->second.c_str(), XS_TEXT("yes")); + else + standalone = -1; + + XmlDeclHandler(version.empty()?NULL:version.c_str(), encoding.empty()?NULL:encoding.c_str(), standalone); + + if (!encoding.empty() && !_stricmp(encoding.c_str(), "utf-8")) + _utf8 = true; + + c = eat_endl(); + } else if (tag == "?xml-stylesheet") { + XMLNode::AttributeMap attributes; + buffer.get_attributes(attributes); + + StyleSheet stylesheet(attributes.get("href"), attributes.get("type"), !XS_icmp(attributes.get("alternate"), XS_TEXT("yes"))); + stylesheet._title = attributes.get("title"); + stylesheet._media = attributes.get("media"); + stylesheet._charset = attributes.get("charset"); + + _format._stylesheets.push_back(stylesheet); + + c = eat_endl(); + } else { + DefaultHandler(b); + c = get(); + } + } else if (str[1] == '!') { + if (!strncmp(str+2, "DOCTYPE ", 8)) { + _format._doctype.parse(str+10); + + c = eat_endl(); + } else if (!strncmp(str+2, "[CDATA[", 7)) { + // parse <![CDATA[ ... ]]> strings + while(!buffer.has_CDEnd()) { + c = get(); + + if (c == EOF) + break; + + buffer.append(c); + } + + DefaultHandler(buffer.str(_utf8)); + + c = get(); + } + } else { + // start tag + const XS_String& tag = buffer.get_tag(); + + if (!tag.empty()) { + XMLNode::AttributeMap attributes; + buffer.get_attributes(attributes); + + StartElementHandler(tag, attributes); + + if (str[b.length()-2] == '/') + EndElementHandler(); + } + + c = get(); + } + } else { + buffer.append(c); + + // read white space + for(;;) { + // check for the encoding of the first line end + if (!_endl_defined) + if (c == '\n') { + _format._endl = "\n"; + _endl_defined = true; + } else if (c == '\r') { + _format._endl = "\r\n"; + _endl_defined = true; + } + + c = get(); + + if (c == EOF) + break; + + if (c == '<') + break; + + buffer.append(c); + } + + DefaultHandler(buffer.str(_utf8)); + } + + buffer.reset(); + } + + return true; +} + +int XMLReaderBase::eat_endl() +{ + int c = get(); + + if (c == '\r') + c = get(); + + if (c == '\n') + c = get(); + + return c; +} + + /// return current parser position as string +std::string XMLReaderBase::get_position() const +{ +/*@TODO display parser position in case of errors + int line = XML_GetCurrentLineNumber(_parser); + int column = XML_GetCurrentColumnNumber(_parser); + + std::ostringstream out; + out << "(" << line << ") : [column " << column << "]"; + + return out.str(); +*/ + return ""; +} + + +#ifdef XMLNODE_LOCATION + +XMLLocation XMLReaderBase::get_location() const +{ + return XMLLocation(); //@TODO XMLLocation for XS-native +} + +std::string XMLLocation::str() const +{ + return ""; //TODO +} + +#endif + + + /// store content, white space and comments +void XMLReaderBase::DefaultHandler(const std::string& s) +{ + _content.append(s); +} + + +} // namespace XMLStorage + +#endif // !defined(XS_USE_EXPAT) && !defined(XS_USE_XERCES)
Propchange: trunk/reactos/base/applications/ibrowser/utility/xs-native.cpp ------------------------------------------------------------------------------ svn:eol-style = native
Propchange: trunk/reactos/base/applications/ibrowser/utility/xs-native.cpp ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision