diff --git a/reactos/base/shell/explorer/explorer.cpp b/reactos/base/shell/explorer/explorer.cpp index 4de57f68858..566b79c27dc 100644 --- a/reactos/base/shell/explorer/explorer.cpp +++ b/reactos/base/shell/explorer/explorer.cpp @@ -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); } diff --git a/reactos/base/shell/explorer/taskbar/favorites.cpp b/reactos/base/shell/explorer/taskbar/favorites.cpp index 579db029bb7..3c919367c3a 100644 --- a/reactos/base/shell/explorer/taskbar/favorites.cpp +++ b/reactos/base/shell/explorer/taskbar/favorites.cpp @@ -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 diff --git a/reactos/base/shell/explorer/utility/xmlstorage.cpp b/reactos/base/shell/explorer/utility/xmlstorage.cpp index f4477017af2..856a2cdd4bf 100644 --- a/reactos/base/shell/explorer/utility/xmlstorage.cpp +++ b/reactos/base/shell/explorer/utility/xmlstorage.cpp @@ -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 // @@ -44,6 +44,10 @@ //#include "xmlstorage.h" #include +#ifdef __GNUC__ +#include +#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(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 << "'; } 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(; ps; --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,"",3)) { s += 9; p = (e-=3); - } else - for(; ps; --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); diff --git a/reactos/base/shell/explorer/utility/xmlstorage.h b/reactos/base/shell/explorer/utility/xmlstorage.h index 8e2d80cb299..418ad2ec811 100644 --- a/reactos/base/shell/explorer/utility/xmlstorage.h +++ b/reactos/base/shell/explorer/utility/xmlstorage.h @@ -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 // @@ -155,6 +155,10 @@ typedef XMLCh XML_Char; #include #include +#ifndef _MSC_VER +#include // vsnprintf(), snprintf() +#endif + #else #include @@ -476,11 +480,13 @@ extern XS_String DecodeXMLString(const XS_String& str); #ifdef __GNUC__ #include -typedef __gnu_cxx::stdio_filebuf STDIO_FILEBUF; -#else -typedef std::filebuf STDIO_FILEBUF; +#define FILE_FILEBUF __gnu_cxx::stdio_filebuf +#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 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 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()) diff --git a/reactos/base/shell/explorer/utility/xs-native.cpp b/reactos/base/shell/explorer/utility/xs-native.cpp index 59c923d65e8..c5bb891cec3 100644 --- a/reactos/base/shell/explorer/utility/xs-native.cpp +++ b/reactos/base/shell/explorer/utility/xs-native.cpp @@ -1,6 +1,6 @@ // - // XML storage classes version 1.2 + // XML storage C++ classes version 1.2 // // Copyright (c) 2006, 2007 Martin Fuchs // @@ -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()