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

mapish.hpp

Go to the documentation of this file.
00001 #ifndef s11n_net_s11n_v1_1_MAP_HPP_INCLUDED
00002 #define s11n_net_s11n_v1_1_MAP_HPP_INCLUDED 1
00003 ////////////////////////////////////////////////////////////////////////
00004 // Declarations for s11n algos for dealing with std::map and std::pair
00005 // types, or compatible.
00006 ////////////////////////////////////////////////////////////////////////
00007 
00008 #include <map>
00009 #include <list>
00010 #include <utility> // pair
00011 
00012 #include <iterator> // insert_iterator
00013 #include <algorithm> // for_each()
00014 
00015 namespace s11n {
00016 
00017 
00018 
00019         /**
00020            The s11n::map namespace defines functors and algorithms for
00021            working with std::map, std::pair, and
00022            conventions-compatible containers.
00023         */
00024         namespace map {
00025 
00026 
00027                 
00028                 /**
00029 
00030                 serialize_streamable_map() is intended for use as a
00031                 serialization proxy for the s11n framework. It
00032                 de/serializes objects of type <tt>std::map&lt;X,Y&gt;</tt>
00033                 into a destination node.
00034 
00035                 NodeType must be node_traits<NodeType>-compliant.
00036 
00037                 MapType must conform to std::map conventions and
00038                 it's key_type and mapped_type must both be Value Types
00039                 which are i/ostreamable (this includes all PODs and
00040                 std::string). Pointers as keys or values are not
00041                 supported by this functor.
00042 
00043         Unlike serialize_map(), this function cannot work on
00044         std::multimaps because it uses NodeType's properties
00045         to hold key/value pairs. The NodeType conventions
00046         specify unique keys for properties, making them
00047         incompatible for generic use with multimap containers
00048         and this algorithm. serialize_map() stores each stored
00049         item as its own object, where duplicate names are
00050         allowed, so it is not affected by this limitation.
00051 
00052                 Always returns true.
00053 
00054                 ACHTUNG: return type changed in 0.9.12.
00055                 */
00056 
00057                 template <typename NodeType, typename MapType>
00058                 bool serialize_streamable_map( NodeType & dest, const MapType & src );
00059 
00060                 /**
00061                    Exactly like serialize_streamable_map(dest,src) except that a subnode,
00062                    named subnodename, of dest is created to store the data. 
00063 
00064                    ACHTUNG: return type changed in 0.9.12.
00065 
00066            As of version 1.1.3, this function guarantees that dest
00067            is not modified if the serialization fails.
00068                 */
00069                 template <typename NodeType, typename MapType>
00070                 bool serialize_streamable_map( NodeType & dest, const std::string & subnodename, const MapType & src );
00071 
00072         /**
00073            A functor which behaves like serialize_streamable_map().
00074         */
00075                 struct serialize_streamable_map_f : ::s11n::serialize_binary_f_tag, ::s11n::deserialize_binary_f_tag
00076         {
00077             template <typename NodeType, typename MapType>
00078             bool operator()( NodeType & dest, const MapType & src ) const
00079             {
00080                 return serialize_streamable_map<NodeType,MapType>( dest, src );
00081             }
00082             template <typename NodeType, typename MapType>
00083             bool operator()( NodeType & dest, const std::string & subnodename, const MapType & src ) const
00084             {
00085                 return serialize_streamable_map<NodeType,MapType>( dest, subnodename, src );
00086             }
00087         };
00088                 /**
00089                    This is the converse of serialize_streamable_map(). It tries to
00090                    read in all properties stored in src and stick them into
00091                    dest.
00092 
00093                    NodeType must support begin() and end() and they must
00094                    return iterators to pair&lt;X,Y&gt;, where X and Y must
00095                    meet the same requirements as the key and value types for
00096                    MapType in serialize_streamable_map(). MapType must support:
00097 
00098                    void insert( MapType::value_type );
00099 
00100                    (Duh.)
00101 
00102                    Always returns true, because the nature of
00103                    stream-based conversion makes it quite difficult to
00104                    generically know if there is an error. In practice,
00105                    such operations essentially always succeed, at
00106                    least for POD-like types.
00107 
00108                    ACHTUNG: return type changed in 0.9.12.
00109                    
00110                 */
00111                 template <typename NodeType, typename MapType>
00112                 bool deserialize_streamable_map( const NodeType & src, MapType & dest );
00113 
00114 
00115                 /**
00116                    Exactly like deserialize_streamable_map(dest,src) except
00117                    that a subnode of dest, named subnodename, is sought to
00118                    pull the data from.
00119                 */
00120                 template <typename NodeType, typename MapType>
00121                 bool deserialize_streamable_map( const NodeType & src, const std::string & subnodename, MapType & dest );
00122 
00123         /**
00124            A functor which behaves like deserialize_streamable_map().
00125         */
00126                 struct deserialize_streamable_map_f : ::s11n::serialize_binary_f_tag, ::s11n::deserialize_binary_f_tag
00127         {
00128             template <typename NodeType, typename MapType>
00129             bool operator()( const NodeType & src, MapType & dest ) const
00130             {
00131                 return deserialize_streamable_map<NodeType,MapType>( src, dest );
00132             }
00133             template <typename NodeType, typename MapType>
00134             bool operator()( const NodeType & src, const std::string & subnodename, MapType & dest ) const
00135             {
00136                 return deserialize_streamable_map<NodeType,MapType>( src, subnodename, dest );
00137             }
00138         };
00139 
00140                 /**
00141                    Serializes a std::pair-compatible type into a "custom"
00142                    format, suitable for saving pairs in standard XML
00143                    (de/serialize_streamable_map() can't do this when keys are
00144                    not valid XML keys, e.g., numeric). Use
00145                    deserialize_streamable_pair() to decode the data.
00146 
00147                    The destination node gets these two properties:
00148 
00149                    - first = src.first
00150 
00151                    - second = src.second
00152 
00153                    PairType must comply with:
00154 
00155                    - first/second types must be i/o streamable (i.e.,
00156                    convertable to strings).
00157 
00158                    Returns true on success... and never fails. Honestly. It'll
00159                    fail at compile-time if it's going to fail.
00160 
00161                    use deserialize_streamable_pair() to convert them back to pairs,
00162                    or fish out the "first" and "second" properties manually.
00163                 */
00164                 template <typename NodeType, typename PairType>
00165                 bool serialize_streamable_pair( NodeType & dest, const PairType & src );
00166 
00167         /**
00168            A functor equivalent of serialize_streamable_pair().
00169 
00170            Added in version 1.1.3.
00171          */
00172                 struct serialize_streamable_pair_f : ::s11n::serialize_binary_f_tag
00173         {
00174             template <typename NodeType, typename PairType>
00175             inline bool operator()( NodeType & dest, const PairType & src ) const
00176             {
00177                 return serialize_streamable_pair<NodeType,PairType>( dest, src );
00178             }
00179         };
00180 
00181                 /**
00182                    The quasi-counterpart of serialize_streamable_pair(). It's
00183                    non-conventional args and return type are a result of
00184                    map::value_type having a const .first element, which
00185                    prohibits us assigning to it. See deserialize_pair() for
00186                    more info on that.
00187 
00188            As of version 1.1.3, this function throws an
00189            s11n_exception if src does not have two properties
00190            named 'first' and 'second'.
00191                 */
00192                 template <typename PairType, typename NodeType>
00193                 PairType deserialize_streamable_pair( const NodeType & src  );
00194 
00195 
00196         /**
00197            Overloaded form with conventional argument ordering.
00198            It is NOT suitable for use with PairTypes from map-like containers,
00199            as those have const keys.
00200 
00201            This function throws an s11n_exception if src does
00202            not have two properties named 'first' and 'second',
00203            in which case dest is not modified.
00204 
00205            Added in 1.1.3.
00206         */
00207                 template <typename NodeType, typename PairType>
00208                 bool deserialize_streamable_pair( const NodeType & src, PairType & dest );
00209 
00210         /**
00211            A functor equivalent of deserialize_streamable_pair().
00212 
00213            Added in version 1.1.3.
00214          */
00215                 struct deserialize_streamable_pair_f : ::s11n::serialize_binary_f_tag
00216         {
00217             template <typename NodeType, typename PairType>
00218             inline bool operator()( const NodeType & src, PairType & dest ) const
00219             {
00220                 return deserialize_streamable_pair<NodeType,PairType>( src, dest );
00221             }
00222         };
00223         
00224                 /**
00225                    Similar to serialize_streamable_map(), but puts
00226                    each key/value pair into it's own node, using
00227                    serialize_streamable_pair(). The end effect is that
00228                    it's output is more verbose, but may be compatible
00229                    with more file formats, regardless of the actual
00230                    key type. e.g., numeric keys are not supported by
00231                    standard XML (though they are by the s11n XML
00232                    parsers), and this algorithm structures the data
00233                    such that this is not a problem.
00234 
00235                    Returns the number of pairs stored.
00236 
00237                    MapType must meet these conditions:
00238 
00239                    value_type must be a pair containing i/ostreamable types
00240                    (e.g. PODs/strings) with no pointer qualifiers.
00241 
00242                    ACHTUNG: return type changed in 0.9.12.
00243 
00244                 */
00245 
00246                 template <typename NodeType, typename MapType>
00247                 bool serialize_streamable_map_pairs( NodeType & dest, const MapType & src );
00248 
00249         /**
00250            A functor equivalent of serialize_streamable_map_pairs().
00251 
00252            Added in version 1.1.3.
00253          */
00254                 struct serialize_streamable_map_pairs_f : ::s11n::serialize_binary_f_tag
00255         {
00256             template <typename NodeType, typename MapType>
00257             inline bool operator()( NodeType & dest, const MapType & src ) const
00258             {
00259                 return serialize_streamable_map_pairs<NodeType,MapType>( dest, src );
00260             }
00261         };
00262         
00263                 /**
00264                    The load-time counterpart to serialize_streamable_map_pairs().
00265 
00266                    ACHTUNG: return type changed in 0.9.12.
00267 
00268                    If it returns false, a child failed to
00269                    deserialize. In this case, dest is not modified
00270                    (version 1.1.3+) or in an undefined state (versions
00271                    older than 1.1.3). On success, dest.swap() is used
00272                    to populate the map, so dest will lose any contents
00273                    it had before calling this function. There is one
00274                    exception to this: if src contains no content for
00275                    this algorithm, true is returned without modifying
00276                    dest. In practice, dest is always empty when passed
00277                    to this function, so this small difference should
00278                    matter little.
00279 
00280            An empty src is not an error.
00281 
00282            In versions prior to 1.1.3, this function was
00283            documented as returning true on empty content, but
00284            actually (erroneously) returned false. This would show up
00285            when de/serializing empty maps.
00286 
00287                 */
00288                 template <typename NodeType, typename MapType>
00289                 bool deserialize_streamable_map_pairs( const NodeType & src, MapType & dest );
00290 
00291         /**
00292            A functor equivalent of deserialize_streamable_map_pairs().
00293 
00294            Added in version 1.1.3.
00295          */
00296                 struct deserialize_streamable_map_pairs_f : ::s11n::serialize_binary_f_tag
00297         {
00298             template <typename NodeType, typename MapType>
00299             inline bool operator()( const NodeType & src, MapType & dest ) const
00300             {
00301                 return deserialize_streamable_map_pairs<NodeType,MapType>( src, dest );
00302             }
00303         };
00304 
00305                 /**
00306                    serialize_pair() can serialize any std::pair type which
00307                    meets these conditions:
00308 
00309                    - PairType's first_type and second_type types must both be
00310                    Serializables. They may be pointer or value types.
00311 
00312            - PairType may not be a pointer type.
00313 
00314            If serialization of one child fails, the whole
00315            process fails and neither child is added to the
00316            dest node. The error, possibly an exception, is
00317            propagated back to the caller.
00318 
00319                    ACHTUNG: never pass the same destination container
00320                    more than once or you will get duplicate and/or
00321                    incorrect data.
00322 
00323                 */
00324                 template <typename NodeType, typename PairType>
00325                 bool serialize_pair( NodeType & dest, const PairType & src );
00326 
00327         /**
00328            A functor equivalent of serialize_pair().
00329 
00330            Added in version 1.1.3.
00331          */
00332                 struct serialize_pair_f : ::s11n::serialize_binary_f_tag
00333         {
00334             template <typename NodeType, typename PairType>
00335             inline bool operator()( NodeType & dest, const PairType & src ) const
00336             {
00337                 return serialize_pair<NodeType,PairType>( dest, src );
00338             }
00339         };
00340 
00341                 /**
00342                    The counterpart to serialize_pair().
00343 
00344                    Note: std::map&lt;X,Y&gt;::value_type is not the
00345                    same as pair&lt;X,Y&gt;, but is pair&lt;const
00346                    X,Y&gt;, so you cannot simply iterate over a map
00347                    and pass each pair to this function, because this
00348                    function cannot assign to the first element of such
00349                    a pair.
00350 
00351            Exceptions: this function propagates exceptions if
00352            an underlying call to deserialize() throws. If it
00353            throws then dest is not modified. Read on for more
00354            gory detail...
00355 
00356            If the assignment operations for
00357            PairType::first_type or PairType::second_type throw
00358            then dest may be modified if this function throws.
00359 
00360            Versions prior to 1.1.3 had a destroy-on-error
00361            policy, such that objects this function allocates
00362            were deleted on error. For this to work as
00363            expected, without memory leaks, algorithms which
00364            this function calls must clean up in the face of
00365            exceptions.  As it turns out, this is a tricky
00366            situation, because deserialization can allocate
00367            arbitrary objects which might or might not need
00368            special clean-up. For example, deserializing a
00369            pair<int,list<vector<double*>>*> will cause doubles
00370            and lists to be allocated on the heap, and if this function
00371            deletes a list containing the vectors which contain
00372            those doubles, those pointers leak.
00373 
00374            Thus...
00375 
00376            As of 1.1.3, s11n_traits<PairType>::cleanup_functor
00377            is used to do cleanup when an an error occurs. This
00378            allows us to keep dest unmodified in the face on an
00379            error.  For this to work properly, the two
00380            s11n_traits::cleanup_functors for
00381            PairType::first_type and PairType::second_type must
00382            implement proper behaviour.
00383                 */
00384                 template <typename NodeType, typename PairType>
00385                 bool deserialize_pair( const NodeType & src, PairType & dest );
00386 
00387         /**
00388            A functor equivalent of deserialize_pair().
00389 
00390            Added in version 1.1.3.
00391          */
00392                 struct deserialize_pair_f : ::s11n::deserialize_binary_f_tag
00393         {
00394             template <typename NodeType, typename PairType>
00395             inline bool operator()( const NodeType & src, PairType & dest ) const
00396             {
00397                 return deserialize_pair<NodeType,PairType>( src, dest );
00398             }
00399         };
00400         
00401 
00402                 /**
00403                    Serialize the given map into dest. MapType's pairs must be
00404                    Serializable and must contain Serializable types, but their
00405                    "pointerness" is irrelevant.
00406 
00407                    See deserialize_map() for important info.
00408 
00409            If serialization of a child fails, the child is not
00410            added to dest and false is returned or any
00411            exception is propagated back to the caller. The
00412            dest list might be in a partially-populated state,
00413            in either case.
00414 
00415            If this function throws, dest may be in a
00416            partially-filled state.
00417 
00418                    ACHTUNG: never pass the same destination container
00419                    to this function more than once or you will get
00420                    duplicate and/or incorrect data.
00421 
00422            As of version 1.1.3, this function throws an s11n_exception
00423            if dest is not empty. The reason for this is to enforce
00424            that clients do not accidentally re-use the same (populated)
00425            node for serialization of multiple objects, which would cause
00426            deserialization of the container to fail.
00427                 */
00428                 template <typename NodeType, typename MapType>
00429                 bool serialize_map( NodeType & dest, const MapType & src );
00430 
00431 
00432 
00433                 /**
00434                    Identical to the two-argument form, but creates a
00435                    subnode of dest, named subnodename, and serializes
00436                    to that node.
00437 
00438            If serialization into the new child node fails, the
00439            child node is not added to dest and the error
00440            (possibly an exception) is propagated back to the
00441            caller.
00442                 */
00443 
00444                 template <typename NodeType, typename MapType>
00445                 bool serialize_map( NodeType & dest, const std::string & subnodename, const MapType & src );
00446 
00447         /**
00448            A functor equivalent of serialize_map().
00449 
00450            Added in version 1.1.3.
00451          */
00452                 struct serialize_map_f : ::s11n::serialize_binary_f_tag
00453         {
00454             template <typename NodeType, typename MapType>
00455             inline bool operator()( NodeType & dest, const MapType & src ) const
00456             {
00457                 return serialize_map<NodeType,MapType>( dest, src );
00458             }
00459 
00460             template <typename NodeType, typename MapType>
00461             inline bool operator()( NodeType & dest, const std::string & subnodename, const MapType & src ) const
00462             {
00463                 return serialize_map<NodeType,MapType>( dest, subnodename, src );
00464             }
00465         };
00466 
00467                 /**
00468                    The counterpart of serializer_map(), deserializes src into the
00469                    given map. MapType must be Serializable and contain pairs
00470                    which themselves are Serializables... ad inifinitum..
00471 
00472            As of 1.1.3, this function relies on s11n_traits::cleanup_functor
00473            for proper cleanup in the face of failed deserialization.
00474            See deserialize_pair() for details. Assuming that cleanup
00475            routines are in place, this function can now guaranty that
00476            dest is not modified if deserialization fails. However,
00477            dest must be empty when it is passed to this function,
00478            or on success its contents may very well go missing.
00479 
00480                    Minor caveat:
00481 
00482                    This operation will only work with maps containing std::pair
00483                    types, not map-like classes which use a different pair
00484                    type. :( The reason is that map&lt;X,Y&gt;::value_type is
00485                    not a pair of (X,Y), but (const Y,Y), which means we cannot
00486                    use the map's value_type for a deser operation because we
00487                    cannot assign to its .first element (i.e., can't
00488                    deserialize it). To get around that we "manually" create a
00489                    new std::pair type using map's key_type and mapped_type
00490                    typedefs, which "loses" the constness for us so we can
00491                    assign to the first_type during deserialization, and then
00492                    insert that pair into the deserializing map.
00493 
00494            MapType must:
00495 
00496            - not be a pointer type.
00497 
00498            - have a swap() member function, to support the
00499            no-change-on-error feature.
00500                 */
00501                 template <typename NodeType, typename MapType>
00502                 bool deserialize_map( const NodeType & src, MapType & dest );
00503 
00504 
00505                 /**
00506                    Identical to the two-argument form, but tries to
00507                    deserialize from a subnode of src named
00508                    subnodename. If no such node is found then false is
00509                    returned, otherwise the result of
00510                    deserialize_map(thechild,dest) is returned.
00511                 */
00512                 template <typename NodeType, typename MapType>
00513                 bool deserialize_map( const NodeType & src, const std::string & subnodename, MapType & dest );
00514 
00515         /**
00516            A functor equivalent of deserialize_map().
00517 
00518            Added in version 1.1.3.
00519          */
00520                 struct deserialize_map_f : ::s11n::deserialize_binary_f_tag
00521         {
00522             template <typename NodeType, typename MapType>
00523             inline bool operator()( const NodeType & src, MapType & dest ) const
00524             {
00525                 return deserialize_map<NodeType,MapType>( src, dest );
00526             }
00527 
00528             template <typename NodeType, typename MapType>
00529             inline bool operator()( const NodeType & src, const std::string & subnodename, MapType & dest ) const
00530             {
00531                 return deserialize_map<NodeType,MapType>( src, subnodename, dest );
00532             }
00533         };
00534 
00535 
00536         /**
00537            A proxy for de/serializing pair types holding two
00538            i/ostreamable components. It is NOT usable with
00539            pairs from map-like containers because those keys are
00540            const, and thus we cannot assign to them.
00541 
00542            Added in 1.1.3.
00543         */
00544                 struct streamable_pair_serializable_proxy : ::s11n::serialize_binary_f_tag, ::s11n::deserialize_binary_f_tag
00545                 {
00546                         /**
00547                            Serializes src to dest.
00548 
00549                            ACHTUNG: never pass the same destination container
00550                            to this operator more than once or you will get
00551                            duplicate and/or incorrect data.
00552 
00553                SerializableType must be a std::pair<X,Y>,
00554                or compatible. X may not be a contst type.
00555 
00556                See serialize_streamable_pair() for more details.
00557 
00558                         */
00559                         template <typename NodeType, typename SerializableType>
00560                         inline bool operator()( NodeType & dest, const SerializableType & src ) const
00561                         {
00562                                 return serialize_streamable_pair( dest, src );
00563                         }
00564 
00565                         /**
00566                            Deserializes dest from src. See the serialize operator
00567                for requirements placed on SerializableType.
00568 
00569                See deserialize_streamable_pair() for more details.
00570                         */
00571                         template <typename NodeType, typename SerializableType>
00572                         inline bool operator()( const NodeType & src, SerializableType & dest ) const
00573                         {
00574                                 return deserialize_streamable_pair( src, dest );
00575                         }
00576                  };
00577 
00578 
00579 
00580 
00581                 /**
00582                    pair_serializable_proxy is a Serializable Proxy for
00583                    std::pairs.
00584                 */
00585                 struct pair_serializable_proxy : ::s11n::serialize_binary_f_tag,
00586                          ::s11n::deserialize_binary_f_tag
00587                 {
00588                         /**
00589                            See ::s11n::map::serialize_pair().
00590                         */
00591                         template <typename NodeType, typename PairType>
00592                         inline bool operator()( NodeType & dest, const PairType & src ) const
00593                         {
00594                                 return serialize_pair( dest, src );
00595                         }
00596                         /**
00597                            See ::s11n::map::deserialize_pair().
00598                         */
00599                         template <typename NodeType, typename PairType>
00600                         inline bool operator()( const NodeType & src, PairType & dest ) const
00601                         {
00602                                 return deserialize_pair( src, dest );
00603                         }
00604                 };
00605 
00606 
00607 
00608                 /**
00609                    A proxy which can serialize std::maps which contain Streamable
00610                    Types.
00611 
00612                    It uses de/serialize_streamable_map(), so see those
00613                    functions for details.
00614                 */
00615                 struct streamable_map_serializable_proxy : ::s11n::serialize_binary_f_tag,
00616                                ::s11n::deserialize_binary_f_tag
00617                 {
00618                         /**
00619                            Serializes src to dest.
00620 
00621                            ACHTUNG: never pass the same destination container
00622                            to this operator more than once or you will get
00623                            duplicate and/or incorrect data.
00624                         */
00625                         template <typename NodeType, typename SerializableType>
00626                         inline bool operator()( NodeType & dest , const SerializableType & src ) const
00627                         {
00628                                 return serialize_streamable_map( dest, src );
00629                         }
00630 
00631                         /**
00632                            Deserializes dest from src.
00633                         */
00634                         template <typename NodeType, typename SerializableType>
00635                         inline bool operator()( const NodeType & src , SerializableType & dest ) const
00636                         {
00637                                 return deserialize_streamable_map( src, dest );
00638                         }
00639                 };
00640 
00641 
00642 
00643                 /**
00644                    map_serializable_proxy is a Serialization Proxy for std::maps.
00645 
00646                    See de/serialize_map(): this functor simply wraps those.
00647 
00648                 */
00649                 struct map_serializable_proxy : ::s11n::serialize_binary_f_tag,
00650                         ::s11n::deserialize_binary_f_tag
00651                 {
00652 
00653                         /**
00654                            Serializes src into dest. Returns true on success,
00655                            false on error. Uses serialize_map(), so see that
00656                            function for details.
00657                         */
00658                         template <typename NodeType, typename MapType>
00659                         inline bool operator()( NodeType & dest , const MapType & src ) const
00660                         {
00661                                 return serialize_map( dest, src );
00662                         }
00663                         /**
00664                            Deserializes src into dest. Returns true on
00665                            success, false on error. Uses serialize_map(), so
00666                            see that function for details.
00667                         */
00668                         template <typename NodeType, typename MapType>
00669                         inline bool operator()( const NodeType & src , MapType & dest ) const
00670                         {
00671                                 return deserialize_map( src, dest );
00672                         }
00673                 };
00674 
00675         
00676         } // namespace map
00677 } // namespace s11n
00678 
00679 #include <s11n.net/s11n/proxy/mapish.tpp> // implementations for template code
00680 #endif // s11n_net_s11n_v1_1_MAP_HPP_INCLUDED

Generated on Sun Dec 18 18:38:03 2005 for libs11n-1.2.2 by  doxygen 1.4.4