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