Mirror reflection library 0.5.13

mirror/stream/xml.hpp

Go to the documentation of this file.
00001 
00010 #ifndef MIRROR_STREAM_XML_1011291729_HPP
00011 #define MIRROR_STREAM_XML_1011291729_HPP
00012 
00013 #include <mirror/stream/base.hpp>
00014 #include <type_traits>
00015 
00016 MIRROR_NAMESPACE_BEGIN
00017 namespace stream {
00018 
00020 
00024 struct to_xml : _target<to_xml> { };
00025 
00026 template <typename T>
00027 class _writer<T, to_xml>
00028 {
00029 private:
00030     static void do_indent(std::ostream& out, int depth)
00031     {
00032         out << std::endl;
00033         while(depth--) out << "    ";
00034     }
00035 
00036     struct write_x
00037     {
00038         std::ostream& out;
00039         const _wrap<T, to_xml>& obj;
00040 
00041         inline write_x(
00042             std::ostream& os,
00043             const _wrap<T, to_xml>& ob
00044         ): out(os)
00045          , obj(ob)
00046         { }
00047 
00048         void indent(int ofs = 0) const
00049         {
00050             do_indent(out, obj.depth()+ofs);
00051         }
00052 
00053         static bool is_special_char(char x)
00054         {
00055             // TODO
00056             return (x == '<') ||
00057                 (x == '>') ||
00058                 (x == '\'') ||
00059                 (x == '"') ||
00060                 (x == '&');
00061         }
00062 
00063         void wr_translated(char x)
00064         {
00065             out << '&';
00066             switch(x)
00067             {
00068                 // TODO
00069                 case '<' : out << "lt";
00070                 case '>' : out << "gt";
00071                 case '\'': out << "apos";
00072                 case '"' : out << "quot";
00073                 case '&' : out << "amp";
00074                 default:;
00075             }
00076             out << ';';
00077         }
00078 
00079         void wr_val(bool x)
00080         {
00081             out << x ? "true" : "false";
00082         }
00083 
00084         void wr_val(char x)
00085         {
00086             if(is_special_char(x))
00087                 wr_translated(x);
00088             else out << x;
00089         }
00090 
00091         void wr_val(unsigned char x)
00092         {
00093             out << int(x);
00094         }
00095 
00096         void wr_val(const std::string& x)
00097         {
00098             std::string::const_iterator i = x.begin(), e = x.end();
00099             while(i != e) wr_val(*i++);
00100         }
00101 
00102         template <typename X>
00103         void wr_val(
00104             const X& x,
00105             typename std::enable_if<
00106                 std::is_arithmetic<X>::value
00107             >::type* = nullptr
00108         )
00109         {
00110             out << x;
00111         }
00112 
00113         template <typename X>
00114         void wr_val(
00115             const X& x,
00116             typename std::enable_if<
00117                 !std::is_arithmetic<X>::value &&
00118                 !std::is_enum<X>::value
00119             >::type* = nullptr
00120         )
00121         {
00122             out << to_xml::from(x, obj);
00123         }
00124 
00125         template <typename X>
00126         void wr_val(
00127             X x,
00128             typename std::enable_if<
00129                 std::is_enum<X>::value
00130             >::type* = nullptr
00131         )
00132         {
00133             out << MIRRORED_ENUM(X)::name_by_value(x);
00134         }
00135     };
00136 
00137     // helper functor executed on all members
00138     struct write_mem : write_x
00139     {
00140         inline write_mem(
00141             std::ostream& os,
00142             const _wrap<T, to_xml>& ob
00143         ): write_x(os, ob)
00144         { }
00145 
00146         template <typename IterInfo>
00147         void operator()(IterInfo)
00148         {
00149             typedef typename IterInfo::type meta_member;
00150             // write the separator if necessary
00151             // write the member name and the separating ':'
00152             this->indent(1);
00153             this->out
00154                 << '<'
00155                 << meta_member::base_name()
00156                 << ">";
00157             // write the value
00158             this->wr_val(meta_member::get(this->obj.value));
00159             this->out
00160                 << '<'
00161                 << meta_member::base_name()
00162                 << "/>";
00163             if(IterInfo::is_last::value) this->indent();
00164         }
00165     };
00166 
00167     // write a structure
00168     template <typename MetaT>
00169     void write(
00170         MetaT,
00171         std::ostream& out,
00172         const _wrap<T, to_xml>& obj,
00173         non_container_tag&
00174     )
00175     {
00176         static_assert(
00177             mp::empty<all_containers<MetaT> >::value,
00178             "Non-container types should not have containers"
00179         );
00180         mp::for_each_ii<members<MetaT> >(write_mem(out, obj));
00181     }
00182 
00183     // helper functor executed on all elements
00184     struct write_elem : write_x
00185     {
00186         std::string name;
00187 
00188         inline write_elem(
00189             std::ostream& os,
00190             const _wrap<T, to_xml>& ob,
00191             const std::string& n
00192         ): write_x(os, ob)
00193          , name(n)
00194         { }
00195 
00196         template <typename Locator>
00197         void operator()(Locator loc, bool first)
00198         {
00199             this->indent(1);
00200             this->out << '<' << name << '>';
00201             // write the value
00202             wr_val(loc.get());
00203             this->out << '<' << name << "/>";
00204         }
00205     };
00206 
00207     // write a simple container
00208     template <typename MetaT>
00209     void write(
00210         MetaT,
00211         std::ostream& out,
00212         const _wrap<T, to_xml>& obj,
00213         simple_container_tag&
00214     )
00215     {
00216         typedef typename mp::front<all_containers<MetaT> >::type
00217             meta_cntnr;
00218         typedef typename default_traversal<
00219             meta_cntnr
00220         >::type meta_trav;
00221         //
00222         write_elem do_write(
00223             out,
00224             obj,
00225             meta_cntnr::element_type::base_name()
00226         );
00227         auto trav=meta_trav::start(obj.value);
00228         if(!trav.done())
00229         {
00230             do_write(trav.front(), true);
00231             trav.step_front();
00232             while(!trav.done())
00233             {
00234                 do_write(trav.front(), false);
00235                 trav.step_front();
00236             }
00237             do_write.indent();
00238         }
00239     }
00240 
00241     // write an optional/container
00242     template <typename MetaT>
00243     void write(
00244         MetaT,
00245         std::ostream& out,
00246         const _wrap<T, to_xml>& obj,
00247         optional_container_tag&
00248     )
00249     {
00250         typedef typename mp::front<all_containers<MetaT> >::type
00251             meta_cnt;
00252         if(!meta_cnt::empty(obj.value))
00253         {
00254             auto tr = meta_cnt::default_traversal::start(obj.value);
00255             assert(!tr.done());
00256             write_x do_write(out, obj);
00257             do_write.wr_val(tr.front().get());
00258         }
00259     }
00260 
00261     struct write_var : write_x
00262     {
00263         inline write_var(
00264             std::ostream& os,
00265             const _wrap<T, to_xml>& ob
00266         ): write_x(os, ob)
00267         { }
00268 
00269         template <typename MetaCntnr>
00270         void operator()(MetaCntnr)
00271         {
00272             if(!MetaCntnr::empty(this->obj.value))
00273             {
00274                 wr_val(
00275                     MetaCntnr::
00276                     default_traversal::
00277                     start(this->obj.value).
00278                     front().get()
00279                 );
00280             }
00281         }
00282     };
00283 
00284     // write an variant/container
00285     template <typename MetaT>
00286     void write(
00287         MetaT,
00288         std::ostream& out,
00289         const _wrap<T, to_xml>& obj,
00290         variant_container_tag&
00291     )
00292     {
00293         write_var do_write(out, obj);
00294         mp::for_each<all_containers<MetaT> >(do_write);
00295     }
00296 
00297     // other containers are not supported
00298     template <typename MetaT>
00299     void write(
00300         MetaT,
00301         std::ostream& out,
00302         const _wrap<T, to_xml>& obj,
00303         container_tag&
00304     );
00305 public:
00306     std::ostream& operator()(
00307         std::ostream& out,
00308         const _wrap<T, to_xml>& obj
00309     )
00310     {
00311         typedef MIRRORED_CLASS(T) meta_T;
00312         typename container_kind<meta_T>::type kind;
00313         write(meta_T(), out, obj, kind);
00314         return out;
00315     }
00316 
00317     std::ostream& operator()(
00318         std::ostream& out,
00319         const _wrap<T, to_xml>& obj,
00320         const name_proc& namer
00321     )
00322     {
00323         typedef MIRRORED_CLASS(T) meta_T;
00324         out << '<'; namer(out); out << '>';
00325         typename container_kind<meta_T>::type kind;
00326         write(meta_T(), out, obj, kind);
00327         out << '<'; namer(out); out << "/>";
00328         return out;
00329     }
00330 };
00331 
00332 } // namespace stream
00333 MIRROR_NAMESPACE_END
00334 
00335 #endif //include guard
00336 

Copyright © 2006-2011 Matus Chochlik, University of Zilina, Zilina, Slovakia.
<matus.chochlik -at- fri.uniza.sk>
<chochlik -at -gmail.com>
Documentation generated on Fri Dec 16 2011 by Doxygen (version 1.7.3).
Important note: Although the 'boostified' version of Mirror uses the Boost C++ libraries Coding Guidelines and is implemented inside of the boost namespace, it IS NOT an officially reviewed and accepted Boost library. Mirror is being developed with the intention to be submitted for review for inclusion to the Boost C++ libraries.