1 #ifndef s11n_SERIALIZE_HPP_INCLUDED
2 #define s11n_SERIALIZE_HPP_INCLUDED
3 ////////////////////////////////////////////////////////////////////////
4 // serialize.hpp:
5 //
6 // Defines the core de/serialize() functions (and close friends).
7 //
8 // License: Public Domain
9 // Author: stephan@s11n.net
10 ////////////////////////////////////////////////////////////////////////
11 
12 #include <stdexcept>
13 
14 
15 ////////////////////////////////////////////////////////////////////////////////
16 // NO DEPS ON s11n_node.hpp ALLOWED!
17 ////////////////////////////////////////////////////////////////////////////////
18 
19 namespace s11n {
20 
21 
22 	namespace Detail {
23 		/***
24 		    s11n_api_marshaler is the internal API marshaller
25 		    for s11n.  See the lib manual for full
26 		    details. Client code is not expected to use or
27 		    specialize this class, but theoretically some
28 		    cases may call for doing so. In s11n versions
29 		    prior to 1.0.x, specializing this type was
30 		    sometimes useful for handling client-side
31 		    template types, but this is no longer necessary
32 		    nor encouraged.
33 
34 		    In the default implementation, s11n_traits<NodeT,SerializableT>
35 		    is used to marshal the de/serialize() calls.
36 
37 		    Changed in 1.1.3:
38 
39 		    - NodeType template param was moved from the static
40 		    functions to the class.
41 
42 		    - Moved class from anonymous namespace into s11n::Detail.
43 		*/
44 		template <typename NodeType,typename SerializableT>
45 		struct s11n_api_marshaler
46 		{
47 			/**
48 			   Same as SerializableT.
49 			*/
50 			typedef SerializableT serializable_type;
51 
52 			typedef NodeType node_type;
53 
54 			/**
55 			   Returns s11n_traits<serializable_type>::serialize_functor()( dest, src ).
56 
57 			   This implementation sets dest's class name to
58 			   s11n_traits<SerializableT>::class_name(&src), which
59 			   is only guaranteed to work properly for monomorphic
60 			   types and base-most types of Serialization
61 			   hierarchies (i.e., the registered
62 			   bases). Polymorphic Serializable subtypes should
63 			   set this class name themselves, or via their
64 			   s11n_traits::class_name() specialization, both
65 			   described in the library manual.
66 
67 			*/
68 			static bool serialize( node_type &dest, const serializable_type & src );
69 
70 			/**
71 			   Returns s11n_traits<SerializableT>::deserialize_functor()(src,dest).
72 			*/
73 			static bool deserialize( const node_type & src, serializable_type & dest );
74 		};
75 
76 		/**
77 		   A specialization to handle pointer types the same as
78 		   reference/value types. It simply translates the pointers
79 		   into references.
80 		*/
81 		template <typename NodeType,typename SerializableT>
82 		struct s11n_api_marshaler<NodeType,SerializableT *>
83 		{
84 			/**
85 			   The SerializableT templatized type, minus any
86 			   pointer part.
87 			*/
88 			typedef SerializableT serializable_type;
89 
90 			typedef NodeType node_type;
91 
92 			/**
93 			   Convenience typedef: this class' quasi-parent type.
94 			*/
95 			typedef s11n_api_marshaler<node_type,serializable_type> parent_type;
96 
97 			/**
98 			   Returns parent_type::serialize( dest, *src );
99 
100 			   src must be a valid pointer, else false is returned.
101 			*/
102 			static bool serialize( node_type &dest, const serializable_type * const & src );
103 
104 			/**
105 			   Returns parent_type::deserialize( src, *dest );
106 
107 			   dest must be a valid pointer, else false is returned.
108 
109 			   Reminder to self: if we dupe the code from
110 			   deserialize(const N&,ST *&), we could
111 			   potentially provide support for passing a
112 			   reference to a null pointer here. No need,
113 			   though, since the public s11n API already
114 			   provides that.
115 			*/
116 			static bool deserialize( const node_type & src, serializable_type * & dest );
117 		};
118 	} // namespace Detail
119 
120 
121         /**
122            Serializes src to target using the default API marshaling
123            mechanism.
124 
125 	   On success it always returns true, else false.
126 
127 	   If a the underlying operation throws, it will pass on the
128 	   exception.
129         */
130         template <typename DataNodeType, typename SerializableT>
131         bool serialize( DataNodeType & target, const SerializableT & src );
132 
133 	/**
134 	   Calls s11n_traits<SerializableType>::cleanup_functor()(s).
135 
136 	   This function is declared as no-throw because of its
137 	   logical role in the destruction process, and dtors are
138 	   normally prohibited from throwing. Any exceptions caught by
139 	   this function are silently ignored (a warning might go out
140 	   to a debug channel, probably cerr, but don't rely on it).
141 
142 	   SerializableType requirements:
143 
144 	   - Must be a Serializable. Specifically, it must have an
145 	   s11n_traits specialization installed.
146 
147 	   - s11n_traits<SerializableType>::cleanup_functor must be
148 	   known to work properly for SerializableType. This is core
149 	   to the whole cleanup functionality, which is core to
150 	   protecting against leaks in the face of errors.
151 
152 	   Technically, if the type can be delete()d without leaking
153 	   pointers, it's safe for use with this function, but this
154 	   function SHOULD NOT be used as general cleanup tool. It is
155 	   ONLY intended to be used with REGISTERED Serializables.
156 
157 	   This function guarantees not to leak when "cleaning up"
158 	   containers holding unmanaged pointers as long as the
159 	   associated cleanup_functors do their part. The model is
160 	   such that once a cleanup_functor is in place for a given
161 	   type, this function will inherently walk it and invoke the
162 	   cleanup rules, which includes freeing any pointers along
163 	   the way.
164 
165 	   Added in 1.1.3.
166 	*/
167 	template <typename SerializableType>
168 	void cleanup_serializable( SerializableType & s ) throw();
169 
170 	/**
171 	   This overload provides cleanup handling for pointer
172 	   types. This simplifies many algorithms over using
173 	   s11n_traits<SerializableType>::cleanup_functor directly, as
174 	   the algorithms do not need to care if they're using
175 	   pointer-qualified types or not in order to clean them up
176 	   properly.
177 
178 	   SerializableType requirements are as for the non-pointered
179 	   variant of this function, plus:
180 
181 	   - delete aSerializableTypeInstance; must be well-formed and
182 	   must neither throw nor invoke undefined behaviour.  (Did
183 	   you realize that "neither" is an exception to English's
184 	   "i-before-e" rule?)
185 
186 	   This function does nothing if s is null, otherwise it calls
187 	   cleanup_serializable(*s), deletes s, then assigns it to 0.
188 
189 	   Postcondition: (0 == s)
190 
191 	   Added in 1.1.3.
192 	*/
193 	template <typename SerializableType>
194 	void cleanup_serializable( SerializableType * & s ) throw();
195 
196 
197         /**
198 	   Intended for use with for_each(), this type cleans up
199 	   Serializables using cleanup_serializable().
200 
201 	   Usage:
202 
203 	   std::for_each( container.begin(), container.end(), cleaner_upper() );
204 
205 	   where the container is parameterized to hold Serializables.
206 
207 	   Provided that the contained type(s) conform to
208 	   cleanup_ptr's requirements, this will recursively clean up
209 	   sub-sub-...subcontainers.
210 
211 	   Note that Serializable containers should have a cleanup
212 	   functor installed as part of their registration, making
213 	   this class unnecessary for most cases: simply calling
214 	   cleanup_serializable() will recursively walk/clean such
215 	   containers. The underlying cleanup algos might use this
216 	   type, however (at least one of them does).
217 
218 	   Added in 1.1.3.
219 	 */
220         struct cleaner_upper
221         {
222                 /**
223                    Calls cleanup_serializable<T>(t)
224                 */
225                 template <typename T>
operator ()s11n::cleaner_upper226                 void operator()( T & t ) throw()
227                 {
228                         cleanup_serializable<T>( t );
229                 }
230                 /**
231                    Calls cleanup_serializable<T>(t).
232                 */
233                 template <typename T>
operator ()s11n::cleaner_upper234                 void operator()( T * & t ) throw()
235                 {
236                         cleanup_serializable<T>( t );
237                 }
238         };
239 
240 
241 	/**
242 	   An auto_ptr-like type intended to simplify
243 	   pointer/exception safety in some deserialization algorithms
244 	   by providing a way to completely and safely destroy
245 	   partially-deserialized objects.
246 
247 	   SerializableT must either have an explicit s11n_traits
248 	   specialization installed or work properly with the default
249 	   functor provided by s11n_traits::cleanup_functor.  In
250 	   practice, this means that types which manage the memory of
251 	   their contained pointers are safe to work with the default,
252 	   whereas the cleanup of unmanaged child pointers (e.g., std
253 	   containers) requires a proper specialization.
254 
255 	   Note that this type does not have copy/assignment ctors,
256 	   due to the conventional constness of their right-hand
257 	   sides: use the swap() or take() members to take over a
258 	   pointer.
259 
260 	   Added in 1.1.3.
261 	*/
262 	template <typename SerializableT>
263 	struct cleanup_ptr
264 	{
265 	public:
266 		typedef SerializableT cleaned_type;
267 	private:
268 		cleaned_type * m_ptr;
269 		cleanup_ptr & operator=( const cleanup_ptr & ); // Not Implemented
270 		cleanup_ptr( const cleanup_ptr & ); // Not Implemented
cleanups11n::cleanup_ptr271 		void cleanup() throw()
272 		{
273 			if( this->m_ptr )
274 			{
275 				cleanup_serializable<cleaned_type>( this->m_ptr );
276 			}
277 		}
278 	public:
279 		/**
280 		   Constructs an object pointing to nothing.
281 		*/
cleanup_ptrs11n::cleanup_ptr282 		cleanup_ptr() throw() : m_ptr(0)
283 		{
284 		}
285 		/**
286 		   Transfers ownership of p to this object.
287 		 */
cleanup_ptrs11n::cleanup_ptr288 		cleanup_ptr( cleaned_type * p ) throw() : m_ptr(p)
289 		{
290 		}
291 
292 		/**
293 		   Uses s11n::cleanup_serializable<cleaned_type>()
294 		   to free up up this->get().
295 		*/
~cleanup_ptrs11n::cleanup_ptr296 		~cleanup_ptr() throw()
297 		{
298 			this->cleanup();
299 		}
300 		/**
301 		   Dereferences this object's pointed-to object.  If
302 		   this object does not point to anything it throws a
303 		   std::runtime_error with an informative what()
304 		   message explaining the error.
305 		 */
operator *s11n::cleanup_ptr306 		cleaned_type & operator*()
307 		{
308 			if( ! this->m_ptr )
309 			{
310 				throw std::runtime_error("Attempt to dereference a null pointer via s11n::cleanup_ptr<>::operator*()" );
311 			}
312 			return *this->m_ptr;
313 		}
314 
315 		/**
316 		   Returns the same as get().
317 		*/
operator ->s11n::cleanup_ptr318 		cleaned_type * operator->() throw()
319 		{
320 			return this->m_ptr;
321 		}
322 
323 		/**
324 		   Returns this object's pointed-to object without
325 		   transfering ownership.
326 		*/
gets11n::cleanup_ptr327 		cleaned_type * get() throw()
328 		{
329 			return this->m_ptr;
330 		}
331 
332 		/**
333 		   Transfers ownership of p to this object. This
334 		   member takes the place of copy/assign operators,
335 		   since those conventionally take a const right-hand
336 		   argument.
337 
338 		   Destroys the object this object pointed to before
339 		   taking over ownership. 0 is a legal value for p.
340 
341 		   If (p == this->get()) then this function does
342 		   nothing.
343 
344 		   Postcondition: p == this->get()
345 		*/
takes11n::cleanup_ptr346 		void take( cleaned_type * p ) throw()
347 		{
348 			if( p != this->m_ptr )
349 			{
350 				this->cleanup();
351 				this->m_ptr = p;
352 			}
353 		}
354 
355 		/**
356 		   Transfers ownership of this->get() to the
357 		   caller.
358 
359 		   Postcondition: 0 == this->get()
360 		*/
releases11n::cleanup_ptr361 		cleaned_type * release() throw()
362 		{
363 			cleaned_type * x = this->m_ptr;
364 			this->m_ptr = 0;
365 			return x;
366 		}
367 
368 		/**
369 		   Cleans up any pointed-to object and points this
370 		   object at 0. Does nothing if this object points
371 		   to no object.
372 
373 		   Postcondition: 0 == this->get()
374 		*/
cleans11n::cleanup_ptr375 		void clean() throw()
376 		{
377 			this->take( 0 );
378 		}
379 
380 		/**
381 		   Swaps ownership of pointers with rhs.
382 		*/
swaps11n::cleanup_ptr383 		void swap( cleanup_ptr & rhs ) throw()
384 		{
385 			cleaned_type * x = this->m_ptr;
386 			this->m_ptr = rhs.m_ptr;
387 			rhs.m_ptr = x;
388 		}
389 	};
390 
391 
392         /**
393            Deserializes target from src using the default API marshaling
394            mechanism. Returns true on success.
395 
396 	   On error it returns false or passes on an exception. In
397 	   either case, target might be in an undefined state, and may
398 	   need manual interaction to free up resources (e.g., a list
399 	   of pointers might have some pointers which need to be
400 	   cleaned up during exception handling). The exact definition
401 	   of its state after a failure is specified by the algorithm
402 	   which deserializes the target (as defined via
403 	   s11n_traits<DeserializableT>::deserialize_functor).
404         */
405         template <typename DataNodeType, typename DeserializableT>
406         bool deserialize( const DataNodeType & src, DeserializableT & target );
407 
408 
409 	/**
410 	   Like the standard form of deserialize(), but if passed a
411 	   null pointer, it attempts to classload the class and assign
412 	   the passed-in pointer to it. If passed a non-null target
413 	   then it behaves as if target were a reference, simply
414 	   passing on the target after dereferencing it.
415 
416 	   For example:
417 
418 <pre>
419 T * t = 0;
420 deserialize<NodeType,T>( mynode, t );
421 // t will be non-0 if it worked.
422 
423 T * x = new X;
424 if( deserialize<NodeType,T>( mynode, x ) )
425 {
426   // x is now populated exactly as if we had called:
427   // deserialize<NodeType,T>( mynode, *x );
428 }
429 </pre>
430 
431            To get the class name, the algorithm first tries
432            node_traits<DataNodeType>::class_name(src). If it cannot
433            load a class using that name, it tries
434            s11n_traits<DeserializableT>::class_name(target).
435 
436            Underlying calls to s11n::cl::classload() and serialization
437            proxies may throw. If they do, the exception is passed on
438 	   to the caller.
439 
440 	   If passed a null pointer and this function fails, target is
441 	   not modified. If deserialization fails, any
442 	   internally-created (DeserializableT*) is deallocated using
443 	   cleanup_serializable(). If passed a non-null pointer and
444 	   the function fails, behaviour is as for the non-pointer
445 	   variant of deserialize() - target may or may not be in a
446 	   defined state, as defined by the specific proxy algorithm.
447 
448 
449 	   Added in s11n version 1.1.3.
450 
451 	*/
452         template <typename DataNodeType, typename DeserializableT>
453 	bool deserialize( const DataNodeType & src, DeserializableT * & target );
454 
455 	/**
456 	   Identical to deserialize(const
457 	   DataNodeType&,DeserializableT*&) except that it works on a
458 	   cleanup_ptr<>. The target may be empty (pointing to zero):
459 	   if it is then dynamic loading is attempted, as described
460 	   in the docs for the non-cleanup_ptr variant of this
461 	   function.
462 
463 	   Returns true if deserialization to the target succeeds,
464 	   else false.  If it returns false, target.get() still points
465 	   to the same object it did when function was called (which
466 	   may be 0). Whether or not the contained object is modified
467 	   on deserialization failure depends on the underlying
468 	   algorithm used to deserialize it.
469 	*/
470         template <typename DataNodeType, typename DeserializableT>
471 	bool deserialize( const DataNodeType & src, cleanup_ptr<DeserializableT> & target );
472 
473         /**
474            Tries to deserialize a DeserializableT from src, using
475            <code>s11n_traits<DeserializableT>::factory_type()(node_traits<DataNodeType>::class_name(src))</code>
476            to create a new DeserializableT.
477 
478 	   DeserializableT may not be a pointer-qualified type.
479 
480 	   On error it returns 0 or propagates on an exception,
481 	   otherwise returns a pointer to a new object, which the
482 	   caller takes ownership of.
483 
484 	   As of 1.1.3, this function relies on
485 	   s11n::cleanup_serializable() in order to be able to specify
486 	   what happens to the internally allocated object if
487 	   deserialization fails. That function is called on the
488 	   object before this function returns if deserialization
489 	   fails.
490 
491 	   Prior to 1.1.3 this function would leak if this function
492 	   failed and if DeserializableT contained unmanaged pointers
493 	   (even indirectly, via sub-containment), such as in
494 	   list<int*> or list<map<int,string*>>.
495         */
496         template <typename DataNodeType, typename DeserializableT>
497         DeserializableT * deserialize( const DataNodeType & src );
498 
499 
500         /**
501            Clones an arbitrary SerializableType using its
502            DataNodeType serialization implementation.
503 
504            Returns a clone of tocp, or returns 0 on error.
505            The caller owns the returned pointer.
506 
507            This copy is polymorphism-safe as long as all participating
508            Serializables (re)implement the appropriate de/serialize
509            operations, similarly to as they would do for a copy ctor
510            or classical Clone() member function.
511 
512            Tip: s11n_clone() is a convenient way to test new
513            de/serialize functions, e.g., for new Serializables,
514            because if it works then deserializing from streams/files
515            will also work. This function takes SerializableType
516            through the whole de/serialize process except for i/o,
517            including classloading.
518 
519 	   This function was renamed from clone() in version 1.1.
520 
521 	   Exceptions and errors:
522 
523 	   This function may return 0 or throw on an error, as
524 	   dictated by serialize() and then deserialize() (in that
525 	   order). Thus safety guarantees are defined in terms
526 	   of those operations.
527         */
528         template <typename DataNodeType, typename SerializableType>
529         SerializableType * s11n_clone( const SerializableType & tocp );
530 
531         /**
532            "Casts" t1 to t2 using serialization. This will work
533            whenever t1 and t2 are "semantically compatible", whatever
534            that really means. It can be used, e.g., to copy a
535            list<int> to a vector<double>, provided both
536            types have been proxied. In practice, this means: if Type1
537            and Type2 both use the same, or compatible, de/ser
538            algorithms, they are s11n_cast-able to one another.
539 
540            Note that in the case of containers, the pointerness of the
541            contained types is irrelevant: this works on both, thus
542            a list<int> can be "cast" to a vector<double*>.
543 
544            As usual for a failed deserialization, if it returns false
545            then t2 may be in an undefined state. There is no guaranty,
546            however, that t2's deserialize operator will ever be
547            called, as the serialization of t1 must first succeed
548            for that to happen.
549 
550 	   Type2 may not currently be a pointer type, but Type1 may
551 	   be. This will be fixed someday (when someone complains).
552 
553 	   Exceptions and errors:
554 
555 	   On error this function will return false or propagate
556 	   an exception, as dictated by serialize() and then
557 	   deserialize() (in that order).
558 
559 	   If Type1 and Type2 are not guaranteed to be monomorphic or
560 	   base-most Serializable types, then it is good practice to
561 	   explicitely specify them as templatized parameters, and not
562 	   rely on implicit type selection, which might choose the
563 	   wrong type (not the base-most one, which is what s11n is
564 	   "keyed" to), which will mean that s11n "can't find" the
565 	   registration code for the type.
566         */
567         template <typename NodeType, typename Type1, typename Type2>
568         bool s11n_cast( const Type1 & t1, Type2 & t2 );
569 
570 
571 } // namespace s11n
572 
573 #include <s11n.net/s11n/serialize.tpp> // implementations for above-declared code
574 
575 
576 #endif // s11n_SERIALIZE_HPP_INCLUDED
577