Author: martinf
Date: Thu May 1 16:17:35 2008
New Revision: 33226
URL:
http://svn.reactos.org/svn/reactos?rev=33226&view=rev
Log:
update to XMLStorage version 1.3
Modified:
trunk/reactos/base/shell/explorer/utility/xmlstorage.cpp
trunk/reactos/base/shell/explorer/utility/xmlstorage.h
trunk/reactos/base/shell/explorer/utility/xs-native.cpp
Modified: trunk/reactos/base/shell/explorer/utility/xmlstorage.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/explorer/utilit…
==============================================================================
--- trunk/reactos/base/shell/explorer/utility/xmlstorage.cpp [iso-8859-1] (original)
+++ trunk/reactos/base/shell/explorer/utility/xmlstorage.cpp [iso-8859-1] Thu May 1
16:17:35 2008
@@ -1,8 +1,8 @@
//
- // XML storage C++ classes version 1.2
+ // XML storage C++ classes version 1.3
//
- // Copyright (c) 2004, 2005, 2006, 2007 Martin Fuchs <martin-fuchs(a)gmx.net>
+ // Copyright (c) 2004, 2005, 2006, 2007, 2008 Martin Fuchs <martin-fuchs(a)gmx.net>
//
/// \file xmlstorage.cpp
@@ -57,6 +57,10 @@
const LPCXSSTR XS_FLOATFMT = XS_FLOATFMT_STR;
#endif
+const XS_String XS_KEY = XS_KEY_STR;
+const XS_String XS_VALUE = XS_VALUE_STR;
+const XS_String XS_PROPERTY = XS_PROPERTY_STR;
+
/// remove escape characters from zero terminated string
static std::string unescape(const char* s, char b, char e)
@@ -105,18 +109,12 @@
}
- /// move XPath like to position in XML tree
-bool XMLPos::go(const char* path)
-{
- XMLNode* node = _cur;
-
- // Is this an absolute path?
- if (*path == '/') {
- node = _root;
- ++path;
- }
-
- node = node->find_relative(path);
+ /// move to the position defined by xpath in XML tree
+bool XMLPos::go(const XPath& xpath)
+{
+ XMLNode* node = xpath._absolute? _root: _cur;
+
+ node = node->find_relative(xpath);
if (node) {
go_to(node);
@@ -125,18 +123,12 @@
return false;
}
- /// move XPath like to position in XML tree
-bool const_XMLPos::go(const char* path)
-{
- const XMLNode* node = _cur;
-
- // Is this an absolute path?
- if (*path == '/') {
- node = _root;
- ++path;
- }
-
- node = node->find_relative(path);
+ /// move to the position defined by xpath in XML tree
+bool const_XMLPos::go(const XPath& xpath)
+{
+ const XMLNode* node = xpath._absolute? _root: _cur;
+
+ node = node->find_relative(xpath);
if (node) {
go_to(node);
@@ -146,40 +138,7 @@
}
-const XMLNode* XMLNode::find_relative(const char* path) const
-{
- const XMLNode* node = this;
-
- // parse relative path
- while(*path) {
- node = const_cast<XMLNode*>(node)->get_child_relative(path, false); //
get_child_relative() ist const for create==false
-
- if (!node)
- return NULL;
-
- if (*path == '/')
- ++path;
- }
-
- return node;
-}
-
-XMLNode* XMLNode::create_relative(const char* path)
-{
- XMLNode* node = this;
-
- // parse relative path
- while(*path) {
- node = node->get_child_relative(path, true);
-
- if (*path == '/')
- ++path;
- }
-
- return node;
-}
-
-XMLNode* XMLNode::get_child_relative(const char*& path, bool create)
+const char* XPathElement::parse(const char* path)
{
const char* slash = strchr(path, '/');
if (slash == path)
@@ -192,8 +151,7 @@
// look for [n] and [@attr_name="attr_value"] expressions in path components
const char* bracket = strchr(comp.c_str(), '[');
l = bracket? bracket-comp.c_str(): comp.length();
- std::string child_name(comp.c_str(), l);
- std::string attr_name, attr_value;
+ _child_name.assign(comp.c_str(), l);
int n = 0;
if (bracket) {
@@ -203,7 +161,7 @@
n = atoi(p); // read index number
if (n)
- n = n - 1; // convert into zero based index
+ _child_idx = n - 1; // convert into zero based index
const char* at = strchr(p, '@');
@@ -213,30 +171,198 @@
// read attribute name and value
if (equal) {
- attr_name = unescape(p, equal-p);
- attr_value = unescape(equal+1);
+ _attr_name = unescape(p, equal-p);
+ _attr_value = unescape(equal+1);
}
}
}
- XMLNode* child;
-
- if (attr_name.empty())
- // search n.th child node with specified name
- child = find(child_name, n);
+ return path;
+}
+
+XMLNode* XPathElement::find(XMLNode* node) const
+{
+ int n = 0;
+
+ for(XMLNode::Children::const_iterator it=node->_children.begin();
it!=node->_children.end(); ++it)
+ if (matches(**it, n))
+ return *it;
+
+ return NULL;
+}
+
+const XMLNode* XPathElement::const_find(const XMLNode* node) const
+{
+ int n = 0;
+
+ for(XMLNode::Children::const_iterator it=node->_children.begin();
it!=node->_children.end(); ++it)
+ if (matches(**it, n))
+ return *it;
+
+ return NULL;
+}
+
+bool XPathElement::matches(const XMLNode& node, int& n) const
+{
+ if (node != _child_name)
+ if (_child_name != XS_TEXT("*")) // use asterisk as wildcard
+ return false;
+
+ if (!_attr_name.empty())
+ if (node.get(_attr_name) != _attr_value)
+ return false;
+
+ if (_child_idx == -1)
+ return true;
+ else if (n++ == _child_idx)
+ return true;
else
- // search n.th child node with specified name and matching attribute value
- child = find(child_name, attr_name, attr_value, n);
-
- if (!child && create) {
- child = new XMLNode(child_name);
- add_child(child);
-
- if (!attr_name.empty())
- (*this)[attr_name] = attr_value;
- }
-
- return child;
+ return false;
+}
+
+
+void XPath::init(const char* path)
+{
+ // Is this an absolute path?
+ if (*path == '/') {
+ _absolute = true;
+ ++path;
+ } else
+ _absolute = false;
+
+ // parse path
+ while(*path) {
+ XPathElement elem;
+
+ path = elem.parse(path);
+
+ if (!path)
+ break;
+
+ if (*path == '/')
+ ++path;
+
+ push_back(elem);
+ }
+}
+
+
+const XMLNode* XMLNode::find_relative(const XPath& xpath) const
+{
+ const XMLNode* node = this;
+
+ for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
+ node = it->const_find(node);
+
+ if (!node)
+ return NULL;
+ }
+
+ return node;
+}
+
+XMLNode* XMLNode::find_relative(const XPath& xpath)
+{
+ XMLNode* node = this;
+
+ for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
+ node = it->find(node);
+
+ if (!node)
+ return NULL;
+ }
+
+ return node;
+}
+
+XMLNode* XMLNode::create_relative(const XPath& xpath)
+{
+ XMLNode* node = this;
+
+ for(XPath::const_iterator it=xpath.begin(); it!=xpath.end(); ++it) {
+ XMLNode* child = it->find(this);
+
+ if (!child) {
+ child = new XMLNode(it->_child_name);
+ add_child(child);
+
+ if (!it->_attr_name.empty())
+ (*this)[it->_attr_name] = it->_attr_value;
+ }
+ }
+
+ return node;
+}
+
+ /// count the nodes matching the given relative XPath expression
+int XMLNode::count(XPath::const_iterator from, const XPath::const_iterator& to)
const
+{
+ const XPathElement& elem = *from++;
+ int cnt = 0;
+ int n = 0;
+
+ for(XMLNode::Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
+ if (elem.matches(**it, n))
+ if (from != to)
+ // iterate deeper
+ cnt += (*it)->count(from, to);
+ else
+ // increment match counter
+ ++cnt;
+
+ return cnt;
+}
+
+ /// copy matching tree nodes using the given XPath filter expression
+bool XMLNode::filter(const XPath& xpath, XMLNode& target) const
+{
+ XMLNode* ret = filter(xpath.begin(), xpath.end());
+
+ if (ret) {
+ // move returned nodes to target node
+ target._children.move(ret->_children);
+ target._attributes = ret->_attributes;
+
+ delete ret;
+
+ return true;
+ } else
+ return false;
+}
+
+ /// create a new node tree using the given XPath filter expression
+XMLNode* XMLNode::filter(XPath::const_iterator from, const XPath::const_iterator& to)
const
+{
+ XMLNode* copy = NULL;
+
+ const XPathElement& elem = *from++;
+ int cnt = 0;
+ int n = 0;
+
+ for(XMLNode::Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
+ if (elem.matches(**it, n)) {
+ if (!copy)
+ copy = new XMLNode(*this, XMLNode::COPY_NOCHILDREN);
+
+ if (from != to) {
+ XMLNode* ret = (*it)->filter(from, to);
+
+ if (ret) {
+ copy->add_child(ret);
+ ++cnt;
+ }
+ } else {
+ copy->add_child(new XMLNode(**it, XMLNode::COPY_NOCHILDREN));
+ ++cnt;
+ }
+ }
+
+ if (cnt > 0) {
+ return copy;
+ } else {
+ delete copy;
+ return NULL;
+ }
}
@@ -286,9 +412,9 @@
break;
default:
- if ((unsigned)*p<20 && *p!='\t' && *p!='\r'
&& *p!='\n') {
+ if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r'
&& *p!='\n') {
char b[16];
- sprintf(b, "&%d;", (unsigned)*p);
+ sprintf(b, "&#%d;", (unsigned)*p);
for(const char*q=b; *q; )
*o++ = *q++;
} else
@@ -330,8 +456,8 @@
break;
default:
- if ((unsigned)*p<20 && *p!='\t' && *p!='\r'
&& *p!='\n')
- out << "&" << (unsigned)*p << ";";
+ if ((unsigned)*p<0x20 && *p!='\t' && *p!='\r'
&& *p!='\n')
+ out << "&#" << (unsigned)*p << ";";
else
out << *p;
}
@@ -368,7 +494,7 @@
} else if (!XS_nicmp(p+1, XS_TEXT("apos;"), 5)) {
*o++ = '\'';
p += 5;
- } else
+ } else //@@ maybe decode "&#xx;" special characters
*o++ = *p;
} else if (*p=='<' &&
!XS_nicmp(p+1,XS_TEXT("![CDATA["),8)) {
LPCXSSTR e = XS_strstr(p+9, XS_TEXT("]]>"));
@@ -535,18 +661,33 @@
}
+const char* get_xmlsym_end_utf8(const char* p)
+{
+ for(; *p; ++p) {
+ char c = *p;
+
+ if (c == '\xC3') // UTF-8 escape character
+ ++p; //TODO only continue on umlaut characters
+ else if (!isalnum(c) && c!='_' && c!='-')
+ break;
+ }
+
+ return p;
+}
+
+
void DocType::parse(const char* p)
{
while(isspace((unsigned char)*p)) ++p;
const char* start = p;
- while(isxmlsym(*p)) ++p;
+ p = get_xmlsym_end_utf8(p);
_name.assign(start, p-start);
while(isspace((unsigned char)*p)) ++p;
start = p;
- while(isxmlsym(*p)) ++p;
+ p = get_xmlsym_end_utf8(p);
std::string keyword(p, p-start); // "PUBLIC" or "SYSTEM"
while(isspace((unsigned char)*p)) ++p;
@@ -705,7 +846,6 @@
break;
if (p != s)
- {
if (_pos->_children.empty()) { // no children in last node?
if (_last_tag == TAG_START)
_pos->_content.append(s, p-s);
@@ -715,7 +855,7 @@
p = s;
} else
_pos->_children.back()->_trailing.append(s, p-s);
- }
+
std::string leading;
if (p != e)
@@ -753,14 +893,12 @@
}
if (p != s)
- {
if (_pos->_children.empty()) // no children in current node?
_pos->_content.append(s, p-s);
else if (_last_tag == TAG_START)
_pos->_content.append(s, p-s);
else
_pos->_children.back()->_trailing.append(s, p-s);
- }
if (p != e)
_pos->_end_leading.assign(p, e-p);
@@ -786,5 +924,91 @@
XS_String XMLWriter::s_empty_attr;
+void XMLWriter::create(const XS_String& name)
+{
+ if (!_stack.empty()) {
+ StackEntry& last = _stack.top();
+
+ if (last._state < PRE_CLOSED) {
+ write_attributes(last);
+ close_pre(last);
+ }
+
+ ++last._children;
+ }
+
+ StackEntry entry;
+ entry._node_name = name;
+ _stack.push(entry);
+
+ write_pre(entry);
+}
+
+bool XMLWriter::back()
+{
+ if (!_stack.empty()) {
+ write_post(_stack.top());
+
+ _stack.pop();
+ return true;
+ } else
+ return false;
+}
+
+void XMLWriter::close_pre(StackEntry& entry)
+{
+ _out << '>';
+
+ entry._state = PRE_CLOSED;
+}
+
+void XMLWriter::write_pre(StackEntry& entry)
+{
+ if (_format._pretty >= PRETTY_LINEFEED)
+ _out << _format._endl;
+
+ if (_format._pretty == PRETTY_INDENT)
+ for(size_t i=_stack.size(); --i>0; )
+ _out << XML_INDENT_SPACE;
+
+ _out << '<' << EncodeXMLString(entry._node_name);
+ //entry._state = PRE;
+}
+
+void XMLWriter::write_attributes(StackEntry& entry)
+{
+ for(AttrMap::const_iterator it=entry._attributes.begin(); it!=entry._attributes.end();
++it)
+ _out << ' ' << EncodeXMLString(it->first) <<
"=\"" << EncodeXMLString(it->second) <<
"\"";
+
+ entry._state = ATTRIBUTES;
+}
+
+void XMLWriter::write_post(StackEntry& entry)
+{
+ if (entry._state < ATTRIBUTES)
+ write_attributes(entry);
+
+ if (entry._children || !entry._content.empty()) {
+ if (entry._state < PRE_CLOSED)
+ close_pre(entry);
+
+ _out << entry._content;
+ //entry._state = CONTENT;
+
+ if (_format._pretty>=PRETTY_LINEFEED && entry._content.empty())
+ _out << _format._endl;
+
+ if (_format._pretty==PRETTY_INDENT && entry._content.empty())
+ for(size_t i=_stack.size(); --i>0; )
+ _out << XML_INDENT_SPACE;
+
+ _out << "</" << EncodeXMLString(entry._node_name) <<
">";
+ } else {
+ _out << "/>";
+ }
+
+ entry._state = POST;
+}
+
} // namespace XMLStorage
Modified: trunk/reactos/base/shell/explorer/utility/xmlstorage.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/explorer/utilit…
==============================================================================
--- trunk/reactos/base/shell/explorer/utility/xmlstorage.h [iso-8859-1] (original)
+++ trunk/reactos/base/shell/explorer/utility/xmlstorage.h [iso-8859-1] Thu May 1
16:17:35 2008
@@ -1,8 +1,8 @@
//
- // XML storage C++ classes version 1.2
+ // XML storage C++ classes version 1.3
//
- // Copyright (c) 2004, 2005, 2006, 2007 Martin Fuchs <martin-fuchs(a)gmx.net>
+ // Copyright (c) 2004, 2005, 2006, 2007, 2008 Martin Fuchs <martin-fuchs(a)gmx.net>
//
/// \file xmlstorage.h
@@ -39,9 +39,6 @@
#ifndef _XMLSTORAGE_H
-#ifndef __REACTOS__
-#include <strstream>
-#endif
#ifdef UNICODE
#ifndef _UNICODE
@@ -202,6 +199,10 @@
#define _tcsnicmp strncasecmp
#endif
+#endif
+
+#ifdef __BORLANDC__
+#define _stricmp stricmp
#endif
@@ -264,10 +265,7 @@
#endif
-int inline isxmlsym(unsigned char c)
-{
- return isalnum(c) || c=='_' || c=='-';
-}
+extern const char* get_xmlsym_end_utf8(const char* p);
#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
@@ -397,6 +395,10 @@
#define XS_INTFMT_STR XS_TEXT("%d")
#define XS_FLOATFMT_STR XS_TEXT("%f")
+#define XS_KEY_STR XS_TEXT("key")
+#define XS_VALUE_STR XS_TEXT("value")
+#define XS_PROPERTY_STR XS_TEXT("property")
+
// work around GCC's wide string constant bug
#ifdef __GNUC__
extern const LPCXSSTR XS_EMPTY;
@@ -412,6 +414,10 @@
#define XS_FLOATFMT XS_FLOATFMT_STR
#endif
+extern const XS_String XS_KEY;
+extern const XS_String XS_VALUE;
+extern const XS_String XS_PROPERTY;
+
#ifndef XS_STRING_UTF8
@@ -783,6 +789,46 @@
};
+struct XMLNode;
+
+struct XPathElement
+{
+ XPathElement() : _child_idx(-1) {}
+
+ XPathElement(const XS_String& child_name, int child_idx=-1)
+ : _child_name(child_name), _child_idx(child_idx) {}
+
+ XPathElement(const XS_String& child_name, int child_idx, const XS_String&
attr_name, const XS_String& attr_value)
+ : _child_name(child_name), _child_idx(child_idx),
+ _attr_name(attr_name), _attr_value(attr_value)
+ {
+ }
+
+ XS_String _child_name;
+ int _child_idx;
+
+ XS_String _attr_name;
+ XS_String _attr_value;
+
+ const char* parse(const char* path);
+
+ XMLNode* find(XMLNode* node) const;
+ const XMLNode* const_find(const XMLNode* node) const;
+
+ bool matches(const XMLNode& node, int& n) const;
+};
+
+struct XPath : std::list<XPathElement>
+{
+ XPath(const char* path) {init(path);}
+ XPath(const std::string path) {init(path.c_str());}
+
+ void init(const char* path);
+
+ bool _absolute;
+};
+
+
/// in memory representation of an XML node
struct XMLNode : public XS_String
{
@@ -841,10 +887,40 @@
/// internal children node list
struct Children : public std::list<XMLNode*>
{
- void assign(const Children& other)
+ typedef std::list<XMLNode*> super;
+
+ Children()
+ {
+ }
+
+ Children(Children& other)
+ {
+ for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
+ push_back(*it);
+ }
+
+ void assign(Children& other)
{
clear();
-
+ move(other);
+ }
+
+ void move(Children& other)
+ {
+ for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
+ push_back(*it);
+
+ other.reset();
+ }
+
+ Children& operator=(Children& other)
+ {
+ assign(other);
+ return *this;
+ }
+
+ void copy(const Children& other)
+ {
for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
push_back(new XMLNode(**it));
}
@@ -858,6 +934,23 @@
node->clear();
delete node;
}
+ }
+
+ bool remove(XMLNode* node)
+ {
+ for(iterator it=begin(); it!=end(); ++it)
+ if (*it == node) {
+ erase(it);
+ return true;
+ }
+
+ return false;
+ }
+
+ private:
+ void reset()
+ {
+ super::clear();
}
};
@@ -865,6 +958,7 @@
friend struct XMLPos;
friend struct const_XMLPos;
friend struct XMLReaderBase;
+ friend struct XPathElement;
XMLNode(const XS_String& name)
: XS_String(name)
@@ -892,6 +986,22 @@
_children.push_back(new XMLNode(**it));
}
+ enum COPY_FLAGS {COPY_NOCHILDREN};
+
+ XMLNode(const XMLNode& other, COPY_FLAGS copy_no_children)
+ : XS_String(other),
+ _attributes(other._attributes),
+ _leading(other._leading),
+ _content(other._content),
+ _end_leading(other._end_leading),
+ _trailing(other._trailing)
+#ifdef XMLNODE_LOCATION
+ , _location(other._location)
+#endif
+ {
+// assert(copy_no_children==COPY_NOCHILDREN);
+ }
+
virtual ~XMLNode()
{
while(!_children.empty()) {
@@ -915,7 +1025,8 @@
XMLNode& operator=(const XMLNode& other)
{
- _children.assign(other._children);
+ _children.clear();
+ _children.copy(other._children);
_attributes = other._attributes;
@@ -933,6 +1044,16 @@
_children.push_back(child);
}
+ /// remove all children named 'name'
+ void remove_children(const XS_String& name)
+ {
+ Children::iterator it, next=_children.begin();
+
+ while((it=next++)!=_children.end())
+ if (**it == name)
+ _children.erase(it);
+ }
+
/// write access to an attribute
void put(const XS_String& attr_name, const XS_String& value)
{
@@ -956,10 +1077,16 @@
return def;
}
+ /// remove the attribute 'attr_name'
+ void erase(const XS_String& attr_name)
+ {
+ _attributes.erase(attr_name);
+ }
+
/// convenient value access in children node
- XS_String subvalue(const XS_String& name, const XS_String& attr_name, int n=0)
const
- {
- const XMLNode* node = find(name, n);
+ XS_String subvalue(const XS_String& child_name, const XS_String& attr_name, int
n=0) const
+ {
+ const XMLNode* node = XPathElement(child_name, n).const_find(this);
if (node)
return node->get(attr_name);
@@ -968,12 +1095,12 @@
}
/// convenient storage of distinct values in children node
- XS_String& subvalue(const XS_String& name, const XS_String& attr_name, int
n=0)
- {
- XMLNode* node = find(name, n);
+ XS_String& subvalue(const XS_String& child_name, const XS_String& attr_name,
int n=0)
+ {
+ XMLNode* node = XPathElement(child_name, n).find(this);
if (!node) {
- node = new XMLNode(name);
+ node = new XMLNode(child_name);
add_child(node);
}
@@ -982,9 +1109,9 @@
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// convenient value access in children node
- XS_String subvalue(const char* name, const char* attr_name, int n=0) const
- {
- const XMLNode* node = find(name, n);
+ XS_String subvalue(const char* child_name, const char* attr_name, int n=0) const
+ {
+ const XMLNode* node = XPathElement(child_name, n).const_find(this);
if (node)
return node->get(attr_name);
@@ -993,12 +1120,12 @@
}
/// convenient storage of distinct values in children node
- XS_String& subvalue(const char* name, const XS_String& attr_name, int n=0)
- {
- XMLNode* node = find(name, n);
+ XS_String& subvalue(const char* child_name, const XS_String& attr_name, int
n=0)
+ {
+ XMLNode* node = XPathElement(child_name, n).find(this);
if (!node) {
- node = new XMLNode(name);
+ node = new XMLNode(child_name);
add_child(node);
}
@@ -1070,6 +1197,18 @@
return out.good();
}
+ /// count the nodes matching the given relative XPath expression
+ int count(const XPath& xpath) const
+ {
+ return count(xpath.begin(), xpath.end());
+ }
+
+ /// count the nodes matching the given relative XPath expression
+ int count(XPath::const_iterator from, const XPath::const_iterator& to) const;
+
+ /// copy matching tree nodes using the given XPath filter expression
+ bool filter(const XPath& xpath, XMLNode& target) const;
+
protected:
Children _children;
AttributeMap _attributes;
@@ -1091,72 +1230,22 @@
return NULL;
}
- XMLNode* find(const XS_String& name, int n=0) const
- {
- for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
- if (**it == name)
- if (!n--)
- return *it;
-
- return NULL;
- }
-
- XMLNode* find(const XS_String& name, const XS_String& attr_name, const
XS_String& attr_value, int n=0) const
- {
- for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
- const XMLNode& node = **it;
-
- if (node==name && node.get(attr_name)==attr_value)
- if (!n--)
- return *it;
- }
-
- return NULL;
- }
-
-#if defined(UNICODE) && !defined(XS_STRING_UTF8)
- XMLNode* find(const char* name, int n=0) const
- {
- for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
- if (**it == name)
- if (!n--)
- return *it;
-
- return NULL;
- }
-
- template<typename T, typename U>
- XMLNode* find(const char* name, const T& attr_name, const U& attr_value, int
n=0) const
- {
- for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it) {
- const XMLNode& node = **it;
-
- if (node==name && node.get(attr_name)==attr_value)
- if (!n--)
- return *it;
- }
-
- return NULL;
- }
-#endif
-
/// XPath find function (const)
- const XMLNode* find_relative(const char* path) const;
+ const XMLNode* find_relative(const XPath& xpath) const;
/// XPath find function
- XMLNode* find_relative(const char* path)
- {return const_cast<XMLNode*>(const_cast<const
XMLNode*>(this)->find_relative(path));}
+ XMLNode* find_relative(const XPath& xpath);
/// relative XPath create function
- XMLNode* create_relative(const char* path);
+ XMLNode* create_relative(const XPath& xpath);
+
+ /// 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 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;
-
-protected:
- XMLNode* get_child_relative(const char*& path, bool create); // mutable for
create==true
};
@@ -1179,6 +1268,7 @@
struct iterator
{
typedef XMLNode::Children::iterator BaseIterator;
+ typedef iterator myType;
iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
: _cur(begin),
@@ -1203,7 +1293,7 @@
return *_cur;
}
- iterator& operator++()
+ myType& operator++()
{
++_cur;
search_next();
@@ -1211,9 +1301,9 @@
return *this;
}
- iterator operator++(int)
- {
- iterator ret = *this;
+ myType operator++(int)
+ {
+ myType ret = *this;
++_cur;
search_next();
@@ -1221,14 +1311,14 @@
return ret;
}
- bool operator==(const BaseIterator& other) const
- {
- return _cur == other;
- }
-
- bool operator!=(const BaseIterator& other) const
- {
- return _cur != other;
+ bool operator==(const myType& other) const
+ {
+ return _cur == other._cur;
+ }
+
+ bool operator!=(const myType& other) const
+ {
+ return _cur != other._cur;
}
protected:
@@ -1278,6 +1368,7 @@
struct const_iterator
{
typedef XMLNode::Children::const_iterator BaseIterator;
+ typedef const_iterator myType;
const_iterator(BaseIterator begin, BaseIterator end, const XS_String& filter_name)
: _cur(begin),
@@ -1297,7 +1388,7 @@
return *_cur;
}
- const_iterator& operator++()
+ myType& operator++()
{
++_cur;
search_next();
@@ -1305,9 +1396,9 @@
return *this;
}
- const_iterator operator++(int)
- {
- const_iterator ret = *this;
+ myType operator++(int)
+ {
+ myType ret = *this;
++_cur;
search_next();
@@ -1315,14 +1406,14 @@
return ret;
}
- bool operator==(const BaseIterator& other) const
- {
- return _cur == other;
- }
-
- bool operator!=(const BaseIterator& other) const
- {
- return _cur != other;
+ bool operator==(const myType& other) const
+ {
+ return _cur == other._cur;
+ }
+
+ bool operator!=(const myType& other) const
+ {
+ return _cur != other._cur;
}
protected:
@@ -1464,9 +1555,9 @@
}
/// search for child and go down
- bool go_down(const XS_String& name, int n=0)
- {
- XMLNode* node = _cur->find(name, n);
+ bool go_down(const XS_String& child_name, int n=0)
+ {
+ XMLNode* node = XPathElement(child_name, n).find(_cur);
if (node) {
go_to(node);
@@ -1475,13 +1566,13 @@
return false;
}
- /// move XPath like to position in XML tree
- bool go(const char* path);
+ /// move to the position defined by xpath in XML tree
+ bool go(const XPath& xpath);
/// create child nodes using XPath notation and move to the deepest child
- bool create_relative(const char* path)
- {
- XMLNode* node = _cur->create_relative(path);
+ bool create_relative(const XPath& xpath)
+ {
+ XMLNode* node = _cur->create_relative(xpath);
if (!node)
return false; // invalid path specified
@@ -1496,35 +1587,47 @@
}
/// create node if not already existing and move to it
- void smart_create(const XS_String& name)
- {
- XMLNode* node = _cur->find(name);
+ void smart_create(const XS_String& child_name)
+ {
+ XMLNode* node = XPathElement(child_name).find(_cur);
if (node)
go_to(node);
else
- add_down(new XMLNode(name));
+ add_down(new XMLNode(child_name));
}
/// search matching child node identified by key name and an attribute value
- void smart_create(const XS_String& name, const XS_String& attr_name, const
XS_String& attr_value)
- {
- XMLNode* node = _cur->find(name, attr_name, attr_value);
+ void smart_create(const XS_String& child_name, const XS_String& attr_name, const
XS_String& attr_value)
+ {
+ XMLNode* node = XPathElement(child_name, 0, attr_name, attr_value).find(_cur);
if (node)
go_to(node);
else {
- node = new XMLNode(name);
+ node = new XMLNode(child_name);
add_down(node);
(*node)[attr_name] = attr_value;
}
}
+ /// count the nodes matching the given relative XPath expression
+ int count(const XPath& xpath) const
+ {
+ return _cur->count(xpath);
+ }
+
+ /// create a new node tree using the given XPath filter expression
+ int filter(const XPath& xpath, XMLNode& target) const
+ {
+ return _cur->filter(xpath, target);
+ }
+
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// search for child and go down
- bool go_down(const char* name, int n=0)
- {
- XMLNode* node = _cur->find(name, n);
+ bool go_down(const char* child_name, int n=0)
+ {
+ XMLNode* node = XPathElement(child_name, n).find(_cur);
if (node) {
go_to(node);
@@ -1534,40 +1637,76 @@
}
/// create node and move to it
- void create(const char* name)
- {
- add_down(new XMLNode(name));
+ void create(const char* child_name)
+ {
+ add_down(new XMLNode(child_name));
}
/// create node if not already existing and move to it
- void smart_create(const char* name)
- {
- XMLNode* node = _cur->find(name);
+ void smart_create(const char* child_name)
+ {
+ XMLNode* node = XPathElement(child_name).find(_cur);
if (node)
go_to(node);
else
- add_down(new XMLNode(name));
+ add_down(new XMLNode(child_name));
}
/// search matching child node identified by key name and an attribute value
template<typename T, typename U>
- void smart_create(const char* name, const T& attr_name, const U& attr_value)
- {
- XMLNode* node = _cur->find(name, attr_name, attr_value);
+ void smart_create(const char* child_name, const T& attr_name, const U&
attr_value)
+ {
+ XMLNode* node = XPathElement(child_name, 0, attr_name, attr_value).find(_cur);
if (node)
go_to(node);
else {
- XMLNode* node = new XMLNode(name);
+ node = new XMLNode(child_name);
add_down(node);
(*node)[attr_name] = attr_value;
}
}
#endif
+ /// delete current node and go back to previous position
+ bool delete_this()
+ {
+ if (!_stack.empty()) {
+ XMLNode* pLast = _stack.top();
+
+ if (pLast->_children.remove(_cur)) {
+ _cur = _stack.top();
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /// remove all children named 'name'
+ void remove_children(const XS_String& name)
+ {
+ _cur->remove_children(name);
+ }
+
+ /// remove the attribute 'attr_name' from the current node
+ void erase(const XS_String& attr_name)
+ {
+ _cur->erase(attr_name);
+ }
+
XS_String& str() {return *_cur;}
const XS_String& str() const {return *_cur;}
+
+ // property (key/value pair) setter functions
+ void set_property(const XS_String& key, int value, const XS_String&
name=XS_PROPERTY);
+ void set_property(const XS_String& key, double value, const XS_String&
name=XS_PROPERTY);
+ void set_property(const XS_String& key, const XS_String& value, const
XS_String& name=XS_PROPERTY);
+ void set_property(const XS_String& key, const struct XMLBool& value, const
XS_String& name=XS_PROPERTY);
+
+ void set_property(const XS_String& key, const char* value, const XS_String&
name=XS_PROPERTY)
+ {set_property(key, XS_String(value), name);}
protected:
XMLNode* _root;
@@ -1644,9 +1783,9 @@
}
/// search for child and go down
- bool go_down(const XS_String& name, int n=0)
- {
- XMLNode* node = _cur->find(name, n);
+ bool go_down(const XS_String& child_name, int n=0)
+ {
+ const XMLNode* node = XPathElement(child_name, n).const_find(_cur);
if (node) {
go_to(node);
@@ -1655,14 +1794,14 @@
return false;
}
- /// move XPath like to position in XML tree
- bool go(const char* path);
+ /// move to the position defined by xpath in XML tree
+ bool go(const XPath& xpath);
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
/// search for child and go down
- bool go_down(const char* name, int n=0)
- {
- XMLNode* node = _cur->find(name, n);
+ bool go_down(const char* child_name, int n=0)
+ {
+ const XMLNode* node = XPathElement(child_name, n).const_find(_cur);
if (node) {
go_to(node);
@@ -1698,7 +1837,7 @@
XMLBool(LPCXSSTR value, bool def=false)
{
- if (value && *value)
+ if (value && *value)//@@ also handle white space and return def instead of
false
_value = !XS_icmp(value, XS_TRUE);
else
_value = def;
@@ -1788,7 +1927,7 @@
XMLInt(LPCXSSTR value, int def=0)
{
- if (value && *value)
+ if (value && *value)//@@ also handle white space and return def instead of 0
_value = XS_toi(value);
else
_value = def;
@@ -1813,7 +1952,7 @@
{
XS_CHAR buffer[32];
XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, _value);
- return buffer;
+ return XS_String(buffer);
}
protected:
@@ -1869,7 +2008,7 @@
{
LPTSTR end;
- if (value && *value)
+ if (value && *value)//@@ also handle white space and return def instead of 0
_value = XS_tod(value, &end);
else
_value = def;
@@ -1895,7 +2034,7 @@
{
XS_CHAR buffer[32];
XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, _value);
- return buffer;
+ return XS_String(buffer);
}
protected:
@@ -2022,6 +2161,7 @@
};
+ // read option (for example configuration) values from XML node attributes
template<typename T>
inline void read_option(T& var, const_XMLPos& cfg, LPCXSSTR key)
{
@@ -2031,6 +2171,7 @@
var = val;
}
+ // read integer option values from XML node attributes
template<>
inline void read_option(int& var, const_XMLPos& cfg, LPCXSSTR key)
{
@@ -2039,6 +2180,141 @@
if (!val.empty())
var = XS_toi(val.c_str());
}
+
+
+inline void XMLPos::set_property(const XS_String& key, int value, const
XS_String& name)
+{
+ smart_create(name, XS_KEY, key);
+ XMLIntRef(_cur, XS_VALUE) = value;
+ back();
+}
+
+inline void XMLPos::set_property(const XS_String& key, double value, const
XS_String& name)
+{
+ smart_create(name, XS_KEY, key);
+ XMLDoubleRef(_cur, XS_VALUE) = value;
+ back();
+}
+
+inline void XMLPos::set_property(const XS_String& key, const XS_String& value,
const XS_String& name)
+{
+ smart_create(name, XS_KEY, key);
+ put(XS_VALUE, value);
+ back();
+}
+
+inline void XMLPos::set_property(const XS_String& key, const XMLBool& value,
const XS_String& name)
+{
+ smart_create(name, XS_KEY, key);
+ XMLBoolRef(_cur, XS_VALUE) = value;
+ back();
+}
+
+
+ /// a key/value pair for property data access
+struct XMLProperty {
+ XMLProperty(const XMLNode* node)
+ : _key(node->get(XS_KEY)),
+ _value(node->get(XS_VALUE))
+ {
+ }
+
+ XS_String _key;
+ XS_String _value;
+};
+
+
+ /// utility class to read property settings from a XML tree
+struct XMLPropertyReader
+{
+ XMLPropertyReader(const XMLNode::Children& children)
+ : _filter(children, XS_PROPERTY),
+ _begin(_filter.begin(), _filter.end()),
+ _end(_filter.end(), _filter.end())
+ {
+ }
+
+ XMLPropertyReader(const XMLNode* node)
+ : _filter(node, XS_PROPERTY),
+ _begin(_filter.begin(), _filter.end()),
+ _end(_filter.end(), _filter.end())
+ {
+ }
+
+ /// internal iterator class
+ struct const_iterator
+ {
+ typedef const_XMLChildrenFilter::const_iterator BaseIterator;
+ typedef const_iterator myType;
+
+ const_iterator(BaseIterator begin, BaseIterator end)
+ : _cur(begin),
+ _end(end)
+ {
+ }
+
+ operator BaseIterator()
+ {
+ return _cur;
+ }
+
+ XMLProperty operator*() const
+ {
+ return XMLProperty(*_cur);
+ }
+
+ const XMLNode* get_node() const
+ {
+ return *_cur;
+ }
+
+ myType& operator++()
+ {
+ ++_cur;
+
+ return *this;
+ }
+
+ myType operator++(int)
+ {
+ myType ret = *this;
+
+ ++_cur;
+
+ return ret;
+ }
+
+ bool operator==(const myType& other) const
+ {
+ return _cur == other._cur;
+ }
+
+ bool operator!=(const myType& other) const
+ {
+ return _cur != other._cur;
+ }
+
+ protected:
+ BaseIterator _cur;
+ BaseIterator _end;
+ };
+
+ const_iterator begin()
+ {
+ return _begin;
+ }
+
+ const_iterator end()
+ {
+ return _end;
+ }
+
+protected:
+ const_XMLChildrenFilter _filter;
+
+ const_iterator _begin;
+ const_iterator _end;
+};
#ifdef _MSC_VER
@@ -2245,7 +2521,7 @@
typedef std::char_traits<_E> _Tr;
explicit fast_ostringbuffer()
- {_Init(0, 0, /*std::_Noread*/4);} // optimized for ios::out mode
+ {_Init(0, 0, std::_Noread);} // optimized for ios::out mode
virtual ~fast_ostringbuffer()
{_Tidy();}
@@ -2274,10 +2550,10 @@
else if (_ALSIZE < _Alsize)
_Alsize = _ALSIZE;
- if (_Strmode & std::strstreambuf::_Allocated)
+ if (_Strmode & std::_Allocated)
_Al.deallocate(eback(), _Os);
- _Strmode |= std::strstreambuf::_Allocated;
+ _Strmode |= std::_Allocated;
if (_Os == 0)
{_Seekhigh = _P;
@@ -2291,24 +2567,24 @@
return _C;}}
- void _Init(const _E *_S, size_t _N, std::strstreambuf::_Strstate _M)
+ void _Init(const _E *_S, size_t _N, std::_Strstate _M)
{_Pendsave = 0, _Seekhigh = 0;
_Alsize = _MINSIZE, _Strmode = _M;
setg(0, 0, 0);
setp(0, 0);}
void _Tidy()
- {if (_Strmode & std::strstreambuf::_Allocated)
+ {if (_Strmode & std::_Allocated)
_Al.deallocate(eback(), (pptr() != 0 ? epptr() : egptr()) - eback());
_Seekhigh = 0;
- _Strmode &= ~std::strstreambuf::_Allocated;}
+ _Strmode &= ~std::_Allocated;}
private:
enum {_ALSIZE = 65536/*512*/, _MINSIZE = 32768/*32*/}; // bigger buffer sizes
_E *_Pendsave, *_Seekhigh;
int _Alsize;
- std::strstreambuf::_Strstate _Strmode;
+ std::_Strstate _Strmode;
std::allocator<_E> _Al;
};
@@ -2545,37 +2821,10 @@
}
/// create node and move to it
- void create(const XS_String& name)
- {
- if (!_stack.empty()) {
- StackEntry& last = _stack.top();
-
- if (last._state < PRE_CLOSED) {
- write_attributes(last);
- close_pre(last);
- }
-
- ++last._children;
- }
-
- StackEntry entry;
- entry._node_name = name;
- _stack.push(entry);
-
- write_pre(entry);
- }
+ void create(const XS_String& name);
/// go back to previous position
- bool back()
- {
- if (!_stack.empty()) {
- write_post(_stack.top());
-
- _stack.pop();
- return true;
- } else
- return false;
- }
+ bool back();
/// attribute setting
void put(const XS_String& attr_name, const XS_String& value)
@@ -2626,62 +2875,10 @@
static XS_String s_empty_attr;
- void close_pre(StackEntry& entry)
- {
- _out << '>';
-
- entry._state = PRE_CLOSED;
- }
-
- void write_pre(StackEntry& entry)
- {
- if (_format._pretty >= PRETTY_LINEFEED)
- _out << _format._endl;
-
- if (_format._pretty == PRETTY_INDENT)
- {
- for(size_t i=_stack.size(); --i>0; )
- _out << XML_INDENT_SPACE;
- }
- _out << '<' << EncodeXMLString(entry._node_name);
- //entry._state = PRE;
- }
-
- void write_attributes(StackEntry& entry)
- {
- for(AttrMap::const_iterator it=entry._attributes.begin(); it!=entry._attributes.end();
++it)
- _out << ' ' << EncodeXMLString(it->first) <<
"=\"" << EncodeXMLString(it->second) <<
"\"";
-
- entry._state = ATTRIBUTES;
- }
-
- void write_post(StackEntry& entry)
- {
- if (entry._state < ATTRIBUTES)
- write_attributes(entry);
-
- if (entry._children || !entry._content.empty()) {
- if (entry._state < PRE_CLOSED)
- close_pre(entry);
-
- _out << entry._content;
- //entry._state = CONTENT;
-
- if (_format._pretty>=PRETTY_LINEFEED && entry._content.empty())
- _out << _format._endl;
-
- if (_format._pretty==PRETTY_INDENT && entry._content.empty())
- {
- for(size_t i=_stack.size(); --i>0; )
- _out << XML_INDENT_SPACE;
- }
- _out << "</" << EncodeXMLString(entry._node_name) <<
">";
- } else {
- _out << "/>";
- }
-
- entry._state = POST;
- }
+ void close_pre(StackEntry& entry);
+ void write_pre(StackEntry& entry);
+ void write_attributes(StackEntry& entry);
+ void write_post(StackEntry& entry);
};
Modified: trunk/reactos/base/shell/explorer/utility/xs-native.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/base/shell/explorer/utilit…
==============================================================================
--- trunk/reactos/base/shell/explorer/utility/xs-native.cpp [iso-8859-1] (original)
+++ trunk/reactos/base/shell/explorer/utility/xs-native.cpp [iso-8859-1] Thu May 1
16:17:35 2008
@@ -1,8 +1,8 @@
//
- // XML storage C++ classes version 1.2
+ // XML storage C++ classes version 1.3
//
- // Copyright (c) 2006, 2007 Martin Fuchs <martin-fuchs(a)gmx.net>
+ // Copyright (c) 2006, 2007, 2008 Martin Fuchs <martin-fuchs(a)gmx.net>
//
/// \file xs-native.cpp
@@ -94,7 +94,7 @@
_buffer_str.erase();
}
- void append(char c)
+ void append(int c)
{
size_t wpos = _wptr-_buffer;
@@ -104,7 +104,7 @@
_wptr = _buffer + wpos;
}
- *_wptr++ = c;
+ *_wptr++ = static_cast<char>(c);
}
const std::string& str(bool utf8) // returns UTF-8 encoded buffer content
@@ -149,8 +149,7 @@
if (*q == '?')
++q;
- while(isxmlsym(*q))
- ++q;
+ q = get_xmlsym_end_utf8(q);
#ifdef XS_STRING_UTF8
return XS_String(p, q-p);
@@ -175,8 +174,7 @@
else if (*p == '?')
++p;
- while(isxmlsym(*p))
- ++p;
+ p = get_xmlsym_end_utf8(p);
// read attributes from buffer
while(*p && *p!='>' && *p!='/') {
@@ -185,8 +183,7 @@
const char* attr_name = p;
- while(isxmlsym(*p))
- ++p;
+ p = get_xmlsym_end_utf8(p);
if (*p != '=')
break; //@TODO error handling
@@ -360,8 +357,7 @@
// read white space
for(;;) {
// check for the encoding of the first line end
- if (!_endl_defined)
- {
+ if (!_endl_defined) {
if (c == '\n') {
_format._endl = "\n";
_endl_defined = true;
@@ -370,6 +366,7 @@
_endl_defined = true;
}
}
+
c = get();
if (c == EOF)