- Merge from trunk up to r45543
[reactos.git] / base / shell / explorer / utility / xmlstorage.h
index b16ef90..1913bdc 100644 (file)
@@ -2,7 +2,7 @@
  //
  // XML storage C++ classes version 1.3
  //
- // Copyright (c) 2004, 2005, 2006, 2007, 2008 Martin Fuchs <martin-fuchs@gmx.net>
+ // Copyright (c) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Martin Fuchs <martin-fuchs@gmx.net>
  //
 
  /// \file xmlstorage.h
@@ -60,7 +60,7 @@
 #endif
 
 
-#if _MSC_VER>=1400
+#if _MSC_VER>=1400 // VS2005 or higher
 #ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES                        1
 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT  1
@@ -119,26 +119,32 @@ typedef XMLCh XML_Char;
 
 #ifndef _STRING_DEFINED        // _STRING_DEFINED only allowed if using xmlstorage.cpp embedded in the project
 #if defined(_DEBUG) && defined(_DLL)   // DEBUG version only supported with MSVCRTD
-#if _MSC_VER==1400
+#if _MSC_VER==1500
+#pragma comment(lib, "xmlstorage-vc9d")
+#elif _MSC_VER==1400
 #pragma comment(lib, "xmlstorage-vc8d")
 #else
 #pragma comment(lib, "xmlstorage-vc6d")
 #endif
 #else
 #ifdef _DLL
-#if _MSC_VER==1400
+#if _MSC_VER==1500
+#pragma comment(lib, "xmlstorage-vc9")
+#elif _MSC_VER==1400
 #pragma comment(lib, "xmlstorage-vc8")
 #else
 #pragma comment(lib, "xmlstorage-vc6")
 #endif
 #elif defined(_MT)
-#if _MSC_VER==1400
+#if _MSC_VER==1500
+#pragma comment(lib, "xmlstorage-vc9t")
+#elif _MSC_VER==1400
 #pragma comment(lib, "xmlstorage-vc8t")
 #else
 #pragma comment(lib, "xmlstorage-vc6t")
 #endif
 #else
- // -ML is no more supported by VS2005.
+ // -ML is no more supported since VS2005.
 #pragma comment(lib, "xmlstorage-vc6l")
 #endif
 #endif
@@ -159,9 +165,11 @@ typedef XMLCh XML_Char;
 #include <stdio.h>     // vsnprintf(), snprintf()
 #endif
 
-#else
+#else // _WIN32
 
 #include <wchar.h>
+#include <stdlib.h>
+#include <string.h>    // strcasecmp()
 #include <stdarg.h>
 
 typedef char CHAR;
@@ -197,9 +205,9 @@ typedef const CHAR* LPCTSTR;
 #define _tcsicmp strcasecmp
 #define strnicmp strncasecmp
 #define _tcsnicmp strncasecmp
-#endif
+#endif // UNICODE
 
-#endif
+#endif // _WIN32
 
 #ifdef __BORLANDC__
 #define _stricmp stricmp
@@ -301,14 +309,14 @@ struct XS_String
 #if defined(UNICODE) && !defined(XS_STRING_UTF8)
        XS_String(LPCSTR s) {assign(s);}
        XS_String(LPCSTR s, size_t l) {assign(s, l);}
-       XS_String(const std::string& other) {assign(other.c_str());}
+       XS_String(const std::string& s) {assign(s.c_str());}
        XS_String& operator=(LPCSTR s) {assign(s); return *this;}
        void assign(LPCSTR s) {if (s) {size_t bl=strlen(s); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, bl, b, bl));} else erase();}
        void assign(LPCSTR s, size_t l) {if (s) {size_t bl=l; LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, bl));} else erase();}
 #else
        XS_String(LPCWSTR s) {assign(s);}
        XS_String(LPCWSTR s, size_t l) {assign(s, l);}
-       XS_String(const std::wstring& other) {assign(other.c_str());}
+       XS_String(const std::wstring& ws) {assign(ws.c_str());}
        XS_String& operator=(LPCWSTR s) {assign(s); return *this;}
 #ifdef XS_STRING_UTF8
        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();}
