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 - is Copyable. 00492 00493 - is Default Constructable. 00494 00495 00496 The class name of serialized objects will be taken 00497 from s11n_traits<>::class_name(), which isn't truly 00498 valid because most streamable types are never registed 00499 via s11n_traits. Hmmm. 00500 00501 Its output is significantly bigger than using, e.g. node 00502 properties to store them, but with this proxy any 00503 streamable can be treated as a full-fledged Serializable, 00504 which allows some generic container-based serialization to 00505 be done regardless of the underlying types (see the various 00506 standard container algos for examples). 00507 00508 ACHTUNG: never pass the same Serializable to the 00509 operators more than once or you will get duplicate and/or 00510 incorrect data. (Huh? Is that true?) 00511 */ 00512 struct streamable_type_serialization_proxy 00513 { 00514 /** 00515 */ 00516 streamable_type_serialization_proxy() 00517 {} 00518 00519 /** 00520 Creates a property in dest, called 'v', and sets 00521 its value to src using node_traits<NodeType>::set(dest,"v",src). 00522 00523 Always returns true unless no class name can be found 00524 for src, in which case it returns false to avoid inserting 00525 a non-name node into the data tree (which might 00526 result in unreadable data later). 00527 */ 00528 template <typename NodeType, typename SerType> 00529 bool operator()( NodeType & dest, const SerType & src ) const 00530 { 00531 typedef node_traits<NodeType> NTR; 00532 typedef s11n_traits<SerType> STR; 00533 NTR::class_name( dest, STR::class_name(&src) ); 00534 NTR::set( dest, "v", src ); 00535 return true; 00536 } 00537 00538 /** 00539 Looks for a property set by the serialize operator and sets 00540 dest to its value. The default for dest, in the case 00541 of a missing property or nonconvertable value is 00542 dest itself. 00543 00544 If the property is missing this function throws an 00545 s11n_exception. [Design note: this seems a bit 00546 harsh.] 00547 00548 On success dest gets assigned the property's value 00549 and true is returned. This function cannot catch a 00550 case of inability to convert the value into a 00551 SerType: client code interested in doing so should 00552 compare dest's value to a known error value after 00553 this function returns or throw from that type's 00554 istream operator on error. 00555 */ 00556 template <typename NodeType, typename SerType> 00557 bool operator()( const NodeType & src, SerType & dest ) const 00558 { 00559 typedef node_traits<NodeType> NTR; 00560 if( ! NTR::is_set( src, "v" ) ) 00561 { 00562 throw s11n_exception( "streamable_serializable_proxy: deser failed: property 'v' missing!" ); 00563 } 00564 dest = NTR::get( src, "v", SerType() /* should never happen */ ); 00565 return true; 00566 } 00567 }; 00568 00569 00570 /** 00571 Adds ch as a child of parent. Parent takes over ownership 00572 of ch. 00573 00574 NodeType must have a node_traits<> specialization. 00575 */ 00576 template <typename NodeType, typename ChildType> 00577 inline void add_child( NodeType & parent, ChildType * ch ) 00578 { 00579 typedef ::s11n::node_traits<NodeType> NTR; 00580 NTR::children( parent ).push_back( ch ); 00581 } 00582 00583 00584 /** 00585 Creates a new node, named nodename, as a child of parent. 00586 00587 Returns a reference to the new child, which parent now 00588 owns. 00589 00590 NodeType must have a node_traits<> specialization or work 00591 using the default. 00592 00593 Development tip: this function often comes in handy 00594 during serialization. 00595 */ 00596 template <typename NodeType> 00597 NodeType & create_child( NodeType & parent, const std::string nodename ); 00598 00599 00600 /** 00601 Each child in parent.children() which has the given name is 00602 copied into the target container. 00603 00604 Returns the number of items added to target. 00605 00606 DestContainerT must support an insert iterator which will 00607 insert the pointer type contained in the list returned by 00608 parent.children(). i.e., it must hold (const 00609 NodeT *). 00610 00611 Ownership of the children do not change by calling this 00612 function. Normally they are owned by the parent node 00613 (unless the client explicitely does something to change 00614 that). 00615 */ 00616 template <typename NodeT, typename DestContainerT> 00617 size_t find_children_by_name( const NodeT & parent, const std::string & name, DestContainerT & target ); 00618 00619 /** 00620 Finds the FIRST child in parent with the given name and 00621 returns a pointer to it, or 0 if no such child is found. 00622 00623 Ownership of the child does not change by calling this 00624 function: parent still owns it. 00625 00626 Complexity is linear. 00627 */ 00628 template <typename NodeT> 00629 const NodeT * 00630 find_child_by_name( const NodeT & parent, const std::string & name ); 00631 00632 /** 00633 A non-const overload of find_child_by_name(). Functionally 00634 identical to the const form, except for the constness of 00635 the parent argument and return value. 00636 00637 Ownership of the returned pointer is not changed by calling 00638 this function (normally parent owns it, but clients may 00639 change that without affecting this function). When in 00640 doubt, i.e. during "normal usage", do NOT delete the returned 00641 pointer, because the parent node owns it. This function can 00642 be used to find a child for manual removal from parent via 00643 the API for the node_traits<NodeT>::children(parent) object. 00644 */ 00645 template <typename NodeT> 00646 NodeT * 00647 find_child_by_name( NodeT & parent, const std::string & name ); 00648 00649 namespace debug { 00650 00651 /** 00652 Dumps a tree-like view of n's structure, excluding properties, 00653 to cerr. The second parameter is for use by this function 00654 in recursion: do not pass a value for it, or pass 0 if you 00655 absolutely must pass something. 00656 */ 00657 template <typename NodeT> 00658 void dump_node_structure( const NodeT & n, int indentlv = 0 ); 00659 00660 } // namespace 00661 00662 00663 00664 00665 /** 00666 A functor which simply forwards its arguments to 00667 s11n::serialize_subnode(). 00668 00669 Added in 1.1.3. 00670 */ 00671 struct serialize_subnode_f 00672 { 00673 template <typename NT, typename ST> 00674 inline bool operator()( NT & dest, const std::string & subname, const ST & src ) const 00675 { 00676 return serialize_subnode<NT,ST>( dest, subname, src ); 00677 } 00678 }; 00679 00680 /** 00681 A functor which simply forwards its arguments to 00682 s11n::deserialize_subnode(). 00683 00684 Added in 1.1.3. 00685 */ 00686 struct deserialize_subnode_f 00687 { 00688 template <typename NT, typename ST> 00689 inline bool operator()( NT & dest, const std::string & subname, const ST & src ) const 00690 { 00691 return deserialize_subnode<NT,ST>( dest, subname, src ); 00692 } 00693 }; 00694 00695 /** 00696 This function behaves similar to snprintf(), but returns 00697 the result as a std::string. 00698 00699 buffsize is the maximum size of expanded format strings for 00700 vsnprintf(). This argument "should" be a size_t, but an int 00701 greatly simplifies the integration with vsnprintf (requires 00702 no casting and can cause no under/overflows). If buffsize 00703 is 0 or negative then a "reasonable" buffer size is used, 00704 where "reasonable" is defined as some unspecified value, possibly 00705 1k, possibly 4k, possibly neither. 00706 00707 The format arg is a vsnprintf-compatible format string. 00708 00709 vargs are passed on to vsnprintf(). 00710 00711 Returns an empty string on error. 00712 00713 If the expanded string is larger than buffsize then the last 3 00714 characters of the string are replaced with '...' to show that 00715 the text continues. Thus this function is more suited to 00716 general error/debug reporting and not data serialization. 00717 00718 If your function is a variadic function, you can pass them on 00719 to this function by doing the following... 00720 00721 Assuming your function looks like: 00722 00723 int my_variadic( char const * format, ... ); 00724 00725 Then, from my_variadic() we could pass on the parameters 00726 to format_string() like so: 00727 00728 \code 00729 va_list vargs; 00730 va_start( vargs, format ); 00731 mystring = format_string( 1024 * 2, format, vargs); 00732 va_end(vargs); 00733 \endcode 00734 00735 */ 00736 std::string format_string( int buffsize, 00737 const char *format, 00738 va_list vargs ) throw(); 00739 00740 /** 00741 Functionally identical to 00742 format_string(buffsize,format,va_list). 00743 */ 00744 std::string format_string( int buffsize, 00745 const char *format, 00746 ... ) throw(); 00747 00748 00749 /** 00750 A convenience overload which prefixes si's 00751 file/line/function information to the string. The info 00752 from si is not counted against the size limit defined by 00753 buffsize, so the returned string may legally be larger than 00754 buffsize. 00755 */ 00756 std::string format_string( source_info const si, 00757 int buffsize, 00758 const char *format, 00759 va_list vargs ) throw(); 00760 00761 /** 00762 Functionally identical to 00763 format_string(si,buffsize,format,va_list). 00764 */ 00765 std::string format_string( source_info const si, 00766 int buffsize, 00767 const char *format, 00768 ... ) throw(); 00769 00770 00771 00772 00773 /** 00774 Functionally identical to 00775 format_string(buffsize,format,va_list), but it uses a 00776 dynamically-growing buffer. 00777 */ 00778 std::string format_string( const char *format, 00779 va_list vargs ) throw(); 00780 00781 /** 00782 Functionally identical to 00783 format_string(buffsize,format,va_list), but it uses a 00784 dynamically-growing buffer. 00785 */ 00786 std::string format_string( const char *format,... ) throw(); 00787 00788 00789 /** 00790 Functionally identical to 00791 format_string(source_info,buffsize,format,va_list), but it uses a 00792 dynamically-growing buffer. 00793 */ 00794 std::string format_string( source_info const si, 00795 const char *format, 00796 va_list vargs ) throw(); 00797 00798 /** 00799 Functionally identical to 00800 format_string(source_info,buffsize,format,va_list), but it uses a 00801 dynamically-growing buffer. 00802 */ 00803 std::string format_string( source_info const si, 00804 const char *format, 00805 ... ) throw(); 00806 00807 00808 00809 /** 00810 This is similar to serialize() but adds a version tag to the 00811 serialized data. To deserialize you must use 00812 deserialize_versioned(), passing it the same version. 00813 00814 VersionType must be lexically castable (i.e. i/o-streamable), 00815 must be comparable for equivalence, and is expected to be a 00816 numeric or std::string type, or something similar. 00817 00818 This version is stored as a property (called "version") of dest, 00819 and the src object is stored in a sub-node of dest (named 00820 "vdata"). 00821 00822 On error it returns false or propagates an exception. On 00823 success it returns true. 00824 00825 Added in 1.3.1 + 1.2.7. 00826 */ 00827 template <typename NodeT, typename VersionType, typename SerT> 00828 bool serialize_versioned( NodeT & dest, VersionType const ver, SerT const & src ); 00829 00830 /** 00831 This is the counterpart to serialize_versioned(). If src 00832 contains a property named "version" which lexically matches ver 00833 then a sub-node of src (named "vdata") containing serialized data is 00834 used to deserialize the dest object. 00835 00836 On a version mismatch, or if src does not contain the expected 00837 child node then this function throws an s11n_exception. If 00838 deserialization to dest fails then false might be returned or 00839 an exception may be propagated. 00840 00841 Mis-feature: you cannot pass a (char const *) (i.e. a string 00842 literal) as the version object because that causes lots of 00843 ambiguity errors in the lexical casting proces. You may pass 00844 std::string() objects, however. 00845 00846 Added in 1.3.1 + 1.2.7. 00847 */ 00848 template <typename NodeType, typename VersionType, typename SerType> 00849 bool deserialize_versioned( NodeType const & src, VersionType const ver, SerType & dest ); 00850 00851 } // namespace 00852 00853 00854 #include <s11n.net/s11n/algo.tpp> // implementations 00855 #endif // s11n_net_s11n_v1_3_ALGO_HPP_INCLUDED