aboutsummaryrefslogtreecommitdiff
path: root/src/archive.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/archive.h212
1 files changed, 212 insertions, 0 deletions
diff --git a/src/archive.h b/src/archive.h
new file mode 100644
index 0000000..a2d4c8f
--- /dev/null
+++ b/src/archive.h
@@ -0,0 +1,212 @@
1#ifndef BU_ARCHIVE_H
2#define BU_ARCHIVE_H
3
4#include <stdint.h>
5#include <string>
6#include "bu/archival.h"
7#include "bu/stream.h"
8#include <list>
9#include "bu/hash.h"
10#include "bu/list.h"
11
12namespace Bu
13{
14 /**
15 * Provides a framework for serialization of objects and primitives. The
16 * archive will handle any basic primitive, a few special types, like char *
17 * strings, as well as STL classes and anything that inherits from the
18 * Archival class. Each Archive operates on a Stream, so you can send the
19 * data using an Archive almost anywhere.
20 *
21 * In order to use an Archive to store something to a file, try something
22 * like:
23 *@code
24 * File sOut("output", "wb"); // This is a stream subclass
25 * Archive ar( sOut, Archive::save );
26 * ar << myClass;
27 @endcode
28 * In this example myClass is any class that inherits from Archival. When
29 * the storage operator is called, the Archival::archive() function in the
30 * myClass object is called with a reference to the Archive. This can be
31 * handled in one of two ways:
32 *@code
33 * void MyClass::archive( Archive &ar )
34 * {
35 * ar && sName && nAge && sJob;
36 * }
37 @endcode
38 * Here we don't worry about weather we're loading or saving by using the
39 * smart && operator. This allows us to write very consistent, very simple
40 * archive functions that really do a lot of work. If we wanted to do
41 * something different in the case of loading or saving we would do:
42 *@code
43 * void MyClass::archive( Archive &ar )
44 * {
45 * if( ar.isLoading() )
46 * {
47 * ar >> sName >> nAge >> sJob;
48 * } else
49 * {
50 * ar << sName << nAge << sJob;
51 * }
52 * }
53 @endcode
54 * Archive currently does not provide facility to make fully portable
55 * archives. For example, it will not convert between endianness for you,
56 * nor will it take into account differences between primitive sizes on
57 * different platforms. This, at the moment, is up to the user to ensure.
58 * One way of dealing with the latter problem is to make sure and use
59 * explicit primitive types from the stdint.h header, i.e. int32_t.
60 */
61 class Archive
62 {
63 private:
64 bool bLoading;
65 public:
66 bool isLoading();
67
68 enum
69 {
70 load = true,
71 save = false
72 };
73
74 Archive( Stream &rStream, bool bLoading );
75 virtual ~Archive();
76 virtual void close();
77
78 virtual void write(const void *, int32_t);
79 virtual void read(void *, int32_t);
80
81 virtual Archive &operator<<(bool);
82 virtual Archive &operator<<(int8_t);
83 virtual Archive &operator<<(int16_t);
84 virtual Archive &operator<<(int32_t);
85 virtual Archive &operator<<(int64_t);
86 virtual Archive &operator<<(uint8_t);
87 virtual Archive &operator<<(uint16_t);
88 virtual Archive &operator<<(uint32_t);
89 virtual Archive &operator<<(uint64_t);
90 virtual Archive &operator<<(long);
91 virtual Archive &operator<<(float);
92 virtual Archive &operator<<(double);
93 virtual Archive &operator<<(long double);
94
95 virtual Archive &operator>>(bool &);
96 virtual Archive &operator>>(int8_t &);
97 virtual Archive &operator>>(int16_t &);
98 virtual Archive &operator>>(int32_t &);
99 virtual Archive &operator>>(int64_t &);
100 virtual Archive &operator>>(uint8_t &);
101 virtual Archive &operator>>(uint16_t &);
102 virtual Archive &operator>>(uint32_t &);
103 virtual Archive &operator>>(uint64_t &);
104 virtual Archive &operator>>(long &);
105 virtual Archive &operator>>(float &);
106 virtual Archive &operator>>(double &);
107 virtual Archive &operator>>(long double &);
108
109 virtual Archive &operator&&(bool &);
110 virtual Archive &operator&&(int8_t &);
111 virtual Archive &operator&&(int16_t &);
112 virtual Archive &operator&&(int32_t &);
113 virtual Archive &operator&&(int64_t &);
114 virtual Archive &operator&&(uint8_t &);
115 virtual Archive &operator&&(uint16_t &);
116 virtual Archive &operator&&(uint32_t &);
117 virtual Archive &operator&&(uint64_t &);
118 virtual Archive &operator&&(float &);
119 virtual Archive &operator&&(double &);
120 virtual Archive &operator&&(long double &);
121
122 uint32_t getID( const void *ptr );
123 void assocPtrID( void **ptr, uint32_t id );
124 void readID( const void *ptr, uint32_t id );
125
126 private:
127 Stream &rStream;
128 uint32_t nNextID;
129 Hash<uint32_t,uint32_t> hPtrID;
130 Hash<uint32_t,List<void **> > hPtrDest;
131 };
132
133 Archive &operator<<(Archive &, class Bu::Archival &);
134 Archive &operator>>(Archive &, class Bu::Archival &);
135 //Archive &operator&&(Archive &s, class Bu::Archival &p);
136
137 Archive &operator<<(Archive &, std::string &);
138 Archive &operator>>(Archive &, std::string &);
139 //Archive &operator&&(Archive &, std::string &);
140
141 template<typename T> Archive &operator&&( Archive &ar, T &dat )
142 {
143 if( ar.isLoading() )
144 {
145 return ar >> dat;
146 }
147 else
148 {
149 return ar << dat;
150 }
151 }
152
153 template<typename T> Archive &operator<<( Archive &ar, std::list<T> &l )
154 {
155 typename std::list<T>::size_type num = l.size();
156 ar << num;
157 for( typename std::list<T>::const_iterator i = l.begin(); i != l.end();
158 i++ )
159 {
160 ar << *i;
161 }
162
163 return ar;
164 }
165
166 template<typename T> Archive &operator>>( Archive &ar, std::list<T> &l )
167 {
168 typename std::list<T>::size_type num;
169 ar >> num;
170
171 l.resize( num );
172 for( typename std::list<T>::const_iterator i = l.begin();
173 i != l.end(); i++ )
174 {
175 ar >> *i;
176 }
177
178 return ar;
179 }
180
181 template<typename key, typename value>
182 Archive &operator<<( Archive &ar, Hash<key,value> &h )
183 {
184 ar << h.size();
185 for( typename Hash<key,value>::iterator i = h.begin(); i != h.end(); i++ )
186 {
187 //std::pair<key,value> p = *i;
188 ar << (i.getKey()) << (i.getValue());
189 }
190
191 return ar;
192 }
193
194 template<typename key, typename value>
195 Archive &operator>>( Archive &ar, Hash<key,value> &h )
196 {
197 h.clear();
198 uint32_t nSize;
199 ar >> nSize;
200
201 for( uint32_t j = 0; j < nSize; j++ )
202 {
203 key k; value v;
204 ar >> k >> v;
205 h.insert( k, v );
206 }
207
208 return ar;
209 }
210}
211
212#endif