- Bugfix for UTF-8 strings - insert more XS_vsnprintf() calls - additional comments - struct XMLWriter Modified: trunk/reactos/subsys/system/explorer/utility/xmlstorage.cpp Modified: trunk/reactos/subsys/system/explorer/utility/xmlstorage.h _____
Modified: trunk/reactos/subsys/system/explorer/utility/xmlstorage.cpp --- trunk/reactos/subsys/system/explorer/utility/xmlstorage.cpp 2005-09-21 18:24:16 UTC (rev 17972) +++ trunk/reactos/subsys/system/explorer/utility/xmlstorage.cpp 2005-09-21 21:44:39 UTC (rev 17973) @@ -36,6 +36,10 @@
*/
+#ifndef _NO_COMMENT +#define _NO_COMMENT // no #pragma comment(lib, ...) statements in .lib files +#endif + //#include "xmlstorage.h" #include <precomp.h>
@@ -51,6 +55,7 @@ namespace XMLStorage {
+ /// remove escape characters from zero terminated string static std::string unescape(const char* s, char b='"', char e='"') { const char* end = s + strlen(s); @@ -68,6 +73,7 @@ return std::string(s, end-s); }
+ /// remove escape characters from string with specified length static std::string unescape(const char* s, int l, char b='"', char e='"') { const char* end = s + l; @@ -391,6 +397,7 @@ }
+ /// return error strings for Expat errors std::string XMLReaderBase::get_error_string() const { XML_Error error = XML_GetErrorCode(_parser); @@ -453,6 +460,7 @@ }
+ /// encode XML string literals std::string EncodeXMLString(const XS_String& str) { LPCXSSTR s = str.c_str(); @@ -492,6 +500,7 @@ #endif }
+ /// decode XML string literals XS_String DecodeXMLString(const XS_String& str) { LPCXSSTR s = str.c_str(); _____
Modified: trunk/reactos/subsys/system/explorer/utility/xmlstorage.h --- trunk/reactos/subsys/system/explorer/utility/xmlstorage.h 2005-09-21 18:24:16 UTC (rev 17972) +++ trunk/reactos/subsys/system/explorer/utility/xmlstorage.h 2005-09-21 21:44:39 UTC (rev 17973) @@ -140,8 +140,8 @@
XS_String& operator=(LPCWSTR s) {assign(s); return *this;} #ifdef XS_STRING_UTF8 void assign(const XS_String& s) {assign(s.c_str());} - void assign(LPCWSTR s) {if (s) {int bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, bl, b, bl, 0, 0));} else erase();} - void assign(LPCWSTR s, int l) {int bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, l, b, bl, 0, 0));} else erase();} + void assign(LPCWSTR s) {if (s) {int bl=2*wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, bl, b, bl, 0, 0));} else erase();} + void assign(LPCWSTR s, int l) {int bl=2*l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, l, b, bl, 0, 0));} else erase();} #else // if !UNICODE && !XS_STRING_UTF8 void assign(LPCWSTR s) {if (s) {int bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, bl, b, bl, 0, 0));} else erase();} void assign(LPCWSTR s, int l) {int bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, l, b, bl, 0, 0));} else erase();} @@ -169,7 +169,7 @@ XS_CHAR b[BUFFER_LEN];
va_start(l, fmt); - super::assign(b, XS_vsprintf(b, fmt, l)); + super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l)); va_end(l);
return *this; @@ -179,7 +179,7 @@ { XS_CHAR b[BUFFER_LEN];
- super::assign(b, XS_vsprintf(b, fmt, l)); + super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
return *this; } @@ -190,7 +190,7 @@ XS_CHAR b[BUFFER_LEN];
va_start(l, fmt); - super::append(b, XS_vsprintf(b, fmt, l)); + super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l)); va_end(l);
return *this; @@ -200,7 +200,7 @@ { XS_CHAR b[BUFFER_LEN];
- super::append(b, XS_vsprintf(b, fmt, l)); + super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
return *this; } @@ -336,6 +336,7 @@
#else
+ /// converter from Expat strings to XMLStorage internal strings struct String_from_XML_Char : public XS_String { String_from_XML_Char(const XML_Char* str) @@ -397,6 +398,7 @@ typedef std::map<XS_String, XS_String> AttributeMap; #endif
+ /// internal children node list struct Children : public std::list<XMLNode*> { void assign(const Children& other) @@ -678,9 +680,10 @@ } #endif
- /// XPath find functions + /// XPath find function (const) const XMLNode* find_relative(const char* path) const;
+ /// XPath find function XMLNode* find_relative(const char* path) {return const_cast<XMLNode*>(const_cast<const XMLNode*>(this)->find_relative(path));}
@@ -708,6 +711,7 @@ { }
+ /// internal iterator class struct iterator { typedef XMLNode::Children::iterator BaseIterator; @@ -806,6 +810,7 @@ { }
+ /// internal iterator class struct const_iterator { typedef XMLNode::Children::const_iterator BaseIterator; @@ -954,6 +959,7 @@ return _cur->get(attr_name); }
+ /// attribute setting void put(const XS_String& attr_name, const XS_String& value) { _cur->put(attr_name, value); @@ -1230,6 +1236,7 @@ #endif
+ /// type converter for boolean data struct XMLBool { XMLBool(bool value=false) @@ -1277,6 +1284,7 @@ void operator=(const XMLBool&); // disallow assignment operations };
+ /// type converter for boolean data with write access struct XMLBoolRef { XMLBoolRef(XMLNode* node, const XS_String& attr_name, bool def=false) @@ -1318,6 +1326,7 @@ };
+ /// type converter for integer data struct XMLInt { XMLInt(int value) @@ -1362,6 +1371,7 @@ void operator=(const XMLInt&); // disallow assignment operations };
+ /// type converter for integer data with write access struct XMLIntRef { XMLIntRef(XMLNode* node, const XS_String& attr_name, int def=0) @@ -1395,6 +1405,7 @@ };
+ /// type converter for string data struct XMLString { XMLString(const XS_String& value) @@ -1437,6 +1448,7 @@ void operator=(const XMLString&); // disallow assignment operations };
+ /// type converter for string data with write access struct XMStringRef { XMStringRef(XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_TEXT("")) @@ -1580,6 +1592,7 @@ };
+ /// management of XML file headers struct XMLHeader { XMLHeader(const std::string& xml_version="1.0", const std::string& encoding="UTF-8", const std::string& doctype="") @@ -1595,6 +1608,7 @@
if (!_doctype.empty()) out << _doctype << '\n'; + if (!_additional.empty()) out << _additional << '\n'; } @@ -1606,6 +1620,7 @@ };
+ /// XML document holder struct XMLDoc : public XMLNode { XMLDoc() @@ -1715,6 +1730,7 @@ };
+ /// XML message wrapper struct XMLMessage : public XMLDoc { XMLMessage(const char* name) @@ -1727,6 +1743,174 @@ };
+enum PRETTY_FLAGS { + PRETTY_PLAIN = 0, + PRETTY_LINEFEED = 1, + PRETTY_INDENT = 2 +}; + +struct XMLWriter +{ + XMLWriter(std::ostream& out, PRETTY_FLAGS pretty=PRETTY_INDENT, const XMLHeader& header=XMLHeader()) + : _pofstream(NULL), + _out(out), + _pretty(pretty) + { + header.print(_out, false); + } + + XMLWriter(LPCTSTR path, PRETTY_FLAGS pretty=PRETTY_INDENT, const XMLHeader& header=XMLHeader()) + : _pofstream(new tofstream(path)), + _out(*_pofstream), + _pretty(pretty) + { + header.print(_out, false); + } + + ~XMLWriter() + { + _out << std::endl; + delete _pofstream; + } + + /// 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); + } + + /// go back to previous position + bool back() + { + if (!_stack.empty()) { + write_post(_stack.top()); + + _stack.pop(); + return true; + } else + return false; + } + + /// attribute setting + void put(const XS_String& attr_name, const XS_String& value) + { + if (!_stack.empty()) + _stack.top()._attributes[attr_name] = value; + } + + /// C++ write access to an attribute + XS_String& operator[](const XS_String& attr_name) + { + if (_stack.empty()) + return s_empty_attr; + + return _stack.top()._attributes[attr_name]; + } + + void set_content(const XS_String& s) + { + if (!_stack.empty()) + _stack.top()._content = s; + } + + // public for access in StackEntry + enum WRITESTATE { + NOTHING, /*PRE,*/ ATTRIBUTES, PRE_CLOSED, /*CONTENT,*/ POST + }; + +protected: + tofstream* _pofstream; + std::ostream& _out; + PRETTY_FLAGS _pretty; + + typedef XMLNode::AttributeMap AttrMap; + + struct StackEntry { + XS_String _node_name; + AttrMap _attributes; + std::string _content; + WRITESTATE _state; + bool _children; + + StackEntry() : _children(false), _state(NOTHING) {} + }; + + std::stack<StackEntry> _stack; + + static XS_String s_empty_attr; + + void close_pre(StackEntry& entry) + { + _out << '>'; + + entry._state = PRE_CLOSED; + } + + void write_pre(StackEntry& entry) + { + if (_pretty >= PRETTY_LINEFEED) + _out << std::endl; + + if (_pretty == PRETTY_INDENT) + for(int 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 (_pretty>=PRETTY_LINEFEED && entry._content.empty()) + _out << std::endl; + + if (_pretty==PRETTY_INDENT && entry._content.empty()) + for(int i=_stack.size(); --i>0; ) + _out << XML_INDENT_SPACE; + + _out << "</" << EncodeXMLString(entry._node_name) << ">"; + } else { + _out << "/>"; + } + + entry._state = POST; + } +}; + + } // namespace XMLStorage
#define _XMLSTORAGE_H