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 \
|
webchild.o \
|
||||||
mainframe.o \
|
mainframe.o \
|
||||||
favorites.o \
|
favorites.o \
|
||||||
|
xs-native.o \
|
||||||
xmlstorage.o
|
xmlstorage.o
|
||||||
|
|
||||||
LIBS = gdi32 comctl32 shell32 ole32 uuid oleaut32
|
LIBS = gdi32 comctl32 shell32 ole32 uuid oleaut32
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX) libexpat.dll
|
$(TARGET): $(OBJECTS) $(PROGRAM)$(RES_SUFFIX)
|
||||||
$(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS))
|
$(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS))
|
||||||
|
|
||||||
ibrowser$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico
|
ibrowser$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico
|
||||||
|
|
|
@ -52,6 +52,7 @@ OBJECTS = \
|
||||||
webchild.o \
|
webchild.o \
|
||||||
mainframe.o \
|
mainframe.o \
|
||||||
favorites.o \
|
favorites.o \
|
||||||
|
xs-native.o \
|
||||||
xmlstorage.o
|
xmlstorage.o
|
||||||
|
|
||||||
LIBS = gdi32 comctl32 shell32 ole32 oleaut32 uuid
|
LIBS = gdi32 comctl32 shell32 ole32 oleaut32 uuid
|
||||||
|
@ -61,7 +62,7 @@ all: precomp.h.gch $(TARGET)
|
||||||
precomp.h.gch: *.h utility/*.h
|
precomp.h.gch: *.h utility/*.h
|
||||||
$(CXX) $(CFLAGS) precomp.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))
|
$(LINK) $(LFLAGS) -o $@ $^ $(addprefix -l,$(LIBS)) $(addprefix -l,$(DELAYIMPORTS))
|
||||||
|
|
||||||
ibrowser$(RES_SUFFIX): $(PROGRAM)_intres.rc res/*.bmp res/*.ico
|
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;
|
XMLDoc xbel;
|
||||||
|
|
||||||
if (!xbel.read(path))
|
if (!xbel.read(path))
|
||||||
if (xbel._last_error == XML_ERROR_NO_ELEMENTS)
|
/*@@ if (xbel._last_error == XML_ERROR_NO_ELEMENTS)
|
||||||
return false;
|
return false;
|
||||||
else
|
else */
|
||||||
MessageBox(0/*@@g_Globals._hwndDesktop*/, String(xbel._last_error_msg.c_str()),
|
MessageBox(0/*@@g_Globals._hwndDesktop*/, xbel._errors.str(),
|
||||||
TEXT("ROS Explorer - reading bookmark file"), MB_OK);
|
TEXT("ROS Explorer - reading bookmark file"), MB_OK);
|
||||||
|
|
||||||
const_XMLPos pos(&xbel);
|
const_XMLPos pos(&xbel);
|
||||||
|
@ -457,9 +457,9 @@ void Favorites::write(LPCTSTR path) const
|
||||||
super::write(pos);
|
super::write(pos);
|
||||||
pos.back();
|
pos.back();
|
||||||
|
|
||||||
xbel._header._doctype = "<!DOCTYPE xbel"
|
xbel._format._doctype._name = "xbel";
|
||||||
" PUBLIC \"+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML\"\n"
|
xbel._format._doctype._public = "//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML";
|
||||||
" \"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">";
|
xbel._format._doctype._system = "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd";
|
||||||
|
|
||||||
xbel.write(path);
|
xbel.write(path);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ CFG=IBROWSER - WIN32 DEBUG
|
||||||
# PROP AllowPerConfigDependencies 0
|
# PROP AllowPerConfigDependencies 0
|
||||||
# PROP Scc_ProjName ""
|
# PROP Scc_ProjName ""
|
||||||
# PROP Scc_LocalPath ""
|
# PROP Scc_LocalPath ""
|
||||||
CPP=cl.exe
|
CPP=cl.cmd
|
||||||
RSC=rc.exe
|
RSC=rc.exe
|
||||||
|
|
||||||
!IF "$(CFG)" == "ibrowser - Win32 Release"
|
!IF "$(CFG)" == "ibrowser - Win32 Release"
|
||||||
|
@ -199,6 +199,10 @@ SOURCE=.\utility\xmlstorage.cpp
|
||||||
|
|
||||||
SOURCE=.\utility\xmlstorage.h
|
SOURCE=.\utility\xmlstorage.h
|
||||||
# End Source File
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=".\utility\xs-native.cpp"
|
||||||
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Group "resources"
|
# Begin Group "resources"
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
<module name="ibrowser" type="win32gui" installbase="system32" installname="ibrowser.exe" allowwarnings ="true">
|
<module name="ibrowser" type="win32gui" installbase="system32" installname="ibrowser.exe" allowwarnings ="true">
|
||||||
<linkerflag>-fexceptions</linkerflag>
|
<linkerflag>-fexceptions</linkerflag>
|
||||||
<include base="ibrowser">.</include>
|
<include base="ibrowser">.</include>
|
||||||
<include base="ReactOS">include/expat</include>
|
|
||||||
<define name="__USE_W32API" />
|
<define name="__USE_W32API" />
|
||||||
<define name="UNICODE" />
|
<define name="UNICODE" />
|
||||||
<define name="WIN32" />
|
<define name="WIN32" />
|
||||||
|
@ -18,12 +17,12 @@
|
||||||
<library>ole32</library>
|
<library>ole32</library>
|
||||||
<library>oleaut32</library>
|
<library>oleaut32</library>
|
||||||
<library>shell32</library>
|
<library>shell32</library>
|
||||||
<library>expat</library>
|
|
||||||
<pch>precomp.h</pch>
|
<pch>precomp.h</pch>
|
||||||
<directory name="utility">
|
<directory name="utility">
|
||||||
<file>utility.cpp</file>
|
<file>utility.cpp</file>
|
||||||
<file>window.cpp</file>
|
<file>window.cpp</file>
|
||||||
<file>xmlstorage.cpp</file>
|
<file>xmlstorage.cpp</file>
|
||||||
|
<file>xs-native.cpp</file>
|
||||||
</directory>
|
</directory>
|
||||||
<file>ibrowser.cpp</file>
|
<file>ibrowser.cpp</file>
|
||||||
<file>favorites.cpp</file>
|
<file>favorites.cpp</file>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) External Target" 0x0106
|
# 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 This is not a valid makefile. To build this project using NMAKE,
|
||||||
!MESSAGE use the Export Makefile command and run
|
!MESSAGE use the Export Makefile command and run
|
||||||
!MESSAGE
|
!MESSAGE
|
||||||
|
@ -13,7 +13,7 @@ CFG=make_ibrowser - Win32 bjam
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
!MESSAGE
|
!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
|
||||||
!MESSAGE Possible choices for configuration are:
|
!MESSAGE Possible choices for configuration are:
|
||||||
!MESSAGE
|
!MESSAGE
|
||||||
|
@ -43,7 +43,7 @@ CFG=make_ibrowser - Win32 bjam
|
||||||
# PROP Use_Debug_Libraries 0
|
# PROP Use_Debug_Libraries 0
|
||||||
# PROP Output_Dir "Release"
|
# PROP Output_Dir "Release"
|
||||||
# PROP Intermediate_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 Rebuild_Opt "clean all"
|
||||||
# PROP Target_File "ibrowser.exe"
|
# PROP Target_File "ibrowser.exe"
|
||||||
# PROP Bsc_Name ""
|
# PROP Bsc_Name ""
|
||||||
|
@ -64,7 +64,7 @@ CFG=make_ibrowser - Win32 bjam
|
||||||
# PROP Use_Debug_Libraries 1
|
# PROP Use_Debug_Libraries 1
|
||||||
# PROP Output_Dir "Debug"
|
# PROP Output_Dir "Debug"
|
||||||
# PROP Intermediate_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 Rebuild_Opt "clean all"
|
||||||
# PROP Target_File "ibrowser.exe"
|
# PROP Target_File "ibrowser.exe"
|
||||||
# PROP Bsc_Name "msdevfilt -gcc -pipe "perl d:\tools\gSTLFilt.pl" make -f Makefile.MinGW UNICODE=0 DEBUG=1"
|
# 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 Use_Debug_Libraries 1
|
||||||
# PROP Output_Dir "UDebug"
|
# PROP Output_Dir "UDebug"
|
||||||
# PROP Intermediate_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 Rebuild_Opt "clean all"
|
||||||
# PROP Target_File "ibrowser.exe"
|
# PROP Target_File "ibrowser.exe"
|
||||||
# PROP Bsc_Name ""
|
# PROP Bsc_Name ""
|
||||||
|
@ -106,7 +106,7 @@ CFG=make_ibrowser - Win32 bjam
|
||||||
# PROP Use_Debug_Libraries 0
|
# PROP Use_Debug_Libraries 0
|
||||||
# PROP Output_Dir "URelease"
|
# PROP Output_Dir "URelease"
|
||||||
# PROP Intermediate_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 Rebuild_Opt "clean all"
|
||||||
# PROP Target_File "ibrowser.exe"
|
# PROP Target_File "ibrowser.exe"
|
||||||
# PROP Bsc_Name ""
|
# PROP Bsc_Name ""
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//
|
//
|
||||||
// xmlstorage.cpp
|
// 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 "xmlstorage.h"
|
||||||
#include <precomp.h>
|
#include <precomp.h>
|
||||||
|
|
||||||
|
|
||||||
// work around GCC's wide string constant bug
|
// work around GCC's wide string constant bug
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
const LPCXSSTR XMLStorage::XS_TRUE = XS_TEXT("true");
|
const LPCXSSTR XMLStorage::XS_EMPTY = XS_EMPTY_STR;
|
||||||
const LPCXSSTR XMLStorage::XS_FALSE = XS_TEXT("false");
|
const LPCXSSTR XMLStorage::XS_TRUE = XS_TRUE_STR;
|
||||||
const LPCXSSTR XMLStorage::XS_NUMBERFMT = XS_TEXT("%d");
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
namespace XMLStorage {
|
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);
|
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);
|
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;
|
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);
|
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
|
/// move XPath like to position in XML tree
|
||||||
bool XMLPos::go(const char* path)
|
bool XMLPos::go(const char* path)
|
||||||
|
@ -137,7 +155,7 @@ const XMLNode* XMLNode::find_relative(const char* path) const
|
||||||
if (slash == path)
|
if (slash == path)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
int l = slash? slash-path: strlen(path);
|
size_t l = slash? slash-path: strlen(path);
|
||||||
std::string comp(path, l);
|
std::string comp(path, l);
|
||||||
path += l;
|
path += l;
|
||||||
|
|
||||||
|
@ -198,7 +216,7 @@ XMLNode* XMLNode::create_relative(const char* path)
|
||||||
if (slash == path)
|
if (slash == path)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
int l = slash? slash-path: strlen(path);
|
size_t l = slash? slash-path: strlen(path);
|
||||||
std::string comp(path, l);
|
std::string comp(path, l);
|
||||||
path += l;
|
path += l;
|
||||||
|
|
||||||
|
@ -259,204 +277,14 @@ XMLNode* XMLNode::create_relative(const char* path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// read XML stream into XML tree below _pos
|
/// encode XML string literals
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string EncodeXMLString(const XS_String& str)
|
std::string EncodeXMLString(const XS_String& str)
|
||||||
{
|
{
|
||||||
LPCXSSTR s = str.c_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;
|
LPXSSTR o = buffer;
|
||||||
|
|
||||||
for(LPCXSSTR p=s; *p; ++p)
|
for(LPCXSSTR p=s; *p; ++p)
|
||||||
|
@ -482,6 +310,12 @@ std::string EncodeXMLString(const XS_String& str)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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;
|
*o++ = *p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,8 +324,66 @@ std::string EncodeXMLString(const XS_String& str)
|
||||||
#else
|
#else
|
||||||
return get_utf8(buffer, o-buffer);
|
return get_utf8(buffer, o-buffer);
|
||||||
#endif
|
#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)
|
XS_String DecodeXMLString(const XS_String& str)
|
||||||
{
|
{
|
||||||
LPCXSSTR s = str.c_str();
|
LPCXSSTR s = str.c_str();
|
||||||
|
@ -517,6 +409,16 @@ XS_String DecodeXMLString(const XS_String& str)
|
||||||
p += 5;
|
p += 5;
|
||||||
} else
|
} else
|
||||||
*o++ = *p;
|
*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
|
} else
|
||||||
*o++ = *p;
|
*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
|
/// 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--; )
|
for(int i=indent; i--; )
|
||||||
out << XML_INDENT_SPACE;
|
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)
|
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
|
||||||
out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
|
out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
|
||||||
|
|
||||||
if (!_children.empty() || !_content.empty()) {
|
if (!_children.empty()/*@@ || !_content.empty()*/) {
|
||||||
out << ">\n";
|
out << '>' << format._endl;
|
||||||
|
|
||||||
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
|
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--; )
|
for(int i=indent; i--; )
|
||||||
out << XML_INDENT_SPACE;
|
out << XML_INDENT_SPACE;
|
||||||
|
|
||||||
out << "</" << EncodeXMLString(*this) << ">\n";
|
out << "</" << EncodeXMLString(*this) << '>' << format._endl;
|
||||||
} else
|
} else
|
||||||
out << "/>\n";
|
out << "/>" << format._endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// write node with children tree to output stream using smart formating
|
/// 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())
|
if (_leading.empty())
|
||||||
for(int i=indent; i--; )
|
for(int i=indent; i--; )
|
||||||
|
@ -592,7 +514,7 @@ void XMLNode::smart_write_worker(std::ostream& out, int indent) const
|
||||||
out << '>';
|
out << '>';
|
||||||
|
|
||||||
if (_content.empty())
|
if (_content.empty())
|
||||||
out << '\n';
|
out << format._endl;
|
||||||
else
|
else
|
||||||
out << _content;
|
out << _content;
|
||||||
|
|
||||||
|
@ -600,7 +522,7 @@ void XMLNode::smart_write_worker(std::ostream& out, int indent) const
|
||||||
|
|
||||||
if (it != _children.end()) {
|
if (it != _children.end()) {
|
||||||
for(; it!=_children.end(); ++it)
|
for(; it!=_children.end(); ++it)
|
||||||
(*it)->smart_write_worker(out, indent+1);
|
(*it)->smart_write_worker(out, format, indent+1);
|
||||||
|
|
||||||
if (_end_leading.empty())
|
if (_end_leading.empty())
|
||||||
for(int i=indent; i--; )
|
for(int i=indent; i--; )
|
||||||
|
@ -614,10 +536,269 @@ void XMLNode::smart_write_worker(std::ostream& out, int indent) const
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_trailing.empty())
|
if (_trailing.empty())
|
||||||
out << '\n';
|
out << format._endl;
|
||||||
else
|
else
|
||||||
out << _trailing;
|
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
|
} // 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