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 #include <s11n.net/s11n/exception.hpp> // s11n_exception 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 /** Same as the NodeType template parameter. */ 00053 typedef NodeType node_type; 00054 00055 /** 00056 Returns s11n_traits<serializable_type>::serialize_functor()( dest, src ). 00057 00058 This implementation sets dest's class name to 00059 s11n_traits<SerializableT>::class_name(&src), which 00060 is only guaranteed to work properly for monomorphic 00061 types and base-most types of Serialization 00062 hierarchies (i.e., the registered 00063 bases). Polymorphic Serializable subtypes should 00064 set this class name themselves, or via their 00065 s11n_traits::class_name() specialization, both 00066 described in the library manual. 00067 00068 */ 00069 static bool serialize( node_type &dest, const serializable_type & src ); 00070 00071 /** 00072 Returns s11n_traits<SerializableT>::deserialize_functor()(src,dest). 00073 */ 00074 static bool deserialize( const node_type & src, serializable_type & dest ); 00075 }; 00076 00077 /** 00078 A specialization to handle pointer types the same as 00079 reference/value types. It simply translates the pointers 00080 into references. 00081 */ 00082 template <typename NodeType,typename SerializableT> 00083 struct s11n_api_marshaler<NodeType,SerializableT *> 00084 { 00085 /** 00086 The SerializableT templatized type, minus any 00087 pointer part. 00088 */ 00089 typedef SerializableT serializable_type; 00090 00091 /** Same as the NodeType template parameter. */ 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 This type is usable as a Finalizer for 00223 s11n::refcount::rcptr, by the way. 00224 */ 00225 struct cleaner_upper 00226 { 00227 /** 00228 Calls cleanup_serializable<T>(t) 00229 */ 00230 template <typename T> 00231 void operator()( T & t ) throw() 00232 { 00233 cleanup_serializable<T>( t ); 00234 } 00235 /** 00236 Calls cleanup_serializable<T>(t). 00237 */ 00238 template <typename T> 00239 void operator()( T * & t ) throw() 00240 { 00241 cleanup_serializable<T>( t ); 00242 } 00243 }; 00244 00245 00246 /** 00247 An auto_ptr-like type intended to simplify 00248 pointer/exception safety in some deserialization algorithms 00249 by providing a way to completely and safely destroy 00250 partially-deserialized objects. 00251 00252 SerializableT must either have an explicit s11n_traits 00253 specialization installed or work properly with the default 00254 functor provided by s11n_traits::cleanup_functor. In 00255 practice, this means that types which manage the memory of 00256 their contained pointers are safe to work with the default, 00257 whereas the cleanup of unmanaged child pointers (e.g., std 00258 containers) requires a proper specialization. 00259 00260 Note that this type does not have copy/assignment ctors, 00261 due to the conventional constness of their right-hand 00262 sides: use the swap() or take() members to take over a 00263 pointer. 00264 00265 Added in 1.1.3. 00266 */ 00267 template <typename SerializableT> 00268 struct cleanup_ptr 00269 { 00270 public: 00271 typedef SerializableT cleaned_type; 00272 private: 00273 cleaned_type * m_ptr; 00274 cleanup_ptr & operator=( const cleanup_ptr & ); // Not Implemented 00275 cleanup_ptr( const cleanup_ptr & ); // Not Implemented 00276 void cleanup() throw() 00277 { 00278 if( this->m_ptr ) 00279 { 00280 cleanup_serializable<cleaned_type>( this->m_ptr ); 00281 } 00282 } 00283 public: 00284 /** 00285 Constructs an object pointing to nothing. 00286 */ 00287 cleanup_ptr() throw() : m_ptr(0) 00288 { 00289 } 00290 /** 00291 Transfers ownership of p to this object. 00292 */ 00293 cleanup_ptr( cleaned_type * p ) throw() : m_ptr(p) 00294 { 00295 } 00296 00297 /** 00298 Uses s11n::cleanup_serializable<cleaned_type>() 00299 to free up up this->get(). 00300 */ 00301 ~cleanup_ptr() throw() 00302 { 00303 this->cleanup(); 00304 } 00305 /** 00306 Dereferences this object's pointed-to object. If 00307 this object does not point to anything it throws a 00308 std::runtime_error with an informative what() 00309 message explaining the error. 00310 */ 00311 cleaned_type & operator*() 00312 { 00313 if( ! this->m_ptr ) 00314 { 00315 throw s11n_exception( S11N_SOURCEINFO, 00316 "Attempt to dereference a null pointer via s11n::cleanup_ptr<>::operator*()" ); 00317 } 00318 return *this->m_ptr; 00319 } 00320 00321 /** 00322 Returns the same as get(). 00323 */ 00324 cleaned_type * operator->() throw() 00325 { 00326 return this->m_ptr; 00327 } 00328 00329 /** 00330 Returns this object's pointed-to object without 00331 transfering ownership. 00332 */ 00333 cleaned_type * get() throw() 00334 { 00335 return this->m_ptr; 00336 } 00337 00338 /** 00339 Transfers ownership of p to this object. This 00340 member takes the place of copy/assign operators, 00341 since those conventionally take a const right-hand 00342 argument. 00343 00344 Destroys the object this object pointed to before 00345 taking over ownership. 0 is a legal value for p. 00346 00347 If (p == this->get()) then this function does 00348 nothing. 00349 00350 Postcondition: p == this->get() 00351 */ 00352 void take( cleaned_type * p ) throw() 00353 { 00354 if( p != this->m_ptr ) 00355 { 00356 this->cleanup(); 00357 this->m_ptr = p; 00358 } 00359 } 00360 00361 /** 00362 Transfers ownership of this->get() to the 00363 caller. 00364 00365 Postcondition: 0 == this->get() 00366 */ 00367 cleaned_type * release() throw() 00368 { 00369 cleaned_type * x = this->m_ptr; 00370 this->m_ptr = 0; 00371 return x; 00372 } 00373 00374 /** 00375 Cleans up any pointed-to object and points this 00376 object at 0. Does nothing if this object points 00377 to no object. 00378 00379 Postcondition: 0 == this->get() 00380 */ 00381 void clean() throw() 00382 { 00383 this->take( 0 ); 00384 } 00385 00386 /** 00387 Swaps ownership of pointers with rhs. 00388 */ 00389 void swap( cleanup_ptr & rhs ) throw() 00390 { 00391 cleaned_type * x = this->m_ptr; 00392 this->m_ptr = rhs.m_ptr; 00393 rhs.m_ptr = x; 00394 } 00395 00396 /** 00397 Returns the same as (!this->get()). 00398 */ 00399 bool empty() const throw() 00400 { 00401 return 0 == this->m_ptr; 00402 } 00403 }; 00404 00405 00406 /** 00407 Deserializes target from src using the default API marshaling 00408 mechanism. Returns true on success. 00409 00410 On error it returns false or passes on an exception. In 00411 either case, target might be in an undefined state, and may 00412 need manual interaction to free up resources (e.g., a list 00413 of pointers might have some pointers which need to be 00414 cleaned up during exception handling). The exact definition 00415 of its state after a failure is specified by the algorithm 00416 which deserializes the target (as defined via 00417 s11n_traits<DeserializableT>::deserialize_functor). 00418 */ 00419 template <typename DataNodeType, typename DeserializableT> 00420 bool deserialize( const DataNodeType & src, DeserializableT & target ); 00421 00422 00423 /** 00424 Like the standard form of deserialize(), but if passed a 00425 null pointer, it attempts to classload the class and assign 00426 the passed-in pointer to it. If passed a non-null target 00427 then it behaves as if target were a reference, simply 00428 passing on the target after dereferencing it. 00429 00430 For example: 00431 00432 <pre> 00433 T * t = 0; 00434 deserialize<NodeType,T>( mynode, t ); 00435 // t will be non-0 if it worked. 00436 00437 T * x = new X; 00438 if( deserialize<NodeType,T>( mynode, x ) ) 00439 { 00440 // x is now populated exactly as if we had called: 00441 // deserialize<NodeType,T>( mynode, *x ); 00442 } 00443 </pre> 00444 00445 To get the class name, the algorithm first tries 00446 node_traits<DataNodeType>::class_name(src). If it cannot 00447 load a class using that name, it tries 00448 s11n_traits<DeserializableT>::class_name(target). 00449 00450 Underlying calls to s11n::cl::classload() and serialization 00451 proxies may throw. If they do, the exception is passed on 00452 to the caller. 00453 00454 If passed a null pointer and this function fails, target is 00455 not modified. If deserialization fails, any 00456 internally-created (DeserializableT*) is deallocated using 00457 cleanup_serializable(). If passed a non-null pointer and 00458 the function fails, behaviour is as for the non-pointer 00459 variant of deserialize() - target may or may not be in a 00460 defined state, as defined by the specific proxy algorithm. 00461 00462 00463 Added in s11n version 1.1.3. 00464 00465 */ 00466 template <typename DataNodeType, typename DeserializableT> 00467 bool deserialize( const DataNodeType & src, DeserializableT * & target ); 00468 00469 /** 00470 Identical to deserialize(const 00471 DataNodeType&,DeserializableT*&) except that it works on a 00472 cleanup_ptr<>. The target may be empty (pointing to zero): 00473 if it is then dynamic loading is attempted, as described 00474 in the docs for the non-cleanup_ptr variant of this 00475 function. 00476 00477 Returns true if deserialization to the target succeeds, 00478 else false. If it returns false, target.get() still points 00479 to the same object it did when function was called (which 00480 may be 0). Whether or not the contained object is modified 00481 on deserialization failure depends on the underlying 00482 algorithm used to deserialize it. 00483 */ 00484 template <typename DataNodeType, typename DeserializableT> 00485 bool deserialize( const DataNodeType & src, cleanup_ptr<DeserializableT> & target ); 00486 00487 /** 00488 Tries to deserialize a DeserializableT from src, using 00489 <code>s11n_traits<DeserializableT>::factory_type()(node_traits<DataNodeType>::class_name(src))</code> 00490 to create a new DeserializableT. 00491 00492 DeserializableT may not be a pointer-qualified type. 00493 00494 On error it returns 0 or propagates on an exception, 00495 otherwise returns a pointer to a new object, which the 00496 caller takes ownership of. 00497 00498 As of 1.1.3, this function relies on 00499 s11n::cleanup_serializable() in order to be able to specify 00500 what happens to the internally allocated object if 00501 deserialization fails. That function is called on the 00502 object before this function returns if deserialization 00503 fails. 00504 00505 Prior to 1.1.3 this function would leak if this function 00506 failed and if DeserializableT contained unmanaged pointers 00507 (even indirectly, via sub-containment), such as in 00508 list<int*> or list<map<int,string*>>. 00509 */ 00510 template <typename DataNodeType, typename DeserializableT> 00511 DeserializableT * deserialize( const DataNodeType & src ); 00512 00513 00514 /** 00515 Clones an arbitrary SerializableType using its 00516 DataNodeType serialization implementation. 00517 00518 Returns a clone of tocp, or returns 0 on error. 00519 The caller owns the returned pointer. 00520 00521 This copy is polymorphism-safe as long as all participating 00522 Serializables (re)implement the appropriate de/serialize 00523 operations, similarly to as they would do for a copy ctor 00524 or classical Clone() member function. 00525 00526 Tip: s11n_clone() is a convenient way to test new 00527 de/serialize functions, e.g., for new Serializables, 00528 because if it works then deserializing from streams/files 00529 will also work. This function takes SerializableType 00530 through the whole de/serialize process except for i/o, 00531 including classloading. 00532 00533 This function was renamed from clone() in version 1.1. 00534 00535 Exceptions and errors: 00536 00537 This function may return 0 or throw on an error, as 00538 dictated by serialize() and then deserialize() (in that 00539 order). Thus safety guarantees are defined in terms 00540 of those operations. 00541 */ 00542 template <typename DataNodeType, typename SerializableType> 00543 SerializableType * s11n_clone( const SerializableType & tocp ); 00544 00545 /** 00546 "Casts" t1 to t2 using serialization. This will work 00547 whenever t1 and t2 are "semantically compatible", whatever 00548 that really means. It can be used, e.g., to copy a 00549 list<int> to a vector<double>, provided both 00550 types have been proxied. In practice, this means: if Type1 00551 and Type2 both use the same, or compatible, de/ser 00552 algorithms, they are s11n_cast-able to one another. 00553 00554 Note that in the case of containers, the pointerness of the 00555 contained types is irrelevant: this works on both, thus 00556 a list<int> can be "cast" to a vector<double*>. 00557 00558 As usual for a failed deserialization, if it returns false 00559 then t2 may be in an undefined state. There is no guaranty, 00560 however, that t2's deserialize operator will ever be 00561 called, as the serialization of t1 must first succeed 00562 for that to happen. 00563 00564 Type2 may not currently be a pointer type, but Type1 may 00565 be. This will be fixed someday (when someone complains). 00566 00567 Exceptions and errors: 00568 00569 On error this function will return false or propagate 00570 an exception, as dictated by serialize() and then 00571 deserialize() (in that order). 00572 00573 If Type1 and Type2 are not guaranteed to be monomorphic or 00574 base-most Serializable types, then it is good practice to 00575 explicitely specify them as templatized parameters, and not 00576 rely on implicit type selection, which might choose the 00577 wrong type (not the base-most one, which is what s11n is 00578 "keyed" to), which will mean that s11n "can't find" the 00579 registration code for the type. What that means is, if t1 00580 or t2 may be polymorphic types, then it is best to 00581 explicitly specify their base-most s11n-registered common 00582 ancestor as the template parameters for Type1 and/or Type2. 00583 e.g.: 00584 00585 \code 00586 BaseT * lhs = new SubT; 00587 ... populate lhs ... 00588 BaseT * rhs = new SubT; 00589 s11n_cast<s11n_node,BaseT,BaseT>( *lhs, *rhs ); 00590 \endcode 00591 00592 */ 00593 template <typename NodeType, typename Type1, typename Type2> 00594 bool s11n_cast( const Type1 & t1, Type2 & t2 ); 00595 00596 00597 } // namespace s11n 00598 00599 #include <s11n.net/s11n/serialize.tpp> // implementations for above-declared code 00600 00601 00602 #endif // s11n_SERIALIZE_HPP_INCLUDED