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 NodeT objects match 00399 a certain name. NodeT must be compatible with 00400 node_traits<NodeT>. 00401 00402 This class is admittedly to avoid the use of bind1st/bind2nd 00403 :/. 00404 */ 00405 template <typename NodeT> 00406 struct same_name 00407 { 00408 typedef NodeT node_type; 00409 typedef ::s11n::node_traits< NodeT > traits_t; 00410 explicit same_name( const std::string & n ) : m_name(n) 00411 {} 00412 00413 inline bool operator()( const node_type * x ) const 00414 { 00415 return ( ! x ) 00416 ? this->m_name.empty() 00417 : (traits_t::name( *x ) == 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 throws an 00566 s11n_exception. [Design note: this seems a bit 00567 harsh.] 00568 00569 On success dest gets assigned the property's value 00570 and true is returned. This function cannot catch a 00571 case of inability to convert the value into a 00572 SerType: client code interested in doing so should 00573 compare dest's value to a known error value after 00574 this function returns or throw from that type's 00575 istream operator on error. 00576 */ 00577 template <typename NodeType, typename SerType> 00578 bool operator()( const NodeType & src, SerType & dest ) const 00579 { 00580 typedef node_traits<NodeType> NTR; 00581 if( ! NTR::is_set( src, "v" ) ) 00582 { 00583 throw s11n_exception( "streamable_serializable_proxy: deser failed: property 'v' missing!" ); 00584 } 00585 dest = NTR::get( src, "v", SerType() /* should never happen */ ); 00586 return true; 00587 } 00588 }; 00589 00590 00591 /** 00592 Adds ch as a child of parent. Parent takes over ownership 00593 of ch. 00594 00595 NodeType must have a node_traits<> specialization. 00596 */ 00597 template <typename NodeType, typename ChildType> 00598 inline void add_child( NodeType & parent, ChildType * ch ) 00599 { 00600 typedef ::s11n::node_traits<NodeType> NTR; 00601 NTR::children( parent ).push_back( ch ); 00602 } 00603 00604 00605 /** 00606 Creates a new node, named nodename, as a child of parent. 00607 00608 Returns a reference to the new child, which parent now 00609 owns. 00610 00611 NodeType must have a node_traits<> specialization or work 00612 using the default. 00613 00614 Development tip: this function often comes in handy 00615 during serialization. 00616 */ 00617 template <typename NodeType> 00618 NodeType & create_child( NodeType & parent, const std::string nodename ); 00619 00620 00621 /** 00622 Each child in parent.children() which has the given name is 00623 copied into the target container. 00624 00625 Returns the number of items added to target. 00626 00627 DestContainerT must support an insert iterator which will 00628 insert the pointer type contained in the list returned by 00629 parent.children(). i.e., it must hold (const 00630 NodeT *). 00631 00632 Ownership of the children do not change by calling this 00633 function. Normally they are owned by the parent node 00634 (unless the client explicitely does something to change 00635 that). 00636 */ 00637 template <typename NodeT, typename DestContainerT> 00638 size_t find_children_by_name( const NodeT & parent, const std::string & name, DestContainerT & target ); 00639 00640 /** 00641 Finds the FIRST child in parent with the given name and 00642 returns a pointer to it, or 0 if no such child is found. 00643 00644 Ownership of the child does not change by calling this 00645 function: parent still owns it. 00646 00647 Complexity is linear. 00648 */ 00649 template <typename NodeT> 00650 const NodeT * 00651 find_child_by_name( const NodeT & parent, const std::string & name ); 00652 00653 /** 00654 A non-const overload of find_child_by_name(). Functionally 00655 identical to the const form, except for the constness of 00656 the parent argument and return value. 00657 00658 Ownership of the returned pointer is not changed by calling 00659 this function (normally parent owns it, but clients may 00660 change that without affecting this function). When in 00661 doubt, i.e. during "normal usage", do NOT delete the returned 00662 pointer, because the parent node owns it. This function can 00663 be used to find a child for manual removal from parent via 00664 the API for the node_traits<NodeT>::children(parent) object. 00665 */ 00666 template <typename NodeT> 00667 NodeT * 00668 find_child_by_name( NodeT & parent, const std::string & name ); 00669 00670 namespace debug { 00671 00672 /** 00673 Dumps a tree-like view of n's structure, excluding properties, 00674 to cerr. The second parameter is for use by this function 00675 in recursion: do not pass a value for it. 00676 */ 00677 template <typename NodeT> 00678 void dump_node_structure( const NodeT & n, int indentlv = 0 ); 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 /** 00716 This is similar to serialize() but adds a version tag to the 00717 serialized data. To deserialize you must use 00718 deserialize_versioned(), passing it the same version. 00719 00720 VersionType must be lexically castable (i.e. i/o-streamable), 00721 must be comparable for equivalence, and is expected to be a 00722 numeric or std::string type, or something similar. 00723 00724 This version is stored as a property (called "version") of dest, 00725 and the src object is stored in a sub-node of dest (named 00726 "vdata"). 00727 00728 On error it returns false or propagates an exception. On 00729 success it returns true. 00730 00731 Added in 1.3.1 + 1.2.7. 00732 */ 00733 template <typename NodeT, typename VersionType, typename SerT> 00734 bool serialize_versioned( NodeT & dest, VersionType const ver, SerT const & src ); 00735 00736 /** 00737 This is the counterpart to serialize_versioned(). If src 00738 contains a property named "version" which lexically matches ver 00739 then a sub-node of src (named "vdata") containing serialized data is 00740 used to deserialize the dest object. 00741 00742 On a version mismatch, or if src does not contain the expected 00743 child node then this function throws an s11n_exception. If 00744 deserialization to dest fails then false might be returned or 00745 an exception may be propagated. 00746 00747 Mis-feature: you cannot pass a (char const *) (i.e. a string 00748 literal) as the version object because that causes lots of 00749 ambiguity errors in the lexical casting proces. You may pass 00750 std::string() objects, however. 00751 00752 Added in 1.3.1 + 1.2.7. 00753 */ 00754 template <typename NodeType, typename VersionType, typename SerType> 00755 bool deserialize_versioned( NodeType const & src, VersionType const ver, SerType & dest ); 00756 00757 } // namespace 00758 00759 00760 #include <s11n.net/s11n/algo.tpp> // implementations 00761 #endif // s11n_net_s11n_v1_1_ALGO_HPP_INCLUDED