@@ -320,6 +328,12 @@ struct XS_String
 #endif
 #endif // _WIN32
 
+#ifdef __ISSD_H
+//     XS_String(const _ISSD RString& s) {assign(s.c_str());}
+//     void assign(const _ISSD RString& s) {assign(s.c_str());}
+       XS_String& operator=(const _ISSD RString& s) {assign(s); return *this;}
+#endif
+
 #ifdef XS_STRING_UTF8
        void assign(const XS_String& s) {assign(s.c_str());}
 #endif
@@ -418,6 +432,9 @@ extern const XS_String XS_KEY;
 extern const XS_String XS_VALUE;
 extern const XS_String XS_PROPERTY;
 
+#define CDATA_START "<![CDATA["
+#define CDATA_END "]]>"
+
 
 #ifndef XS_STRING_UTF8
 
@@ -484,7 +501,7 @@ inline std::string get_utf8(const XS_String& s)
 #endif // XS_STRING_UTF8
 
 extern std::string EncodeXMLString(const XS_String& str, bool cdata=false);
-extern XS_String DecodeXMLString(const XS_String& str);
+extern XS_String DecodeXMLString(const std::string& str);
 
 
 #ifdef __GNUC__
@@ -501,7 +518,8 @@ struct FileHolder
 {
        FileHolder(LPCTSTR path, LPCTSTR mode)
        {
-#ifdef __STDC_WANT_SECURE_LIB__        // secure CRT functions using VS 2005
+//@@ _MS_VER: temporarily needed for the ReactOS build environment
+#if defined(__STDC_WANT_SECURE_LIB__) && defined(_MS_VER)      // secure CRT functions using VS 2005
                if (_tfopen_s(&_pfile, path, mode) != 0)
                        _pfile = NULL;
 #else
@@ -533,6 +551,8 @@ struct tifstream : public std::istream, FileHolder
                _buf(_pfile)
 #endif
        {
+               if (!_pfile)
+                       setstate(badbit);
        }
 
 protected:
@@ -553,6 +573,8 @@ struct tofstream : public std::ostream, FileHolder
                _buf(_pfile)
 #endif
        {
+               if (!_pfile)
+                       setstate(badbit);
        }
 
        ~tofstream()
@@ -820,6 +842,7 @@ struct XPathElement
 
 struct XPath : std::list<XPathElement>
 {
+       XPath() : _absolute(false) {}
        XPath(const char* path) {init(path);}
        XPath(const std::string path) {init(path.c_str());}
 
@@ -961,13 +984,15 @@ struct XMLNode : public XS_String
        friend struct XPathElement;
 
        XMLNode(const XS_String& name)
-        :      XS_String(name)
+        :      XS_String(name),
+               _cdata_content(false)
        {
        }
 
        XMLNode(const XS_String& name, const std::string& leading)
         :      XS_String(name),
-               _leading(leading)
+               _leading(leading),
+               _cdata_content(false)
        {
        }
 
@@ -977,10 +1002,11 @@ struct XMLNode : public XS_String
                _leading(other._leading),
                _content(other._content),
                _end_leading(other._end_leading),
-               _trailing(other._trailing)
+               _trailing(other._trailing),
 #ifdef XMLNODE_LOCATION
-               , _location(other._location)
+               _location(other._location),
 #endif
+               _cdata_content(false)
        {
                for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
                        _children.push_back(new XMLNode(**it));
@@ -994,10 +1020,11 @@ struct XMLNode : public XS_String
                _leading(other._leading),
                _content(other._content),
                _end_leading(other._end_leading),
-               _trailing(other._trailing)
+               _trailing(other._trailing),
 #ifdef XMLNODE_LOCATION
-               , _location(other._location)
+               _location(other._location),
 #endif
+               _cdata_content(false)
        {
 //             assert(copy_no_children==COPY_NOCHILDREN);
        }
@@ -1049,7 +1076,7 @@ struct XMLNode : public XS_String
        {
                Children::iterator it, next=_children.begin();
 
-               while((it=next++)!=_children.end())
+               while((it=next++) != _children.end())
                        if (**it == name)
                                _children.erase(it);
        }
@@ -1153,23 +1180,41 @@ struct XMLNode : public XS_String
                return _attributes;
        }
 
+        /// read element node content
        XS_String get_content() const
        {
-#ifdef XS_STRING_UTF8
-               const XS_String& ret = _content;
-#else
-               XS_String ret;
-               assign_utf8(ret, _content.c_str(), _content.length());
-#endif
+               return DecodeXMLString(_content);
+       }
+
+        /// read content of a subnode specified by an XPath expression
+       XS_String get_sub_content(const XPath& xpath) const
+       {
+               const XMLNode* node = find_relative(xpath);
 
-               return DecodeXMLString(ret.c_str());
+               if (node)
+                       return node->get_content();
+               else
+                       return XS_EMPTY_STR;
        }
 
+        /// set element node content
        void set_content(const XS_String& s, bool cdata=false)
        {
                _content.assign(EncodeXMLString(s.c_str(), cdata));
        }
 
+        /// set content of a subnode specified by an XPath expression
+       bool set_sub_content(const XPath& xpath, const XS_String& s, bool cdata=false)
+       {
+               XMLNode* node = create_relative(xpath);
+
+               if (node) {
+                       node->set_content(s, cdata);
+                       return true;
+               } else
+                       return false;
+       }
+
 #ifdef XMLNODE_LOCATION
        const XMLLocation& get_location() const {return _location;}
 #endif
@@ -1187,10 +1232,10 @@ struct XMLNode : public XS_String
                        break;
 
                  case FORMAT_ORIGINAL:
-                       write_worker(out);
+                       original_write_worker(out);
                        break;
 
-               default:         // FORMAT_SMART
+                 default:      // FORMAT_SMART
                        smart_write_worker(out, format, indent);
                }
 
@@ -1209,6 +1254,20 @@ struct XMLNode : public XS_String
         /// copy matching tree nodes using the given XPath filter expression
        bool filter(const XPath& xpath, XMLNode& target) const;
 
+        /// XPath find function (const)
+       const XMLNode* find_relative(const XPath& xpath) const;
+
+        /// XPath find function
+       XMLNode* find_relative(const XPath& xpath);
+
+       XMLNode* get_first_child() const
+       {
+               if (!_children.empty())
+                       return _children.front();
+               else
+                       return NULL;
+       }
+
 protected:
        Children _children;
        AttributeMap _attributes;
@@ -1222,19 +1281,7 @@ protected:
        XMLLocation     _location;
 #endif
 
-       XMLNode* get_first_child() const
-       {
-               if (!_children.empty())
-                       return _children.front();
-               else
-                       return NULL;
-       }
-
-        /// XPath find function (const)
-       const XMLNode* find_relative(const XPath& xpath) const;
-
-        /// XPath find function
-       XMLNode* find_relative(const XPath& xpath);
+       bool    _cdata_content;
 
         /// relative XPath create function
        XMLNode* create_relative(const XPath& xpath);
@@ -1242,7 +1289,7 @@ protected:
         /// create a new node tree using the given XPath filter expression
        XMLNode* filter(XPath::const_iterator from, const XPath::const_iterator& to) const;
 
-       void    write_worker(std::ostream& out) const;
+       void    original_write_worker(std::ostream& out) const;
        void    plain_write_worker(std::ostream& out) const;
        void    pretty_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
        void    smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const;
@@ -1523,6 +1570,7 @@ struct XMLPos
         /// index operator attribute access
        template<typename T> XS_String get(const T& attr_name) const {return (*_cur)[attr_name];}
        XS_String& operator[](const XS_String& attr_name) {return (*_cur)[attr_name];}
+       const XS_String& operator[](const XS_String& attr_name) const {return (*_cur)[attr_name];}
 
         /// insert children when building tree
        void add_down(XMLNode* child)
@@ -1566,6 +1614,19 @@ struct XMLPos
                        return false;
        }
 
+        /// iterate to the next matching child
+       bool iterate(const XS_String& child_name, size_t& cnt)
+       {
+               XMLNode* node = XPathElement(child_name, cnt).find(_cur);
+
+               if (node) {
+                       go_to(node);
+                       ++cnt;
+                       return true;
+               } else
+                       return false;
+       }
+
         /// move to the position defined by xpath in XML tree
        bool go(const XPath& xpath);
 
@@ -1586,6 +1647,14 @@ struct XMLPos
                add_down(new XMLNode(name));
        }
 
