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

traits.hpp

Go to the documentation of this file.
00001 #ifndef s11n_S11N_TRAITS_HPP_INCLUDED
00002 #define s11n_S11N_TRAITS_HPP_INCLUDED 1
00003 
00004 
00005 #include <vector>
00006 #include <map>
00007 
00008 #include <s11n.net/s11n/classload.hpp> // default classloader/factory implementation.
00009 #include <s11n.net/s11n/export.hpp> // S11N_EXPORT_API
00010 #include <s11n.net/s11n/type_traits.hpp>
00011 
00012 namespace s11n {
00013 
00014         /**
00015            node_traits encapsulates information relevant to Data
00016            Nodes, much in the same way that std::char_traits
00017            encapsulates character type information.
00018 
00019            The default implementation works with
00020            s11n::s11n_node or API-compatible
00021            types. Specializations may be defined to work with
00022            other node types.
00023 
00024            By using node_traits, instead of directly accessing a
00025            Node's API, client code may remain blissfully ignorant of
00026            the underlying node type.
00027 
00028        All API docs for this class which do not explicitely say
00029        "this implementation" (or similar) apply to all
00030        specializations of this type. They act as the "requirements
00031        document" for implementors of specializations.
00032 
00033        Changes from 1.0.x to 1.1.x:
00034 
00035        - Removed begin() and end(), because they are just as
00036        easily accessed via children().begin/end(), and it was not
00037        easy to remember if they returned iterators to the children
00038        or the properties.
00039 
00040        - Removed iterator typedefs, as they are (almost) as easily
00041        accessed via the appropriate container's typedefs. Again, this
00042        was to avoid confusion between the properties and children
00043        iterator types.
00044         */
00045         template <typename NodeT>
00046         struct S11N_EXPORT_API node_traits
00047         {
00048     public:
00049                 /**
00050                    The same as NodeT.
00051                 */
00052                 typedef NodeT node_type;
00053 
00054                 /**
00055                    The type uses to store properties for node_type
00056                    objects.
00057                 */
00058                 typedef typename node_type::map_type property_map_type;
00059 
00060 
00061                 /**
00062                    The type used to store children of node_type
00063                    objects.
00064                 */
00065                 typedef typename node_type::child_list_type child_list_type;
00066 
00067 
00068 
00069 
00070                 /**
00071                    Returns a new node_type. The caller owns the
00072                    returned pointer.
00073 
00074            It is illegal for this function to return 0. If it
00075            cannot create a node for some reason, it must throw
00076            an exception.
00077                 */
00078                 static node_type * create()
00079                 {
00080                         return new node_type;
00081                 }
00082 
00083                 /**
00084                    Returns a new node_type with the given name. The
00085                    caller owns the returned pointer.
00086 
00087            See create() for the no-null-return rule.
00088                 */
00089                 static node_type * create( const std::string & nodename )
00090                 {
00091                         node_type * n = create();
00092                         name( *n, nodename );
00093                         return n;
00094                 }
00095 
00096 
00097                 /**
00098                    Sets the property key to the given value in
00099                    the given node.
00100 
00101                    ValueT must support complementary ostream<< and
00102                    istream>> operators.
00103                 */
00104                 template <typename ValueT>
00105                 static void set( node_type & node,
00106                                  const std::string & key,
00107                                  const ValueT & value )
00108                 {
00109                         node.set( key, value );
00110                 }
00111 
00112                 /**
00113                    Unsets (removes) the given property from node. It
00114                    is not an error to unset an non-existing key.
00115                 */
00116                 static void unset( node_type & node,
00117                                    const std::string & key )
00118                 {
00119                         node.unset( key );
00120                 }
00121 
00122                 /**
00123                    Returns true if node contains a property
00124                    named key, else returns false.
00125                 */
00126                 static bool is_set( const node_type & node,
00127                                     const std::string & key )
00128                 {
00129                         return node.is_set( key );
00130                 }
00131 
00132 
00133                 /**
00134                    Returns an immutable reference to the node's map of properties.
00135                 */
00136                 static const property_map_type & properties( const node_type & node )
00137                 {
00138                         return node.properties();
00139                 }
00140 
00141                 /**
00142                    Returns a mutable reference to the node's map of properties.
00143                 */
00144                 static property_map_type & properties( node_type & node )
00145                 {
00146                         return node.properties();
00147                 }
00148 
00149                 /**
00150                    Returns the value of the property with the given
00151                    key, or default_value if that property does not
00152                    exist or cannot be lexically cast to type ValueT.
00153 
00154                    ValueT must support complementary ostream<< and
00155                    istream>> operators.
00156                 */
00157                 template <typename ValueT>
00158                 static ValueT
00159                 get( const node_type & node,
00160                      const std::string & key,
00161                      const ValueT & default_value )
00162                 {
00163                         return node.template get<ValueT>( key, default_value );
00164                 }
00165 
00166                 /**
00167                    Returns a mutable list of children
00168                    belonging to node.
00169                 */
00170                 static child_list_type & children( node_type & node )
00171                 {
00172                         return node.children();
00173                 }
00174 
00175                 /**
00176                    Returns an immutable list of children
00177                    belonging to node.
00178                 */
00179                 static const child_list_type & children( const node_type & node )
00180                 {
00181                         return node.children();
00182                 }
00183 
00184                 /**
00185                    Sets the class name of the type for which node
00186                    holds serialized data.
00187                 */
00188                 static void class_name( node_type & node, const std::string & classname )
00189                 {
00190                         node.class_name( classname );
00191                 }
00192 
00193 
00194                 /**
00195                    Returns the class name of the type for which node
00196                    holds serialized data.
00197                 */
00198                 static std::string class_name( const node_type & node )
00199                 {
00200                         return node.class_name();
00201                 }
00202 
00203                 /**
00204                    Sets node's name. See the s11n lib manual for what
00205                    conventions to follow. In short: the "variable name"
00206                    rules from most programming languages are a good
00207                    guideline.
00208                 */
00209                 static void name( node_type & node, const std::string & name )
00210                 {
00211                         node.name( name );
00212                 }
00213 
00214 
00215                 /**
00216                    Returns node's name.
00217                 */
00218                 static std::string name( const node_type & node )
00219                 {
00220                         return node.name();
00221                 }
00222 
00223                 /**
00224                    Removes all children and properties from node,
00225                    freeing up their resources. Whether the node's
00226                    name() and class_name() are cleared is
00227                    implementation-defined. In practice, those are
00228                    overwritten by algos as needed, so it has not been
00229                    a concern.
00230                 */
00231                 static void clear( node_type & node )
00232                 {
00233                         node.clear();
00234                 }
00235 
00236         /**
00237            Returns true if this object has no properties
00238            and no children. The name() and class_name()
00239            are *not* considered.
00240 
00241            Added in version 1.1.3.
00242         */
00243         static bool empty( const node_type & node )
00244         {
00245             return node.empty();
00246         }
00247 
00248         /**
00249            Swaps all publically-visible internal state of lhs
00250            with that of rhs. This includes:
00251 
00252            - class_name()
00253 
00254            - name()
00255 
00256            - children()
00257 
00258            - properties()
00259 
00260            Added in version 1.1.3.
00261         */
00262         static void swap( node_type & lhs, node_type & rhs )
00263         {
00264             return lhs.swap( rhs );
00265         }
00266 
00267         }; // end node_traits<>
00268 
00269 
00270 //  /**
00271 //     An unfortunate necessity.
00272 //  */
00273 //         template <typename NodeT>
00274 //         struct S11N_EXPORT_API node_traits<NodeT const> : node_traits<NodeT> {};
00275 
00276 
00277         /**
00278            A default serialization proxy, which simply
00279            forwards de/serialize calls to an interface
00280            implemented as two overloaded member functions
00281            SerializableType::operator()( NodeT ).
00282         */
00283         struct S11N_EXPORT_API default_serialize_functor
00284         {
00285                 /**
00286                    Serialize src to dest using src.operator()( dest ).
00287 
00288                    The serialize operator must look like:
00289 
00290                    bool operator()( NodeT & ) const;
00291 
00292                    It may be virtual or a function template.
00293                 */
00294                 template <typename NodeT, typename SerializableType>
00295                 bool operator()( NodeT & dest, const SerializableType & src ) const
00296                 {
00297                         return src.operator()( dest );
00298                 }
00299 
00300                 /**
00301                    Deserialize dest from src using dest.operator()( src ).
00302 
00303                    The deserialize operator must look like:
00304 
00305                    bool operator()( const NodeT & );
00306 
00307                    It may be virtual or a function template.
00308                 */
00309                 template <typename NodeT, typename DeserializableType>
00310                 bool operator()( const NodeT & src, DeserializableType & dest ) const
00311                 {
00312                         return dest.operator()( src );
00313                 }
00314         };
00315 
00316 
00317     /**
00318        A default implementation for
00319        s11n_traits::cleanup_functor. Compatible implementations
00320        and specializations must follow the conventions defined for
00321        this class.
00322 
00323        This implementation is only suitable for cleaning up types
00324        which manage any child pointers which are assigned to them
00325        during deserialization. For example, std:: containers do
00326        not own their pointers, and therefor require a
00327        specialization of this type to clean them up.
00328 
00329        SerializableType must be a Serializable and may be
00330        pointer-qualified.
00331 
00332        The library manual goes into more detail about what this
00333        type is for.
00334 
00335        The operations of this class are declared as throw() because
00336        of their logical role in the destruction process, and destructors
00337        are not generally allowed to throw.
00338     */
00339     template <typename SerializableType>
00340     struct default_cleanup_functor
00341     {
00342         typedef typename type_traits<SerializableType>::type serializable_type;
00343 
00344         /**
00345            Default implementation does nothing, though we
00346            should arguably assign to a default-constructed
00347            object.
00348 
00349            Specializations must do any cleanup they need to
00350            here. For example, container specializations must
00351            a) deallocate any heap-based entries and b) empty
00352            the list. Specializations are free to do a
00353            default-assign, as mentioned above, but are not
00354            required to. Specializations for containers must
00355            recursively use s11n_trait::cleanup_functor for
00356            the contained types, to ensure that they can properly
00357            clean up containers holding other containers.
00358         */
00359         void operator()( serializable_type & ) const throw()
00360         {
00361         }
00362 
00363     };
00364 
00365         /**
00366            s11n_traits encapsulates information about what
00367            type(s) are responsible for handling de/serialize
00368            operations for a given type, plus the factory for
00369            that type. It should be specialized to define
00370            various aspects of serialization for a given type.
00371 
00372            The interface shown here is the bare minimum which
00373            s11n_traits specializations must implement.
00374            Specializations may optionally add to the
00375            interface, but client code is discouraged from
00376            relying on any extensions.
00377 
00378        This type is stateless, and specializations are
00379        expected to be stateless (at least, they will
00380        be treated as if they are).
00381 
00382            Client code is not expected to need to use this
00383            type directly, except for purposes of plugging in
00384            their types into the s11n framework. More
00385            specifically, it is not expected that Serializables
00386            will use this type.
00387 
00388            Parameterized on:
00389 
00390            SerializableT: the base-most Serializable
00391            type. This is the base-most point of reference for
00392            classloading and "template typing". Subclasses of
00393            SerializableT are assumed to be handleable via the
00394            same de/serialize interface as SerializableT.
00395 
00396        Changes from 1.0.x to 1.1.x:
00397 
00398        - Added class_name() member to replace the ::classname()
00399        family of code in 1.1.0.
00400 
00401        - cleanup_functor added in 1.1.3.
00402 
00403         */
00404         template <typename SerializableT>
00405         struct S11N_EXPORT_API s11n_traits
00406         {
00407         /**
00408            The s11n framework instantiates an s11n_traits
00409            object at some points to allow the traits object
00410            to do things like factory registration.
00411         */
00412         s11n_traits(){}
00413         ~s11n_traits(){}
00414 
00415                 /**
00416                    The type of object we want to [de]serialize.
00417                 */
00418                 typedef SerializableT serializable_type;
00419 
00420                 /**
00421                    Type which will be used to instantiate new objects
00422                    of serializable_type. It must implement:
00423 
00424                    serializable_type * operator()( const std::string & classname ) const;
00425 
00426                    It is expected to return, polymorphically if
00427                    possible, a new serializable_type on success or 0
00428                    on failure.
00429 
00430                    The default factory_type works with types
00431                    registered via the s11n::cl::classload()
00432                    family of functions.
00433                 */
00434                 typedef ::s11n::cl::object_factory<serializable_type> factory_type;
00435 
00436                 /**
00437                    Functor type implementing serialize code.
00438 
00439                    Must implement:
00440 
00441                    bool operator()( SomeNodeType & dest, const base_type & src ) const;
00442 
00443                 */
00444                 typedef ::s11n::default_serialize_functor serialize_functor;
00445 
00446                 /**
00447                    Functor type implementing deserialize code.
00448 
00449                    Must implement:
00450 
00451                    bool operator()( const SomeNodeType & src, base_type & dest ) const;
00452                 */
00453                 typedef ::s11n::default_serialize_functor deserialize_functor;
00454 
00455         /**
00456            This type is used to clean up a partial deserialized object
00457            on error. If this functor, and all specializations it calls,
00458            do their part, we can make much better exception guarantees,
00459            theoretically avoiding any leaks due to exceptions thrown
00460            during deserialization.
00461 
00462            cleanup_functor must follow the conventions laid out by
00463            s11n::default_cleanup_functor<serializable_type>.
00464         */
00465         typedef ::s11n::default_cleanup_functor<serializable_type> cleanup_functor;
00466 
00467         /**
00468            As of s11n 1.1, specializations must define the
00469            class_name() function. This implementation returns
00470            a useless, unspecified class name. Specializations
00471            must return the class name of serializable_type,
00472            preferably polymorphically (polymorphic naming is
00473            unfortunately not possible without some client-side
00474            help).
00475 
00476            instance_hint is a HINT to this class as to the
00477            actual instance we want the name for, and may be
00478            0. It is provided so that class hierarchies which
00479            have virtual functions like className() can make
00480            those available to the core library via s11n_traits
00481            specializations.
00482 
00483            Specializations MUST accept 0 as a valid
00484            instance_hint value are are NEVER REQUIRED to pay
00485            any attention to instance_hint. The default
00486            implementation does nothing with it.
00487 
00488            Design notes:
00489 
00490            - It really should take a default value of 0 for
00491            instance_hint, but the idea of relying on a default
00492            value, considering things like how template
00493            specializations should define them and subclassing
00494            (though that is not an issue *here*), gives me the
00495            willies. Too much room for error there.
00496 
00497            - Also, we could probably argue that it should
00498            return a const string.
00499 
00500            - We could argue that it should return an empty string
00501            instead of a useless one. i don't want to to generate
00502            output which might break parsers, though.
00503            
00504         */
00505         static const std::string class_name( const serializable_type * instance_hint )
00506         {
00507             return "unknown";
00508         }
00509 
00510         }; // end s11n_traits<>
00511 
00512 
00513     /**
00514        A general specialization to treat (T*) as (T) for s11n_traits
00515        purposes. This is necessary for some template argument resolution
00516        to work as desired.
00517 
00518        Added in 1.1.3.
00519     */
00520     template <typename T>
00521     struct S11N_EXPORT_API s11n_traits<T *> : public s11n_traits<T> {};
00522 
00523 
00524 }  // namespace s11n
00525 
00526 
00527 #endif // s11n_S11N_TRAITS_HPP_INCLUDED

Generated on Sat Dec 10 13:33:58 2005 for libs11n-1.2.1 by  doxygen 1.4.4