Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / serialization / doc / archive_reference.html
1 <!doctype HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2 <html>
3 <!--
4 (C) Copyright 2002-10 Robert Ramey - http://www.rrsd.com . 
5 Use, modification and distribution is subject to the Boost Software
6 License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 http://www.boost.org/LICENSE_1_0.txt)
8 -->
9 <head>
10 <meta http-equiv="Content-Type" content="text/html; UTF-8">
11 <link rel="stylesheet" type="text/css" href="../../../boost.css">
12 <link rel="stylesheet" type="text/css" href="style.css">
13 <title>Serialization - More on Archives</title>
14 </head>
15 <body link="#0000ff" vlink="#800080">
16 <table border="0" cellpadding="7" cellspacing="0" width="100%" summary="header">
17   <tr> 
18     <td valign="top" width="300"> 
19       <h3><a href="../../../index.htm"><img height="86" width="277" alt="C++ Boost" src="../../../boost.png" border="0"></a></h3>
20     </td>
21     <td valign="top"> 
22       <h1 align="center">Serialization</h1>
23       <h2 align="center">Archive Class Reference</h2>
24     </td>
25   </tr>
26 </table>
27 <hr>
28 <dl class="page-index">
29   <dt><a href="#trivial">Trivial Archive</a>
30   <dt><a href="#implementation">More Useful Archive Classes</a>
31   <dt><a href="#usage">Usage</a>
32   <dt><a href="#testing">Testing</a>
33   <dt><a href="#polymorphic">Polymorphic Archives</a>
34 </dl>
35
36 <h3><a name="trivial">Trivial Archive</a></h3>
37 The <a href="archives.html"><strong>Archive</strong></a> concept specifies the functions that a
38 class must implement in order to be used to serialize 
39 <a href="serialization.html"><strong>Serializable</strong></a> types.
40
41 Our discussion will focus on archives used for saving as the hierarchy is exactly analogous
42 for archives used for loading data.
43
44 <h4>Minimum Requirments</h4>
45
46 The simplest class which will model the <a href="archives.html"><strong>Archive</strong></a> concept specifies the functions that a
47 class will look like:
48
49 <pre><code>
50 #include &lt;cstddef&gt; // std::size_t
51 //////////////////////////////////////////////////////////////
52 // class trivial_oarchive
53 class trivial_oarchive {
54 public:
55     //////////////////////////////////////////////////////////
56     // public interface used by programs that use the
57     // serialization library
58     typedef boost::mpl::bool_&lt;true&gt; is_saving; 
59     typedef boost::mpl::bool_&lt;false&gt; is_loading;
60     template&lt;class T&gt; void register_type(){}
61     template&lt;class T&gt; trivial_oarchive & operator&lt;&lt;(const T & t){
62         return *this;
63     }
64     template&lt;class T&gt; trivial_oarchive & operator&(const T & t){
65         return *this &lt;&lt; t;
66     }
67     void save_binary(void *address, std::size_t count){};
68 };
69 </code></pre>
70 The simplest possible input archive class is analogous to the above.
71 In the following discussion, only output archives will be addressed.
72 Input archives are exactly symmetrical to output archives.
73 <p>
74 This archive will compile and execute with any types which implement the
75 <a href="serialization.html"><strong>Serializable</strong></a> concept.
76 For an example see
77 <a href="../example/demo_trivial_archive.cpp" target="demo_trivial_archive">
78 <code style="white-space: normal">demo_trivial_archive.cpp</code></a>.
79 Of course this program won't produce any output as it is.  But it provides
80 the starting point for a simple class which can be used to log formatted
81 output.  See the implementation of a <a href="simple_log.html">simple
82 log archive</a> to how this has been done.
83
84 <h3><a name="implementation">More Useful Archive Classes</a></h3>
85 The above example is fine as far as it goes.  But it doesn't implement
86 useful features such as serialization of pointers, class versioning
87 and others. This library implements a family of full featured archive
88 classes appropriate for a variety of purposes.  
89
90 <p>
91 Our archives have been factored into a tree of classes in order to minimize
92 repetition of code.  This is shown in the accompanying 
93 <a target="class_diagram" href="class_diagram.html">class diagram</a>.
94
95 Any class which fulfills the following requirements will fit into
96 this hierarchy and implement all the features we require.  Deriving from
97 the base class <a href="../../../boost/archive/detail/common_oarchive.hpp" target="common_oarchive_hpp">
98 common_oarchive.hpp</a> provides all features we desire which
99 are missing from trivial_oarchive above.
100
101 <pre><code>
102 <a href="../../../boost/archive/detail/common_oarchive.hpp" target="common_oarchive_hpp">
103 #include &lt;cstddef&gt; // std::size_t
104 #include &lt;boost/archive/detail/common_oarchive.hpp&gt;
105 </a>
106 /////////////////////////////////////////////////////////////////////////
107 // class complete_oarchive
108 class complete_oarchive : 
109     public boost::archive::detail::common_oarchive&lt;complete_oarchive&gt;
110 {
111     // permit serialization system privileged access to permit
112     // implementation of inline templates for maximum speed.
113     friend class boost::archive::save_access;
114
115     // member template for saving primitive types.
116     // Specialize for any types/templates that require special treatment
117     template&lt;class T&gt;
118     void save(T &amp; t);
119
120 public:
121     //////////////////////////////////////////////////////////
122     // public interface used by programs that use the
123     // serialization library
124
125     // archives are expected to support this function
126     void save_binary(void *address, std::size_t count);
127 };
128 </code></pre>
129
130 Given a suitable definitions of <code style="white-space: normal">save</code>
131 and <code style="white-space: normal">save_binary</code>, 
132 any program using serialization with a conforming C++ compiler should compile 
133 and run with this archive class.
134
135 <h4>Optional Overrides</h4>
136
137 The <code style="white-space: normal">detail::common_oarchive</code> class contains
138 a number of functions that are used by various parts of the serialization library
139 to help render the archive in a particular form.
140
141 <dl>
142
143 <dt><h4><code>void save_start(char const *)</code></h4></dt>
144 <dd>
145 <strong>Default</strong>:Does nothing.<br>
146 <strong>Purpose</strong>:To inject/retrieve an object name into the archive.  Used
147 by XML archive to inject "&lt;name&gt;" before data.
148 </dd>
149 <p>
150
151 <dt><h4><code>void save_end(char const *)</code></h4></dt>
152 <dd>
153 <strong>Default</strong>:Does nothing.<br>
154 <strong>Purpose</strong>:To inject/retrieve an object name into the archive. Used
155 by XML archive to inject "&lt;/name&gt;" after data.
156 <dd>
157 </dd>
158 <p>
159 <dt><h4><code>void end_preamble()</code></h4></dt>
160 <dd>
161 <strong>Default</strong>:Does nothing.<br>
162 <strong>Purpose</strong>:Called <strong>each time</strong> user data is saved. 
163 It's not called when archive bookkeeping data is saved.  This is used by XML archives 
164 to determine  when to inject a "&gt;" character at the end of an XML header. XML output archives 
165 keep their own internal flag indicating that data being written is header data. This
166 internal flag is reset when an object start tag is written. When 
167 <code style="white-space: normal">void end_preamble()</code> is invoked and this internal flag is set
168 a "&gt;" character is appended to the output and the internal flag is reset. The default
169 implementation for <code style="white-space: normal">void end_preamble()</code> is a no-op thereby permitting it
170 to be optimised away for archive classes that don't use it.
171 </dd>
172 <p>
173 <dt><h4><code>
174 template&lt;class T&gt;
175 void save_override(T & t, int);
176 </code></h4></dt>
177 <dd>
178 <strong>Default</strong>:Invokes <code style="white-space: normal">archive::save(Archive & ar, t)</code><br>
179 This is the main entry into the serialization library.<br>
180 <strong>Purpose</strong>:This can be specialized in cases where the data is to be written 
181 to the archive in some special way.  For example, XML archives implement special handling for
182 name-value pairs by overriding this function template for name-value pairs.  
183 This replaces the default name-value pair handling, which is just to throw away the name,
184 with one appropriate for XML which writes out the start of an XML tag with the correct object name.
185 </dd>
186
187 </dl>
188
189 <h4>Types used by the serialization library</h4>
190 The serialization library injects bookkeeping data into the serialization archive.
191 This data includes things like object ids, version numbers, class names etc.  Each
192 of these objects is included in a wrapper so that the archive class can override the
193 implementation of <code style="white-space: normal">void save_override(T & t, int);</code>.
194 For example, in the XML archive, the override for this type renders an object_id equal to 23 as
195 "object_id=_23".  The following table lists the types defined in the 
196 <code style="white-space: normal">boost::archive namespace</code>
197 used internally by the serialization library:
198 <p>
199 <table border>
200 <tr><th align=left>type</th><th align=left><code style="white-space: normal">default<br>serialized as</code></th>
201 <tr><td><code style="white-space: normal">version_type</code></td><td><code style="white-space: normal">unsigned int</code></td>             
202 <tr><td><code style="white-space: normal">object_id_type</code></td><td><code style="white-space: normal">unsigned int</code></td>   
203 <tr><td><code style="white-space: normal">object_id_reference_type</code></td><td><code style="white-space: normal">unsigned int</code></td>   
204 <tr><td><code style="white-space: normal">class_id_type</code></td><td><code style="white-space: normal">int</code></td>   
205 <tr><td><code style="white-space: normal">class_id_optional_type</code></td><td><code style="white-space: normal">nothing</code></td>   
206 <tr><td><code style="white-space: normal">class_id_reference_type</code></td><td><code style="white-space: normal">int</code></td>   
207 <tr><td><code style="white-space: normal">tracking_type</code></td><td><code style="white-space: normal">bool</code></td>   
208 <tr><td><code style="white-space: normal">classname_type</code></td><td><code style="white-space: normal">string</code></td>   
209 </table>
210 <p>
211 All of these are associated with a default serialization defined in terms of primitive types
212 so it isn't a requirement to define <code style="white-space: normal">save_override</code> 
213 for these types.
214 <p>
215 These are defined in
216 <a href="../../../boost/archive/basic_archive.hpp" target="basic_archive_hpp"><code style="white-space: normal">basic_archive.hpp</code></a>.
217 All of these types have been assigned an 
218 <a target="detail" href="traits.html#level">implementation level</a> of
219 <code style="white-space: normal">primitive</code> and are convertible to types such as int, unsigned int, etc. 
220 so that they have default implementations.  This is illustrated by
221 <a href="../../../boost/archive/basic_text_iarchive.hpp" target="basic_text_iarchive_hpp"><code style="white-space: normal">basic_text_iarchive.hpp</code></a>.
222 which relies upon the default.  However, in some cases, overrides will have to be
223 explicitly provided for these types. For an example see
224 <a href="../../../boost/archive/basic_xml_iarchive.hpp" target="basic_xml_iarchive_hpp"><code style="white-space: normal">basic_xml_iarchive.hpp</code></a>.
225 <p>
226 In real practice, we probably won't be quite done. 
227 One or more of the following issues may need to be addressed:
228 <ul>
229     <li>Even if we are using a conforming compiler, we might want our new archive class
230     to be portable to non-conforming compilers.
231     <li>Our archive format might require extra information inserted into it.  For
232     example, XML archives need &lt;name ... &gt;...&lt;/name&gt; surrounding
233     all data objects.
234     <li>Addressing any of the above may generate more issues to be addressed.
235     <li>The archives included with the library are all templates which use a
236     <code style="white-space: normal">stream</code> or
237     <code style="white-space: normal">streambuf</code>
238     as a template parameter rather than simple classes.
239     Combined with the above, even more issues arise with non-conforming compilers.
240 </ul>
241 The attached <a target="class_diagram" href="class_diagram.html">class diagram</a>
242 shows the relationships between classes used to implement the serialization library.
243 <p>
244 A close examination of the archives included with the library illustrate
245 what it takes to make a portable archive that covers all data types.
246 <h3><a name="usage">Usage</a></h3>
247 The newly created archive will usually be stored in its own header module.  All
248 that is necessary is to include the header and construct an instance of the new archive.
249 EXCEPT for one special case.
250 <ul>
251     <li>Instances of a derived class are serialized through a base class pointer.
252     <li>Such instances are not "registered" neither implicitly nor explicitly. That
253     is, the macro <code style="white-space: normal">BOOT_CLASS_EXPORT</code> is used 
254     to instantiate the serialization code for the included archives.
255 </ul>
256
257 To make this work, the following should be included after the archive
258 class definition.
259 <pre><code>
260 BOOST_SERIALIZATION_REGISTER_ARCHIVE(Archive)
261 </code></pre>
262 Failure to do this will not inhibit the program from compiling, linking
263 and executing properly - except in one case.  If an instance of a derived
264 class is serialized through a pointer to its base class, the program
265 will throw an
266 <a href="exceptions.html#unregistered_class"><code style="white-space: normal">unregistered_class</code></a>
267 exception.
268 <p>
269
270 <h4><a name="testing">Testing</h4>
271 Exhaustive testing of the library requires testing the different aspects of object
272 serialization with each archive.  There are 46 different tests that can run with any archive.  
273 There are 5 "standard archives" included with the system. 
274 (3 in systems that don't support wide charactor i/o). 
275 <p>
276 In addition, there are 28 other tests which aren't related to any particular archive class.
277 <p>
278 The default <code style="white-space: normal">bjam</code> testing setup will run all
279 the above described tests.  This will result in as many as 46 archive tests * 5 
280 standard archives + 28 general tests = 258 tests. Note that a complete test of the
281 library would include DLL vs static library, release vs debug so the actual total 
282 would be closer to 1032 tests.
283 <p>
284 For each archive there is a header file in the test directory similar to the one below.
285 The name of this archive is passed to the test program by setting the
286 environmental variable <code style="white-space: normal">BOOST_ARCHIVE_TEST</code>
287 to the name of the header.  Here is the header file 
288 <code style="white-space: normal">test_archive.hpp</code> . Test header files for
289 other archives are similar.
290 <pre><code>
291 // text_archive test header
292 // include output archive header
293 #include &lt;boost/archive/text_oarchive.hpp&gt;
294 // set name of test output archive
295 typedef boost::archive::text_oarchive test_oarchive;
296 // set name of test output stream
297 typedef std::ofstream test_ostream;
298
299 // repeat the above for input archive
300 #include &lt;boost/archive/text_iarchive.hpp&gt;
301 typedef boost::archive::text_iarchive test_iarchive;
302 typedef std::ifstream test_istream;
303
304 // define open mode for streams
305 //   binary archives should use std::ios_base::binary
306 #define TEST_STREAM_FLAGS (std::ios_base::openmode)0
307 </code></pre>
308
309 To test a new archive, for example, portable binary archives, with the gcc compiler, 
310 make a header file <code style="white-space: normal">portable_binary_archive.hpp</code>
311 and invoke <code style="white-space: normal">bjam</code> with
312 <pre><code> 
313 -sBOOST_ARCHIVE_LIST=portable_binary_archive.hpp
314 </code></pre>
315 This process in encapsulated in the shell or cmd script 
316 <code style="white-space: normal">library_test</code> whose command line is
317 <pre><code>
318 library_test --toolset=gcc -sBOOST_ARCHIVE_LIST=portable_binary_archive.hpp
319 </code></pre>
320 <h3><a name="polymorphic">Polymorphic Archives</a></h3>
321
322 <h4>Motivation</h4>
323
324 All archives described so far are implemented as templates.  Code to save and load
325 data to archives is regenerated for each combination of archive class and data type.
326 Under these cirumstances, a good optimizing compiler that can expand 
327 <code>inline</code> functions to enough depth will generate fast code.  
328 However:
329 <ul>
330 <li>Much inline code may be replicated.
331 <li>If there are several archive classes, code will be regenerated for each archive class.
332 <li>If serialization code is placed in a library, that library must be rebuilt 
333 each time a new archive class is created.
334 <li>If serialization code is placed in a DLL,
335   <ul>
336   <li>The DLL will contain versions of code for each known archive type.  
337     This would result in loading of DLLs which contain
338     much code that is not used - basically defeating one of the main motivations
339     for choosing to use a DLL in the first place.
340   <li>If a new archive is created and an application shipped, all DLLs have to be
341     rebuilt, and reshipped along with the application which uses the new archive.  Thus
342     the other main motivation for using a DLL is defeated.
343   </ul>
344 </ul>
345
346 <h4>Implementation</h4>
347 The solution is the pair <code>polymorphic_oarchive</code>
348 and <code>polymorphic_iarchive</code>.  They present a common interface of virtual
349 functions - no templates - that is equivalent to the standard templated one.
350
351 This is shown in the accompanying 
352 <a target="class_diagram" href="class_diagram.html">class diagram</a>
353 <p>
354 The accompanying demo program in files
355
356 <a target=demo_polymorphic_cp href="../example/demo_polymorphic.cpp"><code style="white-space: normal">demo_polymorphic.cpp</code></a>, 
357 <a target=demo_polymorphic_A_hpp href="../example/demo_polymorphic_A.hpp"><code style="white-space: normal">demo_polymorphic_A.hpp</code></a>, and 
358 <a target=demo_polymorphic_A_cpp href="../example/demo_polymorphic_A.cpp"><code style="white-space: normal">demo_polymorphic_A</code></a>
359 show how polymorphic archives are to be used. Note the following:
360 <ul>
361   <li><a target=demo_polymorphic_A_hpp href="../example/demo_polymorphic_A.hpp"><code style="white-space: normal">demo_polymorphic_A.hpp</code></a> and
362 <a target=demo_polymorphic_A_cpp href="../example/demo_polymorphic_A.cpp"><code style="white-space: normal">demo_polymorphic_A.cpp</code></a>
363 contain no templates and no reference to any specific archive implementation.  That is, they will
364 only have to be compiled once for all archive implementations.  This even applies to archives classes
365 created in the future.
366   <li>The main program <a target=demo_polymorphic_cp href="../example/demo_polymorphic.cpp"><code style="white-space: normal">demo_polymorphic.cpp</code></a>
367 specifies a specific archive implementation.  
368 </ul>
369 As can be seen in the
370 <a target="class_diagram" href="class_diagram.html">class diagram</a>
371 and the header files, this implementation is just a composition of the polymorphic
372 interface and the standard template driven implementation.  This composition is
373 accomplished by the templates
374 <a target=polymorphic_iarchive_route_hpp href="../../../boost/archive/detail/polymorphic_iarchive_route.hpp"><code style="white-space: normal">polymorphic_iarchive_route.hpp</code></a>
375 and
376 <a target=polymorphic_oarchive_route_hpp href="../../../boost/archive/detail/polymorphic_oarchive_route.hpp"><code style="white-space: normal">polymorphic_oarchive_route.hpp</code></a>
377 which redirect calls to the polymorphic archives to the specific archive.
378 As these contain no code specific to the particular implementation archive, they can be used to create
379 a polymorphic archive implementation from any functioning templated archive implementation.
380 <p>
381 As a convenience, small header files have been included which contain 
382 a <code style="white-space: normal">typedef</code> for a polymorphic implementation for each corresponding
383 templated one.  For example, the headers
384 <a target=polymorphic_text_iarchive_hpp href="../../../boost/archive/polymorphic_text_iarchive.hpp"><code style="white-space: normal">polymorphic_text_iarchive.hpp</code></a>
385 and
386 <a target=polymorphic_text_oarchive_hpp href="../../../boost/archive/polymorphic_text_oarchive.hpp"><code style="white-space: normal">polymorphic_text_oarchive.hpp</code></a>.
387 contain the <code style="white-space: normal">typedef</code> for the polymorphic implementation
388 of the standard text archive classes  
389 <a target=text_iarchive_hpp href="../../../boost/archive/text_iarchive.hpp"><code style="white-space: normal">text_iarchive.hpp</code></a>
390 and
391 <a target=text_oarchive_hpp href="../../../boost/archive/text_oarchive.hpp"><code style="white-space: normal">text_oarchive.hpp</code></a>
392 respectively. All included polymorphic archives use the same naming scheme.
393
394 <h4>Usage</h4>
395 Polymorphic archives address the issues raised above regarding templated implementation.
396 That is, there is no replicated code, and no recompilation for new archives.  This will
397 result in smaller executables for program which use more than one type of archive, and 
398 smaller DLLS. There is a penalty for calling archive functions through a virtual function 
399 dispatch table and there is no possibility for a compiler to <code style="white-space: normal">inline</code> 
400 archive functions.  This will result in a detectable degradation in performance for 
401 saving and loading archives.
402 <p>
403 Note that the concept of polymophic archives is fundamentally incompatible with the
404 serialization of new types that are marked "primitive" by the user with:
405 <pre><code> 
406 BOOST_CLASS_IMPLEMENTATION(my_primitive_type, boost::serialization::primitive_type)
407 </code></pre>
408
409 Code to implement serialization for these types is instantiated "on the fly" in the user's program.
410 But this conflicts with the whole purpose of the polymorphic archive. An attempt to
411 serialize such a primitive type will result in a compilation error since the common polymorhic
412 interface is static and cannot instantiate code for a new type.
413
414 <p>
415 The main utility of polymorphic archives will be to permit the building of class DLLs that will
416 include serialization code for all present and future archives with no redundant code.
417 <hr>
418 <p><i>&copy; Copyright <a href="http://www.rrsd.com">Robert Ramey</a> 2002-2004. 
419 Distributed under the Boost Software License, Version 1.0. (See
420 accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
421 </i></p>
422 </body>
423 </html>