ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

xmlstorage.h
Go to the documentation of this file.
00001 
00002  //
00003  // XML storage C++ classes version 1.3
00004  //
00005  // Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Martin Fuchs <martin-fuchs@gmx.net>
00006  //
00007 
00010 
00011 
00012 /*
00013 
00014   All rights reserved.
00015 
00016   Redistribution and use in source and binary forms, with or without
00017   modification, are permitted provided that the following conditions are met:
00018 
00019   * Redistributions of source code must retain the above copyright
00020     notice, this list of conditions and the following disclaimer.
00021   * Redistributions in binary form must reproduce the above copyright
00022     notice, this list of conditions and the following disclaimer in
00023     the documentation and/or other materials provided with the
00024     distribution.
00025 
00026   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00027   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00029   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00030   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00031   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00034   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00036   POSSIBILITY OF SUCH DAMAGE.
00037 
00038 */
00039 
00040 #ifndef _XMLSTORAGE_H
00041 
00042 
00043 #ifdef UNICODE
00044 #ifndef _UNICODE
00045 #define _UNICODE
00046 #endif
00047 #else
00048 #ifdef _UNICODE
00049 #define UNICODE
00050 #endif
00051 #endif
00052 
00053 #ifndef _WIN32
00054 #ifdef UNICODE
00055 #error no UNICODE build in Unix version available
00056 #endif
00057 #ifndef XS_STRING_UTF8
00058 #define XS_STRING_UTF8
00059 #endif
00060 #endif
00061 
00062 
00063 #if _MSC_VER>=1400 // VS2005 or higher
00064 #ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
00065 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES         1
00066 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT   1
00067 #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES           1
00068 #endif
00069 #endif
00070 
00071 
00072 #ifdef XS_USE_XERCES
00073 
00074 #ifndef UNICODE
00075 #ifndef XS_STRING_UTF8
00076 #define XS_STRING_UTF8
00077 #endif
00078 #endif
00079 
00080 #include <xercesc/parsers/SAXParser.hpp>
00081 #include <xercesc/sax/HandlerBase.hpp>
00082 
00083 using XERCES_CPP_NAMESPACE_QUALIFIER Locator;
00084 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParser;
00085 using XERCES_CPP_NAMESPACE_QUALIFIER HandlerBase;
00086 using XERCES_CPP_NAMESPACE_QUALIFIER InputSource;
00087 using XERCES_CPP_NAMESPACE_QUALIFIER AttributeList;
00088 using XERCES_CPP_NAMESPACE_QUALIFIER SAXParseException;
00089 
00090 typedef XMLCh XML_Char;
00091 
00092 #elif defined(XS_USE_EXPAT)
00093 
00094 #include <expat/expat.h>
00095 
00096 #endif
00097 
00098 
00099 #ifdef _MSC_VER
00100 #pragma warning(disable: 4786)
00101 
00102 #ifndef XS_NO_COMMENT
00103 
00104 #ifdef XS_USE_XERCES
00105 #ifdef _DEBUG
00106 #pragma comment(lib, "xerces-c_2D")
00107 #else
00108 #pragma comment(lib, "xerces-c_2")
00109 #endif
00110 #elif defined(XS_USE_EXPAT)
00111 #ifdef XML_STATIC
00112 #ifndef _DEBUG
00113 #pragma comment(lib, "libexpatMT")
00114 #endif
00115 #else
00116 #pragma comment(lib, "libexpat")
00117 #endif
00118 #endif
00119 
00120 #ifndef _STRING_DEFINED // _STRING_DEFINED only allowed if using xmlstorage.cpp embedded in the project
00121 #if defined(_DEBUG) && defined(_DLL)    // DEBUG version only supported with MSVCRTD
00122 #if _MSC_VER==1500
00123 #pragma comment(lib, "xmlstorage-vc9d")
00124 #elif _MSC_VER==1400
00125 #pragma comment(lib, "xmlstorage-vc8d")
00126 #else
00127 #pragma comment(lib, "xmlstorage-vc6d")
00128 #endif
00129 #else
00130 #ifdef _DLL
00131 #if _MSC_VER==1500
00132 #pragma comment(lib, "xmlstorage-vc9")
00133 #elif _MSC_VER==1400
00134 #pragma comment(lib, "xmlstorage-vc8")
00135 #else
00136 #pragma comment(lib, "xmlstorage-vc6")
00137 #endif
00138 #elif defined(_MT)
00139 #if _MSC_VER==1500
00140 #pragma comment(lib, "xmlstorage-vc9t")
00141 #elif _MSC_VER==1400
00142 #pragma comment(lib, "xmlstorage-vc8t")
00143 #else
00144 #pragma comment(lib, "xmlstorage-vc6t")
00145 #endif
00146 #else
00147  // -ML is no more supported since VS2005.
00148 #pragma comment(lib, "xmlstorage-vc6l")
00149 #endif
00150 #endif
00151 #endif // _STRING_DEFINED
00152 
00153 #endif // XS_NO_COMMENT
00154 
00155 #endif // _MSC_VER
00156 
00157 
00158 #ifdef _WIN32
00159 
00160 #include <windows.h>    // for LPCTSTR
00161 #include <tchar.h>
00162 #include <malloc.h>
00163 
00164 #ifndef _MSC_VER
00165 #include <stdio.h>  // vsnprintf(), snprintf()
00166 #endif
00167 
00168 #else // _WIN32
00169 
00170 #include <wchar.h>
00171 #include <stdlib.h>
00172 #include <string.h> // strcasecmp()
00173 #include <stdarg.h>
00174 
00175 typedef char CHAR;
00176 #ifdef _WCHAR_T_DEFINED
00177 #define __wchar_t wchar_t
00178 #endif
00179 
00180 typedef __wchar_t WCHAR;
00181 typedef unsigned char UCHAR;
00182 typedef char* LPSTR;
00183 typedef const char* LPCSTR;
00184 typedef WCHAR* LPWSTR;
00185 typedef const WCHAR* LPCWSTR;
00186 
00187 #ifndef UNICODE
00188 #define TEXT(x) x
00189 typedef char TCHAR;
00190 typedef unsigned char _TUCHAR;
00191 typedef CHAR* PTSTR;
00192 typedef CHAR* LPTSTR;
00193 typedef const CHAR* LPCTSTR;
00194 
00195 #define _ttoi atoi
00196 #define _tfopen fopen
00197 #define _tcstod strtod
00198 #define _tcslen strlen
00199 #define _tcsstr strstr
00200 #define _snprintf snprintf
00201 #define _sntprintf snprintf
00202 #define _vsnprintf vsnprintf
00203 #define _vsntprintf vsnprintf
00204 #define _stricmp strcasecmp
00205 #define _tcsicmp strcasecmp
00206 #define strnicmp strncasecmp
00207 #define _tcsnicmp strncasecmp
00208 #endif // UNICODE
00209 
00210 #endif // _WIN32
00211 
00212 #ifdef __BORLANDC__
00213 #define _stricmp stricmp
00214 #endif
00215 
00216 
00217 #include <fstream>
00218 #include <sstream>
00219 #include <string>
00220 #include <stack>
00221 #include <list>
00222 #include <map>
00223 
00224 
00225 #ifndef BUFFER_LEN
00226 #define BUFFER_LEN 2048
00227 #endif
00228 
00229 
00230 namespace XMLStorage {
00231 
00232 
00233 #ifndef XS_String
00234 
00235 #ifdef XS_STRING_UTF8
00236 #define XS_CHAR char
00237 #define XS_TEXT(x) x
00238 #define LPXSSTR LPSTR
00239 #define LPCXSSTR LPCSTR
00240 #define XS_cmp strcmp
00241 #define XS_icmp _stricmp
00242 #define XS_ncmp strncmp
00243 #define XS_nicmp strnicmp
00244 #define XS_toi atoi
00245 #define XS_tod strtod
00246 #define XS_len strlen
00247 #define XS_snprintf _snprintf
00248 #define XS_vsnprintf _vsnprintf
00249 #define XS_strstr strstr
00250 #else
00251 #define XS_CHAR TCHAR
00252 #define XS_TEXT(x) TEXT(x)
00253 #define LPXSSTR LPTSTR
00254 #define LPCXSSTR LPCTSTR
00255 #define XS_cmp _tcscmp
00256 #define XS_icmp _tcsicmp
00257 #define XS_ncmp _tcsncmp
00258 #define XS_nicmp _tcsnicmp
00259 #define XS_toi _ttoi
00260 #define XS_tod _tcstod
00261 #define XS_len _tcslen
00262 #define XS_snprintf _sntprintf
00263 #define XS_vsnprintf _vsntprintf
00264 #define XS_strstr _tcsstr
00265 #endif
00266 
00267 #ifndef COUNTOF
00268 #if _MSC_VER>=1400
00269 #define COUNTOF _countof
00270 #else
00271 #define COUNTOF(b) (sizeof(b)/sizeof(b[0]))
00272 #endif
00273 #endif
00274 
00275 
00276 extern const char* get_xmlsym_end_utf8(const char* p);
00277 
00278 
00279 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
00280 
00281 #define XS_String String
00282 
00283 #else // _STRING_DEFINED, !XS_STRING_UTF8
00284 
00286 
00287 struct XS_String
00288 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00289  : public std::wstring
00290 #else
00291  : public std::string
00292 #endif
00293 {
00294 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00295     typedef std::wstring super;
00296 #else
00297     typedef std::string super;
00298 #endif
00299 
00300     XS_String() {}
00301 
00302     XS_String(LPCXSSTR s) {if (s) super::assign(s);}
00303     XS_String(LPCXSSTR s, size_t l) : super(s, l) {}
00304 
00305     XS_String(const super& other) : super(other) {}
00306     XS_String(const XS_String& other) : super(other) {}
00307 
00308 #ifdef _WIN32
00309 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00310     XS_String(LPCSTR s) {assign(s);}
00311     XS_String(LPCSTR s, size_t l) {assign(s, l);}
00312     XS_String(const std::string& s) {assign(s.c_str());}
00313     XS_String& operator=(LPCSTR s) {assign(s); return *this;}
00314     void assign(LPCSTR s) {if (s) {size_t bl=strlen(s); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, bl, b, bl));} else erase();}
00315     void assign(LPCSTR s, size_t l) {if (s) {size_t bl=l; LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, bl));} else erase();}
00316 #else
00317     XS_String(LPCWSTR s) {assign(s);}
00318     XS_String(LPCWSTR s, size_t l) {assign(s, l);}
00319     XS_String(const std::wstring& ws) {assign(ws.c_str());}
00320     XS_String& operator=(LPCWSTR s) {assign(s); return *this;}
00321 #ifdef XS_STRING_UTF8
00322     void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();}
00323     void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();}
00324 #else // if !UNICODE && !XS_STRING_UTF8
00325     void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();}
00326     void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();}
00327 #endif
00328 #endif
00329 #endif // _WIN32
00330 
00331 #ifdef __ISSD_H
00332 //  XS_String(const _ISSD RString& s) {assign(s.c_str());}
00333 //  void assign(const _ISSD RString& s) {assign(s.c_str());}
00334     XS_String& operator=(const _ISSD RString& s) {assign(s); return *this;}
00335 #endif
00336 
00337 #ifdef XS_STRING_UTF8
00338     void assign(const XS_String& s) {assign(s.c_str());}
00339 #endif
00340 
00341     XS_String& operator=(LPCXSSTR s) {if (s) super::assign(s); else erase(); return *this;}
00342     XS_String& operator=(const super& s) {super::assign(s); return *this;}
00343     void assign(LPCXSSTR s) {super::assign(s);}
00344     void assign(LPCXSSTR s, size_t l) {super::assign(s, l);}
00345 
00346     operator LPCXSSTR() const {return c_str();}
00347 
00348 #ifdef _WIN32
00349 #ifdef XS_STRING_UTF8
00350     operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_UTF8, 0, c_str(), bl, b, bl));}
00351 #elif defined(UNICODE)
00352     operator std::string() const {size_t bl=length(); LPSTR b=(LPSTR)alloca(bl); return std::string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), bl, b, bl, 0, 0));}
00353 #else
00354     operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), (int)bl, b, (int)bl));}
00355 #endif
00356 #endif
00357 
00358     XS_String& printf(LPCXSSTR fmt, ...)
00359     {
00360         va_list l;
00361         XS_CHAR b[BUFFER_LEN];
00362 
00363         va_start(l, fmt);
00364         super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
00365         va_end(l);
00366 
00367         return *this;
00368     }
00369 
00370     XS_String& vprintf(LPCXSSTR fmt, va_list l)
00371     {
00372         XS_CHAR b[BUFFER_LEN];
00373 
00374         super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
00375 
00376         return *this;
00377     }
00378 
00379     XS_String& appendf(LPCXSSTR fmt, ...)
00380     {
00381         va_list l;
00382         XS_CHAR b[BUFFER_LEN];
00383 
00384         va_start(l, fmt);
00385         super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
00386         va_end(l);
00387 
00388         return *this;
00389     }
00390 
00391     XS_String& vappendf(LPCXSSTR fmt, va_list l)
00392     {
00393         XS_CHAR b[BUFFER_LEN];
00394 
00395         super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
00396 
00397         return *this;
00398     }
00399 };
00400 
00401 #endif // _STRING_DEFINED, !XS_STRING_UTF8
00402 
00403 #endif // XS_String
00404 
00405 
00406 #define XS_EMPTY_STR XS_TEXT("")
00407 #define XS_TRUE_STR XS_TEXT("true")
00408 #define XS_FALSE_STR XS_TEXT("false")
00409 #define XS_INTFMT_STR XS_TEXT("%d")
00410 #define XS_FLOATFMT_STR XS_TEXT("%f")
00411 
00412 #define XS_KEY_STR XS_TEXT("key")
00413 #define XS_VALUE_STR XS_TEXT("value")
00414 #define XS_PROPERTY_STR XS_TEXT("property")
00415 
00416  // work around GCC's wide string constant bug
00417 #ifdef __GNUC__
00418 extern const LPCXSSTR XS_EMPTY;
00419 extern const LPCXSSTR XS_TRUE;
00420 extern const LPCXSSTR XS_FALSE;
00421 extern const LPCXSSTR XS_INTFMT;
00422 extern const LPCXSSTR XS_FLOATFMT;
00423 #else
00424 #define XS_EMPTY XS_EMPTY_STR
00425 #define XS_TRUE XS_TRUE_STR
00426 #define XS_FALSE XS_FALSE_STR
00427 #define XS_INTFMT XS_INTFMT_STR
00428 #define XS_FLOATFMT XS_FLOATFMT_STR
00429 #endif
00430 
00431 extern const XS_String XS_KEY;
00432 extern const XS_String XS_VALUE;
00433 extern const XS_String XS_PROPERTY;
00434 
00435 #define CDATA_START "<![CDATA["
00436 #define CDATA_END "]]>"
00437 
00438 
00439 #ifndef XS_STRING_UTF8
00440 
00441  // from UTF-8 to XS internal string encoding
00442 inline void assign_utf8(XS_String& s, const char* str, size_t lutf8)
00443 {
00444 #ifdef UNICODE
00445     LPTSTR buffer = (LPTSTR)alloca(sizeof(TCHAR)*lutf8);
00446     int l = MultiByteToWideChar(CP_UTF8, 0, str, (int)lutf8, buffer, (int)lutf8);
00447 #else
00448     LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*lutf8);
00449     int l = MultiByteToWideChar(CP_UTF8, 0, str, (int)lutf8, wbuffer, (int)lutf8);
00450 
00451     int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
00452     l = WideCharToMultiByte(CP_ACP, 0, wbuffer, l, buffer, bl, 0, 0);
00453 #endif
00454 
00455     s.assign(buffer, l);
00456 }
00457 
00458  // from UTF-8 to XS internal string encoding
00459 inline void assign_utf8(XS_String& s, const char* str)
00460 {
00461     assign_utf8(s, str, strlen(str));
00462 }
00463 
00464  // from XS internal string encoding to UTF-8
00465 inline std::string get_utf8(LPCTSTR s, size_t l)
00466 {
00467 #ifdef UNICODE
00468     size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
00469     l = WideCharToMultiByte(CP_UTF8, 0, s, (int)l, buffer, (int)bl, 0, 0);
00470 #else
00471     LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l);
00472     l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l);
00473 
00474     size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
00475     l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0);
00476 #endif
00477 
00478     return std::string(buffer, l);
00479 }
00480 
00481 #ifdef UNICODE
00482  // from XS internal string encoding to UTF-8
00483 inline std::string get_utf8(const char* s, size_t l)
00484 {
00485     LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l);
00486     l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l);
00487 
00488     size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
00489     l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0);
00490 
00491     return std::string(buffer, l);
00492 }
00493 #endif
00494 
00495  // from XS internal string encoding to UTF-8
00496 inline std::string get_utf8(const XS_String& s)
00497 {
00498     return get_utf8(s.c_str(), s.length());
00499 }
00500 
00501 #endif // XS_STRING_UTF8
00502 
00503 extern std::string EncodeXMLString(const XS_String& str, bool cdata=false);
00504 extern XS_String DecodeXMLString(const std::string& str);
00505 
00506 
00507 #ifdef __GNUC__
00508 #include <ext/stdio_filebuf.h>
00509 #define FILE_FILEBUF __gnu_cxx::stdio_filebuf<char>
00510 #elif defined(_MSC_VER)
00511 #define FILE_FILEBUF std::filebuf
00512 #endif
00513 
00514 #ifdef FILE_FILEBUF
00515 
00517 struct FileHolder
00518 {
00519     FileHolder(LPCTSTR path, LPCTSTR mode)
00520     {
00521 //@@ _MS_VER: temporarily needed for the ReactOS build environment
00522 #if defined(__STDC_WANT_SECURE_LIB__) && defined(_MS_VER)   // secure CRT functions using VS 2005
00523         if (_tfopen_s(&_pfile, path, mode) != 0)
00524             _pfile = NULL;
00525 #else
00526         _pfile = _tfopen(path, mode);
00527 #endif
00528     }
00529 
00530     ~FileHolder()
00531     {
00532         if (_pfile)
00533             fclose(_pfile);
00534     }
00535 
00536 protected:
00537     FILE*   _pfile;
00538 };
00539 
00541 struct tifstream : public std::istream, FileHolder
00542 {
00543     typedef std::istream super;
00544 
00545     tifstream(LPCTSTR path)
00546      :  super(&_buf),
00547         FileHolder(path, TEXT("rb")),   // binary mode is important for XMLReader::read_buffer() with MinGW libraries
00548 #ifdef __GNUC__
00549         _buf(_pfile, std::ios::in)
00550 #else
00551         _buf(_pfile)
00552 #endif
00553     {
00554         if (!_pfile)
00555             setstate(badbit);
00556     }
00557 
00558 protected:
00559     FILE_FILEBUF _buf;
00560 };
00561 
00563 struct tofstream : public std::ostream, FileHolder
00564 {
00565     typedef std::ostream super;
00566 
00567     tofstream(LPCTSTR path)
00568      :  super(&_buf),
00569         FileHolder(path, TEXT("wb")),
00570 #ifdef __GNUC__
00571         _buf(_pfile, std::ios::out)
00572 #else
00573         _buf(_pfile)
00574 #endif
00575     {
00576         if (!_pfile)
00577             setstate(badbit);
00578     }
00579 
00580     ~tofstream()
00581     {
00582         flush();
00583     }
00584 
00585 protected:
00586     FILE_FILEBUF _buf;
00587 };
00588 
00589 #else // FILE_FILEBUF
00590 
00591 #ifdef UNICODE
00592 #error UNICODE not supported for this platform
00593 #endif
00594 
00595 struct tifstream : public std::ifstream
00596 {
00597     typedef std::ifstream super;
00598 
00599     tifstream(const char* path)
00600      : super(path, std::ios::in|std::ios::binary)
00601     {
00602     }
00603 };
00604 
00605 struct tofstream : public std::ofstream
00606 {
00607     typedef std::ofstream super;
00608 
00609     tofstream(const char* path)
00610      : super(path, std::ios::out|std::ios::binary)
00611     {
00612     }
00613 };
00614 
00615 #endif
00616 
00617 
00618  // write XML files with 2 spaces indenting
00619 #define XML_INDENT_SPACE "  "
00620 
00621 
00622 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
00623 
00624 #if defined(XML_UNICODE)/*Expat*/ || defined(XS_USE_XERCES)/*Xerces*/   // Are Expat/Xerces XML strings UTF-16 encoded?
00625 typedef XS_String String_from_XML_Char;
00626 
00627 #elif defined(XS_STRING_UTF8)
00628 typedef XS_String String_from_XML_Char;
00629 
00630 #else
00631 
00633 struct String_from_XML_Char : public XS_String
00634 {
00635     String_from_XML_Char(const XML_Char* str)
00636     {
00637         assign_utf8(*this, str);
00638     }
00639 };
00640 
00641 #endif
00642 
00643 #endif // defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
00644 
00645 
00646 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00647 
00648  // optimization for faster UNICODE/ASCII string comparison without temporary A/U conversion
00649 inline bool operator==(const XS_String& s1, const char* s2)
00650 {
00651     LPCWSTR p = s1;
00652     const unsigned char* q = (const unsigned char*)s2;
00653 
00654     while(*p && *q)
00655         if (*p++ != *q++)
00656             return false;
00657 
00658     return *p == *q;
00659 };
00660 
00661 #endif
00662 
00663 
00665 struct XMLError
00666 {
00667     XMLError()
00668      :  _line(0),
00669         _column(0),
00670         _error_code(0)
00671     {
00672     }
00673 
00674     std::string str() const;
00675     friend std::ostream& operator<<(std::ostream&, const XMLError& err);
00676 
00677     XS_String _message;
00678     XS_String _systemId;
00679     int _line;
00680     int _column;
00681     int _error_code;
00682 };
00683 
00685 struct XMLErrorList : public std::list<XMLError>
00686 {
00687     XS_String str() const;
00688 };
00689 
00690 
00691 #ifdef XMLNODE_LOCATION
00692 
00693 struct XMLLocation
00694 {
00695     XMLLocation()
00696      :  _pdisplay_path(NULL),
00697         _line(0),
00698         _column(0)
00699     {
00700     }
00701 
00702     XMLLocation(const char* display_path, int line, int column)
00703      :  _pdisplay_path(display_path),
00704         _line(line),
00705         _column(column)
00706     {
00707     }
00708 
00709     std::string str() const;
00710 
00711 protected:
00712     const char* _pdisplay_path; // character pointer for fast reference
00713     int _line;
00714     int _column;
00715 };
00716 #endif
00717 
00718 
00719 enum PRETTY_FLAGS {
00720     PRETTY_PLAIN    = 0,
00721     PRETTY_LINEFEED = 1,
00722     PRETTY_INDENT   = 2
00723 };
00724 
00725 
00727 struct StyleSheet
00728 {
00729     std::string _href;      // CDATA #REQUIRED
00730     std::string _type;      // CDATA #REQUIRED
00731     std::string _title;     // CDATA #IMPLIED
00732     std::string _media;     // CDATA #IMPLIED
00733     std::string _charset;   // CDATA #IMPLIED
00734     bool        _alternate; // (yes|no) "no"
00735 
00736     StyleSheet() : _alternate(false) {}
00737 
00738     StyleSheet(const std::string& href, const std::string& type="text/xsl", bool alternate=false)
00739      :  _href(href),
00740         _type(type),
00741         _alternate(alternate)
00742     {
00743     }
00744 
00745     bool empty() const {return _href.empty();}
00746     void print(std::ostream& out) const;
00747 };
00748 
00750 struct StyleSheetList : public std::list<StyleSheet>
00751 {
00752     void set(const StyleSheet& stylesheet)
00753     {
00754         clear();
00755         push_back(stylesheet);
00756     }
00757 };
00758 
00759 
00761 struct DocType
00762 {
00763     std::string _name;
00764 
00765      // External Document Types are noted, but not parsed.
00766     std::string _public;
00767     std::string _system;
00768 
00769      // Internal DTDs are not supported.
00770 
00771     void parse(const char* str);
00772     bool empty() const {return _name.empty();}
00773 };
00774 
00776 struct XMLFormat
00777 {
00778     XMLFormat(PRETTY_FLAGS pretty=PRETTY_INDENT, const std::string& xml_version="1.0", const std::string& encoding="utf-8", const DocType& doctype=DocType())
00779      :  _pretty(pretty),
00780         _endl("\n"),
00781         _version(xml_version),
00782         _encoding(encoding),
00783         _doctype(doctype),
00784         _standalone(-1)
00785     {
00786     }
00787 
00788     void print_header(std::ostream& out, bool lf=true) const;
00789 
00790     PRETTY_FLAGS _pretty;
00791     const char* _endl;      // line ending string: "\n" or "\r\n"
00792 
00793     std::string _version;
00794     std::string _encoding;
00795 
00796     DocType     _doctype;
00797 
00798     StyleSheetList _stylesheets;
00799 
00800 //  std::string _additional;
00801 
00802     int     _standalone;
00803 };
00804 
00805 
00806 enum WRITE_MODE {
00807     FORMAT_PLAIN,       
00808     FORMAT_SMART,       
00809     FORMAT_ORIGINAL,    
00810     FORMAT_PRETTY       
00811 };
00812 
00813 
00814 struct XMLNode;
00815 
00816 struct XPathElement
00817 {
00818     XPathElement() : _child_idx(-1) {}
00819 
00820     XPathElement(const XS_String& child_name, int child_idx=-1)
00821      :  _child_name(child_name), _child_idx(child_idx) {}
00822 
00823     XPathElement(const XS_String& child_name, int child_idx, const XS_String& attr_name, const XS_String& attr_value)
00824      :  _child_name(child_name), _child_idx(child_idx),
00825         _attr_name(attr_name), _attr_value(attr_value)
00826     {
00827     }
00828 
00829     XS_String   _child_name;
00830     int         _child_idx;
00831 
00832     XS_String   _attr_name;
00833     XS_String   _attr_value;
00834 
00835     const char* parse(const char* path);
00836 
00837     XMLNode* find(XMLNode* node) const;
00838     const XMLNode* const_find(const XMLNode* node) const;
00839 
00840     bool    matches(const XMLNode& node, int& n) const;
00841 };
00842 
00843 struct XPath : std::list<XPathElement>
00844 {
00845     XPath() : _absolute(false) {}
00846     XPath(const char* path) {init(path);}
00847     XPath(const std::string path) {init(path.c_str());}
00848 
00849     void    init(const char* path);
00850 
00851     bool    _absolute;
00852 };
00853 
00854 
00856 struct XMLNode : public XS_String
00857 {
00858 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
00859 
00860      // optimized read access without temporary A/U conversion when using ASCII attribute names
00861     struct AttributeMap : public std::map<XS_String, XS_String>
00862     {
00863         typedef std::map<XS_String, XS_String> super;
00864 
00865         const_iterator find(const char* x) const
00866         {
00867             for(const_iterator it=begin(); it!=end(); ++it)
00868                 if (it->first == x)
00869                     return it;
00870 
00871             return end();
00872         }
00873 
00874         const_iterator find(const key_type& x) const
00875         {
00876             return super::find(x);
00877         }
00878 
00879         iterator find(const key_type& x)
00880         {
00881             return super::find(x);
00882         }
00883 
00884         XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
00885         {
00886             const_iterator found = find(x);
00887 
00888             if (found != end())
00889                 return found->second;
00890             else
00891                 return def;
00892         }
00893     };
00894 #else
00895 
00896     struct AttributeMap : public std::map<XS_String, XS_String>
00897     {
00898         XS_String get(const char* x, LPCXSSTR def=XS_EMPTY_STR) const
00899         {
00900             const_iterator found = find(x);
00901 
00902             if (found != end())
00903                 return found->second;
00904             else
00905                 return def;
00906         }
00907     };
00908 #endif
00909 
00911     struct Children : public std::list<XMLNode*>
00912     {
00913         typedef std::list<XMLNode*> super;
00914 
00915         Children()
00916         {
00917         }
00918 
00919         Children(Children& other)
00920         {
00921             for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
00922                 push_back(*it);
00923         }
00924 
00925         void assign(Children& other)
00926         {
00927             clear();
00928             move(other);
00929         }
00930 
00931         void move(Children& other)
00932         {
00933             for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
00934                 push_back(*it);
00935 
00936             other.reset();
00937         }
00938 
00939         Children& operator=(Children& other)
00940         {
00941             assign(other);
00942             return *this;
00943         }
00944 
00945         void copy(const Children& other)
00946         {
00947             for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
00948                 push_back(new XMLNode(**it));
00949         }
00950 
00951         void clear()
00952         {
00953             while(!empty()) {
00954                 XMLNode* node = back();
00955                 pop_back();
00956 
00957                 node->clear();
00958                 delete node;
00959             }
00960         }
00961 
00962         bool remove(XMLNode* node)
00963         {
00964             for(iterator it=begin(); it!=end(); ++it)
00965                 if (*it == node) {
00966                     erase(it);
00967                     return true;
00968                 }
00969 
00970             return false;
00971         }
00972 
00973     private:
00974         void reset()
00975         {
00976             super::clear();
00977         }
00978     };
00979 
00980      // access to protected class members for XMLPos and XMLReader
00981     friend struct XMLPos;
00982     friend struct const_XMLPos;
00983     friend struct XMLReaderBase;
00984     friend struct XPathElement;
00985 
00986     XMLNode(const XS_String& name)
00987      :  XS_String(name),
00988         _cdata_content(false)
00989     {
00990     }
00991 
00992     XMLNode(const XS_String& name, const std::string& leading)
00993      :  XS_String(name),
00994         _leading(leading),
00995         _cdata_content(false)
00996     {
00997     }
00998 
00999     XMLNode(const XMLNode& other)
01000      :  XS_String(other),
01001         _attributes(other._attributes),
01002         _leading(other._leading),
01003         _content(other._content),
01004         _end_leading(other._end_leading),
01005         _trailing(other._trailing),
01006 #ifdef XMLNODE_LOCATION
01007         _location(other._location),
01008 #endif
01009         _cdata_content(false)
01010     {
01011         for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
01012             _children.push_back(new XMLNode(**it));
01013     }
01014 
01015     enum COPY_FLAGS {COPY_NOCHILDREN};
01016 
01017     XMLNode(const XMLNode& other, COPY_FLAGS copy_no_children)
01018      :  XS_String(other),
01019         _attributes(other._attributes),
01020         _leading(other._leading),
01021         _content(other._content),
01022         _end_leading(other._end_leading),
01023         _trailing(other._trailing),
01024 #ifdef XMLNODE_LOCATION
01025         _location(other._location),
01026 #endif
01027         _cdata_content(false)
01028     {
01029 //      assert(copy_no_children==COPY_NOCHILDREN);
01030     }
01031 
01032     virtual ~XMLNode()
01033     {
01034         while(!_children.empty()) {
01035             delete _children.back();
01036             _children.pop_back();
01037         }
01038     }
01039 
01040     void clear()
01041     {
01042         _leading.erase();
01043         _content.erase();
01044         _end_leading.erase();
01045         _trailing.erase();
01046 
01047         _attributes.clear();
01048         _children.clear();
01049 
01050         XS_String::erase();
01051     }
01052 
01053     XMLNode& operator=(const XMLNode& other)
01054     {
01055         _children.clear();
01056         _children.copy(other._children);
01057 
01058         _attributes = other._attributes;
01059 
01060         _leading = other._leading;
01061         _content = other._content;
01062         _end_leading = other._end_leading;
01063         _trailing = other._trailing;
01064 
01065         return *this;
01066     }
01067 
01069     void add_child(XMLNode* child)
01070     {
01071         _children.push_back(child);
01072     }
01073 
01075     void remove_children(const XS_String& name)
01076     {
01077         Children::iterator it, next=_children.begin();
01078 
01079         while((it=next++) != _children.end())
01080             if (**it == name)
01081                 _children.erase(it);
01082     }
01083 
01085     void put(const XS_String& attr_name, const XS_String& value)
01086     {
01087         _attributes[attr_name] = value;
01088     }
01089 
01091     XS_String& operator[](const XS_String& attr_name)
01092     {
01093         return _attributes[attr_name];
01094     }
01095 
01097     template<typename T> XS_String get(const T& attr_name, LPCXSSTR def=XS_EMPTY_STR) const
01098     {
01099         AttributeMap::const_iterator found = _attributes.find(attr_name);
01100 
01101         if (found != _attributes.end())
01102             return found->second;
01103         else
01104             return def;
01105     }
01106 
01108     void erase(const XS_String& attr_name)
01109     {
01110         _attributes.erase(attr_name);
01111     }
01112 
01114     XS_String subvalue(const XS_String& child_name, const XS_String& attr_name, int n=0) const
01115     {
01116         const XMLNode* node = XPathElement(child_name, n).const_find(this);
01117 
01118         if (node)
01119             return node->get(attr_name);
01120         else
01121             return XS_String();
01122     }
01123 
01125     XS_String& subvalue(const XS_String& child_name, const XS_String& attr_name, int n=0)
01126     {
01127         XMLNode* node = XPathElement(child_name, n).find(this);
01128 
01129         if (!node) {
01130             node = new XMLNode(child_name);
01131             add_child(node);
01132         }
01133 
01134         return (*node)[attr_name];
01135     }
01136 
01137 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
01138 
01139     XS_String subvalue(const char* child_name, const char* attr_name, int n=0) const
01140     {
01141         const XMLNode* node = XPathElement(child_name, n).const_find(this);
01142 
01143         if (node)
01144             return node->get(attr_name);
01145         else
01146             return XS_String();
01147     }
01148 
01150     XS_String& subvalue(const char* child_name, const XS_String& attr_name, int n=0)
01151     {
01152         XMLNode* node = XPathElement(child_name, n).find(this);
01153 
01154         if (!node) {
01155             node = new XMLNode(child_name);
01156             add_child(node);
01157         }
01158 
01159         return (*node)[attr_name];
01160     }
01161 #endif
01162 
01163     const Children& get_children() const
01164     {
01165         return _children;
01166     }
01167 
01168     Children& get_children()
01169     {
01170         return _children;
01171     }
01172 
01173     const AttributeMap& get_attributes() const
01174     {
01175         return _attributes;
01176     }
01177 
01178     AttributeMap& get_attributes()
01179     {
01180         return _attributes;
01181     }
01182 
01184     XS_String get_content() const
01185     {
01186         return DecodeXMLString(_content);
01187     }
01188 
01190     XS_String get_sub_content(const XPath& xpath) const
01191     {
01192         const XMLNode* node = find_relative(xpath);
01193 
01194         if (node)
01195             return node->get_content();
01196         else
01197             return XS_EMPTY_STR;
01198     }
01199 
01201     void set_content(const XS_String& s, bool cdata=false)
01202     {
01203         _content.assign(EncodeXMLString(s.c_str(), cdata));
01204     }
01205 
01207     bool set_sub_content(const XPath& xpath, const XS_String& s, bool cdata=false)
01208     {
01209         XMLNode* node = create_relative(xpath);
01210 
01211         if (node) {
01212             node->set_content(s, cdata);
01213             return true;
01214         } else
01215             return false;
01216     }
01217 
01218 #ifdef XMLNODE_LOCATION
01219     const XMLLocation& get_location() const {return _location;}
01220 #endif
01221 
01223     bool write(std::ostream& out, const XMLFormat& format, WRITE_MODE mode=FORMAT_SMART, int indent=0) const
01224     {
01225         switch(mode) {
01226           case FORMAT_PLAIN:
01227             plain_write_worker(out);
01228             break;
01229 
01230           case FORMAT_PRETTY:
01231             pretty_write_worker(out, format, indent);
01232             break;
01233 
01234           case FORMAT_ORIGINAL:
01235             original_write_worker(out);
01236             break;
01237 
01238           default:  // FORMAT_SMART
01239             smart_write_worker(out, format, indent);
01240         }
01241 
01242         return out.good();
01243     }
01244 
01246     int count(const XPath& xpath) const
01247     {
01248         return count(xpath.begin(), xpath.end());
01249     }
01250 
01252     int count(XPath::const_iterator from, const XPath::const_iterator& to) const;
01253 
01255     bool filter(const XPath& xpath, XMLNode& target) const;
01256 
01258     const XMLNode* find_relative(const XPath& xpath) const;
01259 
01261     XMLNode* find_relative(const XPath& xpath);
01262 
01263     XMLNode* get_first_child() const
01264     {
01265         if (!_children.empty())
01266             return _children.front();
01267         else
01268             return NULL;
01269     }
01270 
01271 protected:
01272     Children _children;
01273     AttributeMap _attributes;
01274 
01275     std::string _leading;       // UTF-8 encoded
01276     std::string _content;       // UTF-8 and entity encoded, may contain CDATA sections; decode with DecodeXMLString()
01277     std::string _end_leading;   // UTF-8 encoded
01278     std::string _trailing;      // UTF-8 encoded
01279 
01280 #ifdef XMLNODE_LOCATION
01281     XMLLocation _location;
01282 #endif
01283 
01284     bool    _cdata_content;
01285 
01287     XMLNode* create_relative(const XPath& xpath);
01288 
01290     XMLNode* filter(XPath::const_iterator from, const XPath::const_iterator& to) const;
01291 
01292     void    original_write_worker(std::ostream& out) const;
01293     void    plain_write_worker(std::ostream& out) const;
01294     void    pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
01295     void    smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
01296 };
01297 
01298 
01300 struct XMLChildrenFilter
01301 {
01302     XMLChildrenFilter(XMLNode::Children& children, const XS_String& name)
01303      :  _begin(children.begin(), children.end(), name),
01304         _end(children.end(), children.end(), name)
01305     {
01306     }
01307 
01308     XMLChildrenFilter(XMLNode* node, const XS_String& name)
01309      :  _begin(node->get_children().begin(), node->get_children().end(), name),
01310         _end(node->get_children().end(), node->get_children().end(), name)
01311     {
01312     }
01313 
01315     struct iterator
01316     {
01317         typedef XMLNode::Children::iterator BaseIterator;
01318         typedef iterator myType;
01319 
01320         iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
01321          :  _cur(begin),
01322             _end(end),
01323             _filter_name(filter_name)
01324         {
01325             search_next();
01326         }
01327 
01328         operator BaseIterator()
01329         {
01330             return _cur;
01331         }
01332 
01333         const XMLNode* operator*() const
01334         {
01335             return *_cur;
01336         }
01337 
01338         XMLNode* operator*()
01339         {
01340             return *_cur;
01341         }
01342 
01343         myType& operator++()
01344         {
01345             ++_cur;
01346             search_next();
01347 
01348             return *this;
01349         }
01350 
01351         myType operator++(int)
01352         {
01353             myType ret = *this;
01354 
01355             ++_cur;
01356             search_next();
01357 
01358             return ret;
01359         }
01360 
01361         bool operator==(const myType& other) const
01362         {
01363             return _cur == other._cur;
01364         }
01365 
01366         bool operator!=(const myType& other) const
01367         {
01368             return _cur != other._cur;
01369         }
01370 
01371     protected:
01372         BaseIterator    _cur;
01373         BaseIterator    _end;
01374         XS_String   _filter_name;
01375 
01376         void search_next()
01377         {
01378             while(_cur!=_end && **_cur!=_filter_name)
01379                 ++_cur;
01380         }
01381     };
01382 
01383     iterator begin()
01384     {
01385         return _begin;
01386     }
01387 
01388     iterator end()
01389     {
01390         return _end;
01391     }
01392 
01393 protected:
01394     iterator    _begin;
01395     iterator    _end;
01396 };
01397 
01398 
01400 struct const_XMLChildrenFilter
01401 {
01402     const_XMLChildrenFilter(const XMLNode::Children& children, const XS_String& name)
01403      :  _begin(children.begin(), children.end(), name),
01404         _end(children.end(), children.end(), name)
01405     {
01406     }
01407 
01408     const_XMLChildrenFilter(const XMLNode* node, const XS_String& name)
01409      :  _begin(node->get_children().begin(), node->get_children().end(), name),
01410         _end(node->get_children().end(), node->get_children().end(), name)
01411     {
01412     }
01413 
01415     struct const_iterator
01416     {
01417         typedef XMLNode::Children::const_iterator BaseIterator;
01418         typedef const_iterator myType;
01419 
01420         const_iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
01421          :  _cur(begin),
01422             _end(end),
01423             _filter_name(filter_name)
01424         {
01425             search_next();
01426         }
01427 
01428         operator BaseIterator()
01429         {
01430             return _cur;
01431         }
01432 
01433         const XMLNode* operator*() const
01434         {
01435             return *_cur;
01436         }
01437 
01438         myType& operator++()
01439         {
01440             ++_cur;
01441             search_next();
01442 
01443             return *this;
01444         }
01445 
01446         myType operator++(int)
01447         {
01448             myType ret = *this;
01449 
01450             ++_cur;
01451             search_next();
01452 
01453             return ret;
01454         }
01455 
01456         bool operator==(const myType& other) const
01457         {
01458             return _cur == other._cur;
01459         }
01460 
01461         bool operator!=(const myType& other) const
01462         {
01463             return _cur != other._cur;
01464         }
01465 
01466     protected:
01467         BaseIterator    _cur;
01468         BaseIterator    _end;
01469         XS_String   _filter_name;
01470 
01471         void search_next()
01472         {
01473             while(_cur!=_end && **_cur!=_filter_name)
01474                 ++_cur;
01475         }
01476     };
01477 
01478     const_iterator begin()
01479     {
01480         return _begin;
01481     }
01482 
01483     const_iterator end()
01484     {
01485         return _end;
01486     }
01487 
01488 protected:
01489     const_iterator  _begin;
01490     const_iterator  _end;
01491 };
01492 
01493 
01495 struct XMLPos
01496 {
01497     XMLPos(XMLNode* root)
01498      :  _root(root),
01499         _cur(root)
01500     {
01501     }
01502 
01503     XMLPos(const XMLPos& other)
01504      :  _root(other._root),
01505         _cur(other._cur)
01506     {   // don't copy _stack
01507     }
01508 
01509     XMLPos(XMLNode* node, const XS_String& name)
01510      :  _root(node),
01511         _cur(node)
01512     {
01513         smart_create(name);
01514     }
01515 
01516     XMLPos(XMLNode* node, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
01517      :  _root(node),
01518         _cur(node)
01519     {
01520         smart_create(name, attr_name, attr_value);
01521     }
01522 
01523     XMLPos(const XMLPos& other, const XS_String& name)
01524      :  _root(other._root),
01525         _cur(other._cur)
01526     {
01527         smart_create(name);
01528     }
01529 
01530     XMLPos(const XMLPos& other, const XS_String& name, const XS_String& attr_name, const XS_String& attr_value)
01531      :  _root(other._root),
01532         _cur(other._cur)
01533     {
01534         smart_create(name, attr_name, attr_value);
01535     }
01536 
01538     XMLNode& cur()
01539     {
01540         return *_cur;
01541     }
01542 
01543     const XMLNode& cur() const
01544     {
01545         return *_cur;
01546     }
01547 
01549     operator const XMLNode*() const {return _cur;}
01550     operator XMLNode*() {return _cur;}
01551 
01552     const XMLNode* operator->() const {return _cur;}
01553     XMLNode* operator->() {return _cur;}
01554 
01555     const XMLNode& operator*() const {return *_cur;}
01556     XMLNode& operator*() {return *_cur;}
01557 
01559     XS_String get(const XS_String& attr_name, LPCXSSTR def=XS_EMPTY_STR) const
01560     {
01561         return _cur->get(attr_name, def);
01562     }
01563 
01565     void put(const XS_String& attr_name, const XS_String& value)
01566     {
01567         _cur->put(attr_name, value);
01568     }
01569 
01571     template<typename T> XS_String get(const T& attr_name) const {return (*_cur)[attr_name];}
01572     XS_String& operator[](const XS_String& attr_name) {return (*_cur)[attr_name];}
01573     const XS_String& operator[](const XS_String& attr_name) const {return (*_cur)[attr_name];}
01574 
01576     void add_down(XMLNode* child)
01577     {
01578         _cur->add_child(child);
01579         go_to(child);
01580     }
01581 
01583     bool back()
01584     {
01585         if (!_stack.empty()) {
01586             _cur = _stack.top();
01587             _stack.pop();
01588             return true;
01589         } else
01590             return false;
01591     }
01592 
01594     bool go_down()
01595     {
01596         XMLNode* node = _cur->get_first_child();
01597 
01598         if (node) {
01599             go_to(node);
01600             return true;
01601         } else
01602             return false;
01603     }
01604 
01606     bool go_down(const XS_String& child_name, int n=0)
01607     {
01608         XMLNode* node = XPathElement(child_name, n).find(_cur);
01609 
01610         if (node) {
01611             go_to(node);
01612             return true;
01613         } else
01614             return false;
01615     }
01616 
01618     bool iterate(const XS_String& child_name, size_t& cnt)
01619     {
01620         XMLNode* node = XPathElement(child_name, cnt).find(_cur);
01621 
01622         if (node) {
01623             go_to(node);
01624             ++cnt;
01625             return true;
01626         } else
01627             return false;
01628     }
01629 
01631     bool go(const XPath& xpath);
01632 
01634     bool create_relative(const XPath& xpath)
01635     {
01636         XMLNode* node = _cur->create_relative(xpath);
01637         if (!node)
01638             return false;   // invalid path specified
01639 
01640         go_to(node);
01641         return true;
01642     }
01643 
01645     void create(const XS_String& name)
01646     {
01647         add_down(new XMLNode(name));
01648     }
01649 
01651     void create_node_content(const XS_String& node_name, const XS_String& content)
01652     {
01653         XMLNode* pNode = new XMLNode(node_name);
01654             pNode->set_content(content);
01655         _cur->add_child(pNode);
01656     }
01657 
01659     void smart_create(const XS_String& child_name)
01660     {
01661         XMLNode* node = XPathElement(child_name).find(_cur);
01662 
01663         if (node)
01664             go_to(node);
01665         else
01666             add_down(new XMLNode(child_name));
01667     }
01668 
01670     void smart_create(const XS_String& child_name, const XS_String& attr_name, const XS_String& attr_value)
01671     {
01672         XMLNode* node = XPathElement(child_name, 0, attr_name, attr_value).find(_cur);
01673 
01674         if (node)
01675             go_to(node);
01676         else {
01677             node = new XMLNode(child_name);
01678             add_down(node);
01679             (*node)[attr_name] = attr_value;
01680         }
01681     }
01682 
01684     int count(const XPath& xpath) const
01685     {
01686         return _cur->count(xpath);
01687     }
01688 
01690     int filter(const XPath& xpath, XMLNode& target) const
01691     {
01692         return _cur->filter(xpath, target);
01693     }
01694 
01695 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
01696 
01697     bool go_down(const char* child_name, int n=0)
01698     {
01699         XMLNode* node = XPathElement(child_name, n).find(_cur);
01700 
01701         if (node) {
01702             go_to(node);
01703             return true;
01704         } else
01705             return false;
01706     }
01707 
01709     void create(const char* child_name)
01710     {
01711         add_down(new XMLNode(child_name));
01712     }
01713 
01715     void smart_create(const char* child_name)
01716     {
01717         XMLNode* node = XPathElement(child_name).find(_cur);
01718 
01719         if (node)
01720             go_to(node);
01721         else
01722             add_down(new XMLNode(child_name));
01723     }
01724 
01726     template<typename T, typename U>
01727     void smart_create(const char* child_name, const T& attr_name, const U& attr_value)
01728     {
01729         XMLNode* node = XPathElement(child_name, 0, attr_name, attr_value).find(_cur);
01730 
01731         if (node)
01732             go_to(node);
01733         else {
01734             node = new XMLNode(child_name);
01735             add_down(node);
01736             (*node)[attr_name] = attr_value;
01737         }
01738     }
01739 #endif
01740 
01742     bool delete_this()
01743     {
01744         if (!_stack.empty()) {
01745             XMLNode* pLast = _stack.top();
01746 
01747             if (pLast->_children.remove(_cur)) {
01748                 _cur = _stack.top();
01749                 return true;
01750             }
01751         }
01752 
01753         return false;
01754     }
01755 
01757     void remove_children(const XS_String& name)
01758     {
01759         _cur->remove_children(name);
01760     }
01761 
01763     void erase(const XS_String& attr_name)
01764     {
01765         _cur->erase(attr_name);
01766     }
01767 
01768     XS_String& str() {return *_cur;}
01769     const XS_String& str() const {return *_cur;}
01770 
01771      // property (key/value pair) setter functions
01772     void set_property(const XS_String& key, int value, const XS_String& name=XS_PROPERTY);
01773     void set_property(const XS_String& key, double value, const XS_String& name=XS_PROPERTY);
01774     void set_property(const XS_String& key, const XS_String& value, const XS_String& name=XS_PROPERTY);
01775     void set_property(const XS_String& key, const struct XMLBool& value, const XS_String& name=XS_PROPERTY);
01776 
01777     void set_property(const XS_String& key, const char* value, const XS_String& name=XS_PROPERTY)
01778         {set_property(key, XS_String(value), name);}
01779 
01780 protected:
01781     friend struct const_XMLPos; // access to _root
01782 
01783     XMLNode* _root;
01784     XMLNode* _cur;
01785     std::stack<XMLNode*> _stack;
01786 
01788     void go_to(XMLNode* child)
01789     {
01790         _stack.push(_cur);
01791         _cur = child;
01792     }
01793 };
01794 
01795 
01797 struct const_XMLPos
01798 {
01799     const_XMLPos(const XMLNode* root)
01800      :  _root(root),
01801         _cur(root)
01802     {
01803     }
01804 
01805     const_XMLPos(const const_XMLPos& other)
01806      :  _root(other._root),
01807         _cur(other._cur)
01808     {   // don't copy _stack
01809     }
01810 
01811     const_XMLPos(const XMLPos& other)
01812      :  _root(other._root),
01813         _cur(other._cur)
01814     {   // don't copy _stack
01815     }
01816 
01818     const XMLNode& cur() const
01819     {
01820         return *_cur;
01821     }
01822 
01824     operator const XMLNode*() const {return _cur;}
01825 
01826     const XMLNode* operator->() const {return _cur;}
01827 
01828     const XMLNode& operator*() const {return *_cur;}
01829 
01831     XS_String get(const XS_String& attr_name) const
01832     {
01833         return _cur->get(attr_name);
01834     }
01835 
01837     template<typename T> XS_String get(const T& attr_name) const {return _cur->get(attr_name);}
01838     XS_String operator[](const XS_String& attr_name) const {return _cur->get(attr_name);}
01839 
01841     bool back()
01842     {
01843         if (!_stack.empty()) {
01844             _cur = _stack.top();
01845             _stack.pop();
01846             return true;
01847         } else
01848             return false;
01849     }
01850 
01852     bool go_down()
01853     {
01854         const XMLNode* node = _cur->get_first_child();
01855 
01856         if (node) {
01857             go_to(node);
01858             return true;
01859         } else
01860             return false;
01861     }
01862 
01864     bool go_down(const XS_String& child_name, int n=0)
01865     {
01866         const XMLNode* node = XPathElement(child_name, n).const_find(_cur);
01867 
01868         if (node) {
01869             go_to(node);
01870             return true;
01871         } else
01872             return false;
01873     }
01874 
01876     bool iterate(const XS_String& child_name, size_t& cnt)
01877     {
01878         const XMLNode* node = XPathElement(child_name, cnt).const_find(_cur);
01879 
01880         if (node) {
01881             go_to(node);
01882             ++cnt;
01883             return true;
01884         } else
01885             return false;
01886     }
01887 
01889     bool go(const XPath& xpath);
01890 
01891 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
01892 
01893     bool go_down(const char* child_name, int n=0)
01894     {
01895         const XMLNode* node = XPathElement(child_name, n).const_find(_cur);
01896 
01897         if (node) {
01898             go_to(node);
01899             return true;
01900         } else
01901             return false;
01902     }
01903 #endif
01904 
01905     const XS_String& str() const {return *_cur;}
01906 
01907 protected:
01908     const XMLNode* _root;
01909     const XMLNode* _cur;
01910     std::stack<const XMLNode*> _stack;
01911 
01913     void go_to(const XMLNode* child)
01914     {
01915         _stack.push(_cur);
01916         _cur = child;
01917     }
01918 };
01919 
01920 
01922 struct XMLBool
01923 {
01924     XMLBool(bool value=false)
01925      :  _value(value)
01926     {
01927     }
01928 
01929     XMLBool(LPCXSSTR value, bool def=false)
01930     {
01931         if (value && *value)//@@ also handle white space and return def instead of false
01932             _value = !XS_icmp(value, XS_TRUE);
01933         else
01934             _value = def;
01935     }
01936 
01937     XMLBool(const XMLNode* node, const XS_String& attr_name, bool def=false)
01938     {
01939         const XS_String& value = node->get(attr_name);
01940 
01941         if (!value.empty())
01942             _value = !XS_icmp(value.c_str(), XS_TRUE);
01943         else
01944             _value = def;
01945     }
01946 
01947     operator bool() const
01948     {
01949         return _value;
01950     }
01951 
01952     bool operator!() const
01953     {
01954         return !_value;
01955     }
01956 
01957     operator LPCXSSTR() const
01958     {
01959         return _value? XS_TRUE: XS_FALSE;
01960     }
01961 
01962 protected:
01963     bool    _value;
01964 
01965 private:
01966     void operator=(const XMLBool&); // disallow assignment operations
01967 };
01968 
01970 struct XMLBoolRef
01971 {
01972     XMLBoolRef(XMLNode* node, const XS_String& attr_name, bool def=false)
01973      :  _ref((*node)[attr_name])
01974     {
01975         if (_ref.empty())
01976             assign(def);
01977     }
01978 
01979     operator bool() const
01980     {
01981         return !XS_icmp(_ref.c_str(), XS_TRUE);
01982     }
01983 
01984     bool operator!() const
01985     {
01986         return XS_icmp(_ref.c_str(), XS_TRUE)? true: false;
01987     }
01988 
01989     XMLBoolRef& operator=(bool value)
01990     {
01991         assign(value);
01992 
01993         return *this;
01994     }
01995 
01996     void assign(bool value)
01997     {
01998         _ref.assign(value? XS_TRUE: XS_FALSE);
01999     }
02000 
02001     void toggle()
02002     {
02003         assign(!operator bool());
02004     }
02005 
02006 protected:
02007     XS_String& _ref;
02008 };
02009 
02010 
02012 struct XMLInt
02013 {
02014     XMLInt(int value)
02015      :  _value(value)
02016     {
02017     }
02018 
02019     XMLInt(LPCXSSTR value, int def=0)
02020     {
02021         if (value && *value)//@@ also handle white space and return def instead of 0
02022             _value = XS_toi(value);
02023         else
02024             _value = def;
02025     }
02026 
02027     XMLInt(const XMLNode* node, const XS_String& attr_name, int def=0)
02028     {
02029         const XS_String& value = node->get(attr_name);
02030 
02031         if (!value.empty())
02032             _value = XS_toi(value.c_str());
02033         else
02034             _value = def;
02035     }
02036 
02037     operator int() const
02038     {
02039         return _value;
02040     }
02041 
02042     operator XS_String() const
02043     {
02044         XS_CHAR buffer[32];
02045         XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, _value);
02046         return XS_String(buffer);
02047     }
02048 
02049 protected:
02050     int _value;
02051 
02052 private:
02053     void operator=(const XMLInt&); // disallow assignment operations
02054 };
02055 
02057 struct XMLIntRef
02058 {
02059     XMLIntRef(XMLNode* node, const XS_String& attr_name, int def=0)
02060      :  _ref((*node)[attr_name])
02061     {
02062         if (_ref.empty())
02063             assign(def);
02064     }
02065 
02066     XMLIntRef& operator=(int value)
02067     {
02068         assign(value);
02069 
02070         return *this;
02071     }
02072 
02073     operator int() const
02074     {
02075         return XS_toi(_ref.c_str());
02076     }
02077 
02078     void assign(int value)
02079     {
02080         XS_CHAR buffer[32];
02081         XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, value);
02082         _ref.assign(buffer);
02083     }
02084 
02085 protected:
02086     XS_String& _ref;
02087 };
02088 
02089 
02091 struct XMLDouble
02092 {
02093     XMLDouble(double value)
02094      :  _value(value)
02095     {
02096     }
02097 
02098     XMLDouble(LPCXSSTR value, double def=0.)
02099     {
02100         LPTSTR end;
02101 
02102         if (value && *value)//@@ also handle white space and return def instead of 0
02103             _value = XS_tod(value, &end);
02104         else
02105             _value = def;
02106     }
02107 
02108     XMLDouble(const XMLNode* node, const XS_String& attr_name, double def=0.)
02109     {
02110         LPTSTR end;
02111         const XS_String& value = node->get(attr_name);
02112 
02113         if (!value.empty())
02114             _value = XS_tod(value.c_str(), &end);
02115         else
02116             _value = def;
02117     }
02118 
02119     operator double() const
02120     {
02121         return _value;
02122     }
02123 
02124     operator XS_String() const
02125     {
02126         XS_CHAR buffer[32];
02127         XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, _value);
02128         return XS_String(buffer);
02129     }
02130 
02131 protected:
02132     double _value;
02133 
02134 private:
02135     void operator=(const XMLDouble&); // disallow assignment operations
02136 };
02137 
02139 struct XMLDoubleRef
02140 {
02141     XMLDoubleRef(XMLNode* node, const XS_String& attr_name, double def=0.)
02142      :  _ref((*node)[attr_name])
02143     {
02144         if (_ref.empty())
02145             assign(def);
02146     }
02147 
02148     XMLDoubleRef& operator=(double value)
02149     {
02150         assign(value);
02151 
02152         return *this;
02153     }
02154 
02155     operator double() const
02156     {
02157         LPTSTR end;
02158         return XS_tod(_ref.c_str(), &end);
02159     }
02160 
02161     void assign(double value)
02162     {
02163         XS_CHAR buffer[32];
02164         XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, value);
02165         _ref.assign(buffer);
02166     }
02167 
02168 protected:
02169     XS_String& _ref;
02170 };
02171 
02172 
02174 struct XMLString
02175 {
02176     XMLString(const XS_String& value)
02177      :  _value(value)
02178     {
02179     }
02180 
02181     XMLString(LPCXSSTR value, LPCXSSTR def=XS_EMPTY)
02182     {
02183         if (value && *value)
02184             _value = value;
02185         else
02186             _value = def;
02187     }
02188 
02189     XMLString(const XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
02190     {
02191         const XS_String& value = node->get(attr_name);
02192 
02193         if (!value.empty())
02194             _value = value;
02195         else
02196             _value = def;
02197     }
02198 
02199     operator const XS_String&() const
02200     {
02201         return _value;
02202     }
02203 
02204     const XS_String& c_str() const
02205     {
02206         return _value;
02207     }
02208 
02209 protected:
02210     XS_String   _value;
02211 
02212 private:
02213     void operator=(const XMLString&); // disallow assignment operations
02214 };
02215 
02217 struct XMLStringRef
02218 {
02219     XMLStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
02220      :  _ref((*node)[attr_name])
02221     {
02222         if (_ref.empty())
02223             assign(def);
02224     }
02225 
02226     XMLStringRef(const XS_String& node_name, XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
02227      :  _ref(node->subvalue(node_name, attr_name))
02228     {
02229         if (_ref.empty())
02230             assign(def);
02231     }
02232 
02233     XMLStringRef& operator=(const XS_String& value)
02234     {
02235         assign(value);
02236 
02237         return *this;
02238     }
02239 
02240     operator const XS_String&() const
02241     {
02242         return _ref;
02243     }
02244 
02245     void assign(const XS_String& value)
02246     {
02247         _ref.assign(value);
02248     }
02249 
02250 protected:
02251     XS_String& _ref;
02252 };
02253 
02254 
02255  // read option (for example configuration) values from XML node attributes
02256 template<typename T>
02257     inline void read_option(T& var, const_XMLPos& cfg, LPCXSSTR key)
02258     {
02259         const XS_String& val = cfg.get(key);
02260 
02261         if (!val.empty())
02262             var = val;
02263     }
02264 
02265  // read integer option values from XML node attributes
02266 template<>
02267     inline void read_option(int& var, const_XMLPos& cfg, LPCXSSTR key)
02268     {
02269         const XS_String& val = cfg.get(key);
02270 
02271         if (!val.empty())
02272             var = XS_toi(val.c_str());
02273     }
02274 
02275 
02276 inline void XMLPos::set_property(const XS_String& key, int value, const XS_String& name)
02277 {
02278     smart_create(name, XS_KEY, key);
02279         XMLIntRef(_cur, XS_VALUE) = value;
02280     back();
02281 }
02282 
02283 inline void XMLPos::set_property(const XS_String& key, double value, const XS_String& name)
02284 {
02285     smart_create(name, XS_KEY, key);
02286         XMLDoubleRef(_cur, XS_VALUE) = value;
02287     back();
02288 }
02289 
02290 inline void XMLPos::set_property(const XS_String& key, const XS_String& value, const XS_String& name)
02291 {
02292     smart_create(name, XS_KEY, key);
02293         put(XS_VALUE, value);
02294     back();
02295 }
02296 
02297 inline void XMLPos::set_property(const XS_String& key, const XMLBool& value, const XS_String& name)
02298 {
02299     smart_create(name, XS_KEY, key);
02300         XMLBoolRef(_cur, XS_VALUE) = value;
02301     back();
02302 }
02303 
02304 
02306 struct XMLProperty {
02307     XMLProperty(const XMLNode* node)
02308      :  _key(node->get(XS_KEY)),
02309         _value(node->get(XS_VALUE))
02310     {
02311     }
02312 
02313     XS_String   _key;
02314     XS_String   _value;
02315 };
02316 
02317 
02319 struct XMLPropertyReader
02320 {
02321     XMLPropertyReader(const XMLNode::Children& children)
02322      :  _filter(children, XS_PROPERTY),
02323         _begin(_filter.begin(), _filter.end()),
02324         _end(_filter.end(), _filter.end())
02325     {
02326     }
02327 
02328     XMLPropertyReader(const XMLNode* node)
02329      :  _filter(node, XS_PROPERTY),
02330         _begin(_filter.begin(), _filter.end()),
02331         _end(_filter.end(), _filter.end())
02332     {
02333     }
02334 
02336     struct const_iterator
02337     {
02338         typedef const_XMLChildrenFilter::const_iterator BaseIterator;
02339         typedef const_iterator myType;
02340 
02341         const_iterator(BaseIterator begin, BaseIterator end)
02342          :  _cur(begin),
02343             _end(end)
02344         {
02345         }
02346 
02347         operator BaseIterator()
02348         {
02349             return _cur;
02350         }
02351 
02352         XMLProperty operator*() const
02353         {
02354             return XMLProperty(*_cur);
02355         }
02356 
02357         const XMLNode* get_node() const
02358         {
02359             return *_cur;
02360         }
02361 
02362         myType& operator++()
02363         {
02364             ++_cur;
02365 
02366             return *this;
02367         }
02368 
02369         myType operator++(int)
02370         {
02371             myType ret = *this;
02372 
02373             ++_cur;
02374 
02375             return ret;
02376         }
02377 
02378         bool operator==(const myType& other) const
02379         {
02380             return _cur == other._cur;
02381         }
02382 
02383         bool operator!=(const myType& other) const
02384         {
02385             return _cur != other._cur;
02386         }
02387 
02388     protected:
02389         BaseIterator    _cur;
02390         BaseIterator    _end;
02391     };
02392 
02393     const_iterator begin()
02394     {
02395         return _begin;
02396     }
02397 
02398     const_iterator end()
02399     {
02400         return _end;
02401     }
02402 
02403 protected:
02404     const_XMLChildrenFilter _filter;
02405 
02406     const_iterator  _begin;
02407     const_iterator  _end;
02408 };
02409 
02410 
02411 #ifdef _MSC_VER
02412 #pragma warning(disable: 4355)
02413 #endif
02414 
02416 struct XMLReaderBase
02417 #ifdef XS_USE_XERCES
02418  : public HandlerBase
02419 #endif
02420 {
02421 #ifdef XS_USE_XERCES
02422 
02423     XMLReaderBase(XMLNode* node, InputSource* source, bool adoptSource=false);
02424     virtual ~XMLReaderBase();
02425 
02426     void read();
02427 
02428 protected:
02429     SAXParser*  _parser;
02430     InputSource* _source;
02431     bool        _deleteSource;
02432 
02433     virtual void XMLDecl(const XMLCh* const versionStr, const XMLCh* const encodingStr,
02434                          const XMLCh* const standaloneStr, const XMLCh* const actualEncodingStr);
02435 
02436      // Handlers for the SAX DocumentHandler interface
02437     virtual void setDocumentLocator(const Locator* const locator);
02438     virtual void startElement(const XMLCh* const name, AttributeList& attributes);
02439     virtual void endElement(const XMLCh* const name);
02440     virtual void characters(const XMLCh* const chars, const unsigned int length);
02441     virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length);
02442 
02443      // Handlers for the SAX ErrorHandler interface
02444     virtual void error(const SAXParseException& e);
02445     virtual void fatalError(const SAXParseException& e);
02446     virtual void warning(const SAXParseException& e);
02447     virtual void resetErrors();
02448 
02449 #elif defined(XS_USE_EXPAT) // !XS_USE_XERCES
02450 
02451     XMLReaderBase(XMLNode* node);
02452     virtual ~XMLReaderBase();
02453 
02454 protected:
02455     XML_Parser  _parser;
02456 
02457     static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone=-1);
02458     static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts);
02459     static void XMLCALL XML_EndElementHandler(void* userData, const XML_Char* name);
02460     static void XMLCALL XML_DefaultHandler(void* userData, const XML_Char* s, int len);
02461 
02462     static std::string get_expat_error_string(XML_Error error_code);
02463 
02464 #else // XS_USE_EXPAT
02465 
02466     XMLReaderBase(XMLNode* node)
02467      :  _pos(node),
02468         _endl_defined(false),
02469         _utf8(false)
02470     {
02471         _last_tag = TAG_NONE;
02472     }
02473 
02474     virtual ~XMLReaderBase();
02475 
02476     bool    parse();
02477 
02478 #endif
02479 
02480 public:
02481 #ifndef XS_USE_XERCES
02482     void read();
02483 
02484     std::string get_position() const;
02485 #endif
02486     const XMLFormat& get_format() const {return _format;}
02487     const char* get_endl() const {return _endl_defined? _format._endl: "\n";}
02488 
02489     const XMLErrorList& get_errors() const {return _errors;}
02490     const XMLErrorList& get_warnings() const {return _warnings;}
02491 
02492     void clear_errors() {_errors.clear(); _warnings.clear();}
02493 
02494 #ifdef XMLNODE_LOCATION
02495     const char* _display_path;  // character pointer for fast reference in XMLLocation
02496 
02497 #ifdef XS_USE_XERCES
02498     const Locator* _locator;
02499 #endif
02500 
02501     XMLLocation get_location() const;
02502 #endif
02503 
02504 protected:
02505     XMLPos      _pos;
02506 
02507     std::string _content;       // UTF-8 encoded
02508     enum {TAG_NONE, TAG_START, TAG_END} _last_tag;
02509 
02510     XMLErrorList _errors;
02511     XMLErrorList _warnings;
02512 
02513     XMLFormat   _format;
02514     bool    _endl_defined;
02515 
02516 #ifdef XS_USE_XERCES
02517     //@@
02518 #elif defined(XS_USE_EXPAT)
02519     virtual int read_buffer(char* buffer, int len) = 0;
02520 #else
02521     virtual int get() = 0;
02522     int     eat_endl();
02523 
02524     bool    _utf8;
02525 #endif
02526 
02527     void    finish_read();
02528 
02529     virtual void XmlDeclHandler(const char* version, const char* encoding, int standalone);
02530     virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes);
02531     virtual void EndElementHandler();
02532 #if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
02533     virtual void DefaultHandler(const XML_Char* s, int len);
02534 #else
02535     virtual void DefaultHandler(const std::string& s);
02536 #endif
02537 };
02538 
02539 
02541 
02542 #ifdef XS_USE_XERCES
02543 
02544 struct XercesXMLReader : public XMLReaderBase
02545 {
02546     XercesXMLReader(XMLNode* node, InputSource* source, bool adoptSource=false)
02547      :  XMLReaderBase(node, source, adoptSource)
02548     {
02549     }
02550 
02551     XercesXMLReader(XMLNode* node, LPCTSTR path);
02552     XercesXMLReader(XMLNode* node, const XMLByte* buffer, size_t bytes, const std::string& system_id=std::string());
02553 };
02554 
02555 #define XMLReader XercesXMLReader
02556 
02557 #elif defined(XS_USE_EXPAT)
02558 
02559 struct ExpatXMLReader : public XMLReaderBase
02560 {
02561     ExpatXMLReader(XMLNode* node, std::istream& in)
02562      :  XMLReaderBase(node),
02563         _in(in)
02564     {
02565     }
02566 
02568     int read_buffer(char* buffer, int len)
02569     {
02570         if (!_in.good())
02571             return -1;
02572 
02573         _in.read(buffer, len);
02574 
02575         return _in.gcount();
02576     }
02577 
02578 protected:
02579     std::istream&   _in;
02580 };
02581 
02582 #define XMLReader ExpatXMLReader
02583 
02584 #else // XS_USE_XERCES, XS_USE_EXPAT
02585 
02586 struct XMLReader : public XMLReaderBase
02587 {
02588     XMLReader(XMLNode* node, std::istream& in)
02589      :  XMLReaderBase(node),
02590         _in(in)
02591     {
02592     }
02593 
02595     int get()
02596     {
02597         return _in.get();
02598     }
02599 
02600 protected:
02601     std::istream&   _in;
02602 };
02603 
02604 #endif // XS_USE_XERCES
02605 
02606 
02607 #if defined(_MSC_VER) && _MSC_VER<1400
02608 
02609 struct fast_ostringbuffer : public std::streambuf
02610 {
02611     typedef char _E;
02612     typedef std::char_traits<_E> _Tr;
02613 
02614     explicit fast_ostringbuffer()
02615         {_Init(0, 0, std::_Noread);}    // optimized for ios::out mode
02616 
02617     virtual ~fast_ostringbuffer()
02618         {_Tidy();}
02619 
02620     std::string str() const
02621         {if (pptr() != 0)
02622             {std::string _Str(pbase(),
02623                 (_Seekhigh<pptr()? pptr(): _Seekhigh) - pbase());
02624             return _Str;}
02625         else
02626             return std::string();}
02627 
02628 protected:
02629     virtual int_type overflow(int_type _C = _Tr::eof())
02630         {if (_Tr::eq_int_type(_Tr::eof(), _C))
02631             return _Tr::not_eof(_C);
02632         else if (pptr() != 0 && pptr() < epptr())
02633             {*_Pninc() = _Tr::to_char_type(_C);
02634             return _C;}
02635         else
02636             {size_t _Os = gptr() == 0 ? 0 : epptr() - eback();
02637             size_t _Ns = _Os + _Alsize;
02638             _E *_P = _Al.allocate(_Ns, (void *)0);
02639             if (0 < _Os)
02640                 _Tr::copy(_P, eback(), _Os);
02641             else if (_ALSIZE < _Alsize)
02642                 _Alsize = _ALSIZE;
02643 
02644             if (_Strmode & std::_Allocated)
02645                 _Al.deallocate(eback(), _Os);
02646 
02647             _Strmode |= std::_Allocated;
02648 
02649             if (_Os == 0)
02650                 {_Seekhigh = _P;
02651                 setp(_P, _P + _Ns);
02652                 setg(_P, _P, _P); }
02653             else
02654                 {_Seekhigh = _Seekhigh - eback() + _P;
02655                 setp(pbase() - eback() + _P, pptr() - eback() + _P, _P + _Ns);
02656                 setg(_P, _P, _P);}
02657             *_Pninc() = _Tr::to_char_type(_C);
02658 
02659             return _C;}}
02660 
02661     void _Init(const _E *_S, size_t _N, std::_Strstate _M)
02662         {_Pendsave = 0, _Seekhigh = 0;
02663         _Alsize = _MINSIZE, _Strmode = _M;
02664         setg(0, 0, 0);
02665         setp(0, 0);}
02666 
02667     void _Tidy()
02668         {if (_Strmode & std::_Allocated)
02669             _Al.deallocate(eback(), (pptr() != 0 ? epptr() : egptr()) - eback());
02670         _Seekhigh = 0;
02671         _Strmode &= ~std::_Allocated;}
02672 
02673 private:
02674     enum {_ALSIZE = 65536/*512*/, _MINSIZE = 32768/*32*/};  // bigger buffer sizes
02675 
02676     _E *_Pendsave, *_Seekhigh;
02677     int _Alsize;
02678     std::_Strstate _Strmode;
02679     std::allocator<_E> _Al;
02680 };
02681 
02682 struct fast_ostringstream : public std::iostream
02683 {
02684     typedef std::iostream super;
02685 
02686     explicit fast_ostringstream()
02687         : super(&_Sb) {}
02688 
02689     std::string str() const
02690         {return _Sb.str();}
02691 
02692 private:
02693     fast_ostringbuffer _Sb;
02694 };
02695 
02696 #else
02697 
02698 typedef std::ostringstream fast_ostringstream;
02699 
02700 #endif
02701 
02702 
02704 struct XMLDoc : public XMLNode
02705 {
02706     XMLDoc()
02707      :  XMLNode("")
02708     {
02709     }
02710 
02711     XMLDoc(LPCTSTR path)
02712      :  XMLNode("")
02713     {
02714         read_file(path);
02715     }
02716 
02717 #ifdef XS_USE_XERCES
02718     bool read_file(LPCTSTR path)
02719     {
02720         XMLReader reader(this, path);
02721 
02722 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
02723         return read(reader, std::string(ANS(path)));
02724 #else
02725         return read(reader, XS_String(path));
02726 #endif
02727     }
02728 
02729     bool read_buffer(const char* buffer, size_t len, const std::string& system_id=std::string())
02730     {
02731         XMLReader reader(this, (const XMLByte*)buffer, len, system_id);
02732 
02733         return read(reader, system_id);
02734     }
02735 
02736     bool read_buffer(const std::string& in, const std::string& system_id=std::string())
02737     {
02738         return read_buffer(in.c_str(), in.length(), system_id);
02739     }
02740 
02741 #else // XS_USE_XERCES
02742 
02743     bool read_file(LPCTSTR path)
02744     {
02745         tifstream in(path);
02746         if (!in.good())
02747             return false;
02748 
02749         XMLReader reader(this, in);
02750 
02751 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
02752         return read(reader, std::string(ANS(path)));
02753 #else
02754         return read(reader, XS_String(path));
02755 #endif
02756     }
02757 
02758     bool read_buffer(const char* buffer, size_t len, const std::string& system_id=std::string())
02759     {
02760         return read_buffer(std::string(buffer, len), system_id);
02761     }
02762 
02763     bool read_buffer(const std::string& buffer, const std::string& system_id=std::string())
02764     {
02765         std::istringstream istr(buffer);
02766 
02767         return read_stream(istr, system_id);
02768     }
02769 
02770     bool read_stream(std::istream& in, const std::string& system_id=std::string())
02771     {
02772         XMLReader reader(this, in);
02773 
02774         return read(reader, system_id);
02775     }
02776 #endif // XS_USE_XERCES
02777 
02778     bool read(XMLReaderBase& reader, const std::string& display_path)
02779     {
02780 #ifdef XMLNODE_LOCATION
02781          // make a string copy to handle temporary string objects
02782         _display_path = display_path;
02783         reader._display_path = _display_path.c_str();
02784 #endif
02785 
02786         reader.clear_errors();
02787         reader.read();
02788 
02789         _format = reader.get_format();
02790         _format._endl = reader.get_endl();
02791 
02792         if (!reader.get_errors().empty()) {
02793             _errors = reader.get_errors();
02794             return false;
02795         }
02796 
02797         return true;
02798     }
02799 
02801      // FORMAT_SMART: preserving previous white space and comments
02802     bool write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART) const
02803     {
02804         _format.print_header(out, mode!=FORMAT_PLAIN);
02805 
02806         if (_children.size() == 1)
02807             _children.front()->write(out, _format, mode);
02808         else if (!_children.empty()) {
02809             //throw Exception("more than one XML root!");
02810             return false;
02811         }
02812 
02813         return out.good();
02814     }
02815 
02817     bool write_formating(std::ostream& out) const
02818     {
02819         return write(out, FORMAT_PRETTY);
02820     }
02821 
02822     bool write_file(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const
02823     {
02824         tofstream out(path);
02825 
02826         return write(out, mode);
02827     }
02828 
02829     bool write_formating(LPCTSTR path) const
02830     {
02831         tofstream out(path);
02832 
02833         return write_formating(out);
02834     }
02835 
02836     XMLFormat       _format;
02837     XMLErrorList    _errors;
02838 
02839 #ifdef XMLNODE_LOCATION
02840     std::string     _display_path;
02841 #endif
02842 };
02843 
02844 
02846 struct XMLMessage : public XMLDoc
02847 {
02848     XMLMessage(const char* name)
02849      :  _pos(this)
02850     {
02851         _pos.create(name);
02852     }
02853 
02854     std::string toString() const
02855     {
02856         std::ostringstream out;
02857 
02858         write(out);
02859 
02860         return out.str();
02861     }
02862 
02863     XMLPos  _pos;
02864 
02865 protected:
02866     XMLMessage()
02867      :  _pos(this)
02868     {
02869     }
02870 };
02871 
02872 
02874 struct XMLMessageFromString : public XMLMessage
02875 {
02876     XMLMessageFromString(const std::string& xml_str, const std::string& system_id=std::string())
02877     {
02878         read_buffer(xml_str.c_str(), xml_str.length(), system_id);
02879     }
02880 };
02881 
02882 
02884 struct XMLMessageReader : public XMLPos
02885 {
02886     XMLMessageReader(const std::string& xml_str, const std::string& system_id=std::string())
02887      :  XMLPos(&_msg)
02888     {
02889         _msg.read_buffer(xml_str.c_str(), xml_str.length(), system_id);
02890     }
02891 
02892     const XMLDoc& get_document()
02893     {
02894         return _msg;
02895     }
02896 
02897 protected:
02898     XMLDoc  _msg;
02899 };
02900 
02901 
02903 struct XMLWriter
02904 {
02905     XMLWriter(std::ostream& out, const XMLFormat& format=XMLFormat())
02906      :  _pofstream(NULL),
02907         _out(out),
02908         _format(format)
02909     {
02910         format.print_header(_out, false);   // _format._endl is printed in write_pre()
02911     }
02912 
02913     XMLWriter(LPCTSTR path, const XMLFormat& format=XMLFormat())
02914      :  _pofstream(new tofstream(path)),
02915         _out(*_pofstream),
02916         _format(format)
02917     {
02918         format.print_header(_out, false);   // _format._endl is printed in write_pre()
02919     }
02920 
02921     ~XMLWriter()
02922     {
02923         _out << _format._endl;
02924         delete _pofstream;
02925     }
02926 
02928     void create(const XS_String& name);
02929 
02931     bool back();
02932 
02934     void put(const XS_String& attr_name, const XS_String& value)
02935     {
02936         if (!_stack.empty())
02937             _stack.top()._attributes[attr_name] = value;
02938     }
02939 
02941     XS_String& operator[](const XS_String& attr_name)
02942     {
02943         if (_stack.empty())
02944             return s_empty_attr;
02945 
02946         return _stack.top()._attributes[attr_name];
02947     }
02948 
02949     void set_content(const XS_String& s, bool cdata=false)
02950     {
02951         if (!_stack.empty())
02952             _stack.top()._content = EncodeXMLString(s.c_str(), cdata);
02953     }
02954 
02956     void create_node_content(const XS_String& node_name, const XS_String& content)
02957     {
02958         create(node_name);
02959             set_content(content);
02960         back();
02961     }
02962 
02963      // public for access in StackEntry
02964     enum WRITESTATE {
02965         NOTHING, /*PRE,*/ ATTRIBUTES, PRE_CLOSED, /*CONTENT,*/ POST
02966     };
02967 
02968 protected:
02969     tofstream*      _pofstream;
02970     std::ostream&   _out;
02971     XMLFormat       _format;
02972 
02973     typedef XMLNode::AttributeMap AttrMap;
02974 
02976     struct StackEntry {
02977         XS_String   _node_name;
02978         AttrMap     _attributes;
02979         std::string _content;
02980         WRITESTATE  _state;
02981         bool        _children;
02982 
02983         StackEntry() : _state(NOTHING), _children(false) {}
02984     };
02985 
02986     std::stack<StackEntry> _stack;
02987 
02988     static XS_String s_empty_attr;
02989 
02990     void close_pre(StackEntry& entry);
02991     void write_pre(StackEntry& entry);
02992     void write_attributes(StackEntry& entry);
02993     void write_post(StackEntry& entry);
02994 };
02995 
02996 
02997 }   // namespace XMLStorage
02998 
02999 #define _XMLSTORAGE_H
03000 #endif // _XMLSTORAGE_H

Generated on Sun May 27 2012 04:18:45 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.