00001 #ifndef s11n_net_s11n_v1_1_ALGO_HPP_INCLUDED 00002 #define s11n_net_s11n_v1_1_ALGO_HPP_INCLUDED 1 00003 ///////////////////////////////////////////////////////////////////////// 00004 // algo.hpp: generic functors and algos for use with libs11n. 00005 // Author: stephan beal <stephan@s11n.net> 00006 // License: Public Domain 00007 ///////////////////////////////////////////////////////////////////////// 00008 00009 #include <string> 00010 #include <algorithm> 00011 00012 #include <s11n.net/s11n/s11n_debuggering_macros.hpp> // COUT/CERR 00013 #include <s11n.net/s11n/serialize.hpp> // core de/serialize interface 00014 #include <s11n.net/s11n/traits.hpp> // node_traits 00015 #include <s11n.net/s11n/type_traits.hpp> // type_traits<> 00016 00017 namespace s11n 00018 { 00019 00020 /** 00021 Serializes src to as a subnode of target, named 00022 nodename. Except for the addition of a subnode, it is 00023 identical to serialize( target, src ). 00024 00025 If serialization into the subnode throws the subnode is not 00026 added to target (it is destroyed) and any exception is 00027 propagated back to the caller. 00028 00029 This is a convenience function: not part of the s11n kernel. 00030 00031 00032 Changed in 1.1.3: 00033 00034 - Moved to algo.hpp to be symetric with deserialize_subnode(). 00035 00036 */ 00037 template <typename DataNodeType, typename SerializableT > 00038 bool serialize_subnode( DataNodeType & target, 00039 const std::string & nodename, 00040 const SerializableT & src ); 00041 00042 00043 /** 00044 If a child named subnodename is found in src then this function 00045 returns deserialize( child, target ) and returns it's result, otherwise 00046 it returns 0. 00047 00048 The function might throw, as it uses the two-arg form of 00049 deserialize(). 00050 00051 This is a convenience function: not part of the s11n 00052 kernel. 00053 00054 00055 Changed in 1.1.3: 00056 00057 - Moved to algo.hpp to avoid a circular dependency on 00058 s11n::find_child_by_name(). 00059 00060 */ 00061 template <typename DataNodeType, typename DeserializableT> 00062 bool deserialize_subnode( const DataNodeType & src, 00063 const std::string & subnodename, 00064 DeserializableT & target ); 00065 00066 /** 00067 If a child named subnodename is found in src then this function 00068 returns the result of deserialize(child), otherwise 00069 it returns 0. 00070 00071 The function might throw, as it uses the two-arg form of 00072 deserialize(). 00073 00074 This is a convenience function: not part of the s11n kernel. 00075 00076 Changed in 1.1.3: 00077 00078 - Moved to algo.hpp to avoid a circular dependency on 00079 s11n::find_child_by_name(). 00080 00081 */ 00082 template <typename DataNodeType, typename DeserializableT> 00083 DeserializableT * deserialize_subnode( const DataNodeType & src, 00084 const std::string & subnodename ); 00085 00086 00087 00088 /** 00089 For each item in [first,last), copies the item to OutputIt 00090 if pred(*item) returns true. 00091 00092 Code copied from: 00093 00094 http://www.bauklimatik-dresden.de/privat/nicolai/html/en/cpp.html 00095 */ 00096 00097 template <typename InputIt, typename OutputIt, typename UnaryPredicate> 00098 OutputIt copy_if (InputIt first, 00099 InputIt last, 00100 OutputIt result, 00101 UnaryPredicate pred) 00102 { 00103 while (first != last) 00104 { 00105 if (pred(*first)) *result++ = *first; 00106 ++first; 00107 } 00108 return result; 00109 } 00110 00111 00112 00113 /** 00114 Deletes an object passed to it. 00115 00116 This type accepts non-pointer types for "destruction." This 00117 is a non-operation, and is supported to allow other 00118 template code to generically free objects without needing 00119 to know if they are pointers. This allows some 00120 formerly-non-consolidatable reference-vs-pointer-type code to 00121 share a single implementation, as "delete(myobj)" is not 00122 valid for non-pointer types, but object_deleter()(myobj) 00123 is. 00124 00125 DEPRECATED: this will be removed in favor of 00126 cleanup_serializable(). 00127 00128 @deprecated 00129 */ 00130 struct object_deleter 00131 { 00132 /** 00133 Deletes t. 00134 */ 00135 template <typename T> 00136 void operator()( T * t ) const 00137 { 00138 // ACH!!!! If we use (const T *) for the arguments 00139 // then the (const T &) version is called 00140 // even when a pointer type is passed in!!!! 00141 00142 // i don't fully understand why 00143 // delete( const T * ) is legal, 00144 // considering that it triggers a dtor, 00145 // and dtors are non-const. 00146 //CERR << "object_deleter deleting "<< std::hex<<t<<"\n"; 00147 delete( t ); 00148 } 00149 /** 00150 Does nothing: is here to allow some 00151 reference-vs-pointer-type transparency. 00152 */ 00153 template <typename T> 00154 void operator()( const T & t ) const 00155 { 00156 //CERR << "object_deleter no-op\n"; 00157 } 00158 }; 00159 00160 00161 00162 /** 00163 For each item in [begin,end) object_deleter()(*item) is called. 00164 00165 After this call the container from which the iterators come 00166 still contains the items but they are invalid - deleted 00167 pointers. The client should call erase(begin,end) to delete 00168 the entries, or use convenience function 00169 free_list_entries(), which accepts a list-style 00170 container and empties the list. 00171 00172 DEPRECATED: this will be removed in favor of 00173 cleanup_serializable(). 00174 00175 @deprecated 00176 */ 00177 template <typename IterT> 00178 void delete_objects( IterT begin, IterT end ) 00179 { 00180 std::for_each( begin, end, object_deleter() ); 00181 } 00182 00183 00184 00185 /** 00186 object_reference_wrapper is a type for giving access 00187 to T objects via their dot operator, regardless of whether 00188 they are pointers or not. 00189 00190 Intended for use with value_types which come from, e.g., 00191 std::list, so objects of those types can be called using 00192 the same syntax regardless of whether they are pointer 00193 types or not. 00194 00195 e.g., assuming MyType might be a pointer or a reference, 00196 we can ignore that difference for call-syntax purposes 00197 with: 00198 00199 <pre> 00200 object_reference_wrapper<MyType> wrap; 00201 wrap(myobj).memberfunc(); 00202 </pre> 00203 00204 or: 00205 00206 <pre> 00207 object_reference_wrapper<MyType> wrap(myobj); 00208 wrap().memberfunc(); 00209 </pre> 00210 */ 00211 template <typename T> 00212 struct object_reference_wrapper 00213 { 00214 typedef T value_type; 00215 typedef T base_value_type; 00216 // object_reference_wrapper() : m_ptr(0) {} 00217 object_reference_wrapper( value_type &obj ) : m_ptr(&obj) {}; 00218 /** 00219 Sets this object's proxy object to t and returns t. 00220 */ 00221 base_value_type & operator()( value_type & t ) 00222 { 00223 return this->m_ptr = &t; 00224 return t; 00225 } 00226 /** 00227 Returns this object's wrapped object. 00228 */ 00229 base_value_type & operator()() const { return *(this->m_ptr); } 00230 00231 /** 00232 Returns true if this object is wrapping a non-0 object, else 00233 false. 00234 */ 00235 bool good() const 00236 { 00237 return 0 != this->m_ptr; 00238 } 00239 00240 private: 00241 value_type * m_ptr; 00242 }; 00243 00244 /** 00245 A specialization to wrap pointers to (T *) such that they 00246 can be accessed, via this wrapper, using a dot instead of 00247 <tt>-></tt>. 00248 */ 00249 template <typename T> 00250 struct object_reference_wrapper<T *> 00251 { 00252 typedef T * value_type; 00253 typedef T base_value_type; 00254 // object_reference_wrapper() : m_ptr(0) {} 00255 object_reference_wrapper( value_type & obj ) : m_ptr(obj) {}; 00256 /** Sets this object's proxied object to t and Returns t. */ 00257 base_value_type & operator()( value_type & t ) 00258 { 00259 this->m_ptr = &t; 00260 return *t; 00261 } 00262 /** Returns this object's wrapped object. 00263 */ 00264 base_value_type & operator()() const { return *(this->m_ptr); } 00265 private: 00266 base_value_type * m_ptr; 00267 }; 00268 00269 00270 /** 00271 const_object_reference_wrapper is identical in usage to 00272 object_reference_wrapper, except that it deals with const 00273 objects. It is a separate functor to avoid ambiguity and 00274 some impossible overloads. 00275 */ 00276 template <typename T> 00277 struct const_object_reference_wrapper 00278 { 00279 typedef T value_type; 00280 typedef T base_value_type; 00281 // const_object_reference_wrapper() : m_ptr(0) {} 00282 const_object_reference_wrapper( const value_type &obj ) : m_ptr(&obj) {}; 00283 /** 00284 Sets this object's proxied obj to t and returns t. 00285 */ 00286 const base_value_type & operator()( const value_type & t ) 00287 { 00288 this->m_ptr = &t; 00289 return t; 00290 } 00291 /** 00292 Returns this object's wrapped object. 00293 */ 00294 const base_value_type & operator()() const { return *this->m_ptr; } 00295 private: 00296 const value_type * m_ptr; 00297 }; 00298 00299 /** 00300 A specialization to wrap pointers to (T *) such that they 00301 can be accessed, via this wrapper, using a dot instead of 00302 <tt>-></tt>. 00303 */ 00304 template <typename T> 00305 struct const_object_reference_wrapper<T *> 00306 { 00307 typedef T * value_type; 00308 typedef T base_value_type; 00309 // const_object_reference_wrapper() : m_ptr(0) {} 00310 explicit const_object_reference_wrapper( const value_type & obj ) : m_ptr(obj) {}; 00311 /** Returns (*t). */ 00312 inline const base_value_type & operator()( value_type & t ) 00313 { 00314 this->m_ptr = &t; 00315 return t; 00316 } 00317 /** Returns this object's wrapped object. It does not check for validity.*/ 00318 inline const base_value_type & operator()() const { return *(this->m_ptr); } 00319 private: 00320 const base_value_type * m_ptr; 00321 }; 00322 00323 00324 namespace Detail { 00325 /** 00326 child_pointer_deep_copier is a functor to deep-copy 00327 a list of pointers into another list. Designed for 00328 use with std::for_each and the like. 00329 00330 Assuming T is the type contained in ListType, stripped 00331 of any pointer part, then the following must hold: 00332 00333 00334 - List must support <code>push_back( T * )</code>. 00335 00336 - This must be a valid expression: 00337 00338 <code>T * t = new T( *p );</code> 00339 00340 Where p is a passed to this type's operator(). 00341 00342 ACHTUNG: This is only useful for non-polymorphic 00343 copying. 00344 00345 It might be interesting to note that copying 00346 monomorphic s11n::s11n_node objects this way is 00347 "pseudo-polymorphic" - the copy itself is 00348 monomorphic but the data needed to deserialize the 00349 proper type from the node is maintained. 00350 */ 00351 template <typename ListType> 00352 class child_pointer_deep_copier 00353 { 00354 public: 00355 typedef ListType list_type; 00356 typedef typename ListType::value_type full_value_type; 00357 typedef typename ::s11n::type_traits<full_value_type>::type value_type; // list_type::value_type minus any pointer part. 00358 /** 00359 Target list must outlive this object. 00360 */ 00361 child_pointer_deep_copier( list_type & target ) : m_childs(&target) 00362 {} 00363 00364 /** 00365 Inserts a copy of p into this object's list and returns true. 00366 00367 Returns true if p is successfully copied. 00368 00369 If an exception thrown while copying, this function 00370 will catch it and not modify the underlying 00371 container. In that case, false is returned. 00372 00373 The target list takes ownership of the new copy of p. 00374 */ 00375 bool operator()( const value_type * p ) throw() 00376 { 00377 if( ! this->m_childs || ! p ) return false; 00378 value_type * cp = 0; 00379 try 00380 { 00381 cp = new value_type( *p ); 00382 if( ! cp ) return false; 00383 } 00384 catch(...) 00385 { 00386 delete( cp ); // not necessary 00387 return false; 00388 } 00389 this->m_childs->push_back( cp ); 00390 return true; 00391 } 00392 private: 00393 list_type * m_childs; 00394 }; 00395 00396 00397 /** 00398 Functor to return true if given NameableT objects match a 00399 certain name. NameableT must support: 00400 00401 std::string name() const; 00402 00403 This class is admittedly to avoid the use of bind1st/bind2nd 00404 :/. 00405 */ 00406 template <typename NameableT> 00407 struct same_name 00408 { 00409 typedef NameableT nameable_type; 00410 explicit same_name( const std::string & n ) : m_name(n) 00411 {} 00412 00413 inline bool operator()( const nameable_type * x ) const 00414 { 00415 return ( ! x ) 00416 ? this->m_name.empty() 00417 : (x->name() == this->m_name); 00418 } 00419 private: 00420 std::string m_name; 00421 }; 00422 00423 } // namespace Detail 00424 00425 00426 00427 /** 00428 A helper functor to loop over serializable 00429 children. 00430 00431 Designed for use with std::for_each(). 00432 00433 NodeType must be compatible with s11n node conventions. 00434 00435 Please see the operator() docs for important usage 00436 information, especially if you want to use this 00437 object outside the context of for_each(). 00438 */ 00439 template <typename NodeType> 00440 struct subnode_serializer_f 00441 { 00442 typedef NodeType node_type; 00443 /** 00444 Creates an object for serializing 00445 00446 Preconditions: 00447 00448 - dest must outlive this object. 00449 More correctly, this object's 00450 operator() must not be called after 00451 dest is destroyed. 00452 00453 */ 00454 subnode_serializer_f( node_type & dest, const std::string & subname ) 00455 : result(true), m_root(&dest), m_name(subname) 00456 { 00457 } 00458 00459 /** 00460 Serializes src into a subnode of dest using the 00461 name given in this object's ctor. 00462 00463 Note that during an, e.g., for_each() this object 00464 will return false on a failed serialize, and will 00465 CONTINUE to return false on additional serializations. 00466 This is to avoid the possibility that for_each() 00467 fails on the first item of a list, handles 3000 items, 00468 and then the whole thing fails because of the first one. 00469 Thus, this operator will never process another request 00470 once it has returned false ONCE. 00471 00472 Versions prior to 1.1.3 always dereferenced src, 00473 without checking for a null pointer. As of 1.1.3, 00474 false is returned if (!src). 00475 */ 00476 template <typename SerializableT> 00477 inline bool operator()( const SerializableT * src ) 00478 { 00479 return (src && this->result) 00480 ? (this->result = ::s11n::serialize_subnode( *this->m_root, 00481 this->m_name, 00482 *src )) 00483 : false; 00484 } 00485 template <typename SerializableT> 00486 inline bool operator()( const SerializableT & src ) 00487 { 00488 return this->operator()( &src ); 00489 } 00490 00491 /** 00492 For use as a "return value catcher" for std::for_each(). 00493 See operator() for how it is set. The starting value 00494 is true, which means that looping over an empty list 00495 with this object will return a true result (which is 00496 the convention in s11n). 00497 */ 00498 bool result; 00499 private: 00500 node_type * m_root; 00501 std::string m_name; 00502 }; 00503 00504 00505 00506 00507 /** 00508 A Serializable Proxy for streamable types. It "should" work 00509 with any type which meets these conditions: 00510 00511 - complementary i/ostream operators are implemented (as 00512 member or free functions). 00513 00514 - supports a copy ctor (for deserialization). 00515 00516 00517 The class name of serialized objects will be taken 00518 from s11n_traits<>::class_name(), which isn't truly 00519 valid because most streamable types are never registed 00520 via s11n_traits. Hmmm. 00521 00522 Its output is significantly bigger than using, e.g. node 00523 properties to store them, but with this proxy any 00524 streamable can be treated as a full-fledged Serializable, 00525 which allows some generic container-based serialization to 00526 be done regardless of the underlying types (see the various 00527 standard container algos for examples). 00528 00529 ACHTUNG: never pass the same Serializable to the 00530 operators more than once or you will get duplicate and/or 00531 incorrect data. 00532 */ 00533 struct streamable_type_serialization_proxy 00534 { 00535 /** 00536 */ 00537 streamable_type_serialization_proxy() 00538 {} 00539 00540 /** 00541 Creates a property in dest, called 'v', and sets 00542 its value to src using node_traits<NodeType>::set(dest,"v",src). 00543 00544 Always returns true unless no class name can be found 00545 for src, in which case it returns false to avoid inserting 00546 a non-name node into the data tree (which might 00547 result in unreadable data later). 00548 */ 00549 template <typename NodeType, typename SerType> 00550 bool operator()( NodeType & dest, const SerType & src ) const 00551 { 00552 typedef node_traits<NodeType> NTR; 00553 typedef s11n_traits<SerType> STR; 00554 NTR::class_name( dest, STR::class_name(&src) ); 00555 NTR::set( dest, "v", src ); 00556 return true; 00557 } 00558 00559 /** 00560 Looks for a property set by the serialize operator and sets 00561 dest to its value. The default for dest, in the case 00562 of a missing property or nonconvertable value is 00563 dest itself. 00564 00565 If the property is missing this function does 00566 nothing and returns false. 00567 00568 On success dest gets assigned the property's value 00569 and true is returned. This function cannot catch a 00570 case of inability to convert the value into a 00571 SerType: client code interested in doing so should 00572 compare dest's value to a known error value after 00573 this function returns or throw from that type's 00574 istream operator on error. 00575 */ 00576 template <typename NodeType, typename SerType> 00577 bool operator()( const NodeType & src, SerType & dest ) const 00578 { 00579 typedef node_traits<NodeType> NTR; 00580 if( ! NTR::is_set( src, "v" ) ) 00581 { 00582 throw s11n_exception( "streamable_serializable_proxy: deser failed: property 'v' missing!" ); 00583 } 00584 dest = NTR::get( src, "v", SerType() /* should never happen */ ); 00585 return true; 00586 } 00587 }; 00588 00589 00590 /** 00591 Adds ch as a child of parent. Parent takes over ownership 00592 of ch. 00593 00594 NodeType must have a node_traits<> specialization. 00595 */ 00596 template <typename NodeType, typename ChildType> 00597 inline void add_child( NodeType & parent, ChildType * ch ) 00598 { 00599 typedef ::s11n::node_traits<NodeType> NTR; 00600 NTR::children( parent ).push_back( ch ); 00601 } 00602 00603 00604 /** 00605 Creates a new node, named nodename, as a child of parent. 00606 00607 Returns a reference to the new child, which parent now 00608 owns. 00609 00610 NodeType must have a node_traits<> specialization or work 00611 using the default. 00612 00613 Development tip: this function often comes in handy 00614 during serialization. 00615 */ 00616 template <typename NodeType> 00617 NodeType & create_child( NodeType & parent, const std::string nodename ); 00618 00619 00620 /** 00621 Each child in parent.children() which has the given name is 00622 copied into the target container. 00623 00624 Returns the number of items added to target. 00625 00626 DestContainerT must support an insert iterator which will 00627 insert the pointer type contained in the list returned by 00628 parent.children(). i.e., it must hold (const 00629 NodeT *). 00630 00631 Ownership of the children do not change by calling this 00632 function. Normally they are owned by the parent node 00633 (unless the client explicitely does something to change 00634 that). 00635 */ 00636 template <typename NodeT, typename DestContainerT> 00637 size_t find_children_by_name( const NodeT & parent, const std::string & name, DestContainerT & target ); 00638 00639 /** 00640 Finds the FIRST child in parent with the given name and 00641 returns a pointer to it, or 0 if no such child is found. 00642 00643 Ownership of the child does not change by calling this 00644 function: parent still owns it. 00645 00646 Complexity is linear. 00647 */ 00648 template <typename NodeT> 00649 const NodeT * 00650 find_child_by_name( const NodeT & parent, const std::string & name ); 00651 00652 /** 00653 A non-const overload of find_child_by_name(). Functionally 00654 identical to the const form, except for the constness of 00655 the parent argument and return value. 00656 00657 Ownership of the returned pointer is not changed by calling 00658 this function (normally parent owns it, but clients may 00659 change that without affecting this function). When in 00660 doubt, i.e. during "normal usage", do NOT delete the returned 00661 pointer, because the parent node owns it. This function can 00662 be used to find a child for manual removal from parent via 00663 the API for the node_traits<NodeT>::children(parent) object. 00664 */ 00665 template <typename NodeT> 00666 NodeT * 00667 find_child_by_name( NodeT & parent, const std::string & name ); 00668 00669 namespace debug { 00670 00671 /** 00672 Dumps a tree-like view of n's structure, excluding properties, 00673 to cerr. The second parameter is for use by this function 00674 in recursion: do not pass a value for it. 00675 */ 00676 template <typename NodeT> 00677 void dump_node_structure( const NodeT & n, int indentlv = 0 ); 00678 00679 } // namespace 00680 00681 00682 00683 00684 /** 00685 A functor which simply forwards its arguments to 00686 s11n::serialize_subnode(). 00687 00688 Added in 1.1.3. 00689 */ 00690 struct serialize_subnode_f 00691 { 00692 template <typename NT, typename ST> 00693 inline bool operator()( NT & dest, const std::string & subname, const ST & src ) const 00694 { 00695 return serialize_subnode<NT,ST>( dest, subname, src ); 00696 } 00697 }; 00698 00699 /** 00700 A functor which simply forwards its arguments to 00701 s11n::deserialize_subnode(). 00702 00703 Added in 1.1.3. 00704 */ 00705 struct deserialize_subnode_f 00706 { 00707 template <typename NT, typename ST> 00708 inline bool operator()( NT & dest, const std::string & subname, const ST & src ) const 00709 { 00710 return deserialize_subnode<NT,ST>( dest, subname, src ); 00711 } 00712 }; 00713 00714 00715 } // namespace 00716 00717 00718 #include <s11n.net/s11n/algo.tpp> // implementations 00719 #endif // s11n_net_s11n_v1_1_ALGO_HPP_INCLUDED