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