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