Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members

data_node_functor.h

00001 #ifndef s11n_DATA_NODE_FUNCTOR_H_INCLUDED 00002 #define s11n_DATA_NODE_FUNCTOR_H_INCLUDED 00003 00004 //////////////////////////////////////////////////////////////////////// 00005 // data_node_functor.h 00006 // Some functors/algorithms for working with data_node-compliant types. 00007 // License: Public Domain 00008 // Author: stephan@s11n.net 00009 //////////////////////////////////////////////////////////////////////// 00010 00011 #include <string> 00012 #include <list> 00013 #include <map> 00014 #include <typeinfo> // aid debugging 00015 #include <utility> // std::pair/make_pair 00016 #include <iterator> 00017 #include <iostream> 00018 00019 #include <s11n/phoenix.h> // phoenix class 00020 #include <s11n/to_string.h> // to/from_string() 00021 #include <s11n/debuggering_macros.h> // COUT/CERR 00022 #include <s11n/string_util.h> // translate_entities() 00023 #include <s11n/pointer_stripper.h> // pointer_stripper class 00024 #include <s11n/class_name.h> // unfortunate dependency. 00025 #include <s11n/abstract_creator.h> // abstract_creator class 00026 #include <s11n/data_node_serialize.h> // core de/serialize interface 00027 #include <s11n/data_node_algo.h> // useful data_node algos 00028 00029 //////////////////////////////////////////////////////////////////////// 00030 // NO DEPS ON data_node.h ALLOWED! 00031 //////////////////////////////////////////////////////////////////////// 00032 00033 namespace s11n { 00034 00035 00036 00037 /** 00038 Dumps some info about n to the given ostream, mostly 00039 useful for debugging failed deserialization. 00040 */ 00041 template <typename NodeType> 00042 void dump_node_debug( const NodeType & n, std::ostream & os ) 00043 { 00044 os << "node dump: ["<<n.name()<<"]["<<n.impl_class()<<"]@"<<std::hex<<&n<<"\n"; 00045 typedef typename NodeType::const_iterator PT; 00046 PT b = n.begin(), e = n.end(); 00047 os << "==================== properties:\n"; 00048 for( ; e != b; ++b ) 00049 { 00050 os << (*b).first << " = " << (*b).second << "\n"; 00051 } 00052 os << "[end node]\n"; 00053 } 00054 00055 /** 00056 A helper functor to loop over serializable 00057 children. 00058 00059 Designed for use with std::for_each(). 00060 00061 NodeType must be compatible with 00062 s11n::data_node. 00063 00064 Please see the operator() docs for important usage 00065 information, especially if you want to use this 00066 object outside the context of for_each(). 00067 */ 00068 template <typename NodeType> 00069 struct data_node_child_serializer 00070 { 00071 typedef NodeType node_type; 00072 /** 00073 Creates an object for serializing 00074 00075 Preconditions: 00076 00077 - dest must outlive this object. 00078 More correctly, this object's 00079 operator() must not be called after 00080 dest is destroyed. 00081 00082 */ 00083 data_node_child_serializer( node_type & dest, const std::string & subname ) 00084 : result(true), m_name(subname), m_root(&dest) 00085 { 00086 } 00087 00088 /** 00089 Serializes src into a subnode of dest using the 00090 name given in this object's ctor. 00091 00092 Note that during an, e.g., for_each() this object 00093 will return false on a failed serialize, and will 00094 CONTINUE to return false on additional serializations. 00095 This is to avoid the possibility that for_each() 00096 fails on the first item of a list, handles 3000 items, 00097 and then the whole thing fails because of the first one. 00098 Thus, this operator will never process another request 00099 once it has returned false ONCE. 00100 */ 00101 template <typename SerializableT> 00102 bool operator()( const SerializableT * src ) 00103 { 00104 if( ! this->result ) return false; 00105 return this->result = 00106 serialize_subnode( *this->m_root, 00107 this->m_name, 00108 *src ); 00109 } 00110 /** 00111 For use as a "return value catcher" for std::for_each(). 00112 See operator() for how it is set. The starting value 00113 is true, which means that looping over an empty list 00114 with this object will return a true result (which is 00115 the convention in s11n). 00116 */ 00117 bool result; 00118 private: 00119 std::string m_name; 00120 node_type * m_root; 00121 }; 00122 00123 /** 00124 A helper functor deserialize a set of data_nodes. 00125 00126 Designed for use with std::for_each(). 00127 00128 ListType must be compatible with 00129 <code>std::list<SomeSerializableType *></code>. 00130 */ 00131 template <typename ListType> 00132 struct data_node_child_deserializer 00133 { 00134 /** 00135 The ListType templatized type. Must support: 00136 00137 push_back(value_type *); 00138 */ 00139 typedef ListType list_type; 00140 /** 00141 value_type is equivalent to a SerializableType. 00142 */ 00143 typedef typename pointer_stripper< 00144 typename list_type::value_type 00145 >::value_type value_type; 00146 00147 /** 00148 Creates an object for deserializing Serializables 00149 into a target list. 00150 00151 If tolerant is true then this object will always 00152 try to deserialize new items passed to it's 00153 operator(). If it is false (the default) it will 00154 stop processing after a single failure. 00155 00156 Preconditions: 00157 00158 - dest must outlive this object. More correctly, 00159 this object's operator() must not be called after 00160 either dest is destroyed. 00161 00162 */ 00163 data_node_child_deserializer( list_type & dest, 00164 bool tolerant = false ) 00165 : result(true), m_tolerant(tolerant), m_list(&dest) 00166 { 00167 } 00168 00169 /** 00170 Tries to deserialize a (value_type *) from src. On error it returns 0, 00171 else it inserts the new child into this object's destination container 00172 and returns true. 00173 00174 Postconditions: 00175 00176 - If successful, this object's destination container owns the returned 00177 pointers. 00178 */ 00179 template <typename NodeType> 00180 bool operator()( const NodeType * src ) 00181 { 00182 if( ! result && ! this->m_tolerant ) return false; // once an item fails, stop processing them. 00183 if( ! src ) return result = false; 00184 value_type * ch = 0; 00185 ch = s11n::deserialize<NodeType,value_type>( *src ); 00186 //CERR << "data_node_child_deserializer<>("<<src->name()<<") = " 00187 // << std::hex << ch <<"\n"; 00188 if( ! ch ) return result = false; 00189 this->m_list->push_back( ch ); 00190 return result = true; 00191 } 00192 00193 /** 00194 For use as a "return value catcher" for std::for_each(). 00195 00196 If tolerant is true then this will only reveal the value of 00197 the most-recently-processed node. 00198 */ 00199 bool result; 00200 private: 00201 bool m_tolerant; 00202 list_type * m_list; 00203 }; 00204 00205 00206 00207 00208 /** 00209 A Serializable Proxy for streamable types. It "should" work 00210 with any type which meets these conditions: 00211 00212 - i/ostream operators are implemented (as member or free 00213 functions). 00214 00215 - supports a copy ctor (for deserialization). 00216 00217 - has a class_name&lt;&gt; specialization. Such 00218 specializations come pre-installed for PODs, std::string, 00219 and maybe others. Use the CLASS_NAME(T) macro to create these. 00220 00221 00222 It's output is significantly bigger than using, e.g., node 00223 properties to store them, but with this proxy any 00224 streamable can be treated as a full-fledged Serializable, 00225 which allows some generic container-based serialization to 00226 be done regardless of the underlying types (see 00227 list_serializer_proxy for an example). 00228 00229 00230 ACHTUNG: never pass the same Serializable to the 00231 operators more than once or you will get duplicate and/or 00232 incorrect data. 00233 */ 00234 struct streamable_type_serializer_proxy 00235 { 00236 /** 00237 Sets the subnode name used for this object's 00238 serialize operator. 00239 */ 00240 explicit streamable_type_serializer_proxy( const std::string & subnodename ) 00241 : m_subname(subnodename) 00242 {} 00243 /** 00244 Uses a default, unspecified, name for subnode 00245 insertions. 00246 */ 00247 streamable_type_serializer_proxy() : m_subname("") 00248 {} 00249 00250 /** 00251 Creates a property in dest, called 'v', and sets 00252 its value to src. Each node gets the name assigned 00253 via this object's ctor or an undefined dummy name. 00254 Note that the deserialize operator pays no attention 00255 to the subnode names. 00256 00257 Always returns true. 00258 */ 00259 template <typename NodeType, typename SerType> 00260 bool operator()( NodeType & dest, const SerType & src ) const 00261 { 00262 dest.impl_class( class_name<SerType>::name() ); 00263 //dest.impl_class( "pod" ); 00264 // ^^^^ not strictly necessary, but i want 00265 // something smaller than the default string. 00266 //dest.set( "s11n_metadata", "serialized-by:s11n::streamable_type_serializer_proxy" ); 00267 if( ! this->m_subname.empty() ) dest.name( this->m_subname ); 00268 dest.set( "v", src ); 00269 return true; 00270 } 00271 00272 /** 00273 Looks for a property in src called 'v' and sets 00274 dest to it's value. The default for dest, in the case 00275 of a missing property or nonconvertable value is 00276 dest itself. 00277 00278 If the 'v' property is missing this function does 00279 nothing and returns false, otherwise dest gets 00280 assigned the property's value and true is 00281 returned. This function cannot catch a case of 00282 inability to convert 'v' into a SerType: client 00283 code interested in doing so should compare dest's 00284 value to a known error value after this 00285 function returns. 00286 */ 00287 template <typename NodeType, typename SerType> 00288 bool operator()( const NodeType & src, SerType & dest ) const 00289 { 00290 if( ! src.is_set( "v" ) ) 00291 { 00292 CERR << "streamable_serializer_proxy: deser failed: property 'v' missing!\n"; 00293 dump_node_debug( src, std::cerr ); 00294 return false; 00295 } 00296 dest = src.get( "v", dest ); 00297 return true; 00298 } 00299 private: 00300 std::string m_subname; 00301 }; 00302 00303 00304 00305 00306 00307 namespace io { 00308 00309 00310 00311 /** 00312 A helper for serializing properties to a 00313 stream. Intended for use by Serializers, not 00314 Serializables. 00315 00316 NodeType is the container type used for data 00317 serialization (e.g. s11n::data_node). 00318 00319 */ 00320 template <typename NodeType> 00321 class key_value_serializer 00322 { 00323 public: 00324 typedef NodeType node_type; 00325 typedef typename node_type::value_type pair_type; 00326 00327 typedef std::map<std::string,std::string> entity_translation_map; 00328 00329 /** 00330 map: needed so we can do entity translation 00331 in a unified manner here. It must outlive 00332 this object. Pass it 0 for no translation. 00333 Translations are only applied on VALUES, 00334 not KEYS. 00335 00336 prefix: inserted before each property. 00337 00338 separator: inserted between the key and value. 00339 00340 suffix: appended after each entry. 00341 00342 00343 */ 00344 key_value_serializer( const entity_translation_map * map, 00345 std::ostream & dest, 00346 const std::string & prefix, 00347 const std::string & separator, 00348 const std::string & suffix 00349 ) 00350 : m_pre(prefix), m_sep(separator), m_suf(suffix), m_os(dest), m_map(map) 00351 { 00352 } 00353 00354 /** 00355 Sends the following formatted string to os: 00356 00357 {prefix}{src.first}{separator}{src.second}{suffix} 00358 00359 */ 00360 void operator()( const pair_type & src ) const 00361 { 00362 static const std::string errval = ""; 00363 std::string key = s11n::to_string( src.first ); 00364 std::string val = s11n::to_string( src.second ); 00365 // should we xlate the key as well? 00366 if( this->m_map ) 00367 { 00368 s11n::translate_entities( val, *(this->m_map) ); 00369 } 00370 this->m_os << this->m_pre; 00371 this->m_os << key; 00372 this->m_os << this->m_sep; 00373 this->m_os << val; 00374 this->m_os << this->m_suf; 00375 } 00376 private: 00377 std::string m_pre; 00378 std::string m_sep; 00379 std::string m_suf; 00380 std::ostream & m_os; 00381 const entity_translation_map * m_map; 00382 }; 00383 00384 00385 00386 00387 00388 /** 00389 A helper functor to loop over serializable children 00390 of a node from within a Serializer implementation. 00391 00392 Designed for use with std::for_each(). 00393 00394 SerializerT must be compatible with 00395 <code>data_node_serializer<></code>. 00396 00397 */ 00398 template <typename SerializerT> 00399 struct node_child_simple_formatter 00400 { 00401 typedef SerializerT serializer_type; 00402 // typedef typename SerializerT::node_type node_type; 00403 /** 00404 Preconditions: 00405 00406 - Ser must be valid references. 00407 00408 - Both ser and os must outlive this 00409 object. More correctly, this object's 00410 operator() must not be called after either 00411 ser or os are destroyed. 00412 00413 */ 00414 node_child_simple_formatter( serializer_type & ser, std::ostream & os, 00415 const std::string & prefix = "", const std::string & suffix = "\n" ) 00416 : m_ser(ser), m_os(&os), m_pre(prefix), m_suf(suffix) 00417 { 00418 } 00419 00420 /** 00421 Serializes src into this object's target 00422 container, using this object's serializer. 00423 */ 00424 template <typename NodeType> 00425 bool operator()( const NodeType * src ) const 00426 { 00427 if( ! src ) return false; 00428 if( ! this->m_pre.empty() ) *(this->m_os) << this->m_pre; 00429 bool b = this->m_ser.serialize( *src, *(this->m_os) ); 00430 if( ! this->m_suf.empty() ) *(this->m_os) << this->m_suf; 00431 return b; 00432 } 00433 00434 private: 00435 serializer_type & m_ser; 00436 std::ostream * m_os; 00437 std::string m_pre; 00438 std::string m_suf; 00439 }; 00440 00441 00442 } // namespace io 00443 00444 } // namespace s11n 00445 00446 00447 #endif // s11n_DATA_NODE_FUNCTOR_H_INCLUDED

Generated on Tue Jul 20 10:46:48 2004 for s11n by doxygen 1.3.7