zen::Xml
Simple C++ XML Processing
 All Classes Namespaces Functions Variables
cvrt_struc.h
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