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

data_node_io.h

00001 #ifndef s11n_DATA_NODE_IO_H_INCLUDED
00002 #define s11n_DATA_NODE_IO_H_INCLUDED
00003 
00004 ////////////////////////////////////////////////////////////////////////
00005 // data_node_io.h
00006 // some i/o interfaces & helpers for s11n
00007 // License: Public Domain
00008 // Author: stephan@s11n.net
00009 ////////////////////////////////////////////////////////////////////////
00010 
00011 
00012 #include <string>
00013 #include <sstream>
00014 #include <list>
00015 #include <map>
00016 #include <deque>
00017 #include <iostream>
00018 #include <memory>// auto_ptr
00019 
00020 #include <cassert>
00021 #include <typeinfo>
00022 
00023 
00024 // #include <s11n/to_string.h> // to/from_string()
00025 // #include <s11n/string_util.h> // translate_entities()
00026 
00027 #include <s11n/debuggering_macros.h> // COUT/CERR
00028 #include <s11n/file_util.h> // get_i/ostream(), bytes_from_file()
00029 #include <s11n/s11n_core.h> // classloader()
00030 
00031 #include "data_node_serialize.h" // unfortunately dep
00032 
00033 ////////////////////////////////////////////////////////////////////////////////
00034 // NO DEPS ON data_node.h ALLOWED!
00035 ////////////////////////////////////////////////////////////////////////////////
00036 
00037 
00038 namespace s11n {
00039 
00040         namespace io {
00041 
00042 
00043                 /**
00044                    Convenience function for grabbing the first line of a file.
00045 
00046                    If AsFile == true then returns the first line of the
00047                    file, else returns up to the first newline of src.
00048                 */
00049                 std::string get_magic_cookie( const std::string & src, bool AsFile = true );
00050 
00051                 /**
00052                    Convenience function for grabbing the first line of a
00053                    stream.
00054 
00055                    Returns the first line of the given stream, or an
00056                    empty string on error.
00057                 */
00058                 std::string get_magic_cookie( std::istream & is );
00059 
00060                 /**
00061                    data_node_serializer provides an interface for
00062                    saving/loading a given abstract data node type
00063                    to/from streams.
00064 
00065                    It is designed for containers which comply to the
00066                    s11n::data_node interface and
00067                    conventions.
00068 
00069 
00070                    Conventions:
00071 
00072                    Must provide:
00073 
00074                    typedef NodeT node_type
00075 
00076                    Two de/serialize functions, following the
00077                    stream-based interface shown here (filename-based
00078                    variants are optional, but convenient for clients).
00079 
00080                 */
00081                 template <typename NodeT>
00082                 class data_node_serializer
00083                 {
00084                 public:
00085                         /**
00086                            The underlying data type used to store
00087                            serialized data.
00088                         */
00089                         typedef NodeT node_type;
00090 
00091                         data_node_serializer()
00092                         {
00093                                 this->magic_cookie( "WARNING: magic_cookie() not set!" );
00094                                 // ^^^ subclasses must do this.
00095                                 this->metadata().name( "serializer_metadata" );
00096                         };
00097                         virtual ~data_node_serializer(){};
00098 
00099 
00100                         /**
00101                            A convenience typedef, mainly for subclasses.
00102                         */
00103                         typedef std::map<std::string,std::string> translation_map;
00104 
00105                         /**
00106                            Returns a map intended for use with
00107                            s11n::translate_entities().
00108                            
00109                            The default implementation returns an empty map.
00110                            
00111                            Subclasses should override this to return a translation
00112                            map, if they need one. The default map is empty.
00113 
00114                            Be aware that this may very well be called
00115                            post-main(), so subclasses should take that into
00116                            account and provide post-main()-safe maps! (Tip:
00117                            see s11n::phoenix.)
00118                         */
00119                         virtual const translation_map & entity_translations() const
00120                         {
00121                                 typedef phoenix<translation_map,data_node_serializer<node_type> > TMap;
00122                                 return TMap::instance();
00123                         }
00124 
00125 
00126 
00127                         /**
00128                            Must be implemented to format node_type to the given ostream.
00129 
00130                            It should return true on success, false on error.
00131 
00132                            The default implementation always returns false.
00133                         */
00134                         virtual bool serialize( const node_type & src, std::ostream & dest )
00135                         {
00136                                 return false;
00137                         }
00138 
00139                        /**
00140                            Overloaded to save dest to the given filename.
00141 
00142                            The output file is compressed if
00143                            s11n::compression_policy() has
00144                            been set to enable it.
00145 
00146                            Returns true on success, false on error.
00147                         */
00148                         bool serialize( const node_type & src, const std::string & destfile )
00149                         {
00150                                 std::ostream * os = s11n::get_ostream( destfile );
00151                                 if( ! os ) return false;
00152                                 bool b = this->serialize( src, *os );
00153                                 delete( os );
00154                                 return b;
00155                         }
00156 
00157                         /**
00158                            Must be implemented to parse a node_type from the given istream.
00159 
00160                            It should return true on success, false on error.
00161 
00162                            The default implementation always returns false and does nothing.
00163                         */
00164 
00165                         virtual node_type * deserialize( std::istream & )
00166                         {
00167                                 return false;
00168                         }
00169 
00170 
00171                         /**
00172                            Overloaded to load dest from the given filename.
00173 
00174                            It supports zlib/bz2lib decompression for
00175                            files (not source strings) if your s11n lib
00176                            supports them.
00177 
00178                            This is virtual ONLY to avoid a bogus(?) 
00179                            error from gcc when accessing it via
00180                            subclass instances.
00181                         */
00182                         virtual node_type * deserialize( const std::string & src )
00183                         {
00184                                 typedef std::auto_ptr<std::istream> AP;
00185                                 AP is = AP( s11n::get_istream( src ) );
00186                                 if( ! is.get() ) return 0;
00187                                 return this->deserialize( *is );
00188                         }
00189 
00190 
00191                         /**
00192                            Gets this object's magic cookie.
00193 
00194                            Cookies are registered with
00195                            <code>class_loader<noder_serializable<NodeType>></code>
00196                            types to match files to file input parsers.
00197                         */
00198                         std::string magic_cookie() const
00199                         {
00200                                 return this->m_cookie;
00201                         }
00202 
00203                 protected:
00204                         /**
00205                            Sets the magic cookie for this type.
00206                         */
00207                         void magic_cookie( const std::string & c )
00208                         {
00209                                 this->m_cookie = c;
00210                         }
00211 
00212                         /**
00213                            metadata is an experimental feature allowing
00214                            serializers to store arbitrary information
00215                            in their data strings.
00216                          */
00217                         node_type & metadata()
00218                         { return this->m_meta; }
00219                         /**
00220                            A const overload of metadata().
00221                          */
00222                         const node_type & metadata() const
00223                         { return this->m_meta;}
00224                 private:
00225                         std::string m_cookie;
00226                         node_type m_meta;
00227                 }; // data_node_serializer<>
00228 
00229                 /**
00230 
00231                 Tries to load a NodeType object from the given
00232                 node. It uses the cookie from the input stream and
00233                 classload<SerializerBaseType>() to find a matching
00234                 Serializer.
00235 
00236                 0 is returned on error, else a new pointer, which the
00237                 caller owns.
00238 
00239                 Achtung: the first line of input from the input stream
00240                 is consumed by this function (to find the cookie), and
00241                 the cookie is not passed on to the handler! The only
00242                 reliable way around [that i know of] this is to buffer
00243                 the whole input as a string, and i don't wanna do that
00244                 (it's bad for massive data files).
00245 
00246                 ACHTUNG: Only usable for loading ROOT nodes.
00247                 */
00248                 template <typename NodeType, typename SerializerBaseType>
00249                 NodeType * load_node_classload_serializer( std::istream & is )
00250                 {
00251                         typedef SerializerBaseType NS;
00252                         std::string cookie = get_magic_cookie( is );
00253                         // CERR << "cookie="<<cookie<<std::endl;
00254                         if( cookie.empty() )
00255                         {
00256                                 CERR << "Odd: got a null cookie from the istream.\n";
00257                                 return 0; // happens post-main() on valid streams sometimes!?!?!
00258                         }
00259                         typedef std::auto_ptr<NS> AP;
00260                         AP ser = AP( s11n::classload<NS>( cookie ) );
00261                         if( ! (ser.get()) )
00262                         {
00263                                 CERR << "Did not find serializer for cookie ["<<cookie<<"]."<<std::endl;
00264                                 return NULL;
00265                         }
00266                         // CERR << "Dispatching to node loader for cookie ["<<cookie<<"]\n";
00267                         return ser->deserialize( is );
00268                 }
00269 
00270                 /**
00271                    Returns a node pointer, parsed from the given stream, using
00272                    <code>s11n::io::data_node_serializer<NodeType></code>
00273                    as the base type for looking up a stream handler.
00274 
00275                    ACHTUNG: Only usable for loading ROOT nodes.
00276                 */
00277                 template <typename NodeType>
00278                 NodeType * load_node( std::istream & is )
00279                 {
00280                         return load_node_classload_serializer<NodeType,data_node_serializer<NodeType> >( is );
00281                 }
00282 
00283                 /**
00284                    Overloaded form of load_node( istream ), provided for
00285                    convenience.
00286 
00287                    If AsFile is true, input is treated as a file,
00288                    otherwise it is treated as a string containing input
00289                    to parse.
00290 
00291                    ACHTUNG: Only usable for loading ROOT nodes.
00292 
00293                    Maintenance note: AsFile==false may be extremely
00294                    inefficient, as src may get copied one additional
00295                    time.
00296                 */
00297                 template <typename NodeType>
00298                 NodeType * load_node( const std::string & src, bool AsFile = true )
00299                 {
00300                         typedef std::auto_ptr<std::istream> AP;
00301                         AP is = AP( s11n::get_istream( src, AsFile ) );
00302                         if( ! is.get() ) return 0;
00303                         return load_node<NodeType>( *is );
00304                 }
00305 
00306                 /**
00307                    Tries to load a SerializableT from the given stream.
00308                    On success returns a new object, else 0.
00309 
00310                    The caller owns the returned pointer.
00311 
00312                    ACHTUNG: Only usable for loading ROOT nodes.
00313                 */
00314                 template <typename NodeT,typename SerializableT>
00315                 SerializableT * load_serializable( std::istream & src )
00316                 {
00317                         typedef std::auto_ptr<NodeT> AP;
00318                         AP node = AP( load_node<NodeT>( src ) );
00319                         if( ! node.get() )
00320                         {
00321                                 CERR << "load_serializable<>(istream) Could not load a root node from the input.\n";
00322                                 return 0;
00323                         }
00324                         return s11n::deserialize<NodeT,SerializableT>( *node );
00325                 }
00326 
00327                 /**
00328                    An overloaded form which takes an input string. If
00329                    AsFile is true the string is treated as a file
00330                    name, otherwise it is processed as an input stream.
00331 
00332                    ACHTUNG: Only usable for loading ROOT nodes.
00333                 */
00334                 template <typename NodeT,typename SerializableT>
00335                 SerializableT * load_serializable( const std::string & src, bool AsFile = true )
00336                 {
00337                         typedef std::auto_ptr<std::istream> AP;
00338                         AP is = AP( get_istream( src, AsFile ) );
00339                         if( ! is.get() )
00340                         {
00341                                 CERR << "load_serializable<>(string) Could not load a root node from the input.\n";
00342                                 return 0;
00343                         }
00344                         return load_serializable<NodeT,SerializableT>( *is );
00345                 }
00346 
00347 
00348                 /**
00349                    Saves src to the given ostream using the given
00350                    Serializer type.
00351 
00352                    ONLY use this for saving root nodes!
00353                 */
00354                 template <typename NodeType, typename SerializerT>
00355                 bool save_node( const NodeType & src, std::ostream & dest )
00356                 {
00357                         return SerializerT().serialize( src, dest );
00358                 }
00359 
00360 
00361                 /**
00362                    Saves src, a Serializable type, to the given
00363                    ostream using a SerializerT serializer.
00364 
00365                    SerializerT must be compatible with
00366                    s11n::io::data_node_serializer<>
00367                    conventions and must provide a <code>typedef XXX
00368                    node_type</code>, where XXX is a data type
00369                    conforming to s11n::data_node
00370                    conventions.
00371 
00372                    Returns true on success, false on error.
00373 
00374                    ONLY use this for saving root nodes!
00375                 */
00376                 template <typename SerializerT,typename SerializableT>
00377                 bool save_serializable( const SerializableT & src,
00378                                         std::ostream & dest )
00379                 {
00380                         typedef typename SerializerT::node_type node_type;
00381                         node_type node( "serializable" );
00382                         if( ! s11n::serialize<node_type,SerializableT>( node, src ) ) return false;
00383                         return SerializerT().serialize( node, dest );
00384                 }
00385 
00386                 /**
00387                    An overloaded form which takes a filename.
00388 
00389                    ONLY use this for saving root nodes!
00390                 */
00391                 template <typename SerializerT,typename SerializableT>
00392                 bool save_serializable( const SerializableT & src,
00393                                         const std::string & filename )
00394                 {
00395                         typedef std::auto_ptr<std::ostream> AP;
00396                         AP os = AP( s11n::get_ostream( filename ) );
00397                         if( ! os.get() ) return false;
00398                         return save_serializable( src, *os );
00399                 }
00400 
00401 
00402         } // namespace io
00403 
00404 } // namespace s11n
00405 
00406 #endif // s11n_DATA_NODE_IO_H_INCLUDED

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