欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

xmlstorage.h

一个类似windows
H
第 1 页 / 共 3 页
字号:
		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 + -