Mirror reflection library 0.5.13
|
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