+        /// create node with string content
+       void create_node_content(const XS_String& node_name, const XS_String& content)
+       {
+               XMLNode* pNode = new XMLNode(node_name);
+                       pNode->set_content(content);
+               _cur->add_child(pNode);
+       }
+
         /// create node if not already existing and move to it
        void smart_create(const XS_String& child_name)
        {
@@ -1709,6 +1778,8 @@ struct XMLPos
                {set_property(key, XS_String(value), name);}
 
 protected:
+       friend struct const_XMLPos;     // access to _root
+
        XMLNode* _root;
        XMLNode* _cur;
        std::stack<XMLNode*> _stack;
@@ -1735,6 +1806,12 @@ struct const_XMLPos
         :      _root(other._root),
                _cur(other._cur)
        {       // don't copy _stack
+       }
+
+       const_XMLPos(const XMLPos& other)
+        :      _root(other._root),
+               _cur(other._cur)
+       {       // don't copy _stack
        }
 
         /// access to current node
@@ -1758,6 +1835,7 @@ struct const_XMLPos
 
         /// index operator attribute access
        template<typename T> XS_String get(const T& attr_name) const {return _cur->get(attr_name);}
+       XS_String operator[](const XS_String& attr_name) const {return _cur->get(attr_name);}
 
         /// go back to previous position
        bool back()
@@ -1794,6 +1872,19 @@ struct const_XMLPos
                        return false;
        }
 
