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

Generated on Wed Jun 4 21:45:46 2008 for libs11n-1.2.7 by  doxygen 1.5.3