Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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 
00014 
00015 ////////////////////////////////////////////////////////////////////////////////
00016 // NO DEPS ON s11n_node.hpp ALLOWED!
00017 ////////////////////////////////////////////////////////////////////////////////
00018 
00019 #include <s11n.net/s11n/tags.hpp>
00020 
00021 namespace s11n {
00022 
00023 
00024     namespace Detail {
00025         /***
00026             s11n_api_marshaler is the internal API marshaller
00027             for s11n.  See the lib manual for full
00028             details. Client code is not expected to use or
00029             specialize this class, but theoretically some
00030             cases may call for doing so. In s11n versions
00031             prior to 1.0.x, specializing this type was
00032             sometimes useful for handling client-side
00033             template types, but this is no longer necessary
00034             nor encouraged.
00035 
00036             In the default implementation, s11n_traits<NodeT,SerializableT>
00037             is used to marshal the de/serialize() calls.
00038 
00039             Changed in 1.1.3:
00040 
00041             - NodeType template param was moved from the static
00042             functions to the class.
00043 
00044             - Moved class from anonymous namespace into s11n::Detail.
00045         */
00046         template <typename NodeType,typename SerializableT>
00047         struct s11n_api_marshaler
00048         {
00049             /**
00050                Same as SerializableT.
00051             */
00052             typedef SerializableT serializable_type;
00053 
00054             typedef NodeType node_type;
00055 
00056             /**
00057                Returns s11n_traits<serializable_type>::serialize_functor()( dest, src ).
00058 
00059                This implementation sets dest's class name to
00060                s11n_traits<SerializableT>::class_name(&src), which
00061                is only guaranteed to work properly for monomorphic
00062                types and base-most types of Serialization
00063                hierarchies (i.e., the registered
00064                bases). Polymorphic Serializable subtypes should
00065                set this class name themselves, or via their
00066                s11n_traits::class_name() specialization, both
00067                described in the library manual.
00068 
00069             */
00070             static bool serialize( node_type &dest, const serializable_type & src );
00071 
00072             /**
00073                Returns s11n_traits<SerializableT>::deserialize_functor()(src,dest).
00074             */
00075             static bool deserialize( const node_type & src, serializable_type & dest );
00076         };
00077 
00078         /**
00079            A specialization to handle pointer types the same as
00080            reference/value types. It simply translates the pointers
00081            into references.
00082         */
00083         template <typename NodeType,typename SerializableT>
00084         struct s11n_api_marshaler<NodeType,SerializableT *>
00085         {
00086             /**
00087                The SerializableT templatized type, minus any
00088                pointer part.
00089             */
00090             typedef SerializableT serializable_type;
00091 
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         struct cleaner_upper
00223         {
00224                 /**
00225                    Calls cleanup_serializable<T>(t)
00226                 */
00227                 template <typename T>
00228                 void operator()( T & t ) throw()
00229                 {
00230                         cleanup_serializable<T>( t );
00231                 }
00232                 /**
00233                    Calls cleanup_serializable<T>(t).
00234                 */
00235                 template <typename T>
00236                 void operator()( T * & t ) throw()
00237                 {
00238                         cleanup_serializable<T>( t );
00239                 }
00240         };
00241 
00242 
00243     /**
00244        An auto_ptr-like type intended to simplify
00245        pointer/exception safety in some deserialization algorithms
00246        by providing a way to completely and safely destroy
00247        partially-deserialized objects.
00248 
00249        SerializableT must either have an explicit s11n_traits
00250        specialization installed or work properly with the default
00251        functor provided by s11n_traits::cleanup_functor.  In
00252        practice, this means that types which manage the memory of
00253        their contained pointers are safe to work with the default,
00254        whereas the cleanup of unmanaged child pointers (e.g., std
00255        containers) requires a proper specialization.
00256 
00257        Note that this type does not have copy/assignment ctors,
00258        due to the conventional constness of their right-hand
00259        sides: use the swap() or take() members to take over a
00260        pointer.
00261 
00262        Added in 1.1.3.
00263     */
00264     template <typename SerializableT>
00265     struct cleanup_ptr
00266     {
00267     public:
00268         typedef SerializableT cleaned_type;
00269     private:
00270         cleaned_type * m_ptr;
00271         cleanup_ptr & operator=( const cleanup_ptr & ); // Not Implemented
00272         cleanup_ptr( const cleanup_ptr & ); // Not Implemented
00273         void cleanup() throw()
00274         {
00275             if( this->m_ptr )
00276             {
00277                 cleanup_serializable<cleaned_type>( this->m_ptr );
00278             }
00279         }
00280     public:
00281         /**
00282            Constructs an object pointing to nothing.
00283         */
00284         cleanup_ptr() throw() : m_ptr(0) 
00285         {
00286         }
00287         /**
00288            Transfers ownership of p to this object.
00289          */
00290         cleanup_ptr( cleaned_type * p ) throw() : m_ptr(p)
00291         {
00292         }
00293 
00294         /**
00295            Uses s11n::cleanup_serializable<cleaned_type>()
00296            to free up up this->get().
00297         */
00298         ~cleanup_ptr() throw()
00299         {
00300             this->cleanup();
00301         }
00302         /**
00303            Dereferences this object's pointed-to object.  If
00304            this object does not point to anything it throws a
00305            std::runtime_error with an informative what()
00306            message explaining the error.
00307          */
00308         cleaned_type & operator*()
00309         {
00310             if( ! this->m_ptr )
00311             {
00312                 throw std::runtime_error("Attempt to dereference a null pointer via s11n::cleanup_ptr<>::operator*()" );
00313             }
00314             return *this->m_ptr;
00315         }
00316 
00317         /**
00318            Returns the same as get().
00319         */
00320         cleaned_type * operator->() throw()
00321         {
00322             return this->m_ptr;
00323         }
00324 
00325         /**
00326            Returns this object's pointed-to object without
00327            transfering ownership.
00328         */
00329         cleaned_type * get() throw()
00330         {
00331             return this->m_ptr;
00332         }
00333 
00334         /**
00335            Transfers ownership of p to this object. This
00336            member takes the place of copy/assign operators,
00337            since those conventionally take a const right-hand
00338            argument.
00339 
00340            Destroys the object this object pointed to before
00341            taking over ownership. 0 is a legal value for p.
00342 
00343            If (p == this->get()) then this function does
00344            nothing.
00345 
00346            Postcondition: p == this->get() 
00347         */
00348         void take( cleaned_type * p ) throw()
00349         {
00350             if( p != this->m_ptr )
00351             {
00352                 this->cleanup();
00353                 this->m_ptr = p;
00354             }
00355         }
00356 
00357         /**
00358            Transfers ownership of this->get() to the
00359            caller.
00360 
00361            Postcondition: 0 == this->get() 
00362         */
00363         cleaned_type * release() throw()
00364         {
00365             cleaned_type * x = this->m_ptr;
00366             this->m_ptr = 0;
00367             return x;
00368         }
00369 
00370         /**
00371            Cleans up any pointed-to object and points this
00372            object at 0. Does nothing if this object points
00373            to no object.
00374 
00375            Postcondition: 0 == this->get() 
00376         */
00377         void clean() throw()
00378         {
00379             this->take( 0 );
00380         }
00381 
00382         /**
00383            Swaps ownership of pointers with rhs.
00384         */
00385         void swap( cleanup_ptr & rhs ) throw()
00386         {
00387             cleaned_type * x = this->m_ptr;
00388             this->m_ptr = rhs.m_ptr;
00389             rhs.m_ptr = x;
00390         }
00391     };
00392     
00393 
00394         /**
00395            Deserializes target from src using the default API marshaling
00396            mechanism. Returns true on success.
00397 
00398        On error it returns false or passes on an exception. In
00399        either case, target might be in an undefined state, and may
00400        need manual interaction to free up resources (e.g., a list
00401        of pointers might have some pointers which need to be
00402        cleaned up during exception handling). The exact definition
00403        of its state after a failure is specified by the algorithm
00404        which deserializes the target (as defined via
00405        s11n_traits<DeserializableT>::deserialize_functor).
00406         */
00407         template <typename DataNodeType, typename DeserializableT>
00408         bool deserialize( const DataNodeType & src, DeserializableT & target );
00409 
00410 
00411     /**
00412        Like the standard form of deserialize(), but if passed a
00413        null pointer, it attempts to classload the class and assign
00414        the passed-in pointer to it. If passed a non-null target
00415        then it behaves as if target were a reference, simply
00416        passing on the target after dereferencing it.
00417 
00418        For example:
00419 
00420 <pre>
00421 T * t = 0;
00422 deserialize<NodeType,T>( mynode, t );
00423 // t will be non-0 if it worked.
00424 
00425 T * x = new X;
00426 if( deserialize<NodeType,T>( mynode, x ) )
00427 {
00428   // x is now populated exactly as if we had called:
00429   // deserialize<NodeType,T>( mynode, *x );
00430 }
00431 </pre>
00432 
00433            To get the class name, the algorithm first tries
00434            node_traits<DataNodeType>::class_name(src). If it cannot
00435            load a class using that name, it tries
00436            s11n_traits<DeserializableT>::class_name(target).
00437 
00438            Underlying calls to s11n::cl::classload() and serialization
00439            proxies may throw. If they do, the exception is passed on
00440        to the caller.
00441 
00442        If passed a null pointer and this function fails, target is
00443        not modified. If deserialization fails, any
00444        internally-created (DeserializableT*) is deallocated using
00445        cleanup_serializable(). If passed a non-null pointer and
00446        the function fails, behaviour is as for the non-pointer
00447        variant of deserialize() - target may or may not be in a
00448        defined state, as defined by the specific proxy algorithm.
00449 
00450 
00451        Added in s11n version 1.1.3.
00452 
00453     */
00454         template <typename DataNodeType, typename DeserializableT>
00455     bool deserialize( const DataNodeType & src, DeserializableT * & target );
00456 
00457     /**
00458        Identical to deserialize(const
00459        DataNodeType&,DeserializableT*&) except that it works on a
00460        cleanup_ptr<>. The target may be empty (pointing to zero):
00461        if it is then dynamic loading is attempted, as described
00462        in the docs for the non-cleanup_ptr variant of this
00463        function.
00464 
00465        Returns true if target.get() is non-0 at the time this
00466        function exits (regardless of its value at entry time).
00467     */
00468         template <typename DataNodeType, typename DeserializableT>
00469     bool deserialize( const DataNodeType & src, cleanup_ptr<DeserializableT> & target );
00470 
00471         /**
00472            Tries to deserialize a DeserializableT from src, using
00473            <code>s11n_traits<DeserializableT>::factory_type()(node_traits<DataNodeType>::class_name(src))</code>
00474            to create a new DeserializableT. 
00475 
00476        DeserializableT may not be a pointer-qualified type.
00477 
00478        On error it returns 0 or propagates on an exception,
00479        otherwise returns a pointer to a new object, which the
00480        caller takes ownership of.
00481 
00482        As of 1.1.3, this function relies on
00483        s11n::cleanup_serializable() in order to be able to specify
00484        what happens to the internally allocated object if
00485        deserialization fails. That function is called on the
00486        object before this function returns if deserialization
00487        fails.
00488 
00489        Prior to 1.1.3 this function would leak if this function
00490        failed and if DeserializableT contained unmanaged pointers
00491        (even indirectly, via sub-containment), such as in
00492        list<int*> or list<map<int,string*>>.
00493         */
00494         template <typename DataNodeType, typename DeserializableT>
00495         DeserializableT * deserialize( const DataNodeType & src );
00496 
00497 
00498         /**
00499            Clones an arbitrary SerializableType using its
00500            DataNodeType serialization implementation.
00501 
00502            Returns a clone of tocp, or returns 0 on error.
00503            The caller owns the returned pointer.
00504 
00505            This copy is polymorphism-safe as long as all participating
00506            Serializables (re)implement the appropriate de/serialize
00507            operations, similarly to as they would do for a copy ctor
00508            or classical Clone() member function.
00509 
00510            Tip: s11n_clone() is a convenient way to test new
00511            de/serialize functions, e.g., for new Serializables,
00512            because if it works then deserializing from streams/files
00513            will also work. This function takes SerializableType
00514            through the whole de/serialize process except for i/o,
00515            including classloading.
00516 
00517        This function was renamed from clone() in version 1.1.
00518 
00519        Exceptions and errors:
00520 
00521        This function may return 0 or throw on an error, as
00522        dictated by serialize() and then deserialize() (in that
00523        order). Thus safety guarantees are defined in terms
00524        of those operations.
00525         */
00526         template <typename DataNodeType, typename SerializableType>
00527         SerializableType * s11n_clone( const SerializableType & tocp );
00528 
00529         /**
00530            "Casts" t1 to t2 using serialization. This will work
00531            whenever t1 and t2 are "semantically compatible", whatever
00532            that really means. It can be used, e.g., to copy a
00533            list<int> to a vector<double>, provided both
00534            types have been proxied. In practice, this means: if Type1
00535            and Type2 both use the same, or compatible, de/ser
00536            algorithms, they are s11n_cast-able to one another.
00537 
00538            Note that in the case of containers, the pointerness of the
00539            contained types is irrelevant: this works on both, thus
00540            a list<int> can be "cast" to a vector<double*>.
00541 
00542            As usual for a failed deserialization, if it returns false
00543            then t2 may be in an undefined state. There is no guaranty,
00544            however, that t2's deserialize operator will ever be
00545            called, as the serialization of t1 must first succeed
00546            for that to happen.
00547 
00548        Type2 may not currently be a pointer type, but Type1 may
00549        be. This will be fixed someday (when someone complains).
00550 
00551        Exceptions and errors:
00552 
00553        On error this function will return false or propagate
00554        an exception, as dictated by serialize() and then
00555        deserialize() (in that order).
00556 
00557        If Type1 and Type2 are not guaranteed to be monomorphic or
00558        base-most Serializable types, then it is good practice to
00559        explicitely specify them as templatized parameters, and not
00560        rely on implicit type selection, which might choose the
00561        wrong type (not the base-most one, which is what s11n is
00562        "keyed" to), which will mean that s11n "can't find" the
00563        registration code for the type.
00564         */
00565         template <typename NodeType, typename Type1, typename Type2>
00566         bool s11n_cast( const Type1 & t1, Type2 & t2 );
00567 
00568 
00569 } // namespace s11n
00570 
00571 #include <s11n.net/s11n/serialize.tpp> // implementations for above-declared code
00572 
00573 
00574 #endif // s11n_SERIALIZE_HPP_INCLUDED

Generated on Thu Sep 29 20:01:14 2005 for libs11n-1.1.3-dev by  doxygen 1.4.1