serialize.hpp

Go to the documentation of this file.
00001 #ifndef s11n_SERIALIZE_HPP_INCLUDED
00002 #define s11n_SERIALIZE_HPP_INCLUDED
00003 ////////////////////////////////////////////////////////////////////////
00004 // serialize.hpp:
00005 //
00006 // Defines the core de/serialize() functions (and close friends).
00007 //
00008 // License: Public Domain
00009 // Author: stephan@s11n.net
00010 ////////////////////////////////////////////////////////////////////////
00011 
00012 #include <stdexcept>
00013 #include <s11n.net/s11n/exception.hpp> // s11n_exception
00014 
00015 ////////////////////////////////////////////////////////////////////////////////
00016 // NO DEPS ON s11n_node.hpp ALLOWED!
00017 ////////////////////////////////////////////////////////////////////////////////
00018 
00019 namespace s11n {
00020 
00021 
00022     namespace Detail {
00023         /***
00024             s11n_api_marshaler is the internal API marshaller
00025             for s11n.  See the lib manual for full
00026             details. Client code is not expected to use or
00027             specialize this class, but theoretically some
00028             cases may call for doing so. In s11n versions
00029             prior to 1.0.x, specializing this type was
00030             sometimes useful for handling client-side
00031             template types, but this is no longer necessary
00032             nor encouraged.
00033 
00034             In the default implementation, s11n_traits<NodeT,SerializableT>
00035             is used to marshal the de/serialize() calls.
00036 
00037             Changed in 1.1.3:
00038 
00039             - NodeType template param was moved from the static
00040             functions to the class.
00041 
00042             - Moved class from anonymous namespace into s11n::Detail.
00043         */
00044         template <typename NodeType,typename SerializableT>
00045         struct s11n_api_marshaler
00046         {
00047             /**
00048                Same as SerializableT.
00049             */
00050             typedef SerializableT serializable_type;
00051 
00052             /** Same as the NodeType template parameter. */
00053             typedef NodeType node_type;
00054 
00055             /**
00056                Returns s11n_traits<serializable_type>::serialize_functor()( dest, src ).
00057 
00058                This implementation sets dest's class name to
00059                s11n_traits<SerializableT>::class_name(&src), which
00060                is only guaranteed to work properly for monomorphic
00061                types and base-most types of Serialization
00062                hierarchies (i.e., the registered
00063                bases). Polymorphic Serializable subtypes should
00064                set this class name themselves, or via their
00065                s11n_traits::class_name() specialization, both
00066                described in the library manual.
00067 
00068             */
00069             static bool serialize( node_type &dest, const serializable_type & src );
00070 
00071             /**
00072                Returns s11n_traits<SerializableT>::deserialize_functor()(src,dest).
00073             */
00074             static bool deserialize( const node_type & src, serializable_type & dest );
00075         };
00076 
00077         /**
00078            A specialization to handle pointer types the same as
00079            reference/value types. It simply translates the pointers
00080            into references.
00081         */
00082         template <typename NodeType,typename SerializableT>
00083         struct s11n_api_marshaler<NodeType,SerializableT *>
00084         {
00085             /**
00086                The SerializableT templatized type, minus any
00087                pointer part.
00088             */
00089             typedef SerializableT serializable_type;
00090 
00091             /** Same as the NodeType template parameter. */
00092             typedef NodeType node_type;
00093 
00094             /**
00095                Convenience typedef: this class' quasi-parent type.
00096             */
00097             typedef s11n_api_marshaler<node_type,serializable_type> parent_type;
00098 
00099             /**
00100                Returns parent_type::serialize( dest, *src );
00101 
00102                src must be a valid pointer, else false is returned.
00103             */
00104             static bool serialize( node_type &dest, const serializable_type * const & src );
00105 
00106             /**
00107                Returns parent_type::deserialize( src, *dest );
00108 
00109                dest must be a valid pointer, else false is returned.
00110 
00111                Reminder to self: if we dupe the code from
00112                deserialize(const N&,ST *&), we could
00113                potentially provide support for passing a
00114                reference to a null pointer here. No need,
00115                though, since the public s11n API already
00116                provides that.
00117             */
00118             static bool deserialize( const node_type & src, serializable_type * & dest );
00119         };
00120     } // namespace Detail
00121 
00122 
00123         /**
00124            Serializes src to target using the default API marshaling
00125            mechanism.
00126 
00127        On success it always returns true, else false.
00128 
00129        If a the underlying operation throws, it will pass on the
00130        exception.
00131         */
00132         template <typename DataNodeType, typename SerializableT>
00133         bool serialize( DataNodeType & target, const SerializableT & src );
00134 
00135     /**
00136        Calls s11n_traits<SerializableType>::cleanup_functor()(s).
00137 
00138        This function is declared as no-throw because of its
00139        logical role in the destruction process, and dtors are
00140        normally prohibited from throwing. Any exceptions caught by
00141        this function are silently ignored (a warning might go out
00142        to a debug channel, probably cerr, but don't rely on it).
00143 
00144        SerializableType requirements:
00145 
00146        - Must be a Serializable. Specifically, it must have an
00147        s11n_traits specialization installed.
00148 
00149        - s11n_traits<SerializableType>::cleanup_functor must be
00150        known to work properly for SerializableType. This is core
00151        to the whole cleanup functionality, which is core to
00152        protecting against leaks in the face of errors.
00153 
00154        Technically, if the type can be delete()d without leaking
00155        pointers, it's safe for use with this function, but this
00156        function SHOULD NOT be used as general cleanup tool. It is
00157        ONLY intended to be used with REGISTERED Serializables.
00158 
00159        This function guarantees not to leak when "cleaning up"
00160        containers holding unmanaged pointers as long as the
00161        associated cleanup_functors do their part. The model is
00162        such that once a cleanup_functor is in place for a given
00163        type, this function will inherently walk it and invoke the
00164        cleanup rules, which includes freeing any pointers along
00165        the way.
00166 
00167        Added in 1.1.3.
00168     */
00169     template <typename SerializableType>
00170     void cleanup_serializable( SerializableType & s ) throw();
00171 
00172     /**
00173        This overload provides cleanup handling for pointer
00174        types. This simplifies many algorithms over using
00175        s11n_traits<SerializableType>::cleanup_functor directly, as
00176        the algorithms do not need to care if they're using
00177        pointer-qualified types or not in order to clean them up
00178        properly.
00179 
00180        SerializableType requirements are as for the non-pointered
00181        variant of this function, plus:
00182 
00183        - delete aSerializableTypeInstance; must be well-formed and
00184        must neither throw nor invoke undefined behaviour.  (Did
00185        you realize that "neither" is an exception to English's
00186        "i-before-e" rule?)
00187 
00188        This function does nothing if s is null, otherwise it calls
00189        cleanup_serializable(*s), deletes s, then assigns it to 0.
00190 
00191        Postcondition: (0 == s)
00192 
00193        Added in 1.1.3.
00194     */
00195     template <typename SerializableType>
00196     void cleanup_serializable( SerializableType * & s ) throw();
00197 
00198 
00199         /**
00200        Intended for use with for_each(), this type cleans up
00201        Serializables using cleanup_serializable().
00202 
00203        Usage:
00204 
00205        std::for_each( container.begin(), container.end(), cleaner_upper() );
00206 
00207        where the container is parameterized to hold Serializables.
00208 
00209        Provided that the contained type(s) conform to
00210        cleanup_ptr's requirements, this will recursively clean up
00211        sub-sub-...subcontainers.
00212 
00213        Note that Serializable containers should have a cleanup
00214        functor installed as part of their registration, making
00215        this class unnecessary for most cases: simply calling
00216        cleanup_serializable() will recursively walk/clean such
00217        containers. The underlying cleanup algos might use this
00218        type, however (at least one of them does).
00219 
00220        Added in 1.1.3.
00221 
00222        This type is usable as a Finalizer for
00223        s11n::refcount::rcptr, by the way.
00224      */
00225         struct cleaner_upper
00226         {
00227                 /**
00228                    Calls cleanup_serializable<T>(t)
00229                 */
00230                 template <typename T>
00231                 void operator()( T & t ) throw()
00232                 {
00233                         cleanup_serializable<T>( t );
00234                 }
00235                 /**
00236                    Calls cleanup_serializable<T>(t).
00237                 */
00238                 template <typename T>
00239                 void operator()( T * & t ) throw()
00240                 {
00241                         cleanup_serializable<T>( t );
00242                 }
00243         };
00244 
00245 
00246     /**
00247        An auto_ptr-like type intended to simplify
00248        pointer/exception safety in some deserialization algorithms
00249        by providing a way to completely and safely destroy
00250        partially-deserialized objects.
00251 
00252        SerializableT must either have an explicit s11n_traits
00253        specialization installed or work properly with the default
00254        functor provided by s11n_traits::cleanup_functor.  In
00255        practice, this means that types which manage the memory of
00256        their contained pointers are safe to work with the default,
00257        whereas the cleanup of unmanaged child pointers (e.g., std
00258        containers) requires a proper specialization.
00259 
00260        Note that this type does not have copy/assignment ctors,
00261        due to the conventional constness of their right-hand
00262        sides: use the swap() or take() members to take over a
00263        pointer.
00264 
00265        Added in 1.1.3.
00266     */
00267     template <typename SerializableT>
00268     struct cleanup_ptr
00269     {
00270     public:
00271         typedef SerializableT cleaned_type;
00272     private:
00273         cleaned_type * m_ptr;
00274         cleanup_ptr & operator=( const cleanup_ptr & ); // Not Implemented
00275         cleanup_ptr( const cleanup_ptr & ); // Not Implemented
00276         void cleanup() throw()
00277         {
00278             if( this->m_ptr )
00279             {
00280                 cleanup_serializable<cleaned_type>( this->m_ptr );
00281             }
00282         }
00283     public:
00284         /**
00285            Constructs an object pointing to nothing.
00286         */
00287         cleanup_ptr() throw() : m_ptr(0) 
00288         {
00289         }
00290         /**
00291            Transfers ownership of p to this object.
00292          */
00293         cleanup_ptr( cleaned_type * p ) throw() : m_ptr(p)
00294         {
00295         }
00296 
00297         /**
00298            Uses s11n::cleanup_serializable<cleaned_type>()
00299            to free up up this->get().
00300         */
00301         ~cleanup_ptr() throw()
00302         {
00303             this->cleanup();
00304         }
00305         /**
00306            Dereferences this object's pointed-to object.  If
00307            this object does not point to anything it throws a
00308            std::runtime_error with an informative what()
00309            message explaining the error.
00310          */
00311         cleaned_type & operator*()
00312         {
00313             if( ! this->m_ptr )
00314             {
00315                 throw s11n_exception( S11N_SOURCEINFO,
00316                               "Attempt to dereference a null pointer via s11n::cleanup_ptr<>::operator*()" );
00317             }
00318             return *this->m_ptr;
00319         }
00320 
00321         /**
00322            Returns the same as get().
00323         */
00324         cleaned_type * operator->() throw()
00325         {
00326             return this->m_ptr;
00327         }
00328 
00329         /**
00330            Returns this object's pointed-to object without
00331            transfering ownership.
00332         */
00333         cleaned_type * get() throw()
00334         {
00335             return this->m_ptr;
00336         }
00337 
00338         /**
00339            Transfers ownership of p to this object. This
00340            member takes the place of copy/assign operators,
00341            since those conventionally take a const right-hand
00342            argument.
00343 
00344            Destroys the object this object pointed to before
00345            taking over ownership. 0 is a legal value for p.
00346 
00347            If (p == this->get()) then this function does
00348            nothing.
00349 
00350            Postcondition: p == this->get() 
00351         */
00352         void take( cleaned_type * p ) throw()
00353         {
00354             if( p != this->m_ptr )
00355             {
00356                 this->cleanup();
00357                 this->m_ptr = p;
00358             }
00359         }
00360 
00361         /**
00362            Transfers ownership of this->get() to the
00363            caller.
00364 
00365            Postcondition: 0 == this->get() 
00366         */
00367         cleaned_type * release() throw()
00368         {
00369             cleaned_type * x = this->m_ptr;
00370             this->m_ptr = 0;
00371             return x;
00372         }
00373 
00374         /**
00375            Cleans up any pointed-to object and points this
00376            object at 0. Does nothing if this object points
00377            to no object.
00378 
00379            Postcondition: 0 == this->get() 
00380         */
00381         void clean() throw()
00382         {
00383             this->take( 0 );
00384         }
00385 
00386         /**
00387            Swaps ownership of pointers with rhs.
00388         */
00389         void swap( cleanup_ptr & rhs ) throw()
00390         {
00391             cleaned_type * x = this->m_ptr;
00392             this->m_ptr = rhs.m_ptr;
00393             rhs.m_ptr = x;
00394         }
00395 
00396         /**
00397            Returns the same as (!this->get()).
00398         */
00399         bool empty() const throw()
00400         {
00401             return 0 == this->m_ptr;
00402         }
00403     };
00404     
00405 
00406         /**
00407            Deserializes target from src using the default API marshaling
00408            mechanism. Returns true on success.
00409 
00410        On error it returns false or passes on an exception. In
00411        either case, target might be in an undefined state, and may
00412        need manual interaction to free up resources (e.g., a list
00413        of pointers might have some pointers which need to be
00414        cleaned up during exception handling). The exact definition
00415        of its state after a failure is specified by the algorithm
00416        which deserializes the target (as defined via
00417        s11n_traits<DeserializableT>::deserialize_functor).
00418         */
00419         template <typename DataNodeType, typename DeserializableT>
00420         bool deserialize( const DataNodeType & src, DeserializableT & target );
00421 
00422 
00423     /**
00424        Like the standard form of deserialize(), but if passed a
00425        null pointer, it attempts to classload the class and assign
00426        the passed-in pointer to it. If passed a non-null target
00427        then it behaves as if target were a reference, simply
00428        passing on the target after dereferencing it.
00429 
00430        For example:
00431 
00432 <pre>
00433 T * t = 0;
00434 deserialize<NodeType,T>( mynode, t );
00435 // t will be non-0 if it worked.
00436 
00437 T * x = new X;
00438 if( deserialize<NodeType,T>( mynode, x ) )
00439 {
00440   // x is now populated exactly as if we had called:
00441   // deserialize<NodeType,T>( mynode, *x );
00442 }
00443 </pre>
00444 
00445            To get the class name, the algorithm first tries
00446            node_traits<DataNodeType>::class_name(src). If it cannot
00447            load a class using that name, it tries
00448            s11n_traits<DeserializableT>::class_name(target).
00449 
00450            Underlying calls to s11n::cl::classload() and serialization
00451            proxies may throw. If they do, the exception is passed on
00452        to the caller.
00453 
00454        If passed a null pointer and this function fails, target is
00455        not modified. If deserialization fails, any
00456        internally-created (DeserializableT*) is deallocated using
00457        cleanup_serializable(). If passed a non-null pointer and
00458        the function fails, behaviour is as for the non-pointer
00459        variant of deserialize() - target may or may not be in a
00460        defined state, as defined by the specific proxy algorithm.
00461 
00462 
00463        Added in s11n version 1.1.3.
00464 
00465     */
00466         template <typename DataNodeType, typename DeserializableT>
00467     bool deserialize( const DataNodeType & src, DeserializableT * & target );
00468 
00469     /**
00470        Identical to deserialize(const
00471        DataNodeType&,DeserializableT*&) except that it works on a
00472        cleanup_ptr<>. The target may be empty (pointing to zero):
00473        if it is then dynamic loading is attempted, as described
00474        in the docs for the non-cleanup_ptr variant of this
00475        function.
00476 
00477        Returns true if deserialization to the target succeeds,
00478        else false.  If it returns false, target.get() still points
00479        to the same object it did when function was called (which
00480        may be 0). Whether or not the contained object is modified
00481        on deserialization failure depends on the underlying
00482        algorithm used to deserialize it.
00483     */
00484         template <typename DataNodeType, typename DeserializableT>
00485     bool deserialize( const DataNodeType & src, cleanup_ptr<DeserializableT> & target );
00486 
00487         /**
00488            Tries to deserialize a DeserializableT from src, using
00489            <code>s11n_traits<DeserializableT>::factory_type()(node_traits<DataNodeType>::class_name(src))</code>
00490            to create a new DeserializableT. 
00491 
00492        DeserializableT may not be a pointer-qualified type.
00493 
00494        On error it returns 0 or propagates on an exception,
00495        otherwise returns a pointer to a new object, which the
00496        caller takes ownership of.
00497 
00498        As of 1.1.3, this function relies on
00499        s11n::cleanup_serializable() in order to be able to specify
00500        what happens to the internally allocated object if
00501        deserialization fails. That function is called on the
00502        object before this function returns if deserialization
00503        fails.
00504 
00505        Prior to 1.1.3 this function would leak if this function
00506        failed and if DeserializableT contained unmanaged pointers
00507        (even indirectly, via sub-containment), such as in
00508        list<int*> or list<map<int,string*>>.
00509         */
00510         template <typename DataNodeType, typename DeserializableT>
00511         DeserializableT * deserialize( const DataNodeType & src );
00512 
00513 
00514         /**
00515            Clones an arbitrary SerializableType using its
00516            DataNodeType serialization implementation.
00517 
00518            Returns a clone of tocp, or returns 0 on error.
00519            The caller owns the returned pointer.
00520 
00521            This copy is polymorphism-safe as long as all participating
00522            Serializables (re)implement the appropriate de/serialize
00523            operations, similarly to as they would do for a copy ctor
00524            or classical Clone() member function.
00525 
00526            Tip: s11n_clone() is a convenient way to test new
00527            de/serialize functions, e.g., for new Serializables,
00528            because if it works then deserializing from streams/files
00529            will also work. This function takes SerializableType
00530            through the whole de/serialize process except for i/o,
00531            including classloading.
00532 
00533        This function was renamed from clone() in version 1.1.
00534 
00535        Exceptions and errors:
00536 
00537        This function may return 0 or throw on an error, as
00538        dictated by serialize() and then deserialize() (in that
00539        order). Thus safety guarantees are defined in terms
00540        of those operations.
00541         */
00542         template <typename DataNodeType, typename SerializableType>
00543         SerializableType * s11n_clone( const SerializableType & tocp );
00544 
00545         /**
00546            "Casts" t1 to t2 using serialization. This will work
00547            whenever t1 and t2 are "semantically compatible", whatever
00548            that really means. It can be used, e.g., to copy a
00549            list<int> to a vector<double>, provided both
00550            types have been proxied. In practice, this means: if Type1
00551            and Type2 both use the same, or compatible, de/ser
00552            algorithms, they are s11n_cast-able to one another.
00553 
00554            Note that in the case of containers, the pointerness of the
00555            contained types is irrelevant: this works on both, thus
00556            a list<int> can be "cast" to a vector<double*>.
00557 
00558            As usual for a failed deserialization, if it returns false
00559            then t2 may be in an undefined state. There is no guaranty,
00560            however, that t2's deserialize operator will ever be
00561            called, as the serialization of t1 must first succeed
00562            for that to happen.
00563 
00564        Type2 may not currently be a pointer type, but Type1 may
00565        be. This will be fixed someday (when someone complains).
00566 
00567        Exceptions and errors:
00568 
00569        On error this function will return false or propagate
00570        an exception, as dictated by serialize() and then
00571        deserialize() (in that order).
00572 
00573        If Type1 and Type2 are not guaranteed to be monomorphic or
00574        base-most Serializable types, then it is good practice to
00575        explicitely specify them as templatized parameters, and not
00576        rely on implicit type selection, which might choose the
00577        wrong type (not the base-most one, which is what s11n is
00578        "keyed" to), which will mean that s11n "can't find" the
00579        registration code for the type. What that means is, if t1
00580        or t2 may be polymorphic types, then it is best to
00581        explicitly specify their base-most s11n-registered common
00582        ancestor as the template parameters for Type1 and/or Type2.
00583        e.g.:
00584 
00585        \code
00586        BaseT * lhs = new SubT;
00587        ... populate lhs ...
00588        BaseT * rhs = new SubT;
00589        s11n_cast<s11n_node,BaseT,BaseT>( *lhs, *rhs );
00590        \endcode
00591 
00592         */
00593         template <typename NodeType, typename Type1, typename Type2>
00594         bool s11n_cast( const Type1 & t1, Type2 & t2 );
00595 
00596 
00597 } // namespace s11n
00598 
00599 #include <s11n.net/s11n/serialize.tpp> // implementations for above-declared code
00600 
00601 
00602 #endif // s11n_SERIALIZE_HPP_INCLUDED

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