update explorer/xmlstorage

svn path=/trunk/; revision=29338
This commit is contained in:
Martin Fuchs 2007-10-01 19:53:58 +00:00
parent 9c40044087
commit b511687db0
5 changed files with 192 additions and 169 deletions

View file

@ -93,12 +93,12 @@ void ExplorerGlobals::read_persistent()
_cfg_dir.printf(TEXT("%s\\ReactOS"), (LPCTSTR)SpecialFolderFSPath(CSIDL_APPDATA,0));
_cfg_path.printf(TEXT("%s\\ros-explorer-cfg.xml"), _cfg_dir.c_str());
if (!_cfg.read(_cfg_path)) {
if (!_cfg.read_file(_cfg_path)) {
//if (_cfg._last_error != XML_ERROR_NO_ELEMENTS)
MessageBox(_hwndDesktop, _cfg._errors.str(),
TEXT("ROS Explorer - reading user settings"), MB_OK);
_cfg.read(TEXT("explorer-cfg-template.xml"));
_cfg.read_file(TEXT("explorer-cfg-template.xml"));
}
// read bookmarks
@ -115,7 +115,7 @@ void ExplorerGlobals::write_persistent()
// write configuration file
RecursiveCreateDirectory(_cfg_dir);
_cfg.write(_cfg_path);
_cfg.write_file(_cfg_path);
_favorites.write(_favorites_path);
}

View file

