algo.hpp

Go to the documentation of this file.
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

Generated on Wed Jun 4 21:45:18 2008 for libs11n by  doxygen 1.5.3