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

Generated on Sat Mar 20 12:29:24 2010 for libs11n-1.2.10 by  doxygen 1.6.1