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

list.h

00001 //////////////////////////////////////////////////////////////////////// 00002 // 00003 //////////////////////////////////////////////////////////////////////// 00004 #ifndef s11n_LIST_H_INCLUDED 00005 #define s11n_LIST_H_INCLUDED 1 00006 00007 #include <list> 00008 #include <iterator> // insert_iterator 00009 #include <algorithm> // for_each() 00010 #include <stdio.h> // snprintf() 00011 00012 #include <s11n/functor.h> // copy_if, same_name 00013 00014 #include <s11n/data_node_serialize.h> // core serialize funcs 00015 #include <s11n/data_node_functor.h> // data_node_child_serializer functor 00016 #include <s11n/data_node_algo.h> // dump_node_debug() 00017 #include <s11n/abstract_creator.h> // abstract_creator class 00018 00019 namespace s11n { 00020 /** 00021 The s11n::list namespace defines functors and algorithms for 00022 working with std::list/vector-style containers. 00023 */ 00024 namespace list { 00025 00026 00027 /** 00028 Deprecated. See serialize_list(). 00029 00030 Serializes all Serializable objects in the given list. 00031 00032 ListType must contain ([const] SomeSerializableType *). 00033 00034 True is returned on success. 00035 00036 False is returned if any child Serializable in src fails to 00037 serialize. If false is returned then dest is in an 00038 undefined state: it may have been partially serialized, and 00039 certainly wasn't *completely* serialized. 00040 00041 Note that a subnodename is required because it is 00042 patentedly a Bad Idea to store more than one Serializable 00043 in the same node, so this function creates subnodes in 00044 dest. 00045 */ 00046 template <typename NodeT, typename ListType> 00047 bool serialize_pointer_list( NodeT & dest, 00048 const std::string & subnodename, 00049 const ListType & src ) 00050 { 00051 return std::for_each( src.begin(), 00052 src.end(), 00053 s11n::data_node_child_serializer<NodeT>( dest, subnodename ) 00054 ).result; 00055 } 00056 00057 00058 /** 00059 Deprecated. See deserialize_list(). 00060 00061 The complement to serialize_pointer_list(). 00062 00063 Looks for child nodes of src named subnodename. For each 00064 one that it finds it tries to deserialize it to a 00065 (ListType::value_type) and insert it into dest. 00066 00067 Returns false only if children are found but their 00068 deserialization fails. If that happens, dest is in an 00069 undefined state: any other children (not the one which 00070 failed deserialization) might still be in the list, and 00071 there is know way for the client to know which child failed 00072 or why it failed. 00073 */ 00074 template <typename NodeT, typename ListType> 00075 bool deserialize_pointer_list( const NodeT & src, 00076 const std::string & subnodename, 00077 ListType & dest ) 00078 { 00079 //CERR << "deserialize_pointer_list("<<src.name()<<" , "<<subnodename<<", destlist )\n"; 00080 typedef std::list<const NodeT *> MatchList; 00081 MatchList li; 00082 s11n::copy_if( src.children().begin(), 00083 src.children().end(), 00084 std::insert_iterator<MatchList>( li, li.begin() ), 00085 s11n::same_name<NodeT>( subnodename ) 00086 ); 00087 //CERR << "found " << li.size() << " match(es)\n"; 00088 if( ! li.size() ) return false; 00089 bool b = std::for_each( li.begin(), 00090 li.end(), 00091 s11n::data_node_child_deserializer<ListType>( dest ) 00092 ).result; 00093 //CERR << "for_each() returned " << b << ", and result list size=" << dest.size() << "\n"; 00094 return b; 00095 } 00096 00097 /** 00098 serialize_list() supports list/vector-like types containing 00099 any Serializable type. Serializes (src.begin(),src.end()] 00100 to dest. Each item has a node name of that given to the 00101 ctor or an unspecified dummy value. 00102 00103 Returns true on success. If false is returned then dest is 00104 in an undefined state: some number of serializations may 00105 have succeeded before the failure. This operation stops 00106 processing at the first serialization error. 00107 00108 00109 Compatible ListTypes must support: 00110 00111 - a value_type typedef describing the type of it's contents. 00112 00113 - push_back( value_type ) 00114 00115 - const_iterator typedefs. 00116 00117 Restrictions on value_type's type: 00118 00119 - Must be a Serializable. This includes any i/o streamable 00120 type which has a proxy installed by s11n (includes all PODs 00121 and std::string by default). 00122 00123 - may be a pointer type. 00124 00125 Some s11n-side requirements: 00126 00127 - ListType must be registered with the ListType classloader. 00128 00129 ACHTUNG: never pass the same destination container to 00130 this function more than once or you will get duplicate and/or 00131 incorrect data. 00132 */ 00133 template <typename NodeType, typename SerType> 00134 bool serialize_list( NodeType & dest, const SerType & src ) 00135 { 00136 dest.impl_class( class_name<SerType>::name() ); 00137 typename SerType::const_iterator it = src.begin(); 00138 // reminder: (*it) may be a pointer- or a value-type, 00139 // as long as it's a Serializable. 00140 //dest.set( "s11n_metadata", "serialized-by:s11n::list::serialize_list" ); 00141 for( ; src.end() != it; ++it ) 00142 { 00143 NodeType * ch = new NodeType; 00144 if( ! serialize( *ch, *it ) ) 00145 { 00146 CERR << "serialize_list: a child failed to serialize: " << ch->name() << " @ " << std::hex << ch << "\n"; 00147 s11n::dump_node_debug( *ch, std::cerr ); 00148 delete( ch ); 00149 return false; 00150 } 00151 dest.children().push_back( ch ); 00152 } 00153 return true; 00154 } 00155 00156 /** 00157 Identical to the two-argument form of serialize_list(), but 00158 serializes src into a subnode of dest, named subnodename. 00159 */ 00160 template <typename NodeType, typename SerType> 00161 bool serialize_list( NodeType & dest, 00162 const std::string & subnodename, 00163 const SerType & src ) 00164 { 00165 NodeType * ch = new NodeType; 00166 if( ! serialize_list<NodeType,SerType>( *ch, src ) ) 00167 { 00168 delete( ch ); 00169 return false; 00170 } 00171 dest.children().push_back( ch ); 00172 return true; 00173 } 00174 00175 /** 00176 For each (src.children().begin(),end()] an object 00177 of type SerType::value_type is created, deserialized, 00178 and is added to dest via push_back( item ). 00179 00180 See serialize_list() for the list type requirements. 00181 00182 If SerType::value_type is a pointer type then dest owns any 00183 newly-created pointers, and it's owner (or the container 00184 itself) is responsible for cleaning them up. (Non-pointer 00185 types need no explicit clean-up, of course.) 00186 00187 Returns true if all deserializations succeed. Stops 00188 processing and returns false at the first error, in which 00189 case dest is in an undefined state: some children may or 00190 may not have been successfully deserialized into it. The 00191 immediate implication of this is that it will fail if src 00192 contains any other children than the type which dest 00193 expects! 00194 */ 00195 template <typename NodeType, typename SerType> 00196 bool deserialize_list( const NodeType & src, SerType & dest ) 00197 { 00198 // note: some of the odd code here is to allow this 00199 // func to support both value- and pointer-types. 00200 typedef typename SerType::value_type VT; 00201 typedef s11n::abstract_creator<VT> ACVT; 00202 typedef typename NodeType::child_list_type::const_iterator CHIT; 00203 const NodeType * nch = 0; 00204 CHIT it = src.children().begin(); 00205 CHIT et = src.children().end(); 00206 s11n::object_reference_wrapper<SerType> dwrap(dest); 00207 VT ser; // reminder: might be a pointer type 00208 for( ; et != it; ++it ) 00209 { 00210 nch = *it; 00211 if( ! ACVT::create( ser,nch->impl_class() ) ) 00212 { 00213 CERR << "Internal error: abstract_creator<> " 00214 << "could not create a new object of type '" 00215 << nch->impl_class()<<"'!\n"; 00216 return false; 00217 } 00218 if( ! deserialize( *nch, ser ) ) 00219 { 00220 CERR << "deserialize_list(): deser of a child failed!\n"; 00221 CERR << "name="<< nch->name()<< ". implclass="<< nch->impl_class()<<" @ " << std::hex<<nch <<"\n"; 00222 s11n::dump_node_debug( *nch, std::cerr ); 00223 ACVT::release( ser ); 00224 return false; 00225 } 00226 dwrap().insert( dwrap().end(), ser ); 00227 } 00228 return true; 00229 } 00230 00231 /** 00232 Identical to the two-argument form of deserialize_list(), but 00233 deserializes a subnode of src, named subnodename. If no such 00234 child is found in src then false is returned. 00235 */ 00236 template <typename NodeType, typename SerType> 00237 bool deserialize_list( const NodeType & src, 00238 const std::string & subnodename, 00239 SerType & dest ) 00240 { 00241 const NodeType * ch = s11n::find_child_by_name( src, subnodename ); 00242 if( ! ch ) return false; 00243 return deserialize_list<NodeType,SerType>( *ch, dest ); 00244 } 00245 00246 /** 00247 serialize_streamable_list serializes objects of type 00248 <tt>std::list&lt;X&gt;</tt> (and compatible list types, 00249 such as std::vector). It stores them in such a way that 00250 they can be loaded into any compatible container via 00251 deserialize_streamable_list(). 00252 00253 Conventions: 00254 00255 - NodeType must support a generic set(Key,Val) function, as 00256 implemented by the s11n::data_node interface. 00257 00258 - ListType must conform to std::list conventions and it's 00259 value_type must be a non-pointer type which is 00260 i/ostreamable (this includes all PODs and 00261 std::string). Pointers are not supported by 00262 this function. 00263 00264 ACHTUNG: 00265 00266 - Never call this on a node for which you store other 00267 properties, as deserialize_streamable_list() will consume them 00268 if you use that function. 00269 00270 - This function sets dummy property keys, both to please 00271 the conventions of keys having non-empty values and to keep 00272 the list in the proper order. It uses keys which should be 00273 portable to, e.g., standard XML. 00274 00275 Returns the number of items serialized. 00276 */ 00277 template <typename NodeType, typename ListType> 00278 size_t serialize_streamable_list( NodeType & dest, const ListType & src ) 00279 { 00280 typedef typename ListType::const_iterator CIT; 00281 CIT it = src.begin(); 00282 size_t i = 0; 00283 // We zero-pad all keys to be the same length, so that 00284 // they will be kept in the proper order in the 00285 // target's property list (annoying, but necessary). 00286 // We prepend a non-numeric char to make this output 00287 // compatible with standard XML 00288 static const int bsize = 10; 00289 char num[bsize]; 00290 char fmt[bsize]; 00291 size_t sz = src.size(); 00292 int places = 1; // # of digits to use 00293 for( ; sz >= 0x0f; sz = (size_t)(sz/0x0f)) { ++places; } 00294 snprintf( fmt, bsize, "x%%0%dx", places ); 00295 for( ; src.end() != it; ++it ) 00296 { 00297 snprintf( num, bsize, fmt, i ); 00298 ++i; 00299 dest.set( num, (*it) ); 00300 } 00301 return i; 00302 } 00303 00304 00305 /** 00306 Identical to serialize_streamable_list(dest,src), but 00307 creates a subnode in dest, named subnodename, where the 00308 data is stored. 00309 */ 00310 template <typename NodeType, typename ListType> 00311 size_t serialize_streamable_list( NodeType & dest, 00312 const std::string & subnodename, 00313 const ListType & src ) 00314 { 00315 NodeType & n = s11n::create_child( dest, subnodename ); 00316 return serialize_streamable_list<NodeType,ListType>( n, src ); 00317 } 00318 00319 00320 /** 00321 Deserializes dest from src. It reads in all properties from 00322 src, ignoring their keys and taking only their values. This 00323 is suitable for use with the result of a 00324 serialize_streamable_list() call. See that function for more 00325 information, including the conventions which must be 00326 supported by NodeType and ListType. 00327 00328 Returns the number of items deserialized. 00329 */ 00330 template <typename NodeType, typename ListType> 00331 size_t deserialize_streamable_list( const NodeType & src, ListType & dest ) 00332 { 00333 typedef typename ListType::value_type VT; 00334 typename NodeType::const_iterator it = src.begin(); 00335 size_t i = 0; 00336 VT defaultval; 00337 for( ; src.end() != it; ++it ) 00338 { 00339 ++i; 00340 dest.insert( dest.end(), 00341 s11n::from_string<VT>( (*it).second, defaultval ) ); 00342 } 00343 return i; 00344 } 00345 00346 00347 /** 00348 Identical to deserialize_streamable_list(), but looks for 00349 the data in a subnode of src named subnodename. 00350 00351 Returns 0 if no child could be found. 00352 */ 00353 template <typename NodeType, typename ListType> 00354 size_t deserialize_streamable_list( const NodeType & src, 00355 const std::string & subnodename, 00356 ListType & dest ) 00357 { 00358 const NodeType * ch = s11n::find_child_by_name( src, subnodename ); 00359 if( ! ch ) return 0; 00360 return deserialize_streamable_list<NodeType,ListType>( *ch, dest ); 00361 } 00362 00363 00364 00365 /** 00366 list_serializer_proxy is a functor for de/serializing lists 00367 of Serializables. 00368 */ 00369 class list_serializer_proxy 00370 { 00371 public: 00372 list_serializer_proxy() 00373 {} 00374 00375 /** 00376 see serialize_list(). 00377 00378 */ 00379 template <typename NodeType, typename SerType> 00380 bool operator()( NodeType & dest, const SerType & src ) const 00381 { 00382 return serialize_list( dest, src ); 00383 } 00384 00385 /** see deserialize_list(). */ 00386 template <typename NodeType, typename SerType> 00387 bool operator()( const NodeType & src, SerType & dest ) const 00388 { 00389 return deserialize_list( src, dest ); 00390 } 00391 }; 00392 00393 00394 00395 } } // namespace s11n::list 00396 00397 00398 #endif // s11n_LIST_H_INCLUDED

Generated on Wed Jul 28 16:04:14 2004 for s11n by doxygen 1.3.7