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

data_node_functor.h

00001 #ifndef s11n_DATA_NODE_FUNCTOR_H_INCLUDED
00002 #define s11n_DATA_NODE_FUNCTOR_H_INCLUDED
00003 
00004 ////////////////////////////////////////////////////////////////////////
00005 // data_node_functor.h
00006 // Some functors/algorithms for working with data_node-compliant types.
00007 // License: Public Domain
00008 // Author: stephan@s11n.net
00009 ////////////////////////////////////////////////////////////////////////
00010 
00011 #include <string>
00012 #include <list>
00013 #include <map>
00014 #include <typeinfo> // aid debugging
00015 #include <utility> // std::pair/make_pair
00016 #include <iterator>
00017 #include <iostream>
00018 
00019 #include <s11n/phoenix.h> // phoenix class
00020 #include <s11n/to_string.h> // to/from_string()
00021 #include <s11n/debuggering_macros.h> // COUT/CERR
00022 #include <s11n/string_util.h> // translate_entities()
00023 #include <s11n/pointer_stripper.h> // pointer_stripper class
00024 #include <s11n/class_name.h> // unfortunate dependency.
00025 #include <s11n/abstract_creator.h> // abstract_creator class
00026 #include <s11n/data_node_serialize.h> // core de/serialize interface
00027 #include <s11n/data_node_algo.h> // useful data_node algos
00028 
00029 ////////////////////////////////////////////////////////////////////////
00030 // NO DEPS ON data_node.h ALLOWED!
00031 ////////////////////////////////////////////////////////////////////////
00032 
00033 namespace s11n {
00034 
00035 
00036 
00037         /**
00038            Dumps some info about n to the given ostream, mostly
00039            useful for debugging failed deserialization.
00040         */
00041         template <typename NodeType>
00042         void dump_node_debug( const NodeType & n, std::ostream & os )
00043         {
00044                 os << "node dump: ["<<n.name()<<"]["<<n.impl_class()<<"]@"<<std::hex<<&n<<"\n";
00045                 typedef typename NodeType::const_iterator PT;
00046                 PT b = n.begin(), e = n.end();
00047                 os << "==================== properties:\n";
00048                 for( ; e != b; ++b )
00049                 {
00050                         os << (*b).first << " = " << (*b).second << "\n";
00051                 }
00052                 os << "[end node]\n";
00053         }
00054 
00055         /**
00056            A helper functor to loop over serializable
00057            children.
00058 
00059            Designed for use with std::for_each().
00060 
00061            NodeType must be compatible with
00062            s11n::data_node.
00063 
00064            Please see the operator() docs for important usage
00065            information, especially if you want to use this
00066            object outside the context of for_each().
00067         */
00068         template <typename NodeType>
00069         struct data_node_child_serializer
00070         {
00071                 typedef NodeType node_type;
00072                 /**
00073                    Creates an object for serializing
00074 
00075                    Preconditions:
00076 
00077                    - dest must outlive this object.
00078                    More correctly, this object's
00079                    operator() must not be called after
00080                    dest is destroyed.
00081 
00082                 */
00083                 data_node_child_serializer( node_type & dest, const std::string & subname )
00084                         : result(true), m_name(subname), m_root(&dest)
00085                 {
00086                 }
00087  
00088                 /**
00089                    Serializes src into a subnode of dest using the
00090                    name given in this object's ctor.
00091 
00092                    Note that during an, e.g., for_each() this object
00093                    will return false on a failed serialize, and will
00094                    CONTINUE to return false on additional serializations.
00095                    This is to avoid the possibility that for_each()
00096                    fails on the first item of a list, handles 3000 items,
00097                    and then the whole thing fails because of the first one.
00098                    Thus, this operator will never process another request
00099                    once it has returned false ONCE.
00100                 */
00101                 template <typename SerializableT>
00102                 bool operator()( const SerializableT * src )
00103                 {
00104                         if( ! this->result ) return false;
00105                         return this->result = 
00106                                 serialize_subnode( *this->m_root,
00107                                                    this->m_name,
00108                                                    *src );
00109                 }
00110                 /**
00111                    For use as a "return value catcher" for std::for_each().
00112                    See operator() for how it is set. The starting value
00113                    is true, which means that looping over an empty list
00114                    with this object will return a true result (which is
00115                    the convention in s11n).
00116                 */
00117                 bool result;
00118         private:
00119                 std::string m_name;
00120                 node_type * m_root;
00121         };
00122 
00123         /**
00124            A helper functor deserialize a set of data_nodes.
00125 
00126            Designed for use with std::for_each().
00127 
00128            ListType must be compatible with
00129            <code>std::list<SomeSerializableType *></code>.
00130         */
00131         template <typename ListType>
00132         struct data_node_child_deserializer
00133         {
00134                 /**
00135                    The ListType templatized type. Must support:
00136 
00137                    push_back(value_type *);
00138                  */
00139                 typedef ListType list_type;
00140                 /**
00141                    value_type is equivalent to a SerializableType.
00142                 */
00143                 typedef typename pointer_stripper<
00144                             typename list_type::value_type
00145             >::value_type  value_type;
00146 
00147                 /**
00148                    Creates an object for deserializing Serializables
00149                    into a target list.
00150 
00151                    If tolerant is true then this object will always
00152                    try to deserialize new items passed to it's
00153                    operator(). If it is false (the default) it will
00154                    stop processing after a single failure.
00155 
00156                    Preconditions:
00157 
00158                    - dest must outlive this object. More correctly,
00159                    this object's operator() must not be called after
00160                    either dest is destroyed.
00161 
00162                 */
00163                 data_node_child_deserializer( list_type & dest,
00164                                               bool tolerant = false )
00165                         : result(true), m_tolerant(tolerant), m_list(&dest)
00166                 {
00167                 }
00168 
00169                 /**
00170                    Tries to deserialize a (value_type *) from src. On error it returns 0,
00171                    else it inserts the new child into this object's destination container
00172                    and returns true.
00173 
00174                    Postconditions:
00175 
00176                    - If successful, this object's destination container owns the returned
00177                    pointers.
00178                 */
00179                 template <typename NodeType>
00180                 bool operator()( const NodeType * src )
00181                 {
00182                         if( ! result && ! this->m_tolerant ) return false; // once an item fails, stop processing them.
00183                         if( ! src ) return result = false;
00184                         value_type * ch = 0;
00185                         ch = s11n::deserialize<NodeType,value_type>( *src );
00186                         //CERR << "data_node_child_deserializer<>("<<src->name()<<") = "
00187                         //     << std::hex << ch <<"\n";
00188                         if( ! ch ) return result = false;
00189                         this->m_list->push_back( ch );
00190                         return result = true;
00191                 }
00192 
00193                 /**
00194                    For use as a "return value catcher" for std::for_each().
00195 
00196                    If tolerant is true then this will only reveal the value of
00197                    the most-recently-processed node.
00198                 */
00199                 bool result;
00200         private:
00201                 bool m_tolerant;
00202                 list_type * m_list;
00203         };
00204 
00205 
00206 
00207 
00208         /**
00209            A Serializable Proxy for streamable types. It "should" work
00210            with any type which meets these conditions:
00211 
00212            - i/ostream operators are implemented (as member or free
00213            functions).
00214 
00215            - supports a copy ctor (for deserialization).
00216 
00217            - has a class_name&lt;&gt; specialization. Such
00218            specializations come pre-installed for PODs, std::string,
00219            and maybe others. Use the CLASS_NAME(T) macro to create these.
00220 
00221 
00222            It's output is significantly bigger than using, e.g., node
00223            properties to store them, but with this proxy any
00224            streamable can be treated as a full-fledged Serializable,
00225            which allows some generic container-based serialization to
00226            be done regardless of the underlying types (see
00227            list_serializer_proxy for an example).
00228 
00229 
00230          ACHTUNG: never pass the same Serializable to the
00231          operators more than once or you will get duplicate and/or
00232          incorrect data.
00233         */
00234         struct streamable_type_serializer_proxy
00235         {
00236                 /**
00237                    Sets the subnode name used for this object's
00238                    serialize operator.
00239                 */
00240                 explicit streamable_type_serializer_proxy( const std::string & subnodename )
00241                         : m_subname(subnodename)
00242                 {}
00243                 /**
00244                    Uses a default, unspecified, name for subnode
00245                    insertions.
00246                 */
00247                 streamable_type_serializer_proxy() : m_subname("")
00248                 {}
00249 
00250                 /**
00251                    Creates a property in dest, called 'v', and sets
00252                    its value to src. Each node gets the name assigned
00253                    via this object's ctor or an undefined dummy name.
00254                    Note that the deserialize operator pays no attention
00255                    to the subnode names.
00256 
00257                    Always returns true.
00258                 */
00259                 template <typename NodeType, typename SerType>
00260                 bool operator()( NodeType & dest, const SerType & src ) const
00261                 {
00262                         dest.impl_class( class_name<SerType>::name() );
00263                         //dest.impl_class( "pod" );
00264                         // ^^^^ not strictly necessary, but i want
00265                         // something smaller than the default string.
00266                         //dest.set( "s11n_metadata", "serialized-by:s11n::streamable_type_serializer_proxy" );
00267                         if( ! this->m_subname.empty() ) dest.name( this->m_subname );
00268                         dest.set( "v", src );
00269                         return true;
00270                 }
00271 
00272                 /**
00273                    Looks for a property in src called 'v' and sets
00274                    dest to it's value. The default for dest, in the case
00275                    of a missing property or nonconvertable value is
00276                    dest itself.
00277 
00278                    If the 'v' property is missing this function does
00279                    nothing and returns false, otherwise dest gets
00280                    assigned the property's value and true is
00281                    returned. This function cannot catch a case of
00282                    inability to convert 'v' into a SerType: client
00283                    code interested in doing so should compare dest's
00284                    value to a known error value after this
00285                    function returns.
00286                 */
00287                 template <typename NodeType, typename SerType>
00288                 bool operator()( const NodeType & src, SerType & dest ) const
00289                 {
00290                         if( ! src.is_set( "v" ) )
00291                         {
00292                                 CERR << "streamable_serializer_proxy: deser failed: property 'v' missing!\n";
00293                                 dump_node_debug( src, std::cerr );
00294                                 return false;
00295                         }
00296                         dest = src.get( "v", dest );
00297                         return true;
00298                 }
00299         private:
00300                 std::string m_subname;
00301         };
00302 
00303 
00304 
00305 
00306 
00307         namespace io {
00308 
00309 
00310 
00311                 /**
00312                    A helper for serializing properties to a
00313                    stream. Intended for use by Serializers, not
00314                    Serializables.
00315 
00316                    NodeType is the container type used for data
00317                    serialization (e.g. s11n::data_node).
00318 
00319                 */
00320                 template <typename NodeType>
00321                 class key_value_serializer
00322                 {
00323                 public:
00324                         typedef NodeType node_type;
00325                         typedef typename node_type::value_type pair_type;
00326 
00327                         typedef std::map<std::string,std::string> entity_translation_map;
00328 
00329                         /**
00330                            map: needed so we can do entity translation
00331                            in a unified manner here. It must outlive
00332                            this object. Pass it 0 for no translation.
00333                            Translations are only applied on VALUES,
00334                            not KEYS.
00335 
00336                            prefix: inserted before each property.
00337 
00338                            separator: inserted between the key and value.
00339 
00340                            suffix: appended after each entry.
00341 
00342 
00343                         */
00344                         key_value_serializer( const entity_translation_map * map,
00345                                               std::ostream & dest,
00346                                               const std::string & prefix,
00347                                               const std::string & separator,
00348                                               const std::string & suffix
00349                                               )
00350                                 : m_pre(prefix), m_sep(separator), m_suf(suffix), m_os(dest), m_map(map)
00351                         {
00352                         }
00353 
00354                         /**
00355                            Sends the following formatted string to os:
00356 
00357                            {prefix}{src.first}{separator}{src.second}{suffix}
00358 
00359                         */
00360                         void operator()( const pair_type & src ) const
00361                         {
00362                                 static const std::string errval = "";
00363                                 std::string key = s11n::to_string( src.first );
00364                                 std::string val = s11n::to_string( src.second );
00365                                 // should we xlate the key as well?
00366                                 if( this->m_map )
00367                                 {
00368                                         s11n::translate_entities( val, *(this->m_map) );
00369                                 }
00370                                 this->m_os << this->m_pre;
00371                                 this->m_os << key;
00372                                 this->m_os << this->m_sep;
00373                                 this->m_os << val;
00374                                 this->m_os << this->m_suf;
00375                         }
00376                 private:
00377                         std::string m_pre;
00378                         std::string m_sep;
00379                         std::string m_suf;
00380                         std::ostream & m_os;
00381                         const entity_translation_map * m_map;
00382                 };
00383 
00384 
00385 
00386 
00387 
00388                 /**
00389                    A helper functor to loop over serializable children
00390                    of a node from within a Serializer implementation.
00391 
00392                    Designed for use with std::for_each().
00393 
00394                    SerializerT must be compatible with
00395                    <code>data_node_serializer<></code>.
00396 
00397                 */
00398                 template <typename SerializerT>
00399                 struct node_child_simple_formatter
00400                 {
00401                         typedef SerializerT serializer_type;
00402 //                         typedef typename SerializerT::node_type node_type;
00403                         /**
00404                            Preconditions:
00405 
00406                            - Ser must be valid references.
00407 
00408                            - Both ser and os must outlive this
00409                            object. More correctly, this object's
00410                            operator() must not be called after either
00411                            ser or os are destroyed.
00412 
00413                         */
00414                         node_child_simple_formatter( serializer_type & ser, std::ostream & os,
00415                                                const std::string & prefix = "", const std::string & suffix = "\n" )
00416                                 : m_ser(ser), m_os(&os), m_pre(prefix), m_suf(suffix)
00417                         {
00418                         }
00419 
00420                         /**
00421                            Serializes src into this object's target
00422                            container, using this object's serializer.
00423                         */
00424                         template <typename NodeType>
00425                         bool operator()( const NodeType * src ) const
00426                         {
00427                                 if( ! src ) return false;
00428                                 if( ! this->m_pre.empty() ) *(this->m_os) << this->m_pre;
00429                                 bool b = this->m_ser.serialize( *src, *(this->m_os) );
00430                                 if( ! this->m_suf.empty() ) *(this->m_os) << this->m_suf;
00431                                 return b;
00432                         }
00433 
00434                 private:
00435                         serializer_type & m_ser;
00436                         std::ostream * m_os;
00437                         std::string m_pre;
00438                         std::string m_suf;
00439                 };
00440 
00441 
00442         } // namespace io
00443 
00444 } // namespace s11n
00445 
00446 
00447 #endif // s11n_DATA_NODE_FUNCTOR_H_INCLUDED

Generated on Thu Jun 16 16:18:12 2005 for s11n by  doxygen 1.4.3-20050530