📄 xmlstorage.h
字号:
if (!val.empty())
var = val;
}
template<>
inline void read_option(int& var, const_XMLPos& cfg, LPCXSSTR key)
{
const XS_String& val = cfg.get(key);
if (!val.empty())
var = XS_toi(val.c_str());
}
#ifdef _MSC_VER
#pragma warning(disable: 4355)
#endif
/// XML reader base class
struct XMLReaderBase
#ifdef XS_USE_XERCES
: public HandlerBase
#endif
{
#ifdef XS_USE_XERCES
XMLReaderBase(XMLNode* node, InputSource* source, bool adoptSource=false);
virtual ~XMLReaderBase();
void read();
protected:
SAXParser* _parser;
InputSource* _source;
bool _deleteSource;
virtual void XMLDecl(const XMLCh* const versionStr, const XMLCh* const encodingStr,
const XMLCh* const standaloneStr, const XMLCh* const actualEncodingStr);
// Handlers for the SAX DocumentHandler interface
virtual void setDocumentLocator(const Locator* const locator);
virtual void startElement(const XMLCh* const name, AttributeList& attributes);
virtual void endElement(const XMLCh* const name);
virtual void characters(const XMLCh* const chars, const unsigned int length);
virtual void ignorableWhitespace(const XMLCh* const chars, const unsigned int length);
// Handlers for the SAX ErrorHandler interface
virtual void error(const SAXParseException& e);
virtual void fatalError(const SAXParseException& e);
virtual void warning(const SAXParseException& e);
virtual void resetErrors();
#elif defined(XS_USE_EXPAT) // !XS_USE_XERCES
XMLReaderBase(XMLNode* node);
virtual ~XMLReaderBase();
protected:
XML_Parser _parser;
static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone=-1);
static void XMLCALL XML_StartElementHandler(void* userData, const XML_Char* name, const XML_Char** atts);
static void XMLCALL XML_EndElementHandler(void* userData, const XML_Char* name);
static void XMLCALL XML_DefaultHandler(void* userData, const XML_Char* s, int len);
static std::string get_expat_error_string(XML_Error error_code);
#else // XS_USE_EXPAT
XMLReaderBase(XMLNode* node)
: _pos(node),
_endl_defined(false),
_utf8(false)
{
_last_tag = TAG_NONE;
}
virtual ~XMLReaderBase();
bool parse();
#endif
public:
#ifndef XS_USE_XERCES
void read();
std::string get_position() const;
#endif
const XMLFormat& get_format() const {return _format;}
const char* get_endl() const {return _endl_defined? _format._endl: "\n";}
const XMLErrorList& get_errors() const {return _errors;}
const XMLErrorList& get_warnings() const {return _warnings;}
void clear_errors() {_errors.clear(); _warnings.clear();}
#ifdef XMLNODE_LOCATION
const char* _display_path; // character pointer for fast reference in XMLLocation
#ifdef XS_USE_XERCES
const Locator* _locator;
#endif
XMLLocation get_location() const;
#endif
protected:
XMLPos _pos;
std::string _content; // UTF-8 encoded
enum {TAG_NONE, TAG_START, TAG_END} _last_tag;
XMLErrorList _errors;
XMLErrorList _warnings;
XMLFormat _format;
bool _endl_defined;
#ifdef XS_USE_XERCES
//@@
#elif defined(XS_USE_EXPAT)
virtual int read_buffer(char* buffer, int len) = 0;
#else
virtual int get() = 0;
int eat_endl();
bool _utf8;
#endif
void finish_read();
virtual void XmlDeclHandler(const char* version, const char* encoding, int standalone);
virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes);
virtual void EndElementHandler();
#if defined(XS_USE_XERCES) || defined(XS_USE_EXPAT)
virtual void DefaultHandler(const XML_Char* s, int len);
#else
virtual void DefaultHandler(const std::string& s);
#endif
};
/// XML file reader
#ifdef XS_USE_XERCES
struct XercesXMLReader : public XMLReaderBase
{
XercesXMLReader(XMLNode* node, InputSource* source, bool adoptSource=false)
: XMLReaderBase(node, source, adoptSource)
{
}
XercesXMLReader(XMLNode* node, LPCTSTR path);
XercesXMLReader(XMLNode* node, const XMLByte* buffer, size_t bytes, const std::string& system_id=std::string());
};
#define XMLReader XercesXMLReader
#elif defined(XS_USE_EXPAT)
struct ExpatXMLReader : public XMLReaderBase
{
ExpatXMLReader(XMLNode* node, std::istream& in)
: XMLReaderBase(node),
_in(in)
{
}
/// read XML stream into XML tree below _pos
int read_buffer(char* buffer, int len)
{
if (!_in.good())
return -1;
_in.read(buffer, len);
return _in.gcount();
}
protected:
std::istream& _in;
};
#define XMLReader ExpatXMLReader
#else // XS_USE_XERCES, XS_USE_EXPAT
struct XMLReader : public XMLReaderBase
{
XMLReader(XMLNode* node, std::istream& in)
: XMLReaderBase(node),
_in(in)
{
}
/// read one character from XML stream
int get()
{
return _in.get();
}
protected:
std::istream& _in;
};
#endif // XS_USE_XERCES
#if defined(_MSC_VER) && _MSC_VER<1400
struct fast_ostringbuffer : public std::streambuf
{
typedef char _E;
typedef std::char_traits<_E> _Tr;
explicit fast_ostringbuffer()
{_Init(0, 0, std::_Noread);} // optimized for ios::out mode
virtual ~fast_ostringbuffer()
{_Tidy();}
std::string str() const
{if (pptr() != 0)
{std::string _Str(pbase(),
(_Seekhigh<pptr()? pptr(): _Seekhigh) - pbase());
return _Str;}
else
return std::string();}
protected:
virtual int_type overflow(int_type _C = _Tr::eof())
{if (_Tr::eq_int_type(_Tr::eof(), _C))
return _Tr::not_eof(_C);
else if (pptr() != 0 && pptr() < epptr())
{*_Pninc() = _Tr::to_char_type(_C);
return _C;}
else
{size_t _Os = gptr() == 0 ? 0 : epptr() - eback();
size_t _Ns = _Os + _Alsize;
_E *_P = _Al.allocate(_Ns, (void *)0);
if (0 < _Os)
_Tr::copy(_P, eback(), _Os);
else if (_ALSIZE < _Alsize)
_Alsize = _ALSIZE;
if (_Strmode & std::_Allocated)
_Al.deallocate(eback(), _Os);
_Strmode |= std::_Allocated;
if (_Os == 0)
{_Seekhigh = _P;
setp(_P, _P + _Ns);
setg(_P, _P, _P); }
else
{_Seekhigh = _Seekhigh - eback() + _P;
setp(pbase() - eback() + _P, pptr() - eback() + _P, _P + _Ns);
setg(_P, _P, _P);}
*_Pninc() = _Tr::to_char_type(_C);
return _C;}}
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::_Allocated)
_Al.deallocate(eback(), (pptr() != 0 ? epptr() : egptr()) - eback());
_Seekhigh = 0;
_Strmode &= ~std::_Allocated;}
private:
enum {_ALSIZE = 65536/*512*/, _MINSIZE = 32768/*32*/}; // bigger buffer sizes
_E *_Pendsave, *_Seekhigh;
int _Alsize;
std::_Strstate _Strmode;
std::allocator<_E> _Al;
};
struct fast_ostringstream : public std::iostream
{
typedef std::iostream super;
explicit fast_ostringstream()
: super(&_Sb) {}
std::string str() const
{return _Sb.str();}
private:
fast_ostringbuffer _Sb;
};
#else
typedef std::ostringstream fast_ostringstream;
#endif
/// XML document holder
struct XMLDoc : public XMLNode
{
XMLDoc()
: XMLNode("")
{
}
XMLDoc(LPCTSTR path)
: XMLNode("")
{
read(path);
}
#ifdef XS_USE_XERCES
bool read(LPCTSTR path)
{
XMLReader reader(this, path);
#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
return read(reader, std::string(ANS(path)));
#else
return read(reader, XS_String(path));
#endif
}
bool read(const char* buffer, size_t len, const std::string& system_id=std::string())
{
XMLReader reader(this, (const XMLByte*)buffer, len, system_id);
return read(reader, system_id);
}
#else // XS_USE_XERCES
bool read(LPCTSTR path)
{
tifstream in(path);
XMLReader reader(this, in);
#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)
return read(reader, std::string(ANS(path)));
#else
return read(reader, XS_String(path));
#endif
}
bool read(const char* buffer, size_t len, const std::string& system_id=std::string())
{
std::istringstream in(std::string(buffer, len));
return read(in, system_id);
}
bool read(std::istream& in, const std::string& system_id=std::string())
{
XMLReader reader(this, in);
return read(reader, system_id);
}
#endif // XS_USE_XERCES
bool read(XMLReaderBase& reader, const std::string& display_path)
{
#ifdef XMLNODE_LOCATION
// make a string copy to handle temporary string objects
_display_path = display_path;
reader._display_path = _display_path.c_str();
#endif
reader.clear_errors();
reader.read();
_format = reader.get_format();
_format._endl = reader.get_endl();
if (!reader.get_errors().empty()) {
_errors = reader.get_errors();
return false;
}
return true;
}
/// write XML stream preserving previous white space and comments
bool write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART) const
{
_format.print_header(out, mode!=FORMAT_PLAIN);
if (_children.size() == 1)
_children.front()->write(out, _format, mode);
else if (!_children.empty()) {
//throw Exception("more than one XML root!");
return false;
}
return out.good();
}
/// write XML stream with formating
bool write_formating(std::ostream& out) const
{
return write(out, FORMAT_PRETTY);
}
bool write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const
{
tofstream out(path);
return write(out, mode);
}
bool write_formating(LPCTSTR path) const
{
tofstream out(path);
return write_formating(out);
}
XMLFormat _format;
XMLErrorList _errors;
#ifdef XMLNODE_LOCATION
std::string _display_path;
#endif
};
/// XML message wrapper
struct XMLMessage : public XMLDoc
{
XMLMessage(const char* name)
: _pos(this)
{
_pos.create(name);
}
std::string toString() const
{
std::ostringstream out;
write(out);
return out.str();
}
XMLPos _pos;
protected:
XMLMessage()
: _pos(this)
{
}
};
/// helper structure to read XML messages from strings
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);
}
};
/// Reader for XML Messages
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);
}
const XMLDoc& get_document()
{
return _msg;
}
protected:
XMLDoc _msg;
};
/// on the fly XML writer
struct XMLWriter
{
XMLWriter(std::ostream& out, const XMLFormat& format=XMLFormat())
: _pofstream(NULL),
_out(out),
_format(format)
{
format.print_header(_out, false); // _format._endl is printed in write_pre()
}
XMLWriter(LPCTSTR path, const XMLFormat& format=XMLFormat())
: _pofstream(new tofstream(path)),
_out(*_pofstream),
_format(format)
{
format.print_header(_out, false); // _format._endl is printed in write_pre()
}
~XMLWriter()
{
_out << _format._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, bool cdata=false)
{
if (!_stack.empty())
_stack.top()._content = EncodeXMLString(s.c_str(), cdata);
}
// public for access in StackEntry
enum WRITESTATE {
NOTHING, /*PRE,*/ ATTRIBUTES, PRE_CLOSED, /*CONTENT,*/ POST
};
protected:
tofstream* _pofstream;
std::ostream& _out;
const XMLFormat&_format;
typedef XMLNode::AttributeMap AttrMap;
/// container for XMLWriter state information
struct StackEntry {
XS_String _node_name;
AttrMap _attributes;
std::string _content;
WRITESTATE _state;
bool _children;
StackEntry() : _state(NOTHING), _children(false) {}
};
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 (_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;
}
};
} // namespace XMLStorage
#define _XMLSTORAGE_H
#endif // _XMLSTORAGE_H
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -