Mirror reflection library 0.5.13

mirror/stream/json.hpp

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

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.