zen::Xml
Simple C++ XML Processing
|
00001 // ************************************************************************** 00002 // * This file is part of the zen::Xml project. It is distributed under the * 00003 // * Boost Software License: http://www.boost.org/LICENSE_1_0.txt * 00004 // * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved * 00005 // ************************************************************************** 00006 00007 #ifndef ZEN_XML_CONVERT_STRUC_HEADER_018727409908342709743 00008 #define ZEN_XML_CONVERT_STRUC_HEADER_018727409908342709743 00009 00010 #include "dom.h" 00011 00012 namespace zen 00013 { 00020 00021 00026 template <class T> bool readStruc(const XmlElement& input, T& value); 00028 00032 template <class T> void writeStruc(const T& value, XmlElement& output); 00033 00034 00035 00036 00037 00038 00039 00040 00041 00042 00043 00044 00045 00046 00047 00048 00049 00050 //------------------------------ implementation ------------------------------------- 00051 namespace impl_2384343 00052 { 00053 ZEN_INIT_DETECT_MEMBER_TYPE(value_type); 00054 ZEN_INIT_DETECT_MEMBER_TYPE(iterator); 00055 ZEN_INIT_DETECT_MEMBER_TYPE(const_iterator); 00056 00057 ZEN_INIT_DETECT_MEMBER(begin) // 00058 ZEN_INIT_DETECT_MEMBER(end) //we don't know the exact declaration of the member attribute: may be in a base class! 00059 ZEN_INIT_DETECT_MEMBER(insert) // 00060 } 00061 00062 template <typename T> 00063 struct IsStlContainer : 00064 StaticBool< 00065 impl_2384343::HasMemberType_value_type <T>::value&& 00066 impl_2384343::HasMemberType_iterator <T>::value&& 00067 impl_2384343::HasMemberType_const_iterator<T>::value&& 00068 impl_2384343::HasMember_begin <T>::value&& 00069 impl_2384343::HasMember_end <T>::value&& 00070 impl_2384343::HasMember_insert <T>::value> {}; 00071 00072 00073 namespace impl_2384343 00074 { 00075 ZEN_INIT_DETECT_MEMBER_TYPE(first_type); 00076 ZEN_INIT_DETECT_MEMBER_TYPE(second_type); 00077 00078 ZEN_INIT_DETECT_MEMBER(first) //we don't know the exact declaration of the member attribute: may be in a base class! 00079 ZEN_INIT_DETECT_MEMBER(second) // 00080 } 00081 00082 template <typename T> 00083 struct IsStlPair : 00084 StaticBool< 00085 impl_2384343::HasMemberType_first_type <T>::value&& 00086 impl_2384343::HasMemberType_second_type<T>::value&& 00087 impl_2384343::HasMember_first <T>::value&& 00088 impl_2384343::HasMember_second <T>::value> {}; 00089 00090 //###################################################################################### 00091 00092 //Conversion from arbitrary types to an XML element 00093 enum ValueType 00094 { 00095 VALUE_TYPE_STL_CONTAINER, 00096 VALUE_TYPE_STL_PAIR, 00097 VALUE_TYPE_OTHER, 00098 }; 00099 00100 template <class T> 00101 struct GetValueType : StaticEnum<ValueType, 00102 GetTextType<T>::value != TEXT_TYPE_OTHER ? VALUE_TYPE_OTHER : //some string classes are also STL containers, so check this first 00103 IsStlContainer<T>::value ? VALUE_TYPE_STL_CONTAINER : 00104 IsStlPair<T>::value ? VALUE_TYPE_STL_PAIR : 00105 VALUE_TYPE_OTHER> {}; 00106 00107 00108 template <class T, ValueType type> 00109 struct ConvertElement; 00110 /* -> expected interface 00111 { 00112 void writeStruc(const T& value, XmlElement& output) const; 00113 bool readStruc(const XmlElement& input, T& value) const; 00114 }; 00115 */ 00116 00117 00118 //partial specialization: handle conversion for all STL-container types! 00119 template <class T> 00120 struct ConvertElement<T, VALUE_TYPE_STL_CONTAINER> 00121 { 00122 void writeStruc(const T& value, XmlElement& output) const 00123 { 00124 std::for_each(value.begin(), value.end(), 00125 [&](const typename T::value_type & childVal) 00126 { 00127 XmlElement& newChild = output.addChild("Item"); 00128 zen::writeStruc(childVal, newChild); 00129 }); 00130 } 00131 bool readStruc(const XmlElement& input, T& value) const 00132 { 00133 bool success = true; 00134 value.clear(); 00135 00136 auto iterPair = input.getChildren("Item"); 00137 for (auto iter = iterPair.first; iter != iterPair.second; ++iter) 00138 { 00139 typename T::value_type childVal; //MSVC 2010 bug: cannot put this into a lambda body 00140 if (zen::readStruc(*iter, childVal)) 00141 value.insert(value.end(), childVal); 00142 else 00143 success = false; 00144 } 00145 return success; 00146 } 00147 }; 00148 00149 00150 //partial specialization: handle conversion for std::pair 00151 template <class T> 00152 struct ConvertElement<T, VALUE_TYPE_STL_PAIR> 00153 { 00154 void writeStruc(const T& value, XmlElement& output) const 00155 { 00156 XmlElement& child1 = output.addChild("one"); //don't use "1st/2nd", this will confuse a few pedantic XML parsers 00157 zen::writeStruc(value.first, child1); 00158 00159 XmlElement& child2 = output.addChild("two"); 00160 zen::writeStruc(value.second, child2); 00161 } 00162 bool readStruc(const XmlElement& input, T& value) const 00163 { 00164 bool success = true; 00165 const XmlElement* child1 = input.getChild("one"); 00166 if (!child1 || !zen::readStruc(*child1, value.first)) 00167 success = false; 00168 00169 const XmlElement* child2 = input.getChild("two"); 00170 if (!child2 || !zen::readStruc(*child2, value.second)) 00171 success = false; 00172 00173 return success; 00174 } 00175 }; 00176 00177 00178 //partial specialization: not a pure structured type, try text conversion (thereby respect user specializations of writeText()/readText()) 00179 template <class T> 00180 struct ConvertElement<T, VALUE_TYPE_OTHER> 00181 { 00182 void writeStruc(const T& value, XmlElement& output) const 00183 { 00184 std::string tmp; 00185 writeText(value, tmp); 00186 output.setValue(tmp); 00187 } 00188 bool readStruc(const XmlElement& input, T& value) const 00189 { 00190 std::string rawStr; 00191 input.getValue(rawStr); 00192 return readText(rawStr, value); 00193 } 00194 }; 00195 00196 00197 template <class T> inline 00198 void writeStruc(const T& value, XmlElement& output) 00199 { 00200 ConvertElement<T, GetValueType<T>::value>().writeStruc(value, output); 00201 } 00202 00203 00204 template <class T> inline 00205 bool readStruc(const XmlElement& input, T& value) 00206 { 00207 return ConvertElement<T, GetValueType<T>::value>().readStruc(input, value); 00208 } 00209 } 00210 00211 #endif //ZEN_XML_CONVERT_STRUC_HEADER_018727409908342709743