與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;
}
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