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

xmlstorage.h

一个类似windows
H
第 1 页 / 共 3 页
字号:

 //
 // XML storage classes
 //
 // xmlstorage.h
 //
 // Copyright (c) 2004, 2005, 2006 Martin Fuchs <martin-fuchs@gmx.net>
 //


/*

  All rights reserved.

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright
	notice, this list of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright
	notice, this list of conditions and the following disclaimer in
	the documentation and/or other materials provided with the
	distribution.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef _XMLSTORAGE_H


#if _MSC_VER>=1400
#ifndef _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES			1
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT	1
#define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES			1
#endif
#endif


#ifndef _NO_EXPAT

//#include "expat.h"
#include <expat/expat.h>

#else

typedef char XML_Char;

enum XML_Status {
	XML_STATUS_ERROR = 0,
	XML_STATUS_OK = 1
};

enum XML_Error {
	XML_ERROR_NONE,
	XML_ERROR_FAILURE
};

#endif


#ifdef _MSC_VER
#pragma warning(disable: 4786)

#ifndef _NO_COMMENT
#ifndef _NO_EXPAT
#ifdef XML_STATIC
#ifndef _DEBUG
#pragma comment(lib, "libexpatMT")
#endif
#else
#pragma comment(lib, "libexpat")
#endif
#endif

#ifndef _STRING_DEFINED // _STRING_DEFINED only allowed if using xmlstorage.cpp embedded in the project
#if defined(_DEBUG) && defined(_DLL)	// DEBUG version only supported with MSVCRTD
#if _MSC_VER==1400
#pragma comment(lib, "xmlstorage-vc8d")
#else
#pragma comment(lib, "xmlstorage-vc6d")
#endif
#else
#ifdef _DLL
#if _MSC_VER==1400
#pragma comment(lib, "xmlstorage-vc8")
#else
#pragma comment(lib, "xmlstorage-vc6")
#endif
#elif defined(_MT)
#if _MSC_VER==1400
#pragma comment(lib, "xmlstorage-vc8t")
#else
#pragma comment(lib, "xmlstorage-vc6t")
#endif
#else
 // -ML is no more supported by VS2005.
#pragma comment(lib, "xmlstorage-vc6l")
#endif
#endif
#endif // _STRING_DEFINED

#endif // _NO_COMMENT

#endif // _MSC_VER


#ifdef UNICODE
#ifndef _UNICODE
#define _UNICODE
#endif
#else
#ifdef _UNICODE
#define UNICODE
#endif
#endif

#include <windows.h>	// for LPCTSTR

#include <tchar.h>
#include <malloc.h>

#include <fstream>
#include <sstream>
#include <string>
#include <stack>
#include <list>
#include <map>


#ifndef BUFFER_LEN
#define BUFFER_LEN 2048
#endif


namespace XMLStorage {


#ifndef XS_String

#ifdef XS_STRING_UTF8
#define XS_CHAR char
#define XS_TEXT(x) x
#define LPXSSTR LPSTR
#define LPCXSSTR LPCSTR
#define XS_icmp stricmp
#define XS_nicmp strnicmp
#define XS_toi atoi
#define XS_tod strtod
#define XS_len strlen
#define XS_snprintf snprintf
#define XS_vsnprintf vsnprintf
#else
#define XS_CHAR TCHAR
#define XS_TEXT(x) TEXT(x)
#define LPXSSTR LPTSTR
#define LPCXSSTR LPCTSTR
#define XS_icmp _tcsicmp
#define XS_nicmp _tcsnicmp
#define XS_toi _ttoi
#define XS_tod _tcstod
#define XS_len _tcslen
#define XS_snprintf _sntprintf
#define XS_vsnprintf _vsntprintf
#endif

#ifndef COUNTOF
#if _MSC_VER>=1400
#define COUNTOF _countof
#else
#define COUNTOF(b) (sizeof(b)/sizeof(b[0]))
#endif
#endif

#if defined(_STRING_DEFINED) && !defined(XS_STRING_UTF8)

#define XS_String String

#else // _STRING_DEFINED, !XS_STRING_UTF8

 /// string class for TCHAR strings

struct XS_String
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
 : public std::wstring
#else
 : public std::string
#endif
{
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
	typedef std::wstring super;
#else
	typedef std::string super;
#endif

	XS_String() {}

	XS_String(LPCXSSTR s) {if (s) super::assign(s);}
	XS_String(LPCXSSTR s, size_t l) : super(s, l) {}

	XS_String(const super& other) : super(other) {}
	XS_String(const XS_String& other) : super(other) {}

#if defined(UNICODE) && !defined(XS_STRING_UTF8)
	XS_String(LPCSTR s) {assign(s);}
	XS_String(LPCSTR s, size_t l) {assign(s, l);}
	XS_String(const std::string& other) {assign(other.c_str());}
	XS_String& operator=(LPCSTR s) {assign(s); return *this;}
	void assign(LPCSTR s) {if (s) {size_t bl=strlen(s); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, bl, b, bl));} else erase();}
	void assign(LPCSTR s, size_t l) {if (s) {size_t bl=l; LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); super::assign(b, MultiByteToWideChar(CP_ACP, 0, s, l, b, bl));} else erase();}
#else
	XS_String(LPCWSTR s) {assign(s);}
	XS_String(LPCWSTR s, size_t l) {assign(s, l);}
	XS_String(const std::wstring& other) {assign(other.c_str());}
	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) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();}
	void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_UTF8, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();}
#else // if !UNICODE && !XS_STRING_UTF8
	void assign(LPCWSTR s) {if (s) {size_t bl=wcslen(s); LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)bl, b, (int)bl, 0, 0));} else erase();}
	void assign(LPCWSTR s, size_t l) {size_t bl=l; if (s) {LPSTR b=(LPSTR)alloca(bl); super::assign(b, WideCharToMultiByte(CP_ACP, 0, s, (int)l, b, (int)bl, 0, 0));} else erase();}
#endif
#endif

	XS_String& operator=(LPCXSSTR s) {if (s) super::assign(s); else erase(); return *this;}
	XS_String& operator=(const super& s) {super::assign(s); return *this;}
	void assign(LPCXSSTR s) {super::assign(s);}
	void assign(LPCXSSTR s, size_t l) {super::assign(s, l);}

	operator LPCXSSTR() const {return c_str();}

#ifdef XS_STRING_UTF8
	operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_UTF8, 0, c_str(), bl, b, bl));}
#elif defined(UNICODE)
	operator std::string() const {size_t bl=length(); LPSTR b=(LPSTR)alloca(bl); return std::string(b, WideCharToMultiByte(CP_ACP, 0, c_str(), bl, b, bl, 0, 0));}
#else
	operator std::wstring() const {size_t bl=length(); LPWSTR b=(LPWSTR)alloca(sizeof(WCHAR)*bl); return std::wstring(b, MultiByteToWideChar(CP_ACP, 0, c_str(), (int)bl, b, (int)bl));}
#endif

	XS_String& printf(LPCXSSTR fmt, ...)
	{
		va_list l;
		XS_CHAR b[BUFFER_LEN];

		va_start(l, fmt);
		super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
		va_end(l);

		return *this;
	}

	XS_String& vprintf(LPCXSSTR fmt, va_list l)
	{
		XS_CHAR b[BUFFER_LEN];

		super::assign(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));

		return *this;
	}

	XS_String& appendf(LPCXSSTR fmt, ...)
	{
		va_list l;
		XS_CHAR b[BUFFER_LEN];

		va_start(l, fmt);
		super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));
		va_end(l);

		return *this;
	}

	XS_String& vappendf(LPCXSSTR fmt, va_list l)
	{
		XS_CHAR b[BUFFER_LEN];

		super::append(b, XS_vsnprintf(b, COUNTOF(b), fmt, l));

		return *this;
	}
};

#endif // _STRING_DEFINED, !XS_STRING_UTF8

#endif // XS_String


#ifndef XS_STRING_UTF8

inline void assign_utf8(XS_String& s, const char* str)
{
	int lutf8 = (int)strlen(str);

#ifdef UNICODE
	LPTSTR buffer = (LPTSTR)alloca(sizeof(TCHAR)*lutf8);
	int l = MultiByteToWideChar(CP_UTF8, 0, str, lutf8, buffer, lutf8);
#else
	LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*lutf8);
	int l = MultiByteToWideChar(CP_UTF8, 0, str, lutf8, wbuffer, lutf8);

	int bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
	l = WideCharToMultiByte(CP_ACP, 0, wbuffer, l, buffer, bl, 0, 0);
#endif

	s.assign(buffer, l);
}

inline std::string get_utf8(LPCTSTR s, size_t l)
{
#ifdef UNICODE
	size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
	l = WideCharToMultiByte(CP_UTF8, 0, s, (int)l, buffer, (int)bl, 0, 0);
#else
	LPWSTR wbuffer = (LPWSTR)alloca(sizeof(WCHAR)*l);
	l = MultiByteToWideChar(CP_ACP, 0, s, (int)l, wbuffer, (int)l);

	size_t bl=2*l; LPSTR buffer = (LPSTR)alloca(bl);
	l = WideCharToMultiByte(CP_UTF8, 0, wbuffer, (int)l, buffer, (int)bl, 0, 0);
#endif

	return std::string(buffer, l);
}

inline std::string get_utf8(const XS_String& s)
{
	return get_utf8(s.c_str(), s.length());
}

#endif // XS_STRING_UTF8

extern std::string EncodeXMLString(const XS_String& str);
extern XS_String DecodeXMLString(const XS_String& str);


#ifdef __GNUC__
#include <ext/stdio_filebuf.h>
typedef __gnu_cxx::stdio_filebuf<char> STDIO_FILEBUF;
#else
typedef std::filebuf STDIO_FILEBUF;
#endif

struct FileHolder
{
	FileHolder(LPCTSTR path, LPCTSTR mode)
	{
#ifdef __STDC_WANT_SECURE_LIB__ // secure CRT functions using VS 2005
		if (_tfopen_s(&_pfile, path, mode) != 0)
			_pfile = NULL;
#else
		_pfile = _tfopen(path, mode);
#endif
	}

	~FileHolder()
	{
		if (_pfile)
			fclose(_pfile);
	}

protected:
	FILE*	_pfile;
};

 /// input file stream with ANSI/UNICODE file names
struct tifstream : public std::istream, FileHolder
{
	typedef std::istream super;

	tifstream(LPCTSTR path)
	 :	super(&_buf),
		FileHolder(path, TEXT("rb")),	// binary mode is important for XMLReader::read_buffer() with MinGW libraries
#ifdef __GNUC__
		_buf(_pfile, std::ios::in)
#else
		_buf(_pfile)
#endif
	{
	}

protected:
	STDIO_FILEBUF _buf;
};

 /// output file stream with ANSI/UNICODE file names
struct tofstream : public std::ostream, FileHolder
{
	typedef std::ostream super;

	tofstream(LPCTSTR path)
	 :	super(&_buf),
		FileHolder(path, TEXT("w")),
#ifdef __GNUC__
		_buf(_pfile, std::ios::out)
#else
		_buf(_pfile)
#endif
	{
	}

	~tofstream()
	{
		flush();
	}

protected:
	STDIO_FILEBUF _buf;
};


 // write XML files with 2 spaces indenting
#define XML_INDENT_SPACE "  "


#ifdef XML_UNICODE	// Are XML_Char strings UTF-16 encoded?

typedef XS_String String_from_XML_Char;

#elif defined(XS_STRING_UTF8)

typedef XS_String String_from_XML_Char;

#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)
	{
		assign_utf8(*this, str);
	}
};

#endif


#if defined(UNICODE) && !defined(XS_STRING_UTF8)

 // optimization for faster UNICODE/ASCII string comparison without temporary A/U conversion
inline bool operator==(const XS_String& s1, const char* s2)
{
	LPCWSTR p = s1;
	const unsigned char* q = (const unsigned char*)s2;

	while(*p && *q)
		if (*p++ != *q++)
			return false;

	return *p == *q;
};

#endif


#ifdef XMLNODE_LOCATION
 /// location of XML Node including XML file name
struct XMLLocation
{
	XMLLocation()
	 :	_pdisplay_path(NULL),
		_line(0),
		_column(0)
	{
	}

	XMLLocation(const char* display_path, int line, int column)
	 :	_pdisplay_path(display_path),
		_line(line),
		_column(column)
	{
	}

	std::string str() const;

protected:
	const char* _pdisplay_path; // character pointer for fast reference
	int _line;
	int _column;
};
#endif


 /// in memory representation of an XML node
struct XMLNode : public XS_String
{
#if defined(UNICODE) && !defined(XS_STRING_UTF8)
	 // optimized read access without temporary A/U conversion when using ASCII attribute names
	struct AttributeMap : public std::map<XS_String, XS_String>
	{
		typedef std::map<XS_String, XS_String> super;

		const_iterator find(const char* x) const
		{
			for(const_iterator it=begin(); it!=end(); ++it)
				if (it->first == x)
					return it;

			return end();
		}

		const_iterator find(const key_type& x) const
		{
			return super::find(x);
		}

		iterator find(const key_type& x)
		{
			return super::find(x);
		}
	};
#else
	typedef std::map<XS_String, XS_String> AttributeMap;
#endif

	 /// internal children node list
	struct Children : public std::list<XMLNode*>
	{
		void assign(const Children& other)
		{
			clear();

			for(Children::const_iterator it=other.begin(); it!=other.end(); ++it)
				push_back(new XMLNode(**it));
		}

		void clear()
		{
			while(!empty()) {
				XMLNode* node = back();
				pop_back();

				node->clear();
				delete node;
			}
		}
	};

	 // access to protected class members for XMLPos and XMLReader
	friend struct XMLPos;
	friend struct const_XMLPos;
	friend struct XMLReaderBase;

	XMLNode(const XS_String& name)
	 :	XS_String(name)
	{
	}

	XMLNode(const XS_String& name, const std::string& leading)
	 :	XS_String(name),
		_leading(leading)
	{
	}

	XMLNode(const XMLNode& other)
	 :	XS_String(other),
		_attributes(other._attributes),
		_leading(other._leading),
		_content(other._content),
		_end_leading(other._end_leading),
		_trailing(other._trailing)
#ifdef XMLNODE_LOCATION
		, _location(other._location)
#endif
	{
		for(Children::const_iterator it=other._children.begin(); it!=other._children.end(); ++it)
			_children.push_back(new XMLNode(**it));
	}

	virtual ~XMLNode()
	{
		while(!_children.empty()) {
			delete _children.back();
			_children.pop_back();
		}
	}

	void clear()
	{
		_leading.erase();
		_content.erase();
		_end_leading.erase();
		_trailing.erase();

		_attributes.clear();
		_children.clear();

		XS_String::erase();
	}

	XMLNode& operator=(const XMLNode& other)
	{
		_children.assign(other._children);

		_attributes = other._attributes;

		_leading = other._leading;
		_content = other._content;
		_end_leading = other._end_leading;
		_trailing = other._trailing;

		return *this;
	}

	 /// add a new child node
	void add_child(XMLNode* child)
	{
		_children.push_back(child);
	}

	 /// write access to an attribute
	void put(const XS_String& attr_name, const XS_String& value)
	{
		_attributes[attr_name] = value;
	}

	 /// C++ write access to an attribute
	XS_String& operator[](const XS_String& attr_name)
	{
		return _attributes[attr_name];
	}

	 /// read only access to an attribute
	template<typename T> XS_String get(const T& attr_name) const
	{
		AttributeMap::const_iterator found = _attributes.find(attr_name);

		if (found != _attributes.end())
			return found->second;
		else
			return XS_String();
	}

	 /// convenient value access in children node
	XS_String subvalue(const XS_String& name, const XS_String& attr_name, int n=0) const
	{
		const XMLNode* node = find(name, n);

		if (node)
			return node->get(attr_name);
		else
			return XS_String();
	}

	 /// convenient storage of distinct values in children node
	XS_String& subvalue(const XS_String& name, const XS_String& attr_name, int n=0)
	{
		XMLNode* node = find(name, n);

		if (!node) {
			node = new XMLNode(name);
			add_child(node);
		}

		return (*node)[attr_name];
	}

#if defined(UNICODE) && !defined(XS_STRING_UTF8)
	 /// convenient value access in children node
	XS_String subvalue(const char* name, const char* attr_name, int n=0) const
	{
		const XMLNode* node = find(name, n);

		if (node)
			return node->get(attr_name);
		else
			return XS_String();
	}

	 /// convenient storage of distinct values in children node
	XS_String& subvalue(const char* name, const XS_String& attr_name, int n=0)
	{
		XMLNode* node = find(name, n);

		if (!node) {
			node = new XMLNode(name);
			add_child(node);
		}

		return (*node)[attr_name];
	}
#endif

	const Children& get_children() const
	{
		return _children;
	}

	Children& get_children()
	{
		return _children;
	}

	const AttributeMap& get_attributes() const
	{
		return _attributes;
	}

	AttributeMap& get_attributes()
	{
		return _attributes;
	}

	XS_String get_content() const
	{
#ifdef XS_STRING_UTF8
		const XS_String& ret = _content;
#else
		XS_String ret;
		assign_utf8(ret, _content.c_str());
#endif

		return DecodeXMLString(ret.c_str());

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -