diff options
Diffstat (limited to 'src/archive.h')
-rw-r--r-- | src/archive.h | 212 |
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 | |||
12 | namespace 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 | ||