mirror of
https://github.com/reactos/reactos.git
synced 2025-02-25 01:39:30 +00:00
IBrowser: update XMLStorage library and remove Expat dependency
svn path=/trunk/; revision=23398
This commit is contained in:
parent
350cddb3d6
commit
8cb05b5ab7
10 changed files with 1822 additions and 477 deletions
|
@ -50,13 +50,14 @@ OBJECTS = \
|
|||
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
|
||||
|
|
|
@ -52,6 +52,7 @@ OBJECTS = \
|
|||
webchild.o \
|
||||
mainframe.o \
|
||||
favorites.o \
|
||||
xs-native.o \
|
||||
xmlstorage.o
|
||||
|
||||
LIBS = gdi32 comctl32 shell32 ole32 oleaut32 uuid
|
||||
|
@ -61,7 +62,7 @@ all: precomp.h.gch $(TARGET)
|
|||
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
|
||||
|
|
|
@ -1,22 +0,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.
|
|
@ -429,10 +429,10 @@ bool Favorites::read(LPCTSTR path)
|
|||
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 @@ void Favorites::write(LPCTSTR path) const
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ CFG=IBROWSER - WIN32 DEBUG
|
|||
# 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.cpp
|
|||
|
||||
SOURCE=.\utility\xmlstorage.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=".\utility\xs-native.cpp"
|
||||
# End Source File
|
||||
# End Group
|
||||
# Begin Group "resources"
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 @@ CFG=make_ibrowser - Win32 bjam
|
|||
!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 @@ CFG=make_ibrowser - Win32 bjam
|
|||
# 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 @@ CFG=make_ibrowser - Win32 bjam
|
|||
# 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 @@ CFG=make_ibrowser - Win32 bjam
|
|||
# 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 @@ CFG=make_ibrowser - Win32 bjam
|
|||
# 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 ""
|
||||
|
|
|
@ -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 @@ static std::string unescape(const char* s, char b='"', char e='"')
|
|||
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 @@ static std::string unescape(const char* s, int l, char b='"', char e='"')
|
|||
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 @@ const XMLNode* XMLNode::find_relative(const char* path) const
|
|||
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 @@ XMLNode* XMLNode::create_relative(const char* path)
|
|||
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,204 +277,14 @@ XMLNode* XMLNode::create_relative(const char* path)
|
|||
}
|
||||
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
LPCXSSTR s = str.c_str();
|
||||
LPXSSTR buffer = (LPXSSTR)alloca(5*sizeof(XS_CHAR)*XS_len(s)); // worst case. "&"
|
||||
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)
|
||||
|
@ -482,6 +310,12 @@ std::string EncodeXMLString(const XS_String& str)
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -490,8 +324,66 @@ std::string EncodeXMLString(const XS_String& str)
|
|||
#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
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/// decode XML string literals
|
||||
XS_String DecodeXMLString(const XS_String& str)
|
||||
{
|
||||
LPCXSSTR s = str.c_str();
|
||||
|
@ -517,6 +409,16 @@ XS_String DecodeXMLString(const XS_String& str)
|
|||
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 @@ void XMLNode::write_worker(std::ostream& out, int indent) const
|
|||
}
|
||||
|
||||
|
||||
/// 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 @@ void XMLNode::pretty_write_worker(std::ostream& out, int indent) const
|
|||
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 @@ void XMLNode::smart_write_worker(std::ostream& out, int indent) const
|
|||
out << '>';
|
||||
|
||||
if (_content.empty())
|
||||
out << '\n';
|
||||
out << format._endl;
|
||||
else
|
||||
out << _content;
|
||||
|
||||
|
@ -600,7 +522,7 @@ void XMLNode::smart_write_worker(std::ostream& out, int indent) const
|
|||
|
||||
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 @@ void XMLNode::smart_write_worker(std::ostream& out, int indent) const
|
|||
}
|
||||
|
||||
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
|
||||
|
|
File diff suppressed because it is too large
Load diff
438
reactos/base/applications/ibrowser/utility/xs-native.cpp
Normal file
438
reactos/base/applications/ibrowser/utility/xs-native.cpp
Normal file
|
@ -0,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)
|
Loading…
Reference in a new issue