00001 #ifndef s11n_SERIALIZE_HPP_INCLUDED 00002 #define s11n_SERIALIZE_HPP_INCLUDED 00003 //////////////////////////////////////////////////////////////////////// 00004 // serialize.hpp: 00005 // 00006 // Defines the core de/serialize() functions (and close friends). 00007 // 00008 // License: Public Domain 00009 // Author: stephan@s11n.net 00010 //////////////////////////////////////////////////////////////////////// 00011 00012 #include <stdexcept> 00013 00014 00015 //////////////////////////////////////////////////////////////////////////////// 00016 // NO DEPS ON s11n_node.hpp ALLOWED! 00017 //////////////////////////////////////////////////////////////////////////////// 00018 00019 namespace s11n { 00020 00021 00022 namespace Detail { 00023 /*** 00024 s11n_api_marshaler is the internal API marshaller 00025 for s11n. See the lib manual for full 00026 details. Client code is not expected to use or 00027 specialize this class, but theoretically some 00028 cases may call for doing so. In s11n versions 00029 prior to 1.0.x, specializing this type was 00030 sometimes useful for handling client-side 00031 template types, but this is no longer necessary 00032 nor encouraged. 00033 00034 In the default implementation, s11n_traits<NodeT,SerializableT> 00035 is used to marshal the de/serialize() calls. 00036 00037 Changed in 1.1.3: 00038 00039 - NodeType template param was moved from the static 00040 functions to the class. 00041 00042 - Moved class from anonymous namespace into s11n::Detail. 00043 */ 00044 template <typename NodeType,typename SerializableT> 00045 struct s11n_api_marshaler 00046 { 00047 /** 00048 Same as SerializableT. 00049 */ 00050 typedef SerializableT serializable_type; 00051 00052 typedef NodeType node_type; 00053 00054 /** 00055 Returns s11n_traits<serializable_type>::serialize_functor()( dest, src ). 00056 00057 This implementation sets dest's class name to 00058 s11n_traits<SerializableT>::class_name(&src), which 00059 is only guaranteed to work properly for monomorphic 00060 types and base-most types of Serialization 00061 hierarchies (i.e., the registered 00062 bases). Polymorphic Serializable subtypes should 00063 set this class name themselves, or via their 00064 s11n_traits::class_name() specialization, both 00065 described in the library manual. 00066 00067 */ 00068 static bool serialize( node_type &dest, const serializable_type & src ); 00069 00070 /** 00071 Returns s11n_traits<SerializableT>::deserialize_functor()(src,dest). 00072 */ 00073 static bool deserialize( const node_type & src, serializable_type & dest ); 00074 }; 00075 00076 /** 00077 A specialization to handle pointer types the same as 00078 reference/value types. It simply translates the pointers 00079 into references. 00080 */ 00081 template <typename NodeType,typename SerializableT> 00082 struct s11n_api_marshaler<NodeType,SerializableT *> 00083 { 00084 /** 00085 The SerializableT templatized type, minus any 00086 pointer part. 00087 */ 00088 typedef SerializableT serializable_type; 00089 00090 typedef NodeType node_type; 00091 00092 /** 00093 Convenience typedef: this class' quasi-parent type. 00094 */ 00095 typedef s11n_api_marshaler<node_type,serializable_type> parent_type; 00096 00097 /** 00098 Returns parent_type::serialize( dest, *src ); 00099 00100 src must be a valid pointer, else false is returned. 00101 */ 00102 static bool serialize( node_type &dest, const serializable_type * const & src ); 00103 00104 /** 00105 Returns parent_type::deserialize( src, *dest ); 00106 00107 dest must be a valid pointer, else false is returned. 00108 00109 Reminder to self: if we dupe the code from 00110 deserialize(const N&,ST *&), we could 00111 potentially provide support for passing a 00112 reference to a null pointer here. No need, 00113 though, since the public s11n API already 00114 provides that. 00115 */ 00116 static bool deserialize( const node_type & src, serializable_type * & dest ); 00117 }; 00118 } // namespace Detail 00119 00120 00121 /** 00122 Serializes src to target using the default API marshaling 00123 mechanism. 00124 00125 On success it always returns true, else false. 00126 00127 If a the underlying operation throws, it will pass on the 00128 exception. 00129 */ 00130 template <typename DataNodeType, typename SerializableT> 00131 bool serialize( DataNodeType & target, const SerializableT & src ); 00132 00133 /** 00134 Calls s11n_traits<SerializableType>::cleanup_functor()(s). 00135 00136 This function is declared as no-throw because of its 00137 logical role in the destruction process, and dtors are 00138 normally prohibited from throwing. Any exceptions caught by 00139 this function are silently ignored (a warning might go out 00140 to a debug channel, probably cerr, but don't rely on it). 00141 00142 SerializableType requirements: 00143 00144 - Must be a Serializable. Specifically, it must have an 00145 s11n_traits specialization installed. 00146 00147 - s11n_traits<SerializableType>::cleanup_functor must be 00148 known to work properly for SerializableType. This is core 00149 to the whole cleanup functionality, which is core to 00150 protecting against leaks in the face of errors. 00151 00152 Technically, if the type can be delete()d without leaking 00153 pointers, it's safe for use with this function, but this 00154 function SHOULD NOT be used as general cleanup tool. It is 00155 ONLY intended to be used with REGISTERED Serializables. 00156 00157 This function guarantees not to leak when "cleaning up" 00158 containers holding unmanaged pointers as long as the 00159 associated cleanup_functors do their part. The model is 00160 such that once a cleanup_functor is in place for a given 00161 type, this function will inherently walk it and invoke the 00162 cleanup rules, which includes freeing any pointers along 00163 the way. 00164 00165 Added in 1.1.3. 00166 */ 00167 template <typename SerializableType> 00168 void cleanup_serializable( SerializableType & s ) throw(); 00169 00170 /** 00171 This overload provides cleanup handling for pointer 00172 types. This simplifies many algorithms over using 00173 s11n_traits<SerializableType>::cleanup_functor directly, as 00174 the algorithms do not need to care if they're using 00175 pointer-qualified types or not in order to clean them up 00176 properly. 00177 00178 SerializableType requirements are as for the non-pointered 00179 variant of this function, plus: 00180 00181 - delete aSerializableTypeInstance; must be well-formed and 00182 must neither throw nor invoke undefined behaviour. (Did 00183 you realize that "neither" is an exception to English's 00184 "i-before-e" rule?) 00185 00186 This function does nothing if s is null, otherwise it calls 00187 cleanup_serializable(*s), deletes s, then assigns it to 0. 00188 00189 Postcondition: (0 == s) 00190 00191 Added in 1.1.3. 00192 */ 00193 template <typename SerializableType> 00194 void cleanup_serializable( SerializableType * & s ) throw(); 00195 00196 00197 /** 00198 Intended for use with for_each(), this type cleans up 00199 Serializables using cleanup_serializable(). 00200 00201 Usage: 00202 00203 std::for_each( container.begin(), container.end(), cleaner_upper() ); 00204 00205 where the container is parameterized to hold Serializables. 00206 00207 Provided that the contained type(s) conform to 00208 cleanup_ptr's requirements, this will recursively clean up 00209 sub-sub-...subcontainers. 00210 00211 Note that Serializable containers should have a cleanup 00212 functor installed as part of their registration, making 00213 this class unnecessary for most cases: simply calling 00214 cleanup_serializable() will recursively walk/clean such 00215 containers. The underlying cleanup algos might use this 00216 type, however (at least one of them does). 00217 00218 Added in 1.1.3. 00219 */ 00220 struct cleaner_upper 00221 { 00222 /** 00223 Calls cleanup_serializable<T>(t) 00224 */ 00225 template <typename T> 00226 void operator()( T & t ) throw() 00227 { 00228 cleanup_serializable<T>( t ); 00229 } 00230 /** 00231 Calls cleanup_serializable<T>(t). 00232 */ 00233 template <typename T> 00234 void operator()( T * & t ) throw() 00235 { 00236 cleanup_serializable<T>( t ); 00237 } 00238 }; 00239 00240 00241 /** 00242 An auto_ptr-like type intended to simplify 00243 pointer/exception safety in some deserialization algorithms 00244 by providing a way to completely and safely destroy 00245 partially-deserialized objects. 00246 00247 SerializableT must either have an explicit s11n_traits 00248 specialization installed or work properly with the default 00249 functor provided by s11n_traits::cleanup_functor. In 00250 practice, this means that types which manage the memory of 00251 their contained pointers are safe to work with the default, 00252 whereas the cleanup of unmanaged child pointers (e.g., std 00253 containers) requires a proper specialization. 00254 00255 Note that this type does not have copy/assignment ctors, 00256 due to the conventional constness of their right-hand 00257 sides: use the swap() or take() members to take over a 00258 pointer. 00259 00260 Added in 1.1.3. 00261 */ 00262 template <typename SerializableT> 00263 struct cleanup_ptr 00264 { 00265 public: 00266 typedef SerializableT cleaned_type; 00267 private: 00268 cleaned_type * m_ptr; 00269 cleanup_ptr & operator=( const cleanup_ptr & ); // Not Implemented 00270 cleanup_ptr( const cleanup_ptr & ); // Not Implemented 00271 void cleanup() throw() 00272 { 00273 if( this->m_ptr ) 00274 { 00275 cleanup_serializable<cleaned_type>( this->m_ptr ); 00276 } 00277 } 00278 public: 00279 /** 00280 Constructs an object pointing to nothing. 00281 */ 00282 cleanup_ptr() throw() : m_ptr(0) 00283 { 00284 } 00285 /** 00286 Transfers ownership of p to this object. 00287 */ 00288 cleanup_ptr( cleaned_type * p ) throw() : m_ptr(p) 00289 { 00290 } 00291 00292 /** 00293 Uses s11n::cleanup_serializable<cleaned_type>() 00294 to free up up this->get(). 00295 */ 00296 ~cleanup_ptr() throw() 00297 { 00298 this->cleanup(); 00299 } 00300 /** 00301 Dereferences this object's pointed-to object. If 00302 this object does not point to anything it throws a 00303 std::runtime_error with an informative what() 00304 message explaining the error. 00305 */ 00306 cleaned_type & operator*() 00307 { 00308 if( ! this->m_ptr ) 00309 { 00310 throw std::runtime_error("Attempt to dereference a null pointer via s11n::cleanup_ptr<>::operator*()" ); 00311 } 00312 return *this->m_ptr; 00313 } 00314 00315 /** 00316 Returns the same as get(). 00317 */ 00318 cleaned_type * operator->() throw() 00319 { 00320 return this->m_ptr; 00321 } 00322 00323 /** 00324 Returns this object's pointed-to object without 00325 transfering ownership. 00326 */ 00327 cleaned_type * get() throw() 00328 { 00329 return this->m_ptr; 00330 } 00331 00332 /** 00333 Transfers ownership of p to this object. This 00334 member takes the place of copy/assign operators, 00335 since those conventionally take a const right-hand 00336 argument. 00337 00338 Destroys the object this object pointed to before 00339 taking over ownership. 0 is a legal value for p. 00340 00341 If (p == this->get()) then this function does 00342 nothing. 00343 00344 Postcondition: p == this->get() 00345 */ 00346 void take( cleaned_type * p ) throw() 00347 { 00348 if( p != this->m_ptr ) 00349 { 00350 this->cleanup(); 00351 this->m_ptr = p; 00352 } 00353 } 00354 00355 /** 00356 Transfers ownership of this->get() to the 00357 caller. 00358 00359 Postcondition: 0 == this->get() 00360 */ 00361 cleaned_type * release() throw() 00362 { 00363 cleaned_type * x = this->m_ptr; 00364 this->m_ptr = 0; 00365 return x; 00366 } 00367 00368 /** 00369 Cleans up any pointed-to object and points this 00370 object at 0. Does nothing if this object points 00371 to no object. 00372 00373 Postcondition: 0 == this->get() 00374 */ 00375 void clean() throw() 00376 { 00377 this->take( 0 ); 00378 } 00379 00380 /** 00381 Swaps ownership of pointers with rhs. 00382 */ 00383 void swap( cleanup_ptr & rhs ) throw() 00384 { 00385 cleaned_type * x = this->m_ptr; 00386 this->m_ptr = rhs.m_ptr; 00387 rhs.m_ptr = x; 00388 } 00389 }; 00390 00391 00392 /** 00393 Deserializes target from src using the default API marshaling 00394 mechanism. Returns true on success. 00395 00396 On error it returns false or passes on an exception. In 00397 either case, target might be in an undefined state, and may 00398 need manual interaction to free up resources (e.g., a list 00399 of pointers might have some pointers which need to be 00400 cleaned up during exception handling). The exact definition 00401 of its state after a failure is specified by the algorithm 00402 which deserializes the target (as defined via 00403 s11n_traits<DeserializableT>::deserialize_functor). 00404 */ 00405 template <typename DataNodeType, typename DeserializableT> 00406 bool deserialize( const DataNodeType & src, DeserializableT & target ); 00407 00408 00409 /** 00410 Like the standard form of deserialize(), but if passed a 00411 null pointer, it attempts to classload the class and assign 00412 the passed-in pointer to it. If passed a non-null target 00413 then it behaves as if target were a reference, simply 00414 passing on the target after dereferencing it. 00415 00416 For example: 00417 00418 <pre> 00419 T * t = 0; 00420 deserialize<NodeType,T>( mynode, t ); 00421 // t will be non-0 if it worked. 00422 00423 T * x = new X; 00424 if( deserialize<NodeType,T>( mynode, x ) ) 00425 { 00426 // x is now populated exactly as if we had called: 00427 // deserialize<NodeType,T>( mynode, *x ); 00428 } 00429 </pre> 00430 00431 To get the class name, the algorithm first tries 00432 node_traits<DataNodeType>::class_name(src). If it cannot 00433 load a class using that name, it tries 00434 s11n_traits<DeserializableT>::class_name(target). 00435 00436 Underlying calls to s11n::cl::classload() and serialization 00437 proxies may throw. If they do, the exception is passed on 00438 to the caller. 00439 00440 If passed a null pointer and this function fails, target is 00441 not modified. If deserialization fails, any 00442 internally-created (DeserializableT*) is deallocated using 00443 cleanup_serializable(). If passed a non-null pointer and 00444 the function fails, behaviour is as for the non-pointer 00445 variant of deserialize() - target may or may not be in a 00446 defined state, as defined by the specific proxy algorithm. 00447 00448 00449 Added in s11n version 1.1.3. 00450 00451 */ 00452 template <typename DataNodeType, typename DeserializableT> 00453 bool deserialize( const DataNodeType & src, DeserializableT * & target ); 00454 00455 /** 00456 Identical to deserialize(const 00457 DataNodeType&,DeserializableT*&) except that it works on a 00458 cleanup_ptr<>. The target may be empty (pointing to zero): 00459 if it is then dynamic loading is attempted, as described 00460 in the docs for the non-cleanup_ptr variant of this 00461 function. 00462 00463 Returns true if target.get() is non-0 at the time this 00464 function exits (regardless of its value at entry time). 00465 */ 00466 template <typename DataNodeType, typename DeserializableT> 00467 bool deserialize( const DataNodeType & src, cleanup_ptr<DeserializableT> & target ); 00468 00469 /** 00470 Tries to deserialize a DeserializableT from src, using 00471 <code>s11n_traits<DeserializableT>::factory_type()(node_traits<DataNodeType>::class_name(src))</code> 00472 to create a new DeserializableT. 00473 00474 DeserializableT may not be a pointer-qualified type. 00475 00476 On error it returns 0 or propagates on an exception, 00477 otherwise returns a pointer to a new object, which the 00478 caller takes ownership of. 00479 00480 As of 1.1.3, this function relies on 00481 s11n::cleanup_serializable() in order to be able to specify 00482 what happens to the internally allocated object if 00483 deserialization fails. That function is called on the 00484 object before this function returns if deserialization 00485 fails. 00486 00487 Prior to 1.1.3 this function would leak if this function 00488 failed and if DeserializableT contained unmanaged pointers 00489 (even indirectly, via sub-containment), such as in 00490 list<int*> or list<map<int,string*>>. 00491 */ 00492 template <typename DataNodeType, typename DeserializableT> 00493 DeserializableT * deserialize( const DataNodeType & src ); 00494 00495 00496 /** 00497 Clones an arbitrary SerializableType using its 00498 DataNodeType serialization implementation. 00499 00500 Returns a clone of tocp, or returns 0 on error. 00501 The caller owns the returned pointer. 00502 00503 This copy is polymorphism-safe as long as all participating 00504 Serializables (re)implement the appropriate de/serialize 00505 operations, similarly to as they would do for a copy ctor 00506 or classical Clone() member function. 00507 00508 Tip: s11n_clone() is a convenient way to test new 00509 de/serialize functions, e.g., for new Serializables, 00510 because if it works then deserializing from streams/files 00511 will also work. This function takes SerializableType 00512 through the whole de/serialize process except for i/o, 00513 including classloading. 00514 00515 This function was renamed from clone() in version 1.1. 00516 00517 Exceptions and errors: 00518 00519 This function may return 0 or throw on an error, as 00520 dictated by serialize() and then deserialize() (in that 00521 order). Thus safety guarantees are defined in terms 00522 of those operations. 00523 */ 00524 template <typename DataNodeType, typename SerializableType> 00525 SerializableType * s11n_clone( const SerializableType & tocp ); 00526 00527 /** 00528 "Casts" t1 to t2 using serialization. This will work 00529 whenever t1 and t2 are "semantically compatible", whatever 00530 that really means. It can be used, e.g., to copy a 00531 list<int> to a vector<double>, provided both 00532 types have been proxied. In practice, this means: if Type1 00533 and Type2 both use the same, or compatible, de/ser 00534 algorithms, they are s11n_cast-able to one another. 00535 00536 Note that in the case of containers, the pointerness of the 00537 contained types is irrelevant: this works on both, thus 00538 a list<int> can be "cast" to a vector<double*>. 00539 00540 As usual for a failed deserialization, if it returns false 00541 then t2 may be in an undefined state. There is no guaranty, 00542 however, that t2's deserialize operator will ever be 00543 called, as the serialization of t1 must first succeed 00544 for that to happen. 00545 00546 Type2 may not currently be a pointer type, but Type1 may 00547 be. This will be fixed someday (when someone complains). 00548 00549 Exceptions and errors: 00550 00551 On error this function will return false or propagate 00552 an exception, as dictated by serialize() and then 00553 deserialize() (in that order). 00554 00555 If Type1 and Type2 are not guaranteed to be monomorphic or 00556 base-most Serializable types, then it is good practice to 00557 explicitely specify them as templatized parameters, and not 00558 rely on implicit type selection, which might choose the 00559 wrong type (not the base-most one, which is what s11n is 00560 "keyed" to), which will mean that s11n "can't find" the 00561 registration code for the type. 00562 */ 00563 template <typename NodeType, typename Type1, typename Type2> 00564 bool s11n_cast( const Type1 & t1, Type2 & t2 ); 00565 00566 00567 } // namespace s11n 00568 00569 #include <s11n.net/s11n/serialize.tpp> // implementations for above-declared code 00570 00571 00572 #endif // s11n_SERIALIZE_HPP_INCLUDED