xmlstorage.h
字号:
if (_ref.empty())
assign(def);
}
operator bool() const
{
return !XS_icmp(_ref.c_str(), XS_TRUE);
}
bool operator!() const
{
return XS_icmp(_ref.c_str(), XS_TRUE)? true: false;
}
XMLBoolRef& operator=(bool value)
{
assign(value);
return *this;
}
void assign(bool value)
{
_ref.assign(value? XS_TRUE: XS_FALSE);
}
void toggle()
{
assign(!operator bool());
}
protected:
XS_String& _ref;
};
/// type converter for integer data
struct XMLInt
{
XMLInt(int value)
: _value(value)
{
}
XMLInt(LPCXSSTR value, int def=0)
{
if (value && *value)
_value = XS_toi(value);
else
_value = def;
}
XMLInt(const XMLNode* node, const XS_String& attr_name, int def=0)
{
const XS_String& value = node->get(attr_name);
if (!value.empty())
_value = XS_toi(value.c_str());
else
_value = def;
}
operator int() const
{
return _value;
}
operator XS_String() const
{
XS_CHAR buffer[32];
XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, _value);
return buffer;
}
protected:
int _value;
private:
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)
: _ref((*node)[attr_name])
{
if (_ref.empty())
assign(def);
}
XMLIntRef& operator=(int value)
{
assign(value);
return *this;
}
operator int() const
{
return XS_toi(_ref.c_str());
}
void assign(int value)
{
XS_CHAR buffer[32];
XS_snprintf(buffer, COUNTOF(buffer), XS_INTFMT, value);
_ref.assign(buffer);
}
protected:
XS_String& _ref;
};
/// type converter for numeric data
struct XMLDouble
{
XMLDouble(double value)
: _value(value)
{
}
XMLDouble(LPCXSSTR value, double def=0.)
{
LPTSTR end;
if (value && *value)
_value = XS_tod(value, &end);
else
_value = def;
}
XMLDouble(const XMLNode* node, const XS_String& attr_name, double def=0.)
{
LPTSTR end;
const XS_String& value = node->get(attr_name);
if (!value.empty())
_value = XS_tod(value.c_str(), &end);
else
_value = def;
}
operator double() const
{
return _value;
}
operator XS_String() const
{
XS_CHAR buffer[32];
XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, _value);
return buffer;
}
protected:
double _value;
private:
void operator=(const XMLDouble&); // disallow assignment operations
};
/// type converter for numeric data with write access
struct XMLDoubleRef
{
XMLDoubleRef(XMLNode* node, const XS_String& attr_name, double def=0.)
: _ref((*node)[attr_name])
{
if (_ref.empty())
assign(def);
}
XMLDoubleRef& operator=(double value)
{
assign(value);
return *this;
}
operator double() const
{
LPTSTR end;
return XS_tod(_ref.c_str(), &end);
}
void assign(double value)
{
XS_CHAR buffer[32];
XS_snprintf(buffer, COUNTOF(buffer), XS_FLOATFMT, value);
_ref.assign(buffer);
}
protected:
XS_String& _ref;
};
/// type converter for string data
struct XMLString
{
XMLString(const XS_String& value)
: _value(value)
{
}
XMLString(LPCXSSTR value, LPCXSSTR def=XS_TEXT(""))
{
if (value && *value)
_value = value;
else
_value = def;
}
XMLString(const XMLNode* node, const XS_String& attr_name, LPCXSSTR def=XS_TEXT(""))
{
const XS_String& value = node->get(attr_name);
if (!value.empty())
_value = value;
else
_value = def;
}
operator const XS_String&() const
{
return _value;
}
const XS_String& c_str() const
{
return _value;
}
protected:
XS_String _value;
private:
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(""))
: _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_TEXT(""))
: _ref(node->subvalue(node_name, attr_name))
{
if (_ref.empty())
assign(def);
}
XMStringRef& operator=(const XS_String& value)
{
assign(value);
return *this;
}
operator const XS_String&() const
{
return _ref;
}
void assign(const XS_String& value)
{
_ref.assign(value);
}
protected:
XS_String& _ref;
};
template<typename T>
inline void read_option(T& var, const_XMLPos& cfg, LPCXSSTR key)
{
const XS_String& val = cfg.get(key);
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
{
XMLReaderBase(XMLNode* node)
: _pos(node),
_parser(XML_ParserCreate(NULL))
{
XML_SetUserData(_parser, this);
XML_SetXmlDeclHandler(_parser, XML_XmlDeclHandler);
XML_SetElementHandler(_parser, XML_StartElementHandler, XML_EndElementHandler);
XML_SetDefaultHandler(_parser, XML_DefaultHandler);
_last_tag = TAG_NONE;
}
virtual ~XMLReaderBase()
{
XML_ParserFree(_parser);
}
XML_Status read();
std::string get_position() const;
std::string get_instructions() const {return _instructions;}
XML_Error get_error_code() const;
std::string get_error_string() const;
#ifdef XMLNODE_LOCATION
const char* _display_path; // character pointer for fast reference in XMLLocation
XMLLocation get_location() const;
#endif
virtual int read_buffer(char* buffer, int len) = 0;
protected:
XMLPos _pos;
XML_Parser _parser;
std::string _xml_version;
std::string _encoding;
std::string _instructions;
std::string _content;
enum {TAG_NONE, TAG_START, TAG_END} _last_tag;
void finish_read();
virtual void XmlDeclHandler(const XML_Char* version, const XML_Char* encoding, int standalone);
virtual void StartElementHandler(const XS_String& name, const XMLNode::AttributeMap& attributes);
virtual void EndElementHandler();
virtual void DefaultHandler(const XML_Char* s, int len);
static void XMLCALL XML_XmlDeclHandler(void* userData, const XML_Char* version, const XML_Char* encoding, int standalone);
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);
};
/// XML file reader
struct XMLReader : public XMLReaderBase
{
XMLReader(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;
};
/// 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="")
: _version(xml_version),
_encoding(encoding),
_doctype(doctype)
{
}
void print(std::ostream& out, bool pretty=true) const
{
out << "<?xml version=\"" << _version << "\" encoding=\"" << _encoding << "\"?>";
if (pretty)
out << std::endl;
if (!_doctype.empty())
out << _doctype << '\n';
if (!_additional.empty())
out << _additional << '\n';
}
std::string _version;
std::string _encoding;
std::string _doctype;
std::string _additional;
};
/// XML document holder
struct XMLDoc : public XMLNode
{
XMLDoc()
: XMLNode(""),
_last_error(XML_ERROR_NONE)
{
}
XMLDoc(LPCTSTR path)
: XMLNode(""),
_last_error(XML_ERROR_NONE)
{
read(path);
}
bool read(std::istream& in)
{
XMLReader reader(this, in);
return read(reader);
}
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(XMLReaderBase& reader)
{
XML_Status status = reader.read();
_header._additional = reader.get_instructions();
if (status == XML_STATUS_ERROR) {
std::ostringstream out;
out << "input stream" << reader.get_position() << " " << reader.get_error_string();
_last_error = reader.get_error_code();
_last_error_msg = out.str();
}
return status != XML_STATUS_ERROR;
}
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
XML_Status status = reader.read();
_header._additional = reader.get_instructions();
if (status == XML_STATUS_ERROR) {
std::ostringstream out;
out << display_path << reader.get_position() << " " << reader.get_error_string();
_last_error = reader.get_error_code();
_last_error_msg = out.str();
}
return status != XML_STATUS_ERROR;
}
/// write XML stream preserving previous white space and comments
std::ostream& write(std::ostream& out, WRITE_MODE mode=FORMAT_SMART) const
{
_header.print(out);
if (!_children.empty())
_children.front()->write(out);
return out;
}
/// write XML stream with formating
std::ostream& write_formating(std::ostream& out) const
{
return write(out, FORMAT_PRETTY);
}
void write(LPCTSTR path, WRITE_MODE mode=FORMAT_SMART) const
{
tofstream out(path);
write(out, mode);
}
void write_formating(LPCTSTR path) const
{
tofstream out(path);
write_formating(out);
}
XMLHeader _header;
XML_Error _last_error;
std::string _last_error_msg;
#ifdef XMLNODE_LOCATION
std::string _display_path;
#endif
};
/// XML message wrapper
struct XMLMessage : public XMLDoc
{
XMLMessage(const char* name)
: _pos(this)
{
_pos.create(name);
}
XMLPos _pos;
};
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 = EncodeXMLString(s.c_str());
}
// 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() : _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 (_pretty >= PRETTY_LINEFEED)
_out << std::endl;
if (_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 (_pretty>=PRETTY_LINEFEED && entry._content.empty())
_out << std::endl;
if (_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 + -