@ -426,7 +426,7 @@ bool Favorites::read(LPCTSTR path)
{
XMLDoc xbel;
if (!xbel.read(path)) {
if (!xbel.read_file(path)) {
MessageBox(g_Globals._hwndDesktop, xbel._errors.str(),
TEXT("ROS Explorer - reading bookmark file"), MB_OK);
}
@ -457,7 +457,7 @@ void Favorites::write(LPCTSTR path) const
xbel._format._doctype._public = "+//IDN python.org//DTD XML Bookmark Exchange Language 1.0//EN//XML";
xbel._format._doctype._system = "http://www.python.org/topics/xml/dtds/xbel-1.0.dtd";
xbel.write(path);
xbel.write_file(path);
}
/// import Internet Explorer bookmarks from Favorites folder

View file

@ -1,6 +1,6 @@
//
// XML storage classes version 1.2
// XML storage C++ classes version 1.2
//
// Copyright (c) 2004, 2005, 2006, 2007 Martin Fuchs <martin-fuchs@gmx.net>
//
@ -44,6 +44,10 @@
//#include "xmlstorage.h"
#include <precomp.h>
#ifdef __GNUC__
#include <alloca.h>
#endif
namespace XMLStorage {
@ -152,50 +156,7 @@ const XMLNode* XMLNode::find_relative(const char* path) const
// parse relative path
while(*path) {
const char* slash = strchr(path, '/');
if (slash == path)
return NULL;
size_t l = slash? slash-path: strlen(path);
std::string comp(path, l);
path += l;
// 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;
int n = 0;
if (bracket) {
std::string expr = unescape(bracket, '[', ']');
const char* p = expr.c_str();
n = atoi(p); // read index number
if (n)
n = n - 1; // convert into zero based index
const char* at = strchr(p, '@');
if (at) {
p = at + 1;
const char* equal = strchr(p, '=');
// read attribute name and value
if (equal) {
attr_name = unescape(p, equal-p);
attr_value = unescape(equal+1);
}
}
}
if (attr_name.empty())
// search n.th child node with specified name
node = node->find(child_name, n);
else
// search n.th child node with specified name and matching attribute value
node = node->find(child_name, attr_name, attr_value, n);
node = const_cast<XMLNode*>(node)->get_child_relative(path, false); // get_child_relative() ist const for create==false
if (!node)
return NULL;
@ -213,62 +174,7 @@ XMLNode* XMLNode::create_relative(const char* path)
// parse relative path
while(*path) {
const char* slash = strchr(path, '/');
if (slash == path)
return NULL;
size_t l = slash? slash-path: strlen(path);
std::string comp(path, l);
path += l;
// 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;
int n = 0;
if (bracket) {
std::string expr = unescape(bracket, '[', ']');
const char* p = expr.c_str();
n = atoi(p); // read index number
if (n)
n = n - 1; // convert into zero based index
const char* at = strchr(p, '@');
if (at) {
p = at + 1;
const char* equal = strchr(p, '=');
// read attribute name and value
if (equal) {
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 = node->find(child_name, n);
else
// search n.th child node with specified name and matching attribute value
child = node->find(child_name, attr_name, attr_value, n);
if (!child) {
child = new XMLNode(child_name);
node->add_child(child);
if (!attr_name.empty())
(*node)[attr_name] = attr_value;
}
node = child;
node = node->get_child_relative(path, true);
if (*path == '/')
++path;
@ -277,6 +183,66 @@ XMLNode* XMLNode::create_relative(const char* path)
return node;
}
XMLNode* XMLNode::get_child_relative(const char*& path, bool create)
{
const char* slash = strchr(path, '/');
if (slash == path)
return NULL;
size_t l = slash? slash-path: strlen(path);
std::string comp(path, l);
path += l;
// 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;
int n = 0;
if (bracket) {
std::string expr = unescape(bracket, '[', ']');
const char* p = expr.c_str();
n = atoi(p); // read index number
if (n)
n = n - 1; // convert into zero based index
const char* at = strchr(p, '@');
if (at) {
p = at + 1;
const char* equal = strchr(p, '=');
// read attribute name and value
if (equal) {
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);
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;
}
/// encode XML string literals
std::string EncodeXMLString(const XS_String& str, bool cdata)
@ -426,7 +392,7 @@ XS_String DecodeXMLString(const XS_String& str)
/// write node with children tree to output stream using original white space
void XMLNode::write_worker(std::ostream& out, int indent) const
void XMLNode::write_worker(std::ostream& out) const
{
out << _leading << '<' << EncodeXMLString(*this);
@ -437,7 +403,7 @@ void XMLNode::write_worker(std::ostream& out, int indent) const
out << '>' << _content;
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
(*it)->write_worker(out, indent+1);
(*it)->write_worker(out);
out << _end_leading << "</" << EncodeXMLString(*this) << '>';
} else
@ -455,8 +421,12 @@ void XMLNode::plain_write_worker(std::ostream& out) const
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
if (!_children.empty()/*@@ || !_content.empty()*/) {
out << ">";
// strip leading white space from content
const char* content = _content.c_str();
while(isspace((unsigned char)*content)) ++content;
if (!_children.empty() || *content) {
out << ">" << content;
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
(*it)->plain_write_worker(out);
@ -478,8 +448,15 @@ void XMLNode::pretty_write_worker(std::ostream& out, const XMLFormat& format, in
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
if (!_children.empty()/*@@ || !_content.empty()*/) {
out << '>' << format._endl;
// strip leading white space from content
const char* content = _content.c_str();
while(isspace((unsigned char)*content)) ++content;
if (!_children.empty() || *content) {
out << '>' << content;
if (!_children.empty())
out << format._endl;
for(Children::const_iterator it=_children.begin(); it!=_children.end(); ++it)
(*it)->pretty_write_worker(out, format, indent+1);
@ -496,26 +473,34 @@ void XMLNode::pretty_write_worker(std::ostream& out, const XMLFormat& format, in
/// write node with children tree to output stream using smart formating
void XMLNode::smart_write_worker(std::ostream& out, const XMLFormat& format, int indent) const
{
if (_leading.empty())
// strip the first line feed from _leading
const char* leading = _leading.c_str();
if (*leading == '\n') ++leading;
if (!*leading)
for(int i=indent; i--; )
out << XML_INDENT_SPACE;
else
out << _leading;
out << leading;
out << '<' << EncodeXMLString(*this);
for(AttributeMap::const_iterator it=_attributes.begin(); it!=_attributes.end(); ++it)
out << ' ' << EncodeXMLString(it->first) << "=\"" << EncodeXMLString(it->second) << "\"";
if (_children.empty() && _content.empty())
// strip leading white space from content
const char* content = _content.c_str();
while(isspace((unsigned char)*content)) ++content;
if (_children.empty() && !*content)
out << "/>";
else {
out << '>';
if (_content.empty())
if (!*content)
out << format._endl;
else
out << _content;
out << content;
Children::const_iterator it = _children.begin();
@ -523,11 +508,15 @@ void XMLNode::smart_write_worker(std::ostream& out, const XMLFormat& format, int
for(; it!=_children.end(); ++it)
(*it)->smart_write_worker(out, format, indent+1);
if (_end_leading.empty())
// strip the first line feed from _end_leading
const char* end_leading = _end_leading.c_str();
if (*end_leading == '\n') ++end_leading;
if (!*end_leading)
for(int i=indent; i--; )
out << XML_INDENT_SPACE;
else
out << _end_leading;
out << end_leading;
} else
out << _end_leading;
@ -710,16 +699,14 @@ void XMLReaderBase::XmlDeclHandler(const char* version, const char* encoding, in
/// notifications about XML start tag
void XMLReaderBase::StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes)
{
// search for end of first line
const char* s = _content.c_str();
const char* e = s + _content.length();
const char* p = s;
const char* e = p + _content.length();
for(; p<e; ++p)
if (*p == '\n') {
++p;
// search for content end leaving only white space for leading
for(p=e; p>s; --p)
if (!isspace((unsigned char)p[-1]))
break;
}
if (p != s)
if (_pos->_children.empty()) { // no children in last node?
@ -754,29 +741,27 @@ void XMLReaderBase::StartElementHandler(const XS_String& name, const XMLNode::At
/// notifications about XML end tag
void XMLReaderBase::EndElementHandler()
{
// search for end of first line
const char* s = _content.c_str();
const char* p = s;
const char* e = p + _content.length();
const char* e = s + _content.length();
const char* p;
if (!strncmp(s,"<![CDATA[",9) && !strncmp(e-3,"]]>",3)) {
s += 9;
p = (e-=3);
} else
for(; p<e; ++p)
if (*p == '\n') {
++p;
} else {
// search for content end leaving only white space for _end_leading
for(p=e; p>s; --p)
if (!isspace((unsigned char)p[-1]))
break;
}
}
if (p != s)
if (_pos->_children.empty()) // no children in current node?
_pos->_content.append(s, p-s);
else if (_last_tag == TAG_START)
_pos->_content.append(s, p-s);
else
if (_last_tag == TAG_START)
_pos->_content.append(s, p-s);
else
_pos->_children.back()->_trailing.append(s, p-s);
_pos->_children.back()->_trailing.append(s, p-s);
if (p != e)
_pos->_end_leading.assign(p, e-p);

View file

@ -1,6 +1,6 @@
//
// XML storage classes version 1.2
// XML storage C++ classes version 1.2
//
// Copyright (c) 2004, 2005, 2006, 2007 Martin Fuchs <martin-fuchs@gmx.net>
//
@ -155,6 +155,10 @@ typedef XMLCh XML_Char;
#include <tchar.h>
#include <malloc.h>
#ifndef _MSC_VER
#include <stdio.h> // vsnprintf(), snprintf()
#endif
#else
#include <wchar.h>
@ -476,11 +480,13 @@ extern XS_String DecodeXMLString(const XS_String& str);
#ifdef __GNUC__
#include <ext/stdio_filebuf.h>
typedef __gnu_cxx::stdio_filebuf<char> STDIO_FILEBUF;
#else
typedef std::filebuf STDIO_FILEBUF;
#define FILE_FILEBUF __gnu_cxx::stdio_filebuf<char>
#elif defined(_MSC_VER)
#define FILE_FILEBUF std::filebuf
#endif
#ifdef FILE_FILEBUF
/// base class for XMLStorage::tifstream and XMLStorage::tofstream
struct FileHolder
{
@ -521,7 +527,7 @@ struct tifstream : public std::istream, FileHolder
}
protected:
STDIO_FILEBUF _buf;
FILE_FILEBUF _buf;
};
/// output file stream with ANSI/UNICODE file names
@ -546,9 +552,37 @@ struct tofstream : public std::ostream, FileHolder
}
protected:
STDIO_FILEBUF _buf;
FILE_FILEBUF _buf;
};
#else // FILE_FILEBUF
#ifdef UNICODE
#error UNICODE not supported for this platform
#endif
struct tifstream : public std::ifstream
{
typedef std::ifstream super;
tifstream(const char* path)
: super(path, std::ios::in|std::ios::binary)
{
}
};
struct tofstream : public std::ofstream
{
typedef std::ofstream super;
tofstream(const char* path)
: super(path, std::ios::out|std::ios::binary)
{
}
};
#endif
// write XML files with 2 spaces indenting
#define XML_INDENT_SPACE " "
@ -902,7 +936,7 @@ struct XMLNode : public XS_String
_attributes[attr_name] = value;
}
/// C++ write access to an attribute
/// index operator write access to an attribute
XS_String& operator[](const XS_String& attr_name)
{
return _attributes[attr_name];
@ -1023,7 +1057,7 @@ struct XMLNode : public XS_String
break;
case FORMAT_ORIGINAL:
write_worker(out, indent);
write_worker(out);
break;
default: // FORMAT_SMART
@ -1113,10 +1147,13 @@ protected:
/// relative XPath create function
XMLNode* create_relative(const char* path);
void write_worker(std::ostream& out, int indent) 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
};
@ -1367,7 +1404,7 @@ struct XMLPos
return *_cur;
}
/// C++ access to current node
/// automatic access to current node
operator const XMLNode*() const {return _cur;}
operator XMLNode*() {return _cur;}
@ -1378,9 +1415,9 @@ struct XMLPos
XMLNode& operator*() {return *_cur;}
/// attribute access
XS_String get(const XS_String& attr_name) const
XS_String get(const XS_String& attr_name, LPCXSSTR def=XS_EMPTY_STR) const
{
return _cur->get(attr_name);
return _cur->get(attr_name, def);
}
/// attribute setting
@ -1389,7 +1426,7 @@ struct XMLPos
_cur->put(attr_name, value);
}
/// C++ attribute access
/// 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];}
@ -1564,7 +1601,7 @@ struct const_XMLPos
return *_cur;
}
/// C++ access to current node
/// automatic access to current node
operator const XMLNode*() const {return _cur;}
const XMLNode* operator->() const {return _cur;}
@ -1577,7 +1614,7 @@ struct const_XMLPos
return _cur->get(attr_name);
}
/// C++ attribute access
/// index operator attribute access
template<typename T> XS_String get(const T& attr_name) const {return _cur->get(attr_name);}
/// go back to previous position
@ -1944,23 +1981,23 @@ private:
};
/// type converter for string data with write access
struct XMStringRef
struct XMLStringRef
{
XMStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
XMLStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
: _ref((*node)[attr_name])
{
if (_ref.empty())
assign(def);
}
XMStringRef(XMLNode* node, const XS_String& node_name, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
XMLStringRef(const XS_String& node_name, XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_EMPTY)
: _ref(node->subvalue(node_name, attr_name))
{
if (_ref.empty())
assign(def);
}
XMStringRef& operator=(const XS_String& value)
XMLStringRef& operator=(const XS_String& value)
{
assign(value);
@ -2304,11 +2341,11 @@ struct XMLDoc : public XMLNode
XMLDoc(LPCTSTR path)
: XMLNode("")
{
read(path);
read_file(path);
}
#ifdef XS_USE_XERCES
bool read(LPCTSTR path)
bool read_file(LPCTSTR path)
{
XMLReader reader(this, path);
@ -2319,7 +2356,7 @@ struct XMLDoc : public XMLNode
#endif
}
bool read(const char* buffer, size_t len, const std::string& system_id=std::string())
bool read_buffer(const char* buffer, size_t len, const std::string& system_id=std::string())
{
XMLReader reader(this, (const XMLByte*)buffer, len, system_id);
@ -2328,7 +2365,7 @@ struct XMLDoc : public XMLNode
#else // XS_USE_XERCES
bool read(LPCTSTR path)
bool read_file(LPCTSTR path)
{
tifstream in(path);
XMLReader reader(this, in);
@ -2340,7 +2377,7 @@ struct XMLDoc : public XMLNode
#endif
}
bool read(const char* buffer, size_t len, const std::string& system_id=std::string())
bool read_buffer(const char* buffer, size_t len, const std::string& system_id=std::string())
{
std::istringstream in(std::string(buffer, len));
@ -2377,7 +2414,8 @@ struct XMLDoc : public XMLNode
return true;
}
/// write XML stream preserving previous white space and comments
/// write XML stream
// FORMAT_SMART: preserving previous white space and comments
bool write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART) const
{
_format.print_header(out, mode!=FORMAT_PLAIN);
@ -2398,7 +2436,7 @@ struct XMLDoc : public XMLNode
return write(out, FORMAT_PRETTY);
}
bool write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const
bool write_file(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const
{
tofstream out(path);
@ -2454,7 +2492,7 @@ struct XMLMessageFromString : public XMLMessage
{
XMLMessageFromString(const std::string& xml_str, const std::string& system_id=std::string())
{
read(xml_str.c_str(), xml_str.length(), system_id);
read_buffer(xml_str.c_str(), xml_str.length(), system_id);
}
};
@ -2465,7 +2503,7 @@ struct XMLMessageReader : public XMLPos
XMLMessageReader(const std::string& xml_str, const std::string& system_id=std::string())
: XMLPos(&_msg)
{
_msg.read(xml_str.c_str(), xml_str.length(), system_id);
_msg.read_buffer(xml_str.c_str(), xml_str.length(), system_id);
}
const XMLDoc& get_document()
@ -2543,7 +2581,7 @@ struct XMLWriter
_stack.top()._attributes[attr_name] = value;
}
/// C++ write access to an attribute
/// index operator write access to an attribute
XS_String& operator[](const XS_String& attr_name)
{
if (_stack.empty())

View file

@ -1,6 +1,6 @@
//
// XML storage classes version 1.2
// XML storage C++ classes version 1.2
//
// Copyright (c) 2006, 2007 Martin Fuchs <martin-fuchs@gmx.net>
//
@ -224,7 +224,7 @@ protected:
char* _buffer;
char* _wptr;
size_t _len;
std::string _buffer_str; // UF-8 encoded
std::string _buffer_str; // UTF-8 encoded
};
bool XMLReaderBase::parse()
@ -386,7 +386,7 @@ bool XMLReaderBase::parse()
buffer.reset();
}
return true;
return true; //TODO return false on invalid XML
}
int XMLReaderBase::eat_endl()