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

list.h

00001 ////////////////////////////////////////////////////////////////////////
00002 //
00003 ////////////////////////////////////////////////////////////////////////
00004 #ifndef s11n_LIST_H_INCLUDED
00005 #define s11n_LIST_H_INCLUDED 1
00006 
00007 #include <list>
00008 #include <iterator> // insert_iterator
00009 #include <algorithm> // for_each()
00010 #include <stdio.h> // snprintf()
00011 
00012 #include <s11n/functor.h> // copy_if, same_name
00013 
00014 #include <s11n/data_node_serialize.h> // core serialize funcs
00015 #include <s11n/data_node_functor.h> // data_node_child_serializer functor
00016 #include <s11n/data_node_algo.h> // dump_node_debug()
00017 #include <s11n/abstract_creator.h> // abstract_creator class
00018 
00019 namespace s11n {
00020 /**
00021    The s11n::list namespace defines functors and algorithms for
00022    working with std::list/vector-style containers.
00023 */
00024 namespace list {
00025 
00026 
00027         /**
00028            Deprecated. See serialize_list().
00029 
00030            Serializes all Serializable objects in the given list.
00031 
00032            ListType must contain ([const] SomeSerializableType *).
00033         
00034            True is returned on success.
00035 
00036            False is returned if any child Serializable in src fails to
00037            serialize.  If false is returned then dest is in an
00038            undefined state: it may have been partially serialized, and
00039            certainly wasn't *completely* serialized.
00040 
00041            Note that a subnodename is required because it is
00042            patentedly a Bad Idea to store more than one Serializable
00043            in the same node, so this function creates subnodes in
00044            dest.
00045         */
00046         template <typename NodeT, typename ListType>
00047         bool serialize_pointer_list( NodeT & dest,
00048                              const std::string & subnodename,
00049                              const ListType & src )
00050         {
00051                 return std::for_each( src.begin(),
00052                                       src.end(),
00053                                       s11n::data_node_child_serializer<NodeT>( dest, subnodename )
00054                                       ).result;
00055         }
00056 
00057 
00058         /**
00059            Deprecated. See deserialize_list().
00060 
00061            The complement to serialize_pointer_list().
00062         
00063            Looks for child nodes of src named subnodename. For each
00064            one that it finds it tries to deserialize it to a
00065            (ListType::value_type) and insert it into dest.
00066 
00067            Returns false only if children are found but their
00068            deserialization fails. If that happens, dest is in an
00069            undefined state: any other children (not the one which
00070            failed deserialization) might still be in the list, and
00071            there is know way for the client to know which child failed
00072            or why it failed.
00073         */
00074         template <typename NodeT, typename ListType>
00075         bool deserialize_pointer_list( const NodeT & src,
00076                              const std::string & subnodename,
00077                              ListType & dest )
00078         {
00079                 //CERR << "deserialize_pointer_list("<<src.name()<<" , "<<subnodename<<", destlist )\n";
00080                 typedef std::list<const NodeT *> MatchList;
00081                 MatchList li;
00082                 s11n::copy_if( src.children().begin(),
00083                                   src.children().end(),
00084                                   std::insert_iterator<MatchList>( li, li.begin() ),
00085                                   s11n::same_name<NodeT>( subnodename )
00086                                   );
00087                 //CERR << "found " << li.size() << " match(es)\n";
00088                 if( ! li.size() ) return false;
00089                 bool b = std::for_each( li.begin(),
00090                                         li.end(),
00091                                         s11n::data_node_child_deserializer<ListType>( dest )
00092                                       ).result;
00093                 //CERR << "for_each() returned " << b << ", and result list size=" << dest.size() << "\n";
00094                 return b;
00095         }
00096 
00097         /**
00098            serialize_list() supports list/vector-like types containing
00099            any Serializable type. Serializes (src.begin(),src.end()]
00100            to dest. Each item has a node name of that given to the
00101            ctor or an unspecified dummy value.
00102            
00103            Returns true on success. If false is returned then dest is
00104            in an undefined state: some number of serializations may
00105            have succeeded before the failure. This operation stops
00106            processing at the first serialization error.
00107 
00108 
00109            Compatible ListTypes must support:
00110            
00111            - a value_type typedef describing the type of it's contents.
00112 
00113            - push_back( value_type )
00114 
00115            - const_iterator typedefs.
00116 
00117            Restrictions on value_type's type:
00118 
00119            - Must be a Serializable. This includes any i/o streamable
00120            type which has a proxy installed by s11n (includes all PODs
00121            and std::string by default).
00122 
00123            - may be a pointer type.
00124 
00125            Some s11n-side requirements:
00126 
00127            - ListType must be registered with the ListType classloader.
00128 
00129            ACHTUNG: never pass the same destination container to 
00130            this function more than once or you will get duplicate and/or
00131            incorrect data.
00132         */
00133         template <typename NodeType, typename SerType>
00134         bool serialize_list( NodeType & dest, const SerType & src )
00135         {
00136                 dest.impl_class( class_name<SerType>::name() );
00137                 typename SerType::const_iterator it = src.begin();
00138                 // reminder: (*it) may be a pointer- or a value-type,
00139                 // as long as it's a Serializable.
00140                 //dest.set( "s11n_metadata", "serialized-by:s11n::list::serialize_list" );
00141                 for( ; src.end() != it; ++it )
00142                 {
00143                         NodeType * ch = new NodeType;
00144                         if( ! serialize( *ch, *it ) )
00145                         {
00146                                 CERR << "serialize_list: a child failed to serialize: " << ch->name() << " @ " << std::hex << ch << "\n";
00147                                 s11n::dump_node_debug( *ch, std::cerr );
00148                                 delete( ch );
00149                                 return false;
00150                         }
00151                         dest.children().push_back( ch );
00152                 }
00153                 return true;
00154         }
00155 
00156         /**
00157            Identical to the two-argument form of serialize_list(), but
00158            serializes src into a subnode of dest, named subnodename.
00159         */
00160         template <typename NodeType, typename SerType>
00161         bool serialize_list( NodeType & dest,
00162                              const std::string & subnodename,
00163                              const SerType & src )
00164         {
00165                 NodeType * ch = new NodeType;
00166                 if( ! serialize_list<NodeType,SerType>( *ch, src ) )
00167                 {
00168                         delete( ch );
00169                         return false;
00170                 }
00171                 dest.children().push_back( ch );
00172                 return true;
00173         }
00174 
00175         /**
00176            For each (src.children().begin(),end()] an object
00177            of type SerType::value_type is created, deserialized,
00178            and is added to dest via push_back( item ).
00179 
00180            See serialize_list() for the list type requirements.
00181 
00182            If SerType::value_type is a pointer type then dest owns any
00183            newly-created pointers, and it's owner (or the container
00184            itself) is responsible for cleaning them up. (Non-pointer
00185            types need no explicit clean-up, of course.)
00186 
00187            Returns true if all deserializations succeed.  Stops
00188            processing and returns false at the first error, in which
00189            case dest is in an undefined state: some children may or
00190            may not have been successfully deserialized into it. The
00191            immediate implication of this is that it will fail if src
00192            contains any other children than the type which dest
00193            expects!
00194         */
00195         template <typename NodeType, typename SerType>
00196         bool deserialize_list( const NodeType & src, SerType & dest )
00197         {
00198                 // note: some of the odd code here is to allow this
00199                 // func to support both value- and pointer-types.
00200                 typedef typename SerType::value_type VT;
00201                 typedef s11n::abstract_creator<VT> ACVT;
00202                 typedef typename NodeType::child_list_type::const_iterator CHIT;
00203                 const NodeType * nch = 0;
00204                 CHIT it = src.children().begin();
00205                 CHIT et = src.children().end();
00206                 s11n::object_reference_wrapper<SerType> dwrap(dest);
00207                 VT ser; // reminder: might be a pointer type
00208                 for( ; et != it; ++it )
00209                 {
00210                         nch = *it;
00211                         if( ! ACVT::create( ser,nch->impl_class() ) )
00212                         {
00213                                 CERR << "Internal error: abstract_creator<> "
00214                                      << "could not create a new object of type '"
00215                                      << nch->impl_class()<<"'!\n";
00216                                 return false;
00217                         }
00218                         if( ! deserialize( *nch, ser ) )
00219                         {
00220                                 CERR << "deserialize_list(): deser of a child failed!\n";
00221                                 CERR << "name="<< nch->name()<< ". implclass="<< nch->impl_class()<<" @ " << std::hex<<nch <<"\n";
00222                                 s11n::dump_node_debug( *nch, std::cerr );
00223                                 ACVT::release( ser );
00224                                 return false;
00225                         }
00226                         dwrap().insert( dwrap().end(), ser );
00227                 }
00228                 return true;
00229         }
00230 
00231         /**
00232            Identical to the two-argument form of deserialize_list(), but
00233            deserializes a subnode of src, named subnodename. If no such
00234            child is found in src then false is returned.
00235         */
00236         template <typename NodeType, typename SerType>
00237         bool deserialize_list( const NodeType & src,
00238                                const std::string & subnodename,
00239                                SerType & dest )
00240         {
00241                 const NodeType * ch = s11n::find_child_by_name( src, subnodename );
00242                 if( ! ch ) return false;
00243                 return deserialize_list<NodeType,SerType>( *ch, dest );
00244         }        
00245 
00246         /**
00247            serialize_streamable_list serializes objects of type
00248            <tt>std::list&lt;X&gt;</tt> (and compatible list types,
00249            such as std::vector). It stores them in such a way that
00250            they can be loaded into any compatible container via
00251            deserialize_streamable_list().
00252 
00253            Conventions:
00254 
00255            - NodeType must support a generic set(Key,Val) function, as
00256            implemented by the s11n::data_node interface.
00257 
00258            - ListType must conform to std::list conventions and it's
00259            value_type must be a non-pointer type which is
00260            i/ostreamable (this includes all PODs and
00261            std::string). Pointers are not supported by
00262            this function.
00263 
00264            ACHTUNG:
00265 
00266            - Never call this on a node for which you store other
00267            properties, as deserialize_streamable_list() will consume them
00268            if you use that function.
00269 
00270            - This function sets dummy property keys, both to please
00271            the conventions of keys having non-empty values and to keep
00272            the list in the proper order. It uses keys which should be
00273            portable to, e.g., standard XML.
00274 
00275            Returns the number of items serialized.
00276         */
00277         template <typename NodeType, typename ListType>
00278         size_t serialize_streamable_list( NodeType & dest, const ListType & src )
00279         {
00280                 typedef typename ListType::const_iterator CIT;
00281                 CIT it = src.begin();
00282                 size_t i = 0;
00283                 // We zero-pad all keys to be the same length, so that
00284                 // they will be kept in the proper order in the
00285                 // target's property list (annoying, but necessary).
00286                 // We prepend a non-numeric char to make this output
00287                 // compatible with standard XML
00288                 static const int bsize = 10;
00289                 char num[bsize];
00290                 char fmt[bsize];
00291                 size_t sz = src.size();
00292                 int places = 1; // # of digits to use
00293                 for( ; sz >= 0x0f; sz = (size_t)(sz/0x0f)) { ++places; }
00294                 snprintf( fmt, bsize, "x%%0%dx", places );
00295                 for( ; src.end() != it; ++it )
00296                 {
00297                         snprintf( num, bsize, fmt, i );
00298                         ++i;
00299                         dest.set( num, (*it) );
00300                 }
00301                 return i;
00302         }
00303 
00304 
00305         /**
00306            Identical to serialize_streamable_list(dest,src), but
00307            creates a subnode in dest, named subnodename, where the
00308            data is stored.
00309         */
00310         template <typename NodeType, typename ListType>
00311         size_t serialize_streamable_list( NodeType & dest,
00312                                           const std::string & subnodename,
00313                                           const ListType & src )
00314         {
00315                 NodeType & n = s11n::create_child( dest, subnodename );
00316                 return serialize_streamable_list<NodeType,ListType>( n, src );
00317         }
00318 
00319 
00320         /**
00321            Deserializes dest from src. It reads in all properties from
00322            src, ignoring their keys and taking only their values. This
00323            is suitable for use with the result of a
00324            serialize_streamable_list() call. See that function for more
00325            information, including the conventions which must be
00326            supported by NodeType and ListType.
00327            
00328            Returns the number of items deserialized.
00329         */
00330         template <typename NodeType, typename ListType>
00331         size_t deserialize_streamable_list( const NodeType & src, ListType & dest )
00332         {
00333                 typedef typename ListType::value_type VT;
00334                 typename NodeType::const_iterator it = src.begin();
00335                 size_t i = 0;
00336                 VT defaultval;
00337                 for( ; src.end() != it; ++it )
00338                 {
00339                         ++i;
00340                         dest.insert( dest.end(),
00341                                      s11n::from_string<VT>( (*it).second, defaultval ) );
00342                 }
00343                 return i;
00344         }
00345 
00346 
00347         /**
00348            Identical to deserialize_streamable_list(), but looks for
00349            the data in a subnode of src named subnodename.
00350 
00351            Returns 0 if no child could be found.
00352         */
00353         template <typename NodeType, typename ListType>
00354         size_t deserialize_streamable_list( const NodeType & src,
00355                                      const std::string & subnodename,
00356                                      ListType & dest )
00357         {
00358                 const NodeType * ch = s11n::find_child_by_name( src, subnodename );
00359                 if( ! ch ) return 0;
00360                 return deserialize_streamable_list<NodeType,ListType>( *ch, dest );
00361         }
00362 
00363 
00364 
00365         /**
00366            list_serializer_proxy is a functor for de/serializing lists
00367            of Serializables.
00368         */
00369         class list_serializer_proxy
00370         {
00371         public:
00372                 list_serializer_proxy()
00373                 {}
00374 
00375                 /**
00376                    see serialize_list().
00377 
00378                 */
00379                 template <typename NodeType, typename SerType>
00380                 bool operator()( NodeType & dest, const SerType & src ) const
00381                 {
00382                         return serialize_list( dest, src );
00383                 }
00384 
00385                 /** see deserialize_list(). */
00386                 template <typename NodeType, typename SerType>
00387                 bool operator()( const NodeType & src, SerType & dest ) const
00388                 {
00389                         return deserialize_list( src, dest );
00390                 }
00391         };
00392 
00393 
00394 
00395 } } // namespace s11n::list
00396 
00397 
00398 #endif // s11n_LIST_H_INCLUDED

Generated on Tue Oct 26 18:25:59 2004 for s11n by  doxygen 1.3.9.1