]> Dogcows Code - chaz/yoink/blob - src/stlplus/persistence/persistent_callback.tpp
testing new non-autotools build system
[chaz/yoink] / src / stlplus / persistence / persistent_callback.tpp
1 ////////////////////////////////////////////////////////////////////////////////
2
3 // Author: Andy Rushton
4 // Copyright: (c) Southampton University 1999-2004
5 // (c) Andy Rushton 2004-2009
6 // License: BSD License, see ../docs/license.html
7
8 // Polymorphous classes using the callback approach
9
10 // format: magic [ key data ]
11
12 ////////////////////////////////////////////////////////////////////////////////
13 #include "persistent_int.hpp"
14
15 namespace stlplus
16 {
17
18 ////////////////////////////////////////////////////////////////////////////////
19
20 template<typename T>
21 void dump_callback(dump_context& context, const T* const data)
22 throw(persistent_dump_failed)
23 {
24 try
25 {
26 // register the address and get the magic key for it
27 std::pair<bool,unsigned> mapping = context.pointer_map(data);
28 dump_unsigned(context,mapping.second);
29 // if the address is null, then that is all that we need to do
30 // however, if it is non-null and this is the first sight of the address, dump the contents
31 if (data && !mapping.first)
32 {
33 // callback method - get the callback data and perform the dump
34 // this will throw persistent_illegal_type if not recognised, thus the try block
35 dump_context::callback_data callback = context.lookup_callback(typeid(*data));
36 // dump the magic key for the type
37 dump_unsigned(context, callback.first);
38 // now call the callback that dumps the subclass
39 callback.second(context,data);
40 }
41 }
42 catch (const persistent_illegal_type& except)
43 {
44 // convert this to a simpler dump failed exception
45 throw persistent_dump_failed(except.what());
46 }
47 }
48
49 ////////////////////////////////////////////////////////////////////////////////
50
51 template<typename T>
52 void restore_callback(restore_context& context, T*& data)
53 throw(persistent_restore_failed)
54 {
55 try
56 {
57 // first delete any previous object pointed to since the restore creates the object of the right subclass
58 if (data)
59 {
60 delete data;
61 data = 0;
62 }
63 // get the magic key
64 unsigned magic = 0;
65 restore_unsigned(context,magic);
66 // now lookup the magic key to see if this pointer has already been restored
67 // null pointers are always flagged as already restored
68 std::pair<bool,void*> address = context.pointer_map(magic);
69 if (address.first)
70 {
71 // seen before, so simply map it to the existing address
72 data = (T*)address.second;
73 }
74 else
75 {
76 // now restore the magic key that denotes the particular subclass
77 unsigned key = 0;
78 restore_unsigned(context, key);
79 // callback approach
80 // call the create callback to create an object of the right type
81 // then call the restore callback to get the contents
82 // this will throw persistent_illegal_type if not recognised - this is caught below
83 restore_context::callback_data callbacks = context.lookup_callback(key);
84 data = (T*)callbacks.first();
85 // add this pointer to the set of already seen objects
86 // note that the address is mapped before it is dumped so that self-referential structures dump correctly
87 context.pointer_add(magic,data);
88 callbacks.second(context,data);
89 }
90 }
91 catch (const persistent_illegal_type& exception)
92 {
93 // convert this to a simpler dump failed exception
94 throw persistent_restore_failed(exception.what());
95 }
96 }
97
98 ////////////////////////////////////////////////////////////////////////////////
99
100 } // end namespace stlplus
This page took 0.031819 seconds and 4 git commands to generate.