c++ 基於boost序列化XML 和 Properties文件

 與ajson庫用法類似

Example:

struct examle_struct
{
    int                _property_int;
    std::string        _property_str;
    std::string        value_str;
    bool               value_bool;
    int                value_int;
    std::vector<int>   value_vec;
}

AXML(examle_struct, (_property_int)(_property_str)(value_str)(value_bool)(value_int)(value_vec))


int main()
{
    //to xml
    std::istringstream iss;
    examle_struct exam;
    exam._property_int = 1;
    exam._property_str = "hello";
    exam.value_str = "world";
    exam.value_bool = false;
    exam.value_int = 10;
    exam.value_vec << 1 << 2 << 3;
    boost::axml::save(exam, "examle_struct", iss);
    std::cout << iss.str() << std::endl;

    //from xml
    std::string xml_str = iss.str();
    std::ostringstream oss(xml_str);
    examle_struct exam1;
    boost::axml::load(exam1,oss);

    return 0;
}

XML解析 Src:

#pragma once
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <iostream>

#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/property_tree/detail/rapidxml.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/exception/diagnostic_information.hpp>

namespace boost
{
	namespace axml
	{
		using namespace boost::property_tree::detail::rapidxml;

		template <typename ty>
		struct node_support_read_impl
		{
			typedef ty value_type;
			typedef node_support_read_impl<ty> impl;
			static void read(xml_node<char>& xml_value, value_type& value) {}
		};

		template <typename ty>
		struct attribute_support_read_impl
		{
			typedef ty value_type;
			typedef attribute_support_read_impl<ty> impl;
			static void read(xml_attribute<char>& xml_value, value_type& value) {}
		};

		template <typename ty>
		struct node_support_write_impl
		{
			typedef ty value_type;
			typedef node_support_write_impl<ty> impl;
			static void write(std::ostream& stream, std::string name, const value_type& value) {}
		};

		template <typename ty>
		struct attribute_support_write_impl
		{
			typedef ty value_type;
			typedef attribute_support_write_impl<ty> impl;
			static void write(std::ostream& stream, std::string name, const value_type& value) {}
		};

// 		template <typename ty>
// 		struct node_support_read;
// 
// 		template <typename ty>
// 		struct attribute_support_read;
// 
// 		template <typename ty>
// 		struct value_support_write;
// 
// 		template <typename ty>
// 		struct attribute_support_write;

		template<typename ty>
		struct integer_arithmetic_support_read_impl
		{
			typedef ty value_type;
			static void read(xml_base<char>& xml_value, value_type& value)
			{
				std::string str_value(xml_value.value());
				if (str_value.empty())
				{
					value = 0;
					return;
				}
				value = boost::lexical_cast<value_type>(str_value);
			}
		};

		template<typename ty>
		struct integer_arithmetic_support_write_impl
		{
			typedef ty value_type;
			static void write(std::ostream& stream, std::string name, const value_type& value)
			{
				std::string buffer = boost::str(boost::format("%1%") % value);
				if (name[0] == '_')
				{
					std::string attr_name = name.substr(1);
					stream << boost::str(boost::format(" %s=%s") % attr_name %buffer);
				}
				else
				{
					stream << boost::str(boost::format("\n<%s>%s</%s>") % name %buffer %name);
				}
			}
		};

		template<typename ty>
		struct float_arithmetic_support_read_impl
		{
			typedef ty value_type;
			static void read(xml_base<char>& xml_value, value_type& value)
			{
				std::string str_value(xml_value.value());
				if (str_value.empty())
				{
					value = 0.0;
					return;
				}
				value = boost::lexical_cast<value_type>(str_value);
			}
		};

		template<typename ty>
		struct float_arithmetic_support_write_impl
		{
			typedef ty value_type;
			static void write(std::ostream& stream, std::string name, const value_type& value)
			{
				std::string str_value = boost::str(boost::format("%1%") % value);
				if (name[0] == '_')
				{
					std::string attr_name = name.substr(1);
					stream << boost::str(boost::format(" %s=%s") % attr_name %str_value);
				}
				else
				{
					stream << boost::str(boost::format("\n<%s>%s</%s>") % name %str_value %name);
				}
			}
		};