+        /// iterate to the next matching child
+       bool iterate(const XS_String& child_name, size_t& cnt)
+       {
+               const XMLNode* node = XPathElement(child_name, cnt).const_find(_cur);
+
+               if (node) {
+                       go_to(node);
+                       ++cnt;
+                       return true;
+               } else
+                       return false;
+       }
+
         /// move to the position defined by xpath in XML tree
        bool go(const XPath& xpath);
 
@@ -2642,11 +2733,19 @@ struct XMLDoc : public XMLNode
                return read(reader, system_id);
        }
 
+       bool read_buffer(const std::string& in, const std::string& system_id=std::string())
+       {
+               return read_buffer(in.c_str(), in.length(), system_id);
+       }
+
 #else // XS_USE_XERCES
 
        bool read_file(LPCTSTR path)
        {
                tifstream in(path);
+               if (!in.good())
+                       return false;
+
                XMLReader reader(this, in);
 
 #if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
@@ -2658,12 +2757,17 @@ struct XMLDoc : public XMLNode
 
        bool read_buffer(const char* buffer, size_t len, const std::string& system_id=std::string())
        {
-               std::istringstream in(std::string(buffer, len));
+               return read_buffer(std::string(buffer, len), system_id);
+       }
 
-               return read(in, system_id);
+       bool read_buffer(const std::string& buffer, const std::string& system_id=std::string())
+       {
+               std::istringstream istr(buffer);
+
+               return read_stream(istr, system_id);
        }
 
-       bool read(std::istream& in, const std::string& system_id=std::string())
+       bool read_stream(std::istream& in, const std::string& system_id=std::string())
        {
                XMLReader reader(this, in);
 
@@ -2848,6 +2952,14 @@ struct XMLWriter
                        _stack.top()._content = EncodeXMLString(s.c_str(), cdata);
        }
 
+        /// create node with string content
+       void create_node_content(const XS_String& node_name, const XS_String& content)
+       {
+               create(node_name);
+                       set_content(content);
+               back();
+       }
+
         // public for access in StackEntry
        enum WRITESTATE {
                NOTHING, /*PRE,*/ ATTRIBUTES, PRE_CLOSED, /*CONTENT,*/ POST
@@ -2856,7 +2968,7 @@ struct XMLWriter
 protected:
        tofstream*              _pofstream;
        std::ostream&   _out;
-       const XMLFormat&_format;
+       XMLFormat               _format;
 
        typedef XMLNode::AttributeMap AttrMap;