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            - 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

Generated on Sun Apr 27 13:16:03 2008 for libs11n by  doxygen 1.5.3