		template<>
		struct integer_arithmetic_support_read_impl <bool>
		{
			typedef bool value_type;
			static void read(xml_base<char>& xml_value, value_type& value)
			{
				std::string str_value(xml_value.value());
				if (str_value.empty())
				{
					value = 0;
					return;
				}
				if (str_value == "0" || str_value == "false")
				{
					value = 0;
					return;
				}
				value = 1;
			}
		};

		template<>
		struct integer_arithmetic_support_write_impl < bool >
		{
			typedef bool value_type;
			static void write(std::ostream& stream, std::string name, const value_type& value)
			{
				std::string str_value = (value ? "1" : "0");
				if (name[0] == '_')
				{
					std::string attr_name = name.substr(1);
					stream << boost::str(boost::format(" %s=%s") % attr_name %str_value);
				}
				else
				{
					stream << boost::str(boost::format("\n<%s>%s</%s>") % name %str_value %name);
				}
			}
		};

		template <typename ty>
		struct arithmetic_support_read_impl
		{
			typedef ty value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_integral<value_type>,
				integer_arithmetic_support_read_impl<value_type>,
				float_arithmetic_support_read_impl<value_type>
			>::type impl;
		};

		template <typename ty>
		struct arithmetic_support_write_impl
		{
			typedef ty value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_integral<value_type>,
				integer_arithmetic_support_write_impl<value_type>,
				float_arithmetic_support_write_impl<value_type>
			>::type impl;
		};

		template<typename ty>
		struct string_support_read_impl
		{
			typedef ty value_type;

			static void read(xml_base<char>& xml_value, value_type& value)
			{
				std::string str_value(xml_value.value());
				if (str_value.empty())
				{
					value = "";
					return;
				}
				value = str_value;
			}
		};

		template<typename ty>
		struct string_support_write_impl
		{
			typedef ty value_type;
			static void write(std::ostream& stream, std::string name, const value_type& value)
			{
				std::string str_value(value);
				if (name[0] == '_')
				{
					std::string attr_name = name.substr(1);
					stream << boost::str(boost::format(" %s=\"%s\"") % attr_name %str_value);
				}
				else
				{
					stream << boost::str(boost::format("\n<%s>%s</%s>") % name %str_value %name);
				}
			}
		};

		template<typename char_traits_ty, typename char_alloc_type>
		struct node_support_read_impl< ::std::basic_string<char, char_traits_ty, char_alloc_type>>
		{
			typedef ::std::basic_string<char, char_traits_ty, char_alloc_type> value_type;
			typedef  string_support_read_impl<value_type> impl;
		};

		template<typename char_traits_ty, typename char_alloc_type>
		struct attribute_support_read_impl< ::std::basic_string<char, char_traits_ty, char_alloc_type>>
		{
			typedef ::std::basic_string<char, char_traits_ty, char_alloc_type> value_type;
			typedef  string_support_read_impl<value_type> impl;
		};

		template<typename char_traits_ty, typename char_alloc_type>
		struct node_support_write_impl< ::std::basic_string<char, char_traits_ty, char_alloc_type>>
		{
			typedef ::std::basic_string<char, char_traits_ty, char_alloc_type> value_type;
			typedef  string_support_write_impl<value_type> impl;
		};

		template<typename char_traits_ty, typename char_alloc_type>
		struct attribute_support_write_impl< ::std::basic_string<char, char_traits_ty, char_alloc_type>>
		{
			typedef ::std::basic_string<char, char_traits_ty, char_alloc_type> value_type;
			typedef  string_support_write_impl<value_type> impl;
		};

