Mirror reflection library 0.5.13

mirror/stream/simple_struct.hpp

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

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.