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

Generated on Sun Dec 18 18:30:27 2005 for libs11n-1.2.2 by  doxygen 1.4.4