		template<int N>
		struct char_array_support_read_impl
		{
			//typedef ty value_type;
			static void read(xml_node<char>& xml_value, char(&value)[N])
			{
				char * nv = xml_value.value();
				size_t nc = xml_value.value_size();
				size_t vc = N;
				for (size_t i = 0; i<nv && i<vc; ++i)
				{
					value[i] = nv[i];
				}
				if (vc > nc)
					value[nc] = 0;
			}
		};

		template<size_t N>
		struct char_array_support_write_impl
		{
			//typedef ty value_type;
			static inline void write(std::ostream& stream, std::string name, const char(&value)[N])
			{
				const char * str_value = value;
				stream << boost::str(boost::format("\n<%s>%s</%s>") % name %str_value %name);
			}
		};

		template<int N>
		struct node_support_read_impl< char[N]>
		{
			typedef char value_type[N];
			typedef  char_array_support_read_impl<N> impl;
		};

		template<int N>
		struct node_support_write_impl< char[N]>
		{
			typedef const char value_type[N];
			typedef  char_array_support_write_impl<N> impl;
		};


		template<typename ty>
		struct container_seq_support_read_impl
		{
			//typedef ty value_type;
			static void read(xml_node<char>& xml_value, ty& value)
			{
				value.clear();
				xml_node<char> *peer = &xml_value;
				while (peer)
				{
					typename ty::value_type item;
					node_support_read<typename ty::value_type>::impl::read(*peer, item);
					value.push_back(item);
					peer = peer->next_sibling(xml_value.name());
				}
			}
		};

		template<typename ty>
		struct container_seq_support_write_impl
		{
			typedef ty value_type;
			static void write(std::ostream& stream, std::string name, const value_type& value)
			{
				for (typename ty::const_iterator iter = value.cbegin(); iter != value.cend(); ++iter)
				{
					node_support_write<typename ty::value_type>::impl::write(stream, name, *iter);
				}
			}
		};

