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 Jul 20 10:46:48 2004 for s11n by doxygen 1.3.7