		template<typename ty, typename alloc_ty>
		struct node_support_read_impl< ::std::list<ty, alloc_ty>>
		{
			typedef typename ::std::list<ty, alloc_ty> value_type;
			typedef container_seq_support_read_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_write_impl< ::std::list<ty, alloc_ty>>
		{
			typedef typename ::std::list<ty, alloc_ty> value_type;
			typedef container_seq_support_write_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_read_impl< ::std::deque<ty, alloc_ty>>
		{
			typedef typename ::std::deque<ty, alloc_ty> value_type;
			typedef container_seq_support_read_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_write_impl< ::std::deque<ty, alloc_ty>>
		{
			typedef typename ::std::deque<ty, alloc_ty> value_type;
			typedef container_seq_support_write_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_read_impl< ::std::vector<ty, alloc_ty>>
		{
			typedef typename ::std::vector<ty, alloc_ty> value_type;
			typedef container_seq_support_read_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_write_impl< ::std::vector<ty, alloc_ty>>
		{
			typedef typename ::std::vector<ty, alloc_ty> value_type;
			typedef container_seq_support_write_impl<value_type> impl;
		};


		template <typename ty>
		struct node_support_read
		{
			typedef typename ::boost::remove_const<ty>::type value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_arithmetic<value_type>,
				typename arithmetic_support_read_impl< value_type>::impl,
				typename node_support_read_impl<value_type>::impl
			>::type impl;
		};

		template <typename ty>
		struct attribute_support_read
		{
			typedef typename ::boost::remove_const<ty>::type value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_arithmetic<value_type>,
				typename arithmetic_support_read_impl< value_type>::impl,
				typename attribute_support_read_impl<value_type>::impl
			>::type impl;
		};

		template <typename ty>
		struct node_support_write
		{
			typedef typename ::boost::remove_const<ty>::type value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_arithmetic<value_type>,
				typename arithmetic_support_write_impl<value_type>::impl,
				typename node_support_write_impl<value_type>::impl
			>::type impl;
		};

		template <typename ty>
		struct attribute_support_write
		{
			typedef typename ::boost::remove_const<ty>::type value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_arithmetic<value_type>,
				typename arithmetic_support_write_impl<value_type>::impl,
				typename attribute_support_write_impl<value_type>::impl
			>::type impl;
		};

		template<typename ty>
		void axml_read_node(xml_node<char>& xml_value, ty& value)
		{
			node_support_read<ty>::impl::read(xml_value, value);
		}

		template<typename ty>
		void axml_read_attribute(xml_attribute<char>& xml_value, ty& value)
		{
			attribute_support_read<ty>::impl::read(xml_value, value);
		}

		template< typename ty>
		void axml_write_node(std::ostream& stream, std::string name, ty& value)
		{
			node_support_write<ty>::impl::write(stream, name, value);
		}

		template< typename ty>
		void axml_write_attribute(std::ostream& stream, std::string name, ty& value)
		{
			attribute_support_write<ty>::impl::write(stream, name, value);
		}

		template<typename ty>
		inline bool load_from_node(ty& value, const xml_node<char>& node)
		{
			return axml_read_node(node, value);
		}


		template<typename ty>
		inline void load(ty& value, std::istream& stream)
		{
			xml_document<char> document;
			// Load data into vector
			stream.unsetf(std::ios::skipws);
			std::vector<char> v(std::istreambuf_iterator<char>(stream.rdbuf()),
				std::istreambuf_iterator<char>());
			if (!stream.good() || v.empty())
			{
				document.clear();
				throw std::exception("read xml error");
			}
			v.push_back(0); // zero-terminate

			try 
			{
				document.parse<0>(&v.front());
				xml_node<char>* root_node = document.first_node();
				axml_read_node(*root_node, value);
			}
			catch(...)
			{
				document.clear();
				throw;
			}
			document.clear();
		}

		template<typename ty>
		inline void save(ty& value, std::string root_name, std::ostream& stream)
		{
			
			stream << "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
			axml_write_node(stream, root_name, value);
			stream.flush();
			if (!stream)
			{
				throw std::exception("write error");
			}
		}
	}
}

#ifndef AXML

#define AXML_READ_MEMBER( r , v , elem ) \
	member_name = BOOST_DO_STRINGIZE(elem);\
	if (member_name[0] == '_')\
	{\
		xml_attribute<char>* attr = xml_value.first_attribute(member_name + 1);\
		if (attr) {axml_read_attribute(*attr, value.elem);}\
	}\
	else\
	{\
		xml_node<char>* node = xml_value.first_node(member_name);\
		if (node){axml_read_node(*node , value.elem);}\
	}

#define AXML_WRITE_MEMBER( r ,v , elem ) \
	member_name = BOOST_DO_STRINGIZE(elem);\
	if (member_name[0] != '_')\
	{\
		axml_write_node(stream, member_name, value.elem); \
	}

#define AXML_WRITE_ATTR( r ,v , elem ) \
	member_name = BOOST_DO_STRINGIZE(elem);\
	if (member_name[0] == '_')\
	{\
		axml_write_attribute(stream, member_name, value.elem); \
	}



#define AXML(TYPE, MEMBERS)\
namespace boost\
{\
	namespace axml\
	{\
		template <>\
		struct node_support_read_impl<TYPE>\
		{\
			typedef TYPE value_type;\
			typedef node_support_read_impl<TYPE> impl;\
			static inline void read(const xml_node<char>& xml_value , value_type& value)\
			{\
				char * member_name = NULL;\
				BOOST_PP_SEQ_FOR_EACH( AXML_READ_MEMBER , 0 , MEMBERS ) \
				return;\
			}\
		};\
		template <>\
		struct node_support_write_impl<TYPE>\
		{\
			typedef TYPE value_type;	\
			typedef node_support_write_impl<TYPE> impl;\
			static inline void write(std::ostream& stream, std::string name, const value_type& value)\
			{\
				stream << "\n<" << name;\
				char * member_name = NULL;\
				BOOST_PP_SEQ_FOR_EACH( AXML_WRITE_ATTR , 0 , MEMBERS ) \
				stream << ">";\
				BOOST_PP_SEQ_FOR_EACH( AXML_WRITE_MEMBER , 0 , MEMBERS ) \
				stream << "\n</" << name << ">";\
				return;\
			}\
		};\
	}\
}
#endif

Properties解析Src

#pragma once
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <iostream>
#include <exception>
#include <boost/cstdint.hpp>
#include <boost/static_assert.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ptree_fwd.hpp>
#include <boost/property_tree/detail/ptree_implementation.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/seq.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/algorithm/string.hpp>

namespace boost
{
	namespace aprop
	{


		template <typename ty>
		struct node_support_read_impl
		{
			typedef ty value_type;
			typedef node_support_read_impl<ty> impl;
			static void read(property_tree::ptree& aprop_value, value_type& value) {}
		};

		template <typename ty>
		struct node_support_write_impl
		{
			typedef ty value_type;
			typedef node_support_write_impl<ty> impl;
			static void write(std::ostream& stream, std::string prefix, const value_type& value) {}
		};

		template <typename ty>
		struct node_support_read;

		template <typename ty>
		struct node_support_write;

		template<typename ty>
		struct integer_arithmetic_support_read_impl
		{
			typedef ty value_type;
			static void read(property_tree::ptree& aprop_value, value_type& value)
			{
				std::string str_value = aprop_value.data();
				if (str_value.empty())
					value = 0;
				else
					value = boost::lexical_cast<value_type>(str_value);
			}
		};

		template<typename ty>
		struct integer_arithmetic_support_write_impl
		{
			typedef ty value_type;
			static void write(std::ostream& stream, std::string prefix, const value_type& value)
			{
				stream << boost::str(boost::format("%s=%d") % prefix % value)<<std::endl;
			}
		};

		template<typename ty>
		struct float_arithmetic_support_read_impl
		{
			typedef ty value_type;
			static void read(property_tree::ptree& aprop_value, value_type& value)
			{
				std::string str_value(aprop_value.data());
				if (str_value.empty())
					value = 0.0;
				else
					value = boost::lexical_cast<value_type>(str_value);
			}
		};

		template<typename ty>
		struct float_arithmetic_support_write_impl
		{
			typedef ty value_type;
			static void write(std::ostream& stream, std::string prefix, const value_type& value)
			{
				stream << boost::str(boost::format("%s=%f") % prefix % value) << std::endl;
			}
		};

		template<>
		struct integer_arithmetic_support_read_impl <bool>
		{
			typedef bool value_type;
			static void read(property_tree::ptree& aprop_value, value_type& value)
			{
				std::string str_value(aprop_value.data());
				if (str_value == "true")
					value = true;
				else
					value = false;
			}
		};

		template<>
		struct integer_arithmetic_support_write_impl < bool >
		{
			typedef bool value_type;
			static void write(std::ostream& stream, std::string prefix, const value_type& value)
			{
				std::string str_value = (value ? "true" : "false");
				stream << boost::str(boost::format("%s=%s") % prefix % str_value) << std::endl;
			}
		};

		template <typename ty>
		struct arithmetic_support_read_impl
		{
			typedef ty value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_integral<value_type>,
				integer_arithmetic_support_read_impl<value_type>,
				float_arithmetic_support_read_impl<value_type>
			>::type impl;
		};

		template <typename ty>
		struct arithmetic_support_write_impl
		{
			typedef ty value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_integral<value_type>,
				integer_arithmetic_support_write_impl<value_type>,
				float_arithmetic_support_write_impl<value_type>
			>::type impl;
		};

		template<typename ty>
		struct string_support_read_impl
		{
			typedef ty value_type;

			static void read(property_tree::ptree& aprop_value, value_type& value)
			{
				value = aprop_value.data();
			}
		};

		template<typename ty>
		struct string_support_write_impl
		{
			typedef ty value_type;
			static void write(std::ostream& stream, std::string prefix, const value_type& value)
			{
				stream << boost::str(boost::format("%s=%s") % prefix % value) << std::endl;
			}
		};

		template<typename char_traits_ty, typename char_alloc_type>
		struct node_support_read_impl< ::std::basic_string<char, char_traits_ty, char_alloc_type> >
		{
			typedef ::std::basic_string<char, char_traits_ty, char_alloc_type> value_type;
			typedef  string_support_read_impl<value_type> impl;
		};


		template<typename char_traits_ty, typename char_alloc_type>
		struct node_support_write_impl< ::std::basic_string<char, char_traits_ty, char_alloc_type> >
		{
			typedef ::std::basic_string<char, char_traits_ty, char_alloc_type> value_type;
			typedef  string_support_write_impl<value_type> impl;
		};

		template<typename ty>
		struct container_seq_support_read_impl
		{
			//typedef ty value_type;
			static void read(property_tree::ptree& aprop_value, ty& value)
			{
				value.clear();
				for (property_tree::ptree::iterator it = aprop_value.begin();
					it != aprop_value.end(); ++it)
				{
					typename ty::value_type item;
					node_support_read<typename ty::value_type>::impl::read(it->second, item);
					value.push_back(item);
				}
			}
		};

		template<typename ty>
		struct container_seq_support_write_impl
		{
			typedef ty value_type;
			static void write(std::ostream& stream, std::string prefix, const value_type& value)
			{
				for (int i = 0; i < value.size(); ++i)
				{
					node_support_write<typename ty::value_type>::impl::write(stream, prefix, value.at(i));
				}
			}
		};

		template<typename ty, typename alloc_ty>
		struct node_support_read_impl< ::std::list<ty, alloc_ty> >
		{
			typedef typename ::std::list<ty, alloc_ty> value_type;
			typedef container_seq_support_read_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_write_impl< ::std::list<ty, alloc_ty> >
		{
			typedef typename ::std::list<ty, alloc_ty> value_type;
			typedef container_seq_support_write_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_read_impl< ::std::deque<ty, alloc_ty> >
		{
			typedef typename ::std::deque<ty, alloc_ty> value_type;
			typedef container_seq_support_read_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_write_impl< ::std::deque<ty, alloc_ty> >
		{
			typedef typename ::std::deque<ty, alloc_ty> value_type;
			typedef container_seq_support_write_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_read_impl< ::std::vector<ty, alloc_ty> >
		{
			typedef typename ::std::vector<ty, alloc_ty> value_type;
			typedef container_seq_support_read_impl<value_type> impl;
		};

		template<typename ty, typename alloc_ty>
		struct node_support_write_impl< ::std::vector<ty, alloc_ty> >
		{
			typedef typename ::std::vector<ty, alloc_ty> value_type;
			typedef container_seq_support_write_impl<value_type> impl;
		};

		template <typename ty>
		struct node_support_read
		{
			typedef typename ::boost::remove_const<ty>::type value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_arithmetic<value_type>,
				typename arithmetic_support_read_impl< value_type>::impl,
				typename node_support_read_impl<value_type>::impl
			>::type impl;
		};

		template <typename ty>
		struct node_support_write
		{
			typedef typename ::boost::remove_const<ty>::type value_type;
			typedef typename ::boost::mpl::if_<
				::boost::is_arithmetic<value_type>,
				typename arithmetic_support_write_impl<value_type>::impl,
				typename node_support_write_impl<value_type>::impl
			>::type impl;
		};

		template<typename ty>
		void aprop_read_node(property_tree::ptree& aprop_value, ty& value)
		{
			node_support_read<ty>::impl::read(aprop_value, value);
		}

		template< typename ty>
		void aprop_write_node(std::ostream& stream, std::string prefix, ty& value)
		{
			node_support_write<ty>::impl::write(stream, prefix, value);
		}

		inline void print_tree(std::ostream& os,const property_tree::ptree& pt, int tab)
		{
			os << std::string(tab, ' ');
			os << "{\n";

			for (property_tree::ptree::const_iterator iter = pt.begin(); iter != pt.end(); ++iter)
			{
				if (!iter->second.empty())
				{
					os << std::string(tab+2, ' ');
					os << iter->first << ":\n";
					print_tree(os, iter->second, tab+2);
				}
				else
				{
					os << std::string(tab + 2, ' ');
					os << iter->first << ":" << iter->second.data() << "\n";
				}
			}
			os << std::string(tab, ' ');
			os << "}\n";
		}

		template<typename ty>
		inline void load(ty& value, std::istream& stream)
		{
			property_tree::ptree root;
			// Load data into vector
// 			stream.unsetf(std::ios::skipws);
// 			std::vector<char> v(std::istreambuf_iterator<char>(stream.rdbuf()),
// 				std::istreambuf_iterator<char>());
// 			if (!stream.good() || v.empty())
// 			{
// 				throw std::runtime_error("read properties error");
// 			}
// 			v.push_back(0); // zero-terminate

			try
			{
				int line_no = 0;
				while (stream.good())
				{
					++line_no;
					std::string line;
					std::getline(stream, line);
					if (!stream.good() && !stream.eof())
						BOOST_PROPERTY_TREE_THROW(property_tree::file_parser_error(
							"read error", "", line_no));

					line = property_tree::detail::trim(line, stream.getloc());
					if (line.empty() || line[0] == ';' || line[0] == '#')
						continue;

					typename std::string::size_type eqpos = line.find('=');
					if (eqpos == std::string::npos)
						BOOST_PROPERTY_TREE_THROW(property_tree::file_parser_error(
							"missing '='", "", line_no));
					std::string key = property_tree::detail::trim(
						line.substr(0, eqpos), stream.getloc());
					std::string data = property_tree::detail::trim(
						line.substr(eqpos + 1, std::string::npos), stream.getloc());
					boost::algorithm::replace_all(key,"[",".");
					boost::algorithm::replace_all(key, "]", "");
					root.add(key, data);
				}
// 				std::stringstream os;
// 				print_tree(os, root, 0);
// 				std::string dump = os.str();
				aprop_read_node(root, value);
			}
			catch (...)
			{
				throw;
			}
		}

		template<typename ty>
		inline void save(ty& value, std::ostream& stream)
		{
			aprop_write_node(stream, "", value);
			stream.flush();
			if (!stream)
			{
				throw std::runtime_error("write error");
			}
		}
	}
}


#ifndef APROP

#define APROP_READ_MEMBER( r , v , elem ) \
	member_name = BOOST_DO_STRINGIZE(elem);\
	itor = aprop_value.find(member_name);\
	if (itor != aprop_value.not_found())\
	{aprop_read_node(itor->second, value.elem);}
	

#define APROP_WRITE_MEMBER( r ,v , elem ) \
	member_name = BOOST_DO_STRINGIZE(elem);\
	if (prefix.empty())\
	{aprop_write_node(stream, member_name, value.elem);}\
	else\
	{aprop_write_node(stream, prefix + "." + member_name, value.elem);}
	


#define APROP(TYPE, MEMBERS)\
namespace boost\
{\
	namespace aprop\
	{\
		template <>\
		struct node_support_read_impl<TYPE>\
		{\
			typedef TYPE value_type;\
			typedef node_support_read_impl<TYPE> impl;\
			static inline void read(property_tree::ptree& aprop_value, value_type& value)\
			{\
				std::string member_name; \
				property_tree::ptree::assoc_iterator itor;\
				BOOST_PP_SEQ_FOR_EACH( APROP_READ_MEMBER , 0 , MEMBERS ) \
				return;\
			}\
		};\
		template <>\
		struct node_support_write_impl<TYPE>\
		{\
			typedef TYPE value_type;\
			typedef node_support_write_impl<TYPE> impl;\
			static inline void write(std::ostream& stream, std::string prefix, const value_type& value)\
			{\
				std::string member_name;\
				BOOST_PP_SEQ_FOR_EACH( APROP_WRITE_MEMBER , 0 , MEMBERS ) \
				return;\
			}\
		};\
	}\
}
#endif

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章