CppCMS

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

archive_traits.h
1 //
3 // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
4 //
5 // See accompanying file COPYING.TXT file for licensing details.
6 //
8 #ifndef CPPCMS_ARCHIVE_TRAITS_H
9 #define CPPCMS_ARCHIVE_TRAITS_H
10
11 #include <cppcms/serialization_classes.h>
12 #include <cppcms/json.h>
13
14 #include <booster/shared_ptr.h>
15 #include <booster/intrusive_ptr.h>
16 #include <booster/hold_ptr.h>
17 #include <booster/clone_ptr.h>
18 #include <booster/copy_ptr.h>
19
20 #include <booster/traits/enable_if.h>
21 #include <booster/traits/is_base_of.h>
22
23 #include <booster/auto_ptr_inc.h>
24 #include <iterator>
25 #include <map>
26 #include <vector>
27 #include <list>
28 #include <set>
29 #include <sstream>
30
32
33 namespace cppcms {
34
35
36 template<typename S>
37 struct archive_traits<S,typename booster::enable_if<booster::is_base_of<serializable_base,S> >::type > {
38 static void save(serializable_base const &d,archive &a)
39 {
40 d.save(a);
41 }
42 static void load(serializable_base &d,archive &a)
43 {
44 d.load(a);
45 }
46 };
47
48 template<typename T>
49 struct archive_traits<T const> {
50 static void save(T const &o,archive &a)
51 {
52 archive_traits<T>::save(o,a);
53 }
54 static void load(T &o,archive &a)
55 {
56 archive_traits<T>::load(o,a);
57 }
58 };
59
60 template<>
61 struct archive_traits<std::string> {
62 static void save(std::string const &o,archive &a)
63 {
64 a.write_chunk(o.c_str(),o.size());
65 }
66 static void load(std::string &o,archive &a)
67 {
68 std::string res = a.read_chunk_as_string();
69 res.swap(o);
70 }
71 };
72
73 namespace details {
74
75 struct pod_data {
76 void *pointer;
77 size_t len;
78 };
79
80 struct const_pod_data {
81 void const *pointer;
82 size_t len;
83 };
84
85 inline archive &operator<<(archive &a,const_pod_data const &d)
86 {
87 a.write_chunk(d.pointer,d.len);
88 return a;
89 }
90
91
92 inline archive &operator&(archive &a,pod_data const &d)
93 {
94 if(a.mode()==archive::load_from_archive)
95 a.read_chunk(d.pointer,d.len);
96 else
97 a.write_chunk(d.pointer,d.len);
98 return a;
99 }
100 inline archive &operator<<(archive &a,pod_data const &d)
101 {
102 a.write_chunk(d.pointer,d.len);
103 return a;
104 }
105 inline archive &operator>>(archive &a,pod_data const &d)
106 {
107 a.read_chunk(d.pointer,d.len);
108 return a;
109 }
110
111 }
112
113 template<typename T>
114 details::pod_data as_pod(T &v)
115 {
116 details::pod_data d = { &v , sizeof(v) };
117 return d;
118 }
119
120 template<typename T>
121 details::const_pod_data as_pod(T const &v)
122 {
123 details::const_pod_data d = { &v , sizeof(v) };
124 return d;
125 }
126
127 } // cppcms
128
129
130 #define CPPCMS_TRIVIAL_ARCHIVE(Type) \
131 namespace cppcms { \
132 template<> \
133 struct archive_traits<std::vector<Type> > { \
134 typedef std::vector<Type> vec; \
135 static void save(vec const &v,archive &a) \
136 { \
137 void const *p=0; \
138 size_t len= \
139 v.size()*sizeof(Type); \
140 if(!v.empty()) \
141 p=&v.front(); \
142 a.write_chunk(p,len); \
143 } \
144 static void load(vec &v,archive &a) \
145 { \
146 size_t n=a.next_chunk_size() / \
147 sizeof(Type); \
148 v.clear(); \
149 v.resize(n); \
150 void *p=0; \
151 if(!v.empty()) \
152 p=&v.front(); \
153 a.read_chunk(p,n*sizeof(Type)); \
154 } \
155 }; \
156 \
157 template<int n> \
158 struct archive_traits<Type[n]> { \
159 static void save(Type const d[n],archive &a) \
160 { \
161 a.write_chunk(&d[0],sizeof(Type)*n); \
162 } \
163 static void load(Type d[n],archive &a) \
164 { \
165 a.read_chunk(&d[0],sizeof(Type)*n); \
166 } \
167 }; \
168 template<int n> \
169 struct archive_traits<Type const [n]> { \
170 static void save(Type const d[n],archive &a) \
171 { \
172 a.write_chunk(&d[0],sizeof(Type)*n); \
173 } \
174 }; \
175 \
176 template<> \
177 struct archive_traits<Type> { \
178 static void save(Type const d,archive &a) \
179 { \
180 a.write_chunk(&d,sizeof(d)); \
181 } \
182 static void load(Type &d,archive &a) \
183 { \
184 a.read_chunk(&d,sizeof(d)); \
185 } \
186 }; \
187 } /* cppcms */
188
189 CPPCMS_TRIVIAL_ARCHIVE(char)
190 CPPCMS_TRIVIAL_ARCHIVE(signed char)
191 CPPCMS_TRIVIAL_ARCHIVE(unsigned char)
192 CPPCMS_TRIVIAL_ARCHIVE(signed short)
193 CPPCMS_TRIVIAL_ARCHIVE(unsigned short)
194 CPPCMS_TRIVIAL_ARCHIVE(signed int)
195 CPPCMS_TRIVIAL_ARCHIVE(unsigned int)
196 CPPCMS_TRIVIAL_ARCHIVE(signed long)
197 CPPCMS_TRIVIAL_ARCHIVE(unsigned long)
198 CPPCMS_TRIVIAL_ARCHIVE(signed long long)
199 CPPCMS_TRIVIAL_ARCHIVE(unsigned long long)
200 CPPCMS_TRIVIAL_ARCHIVE(wchar_t)
201 CPPCMS_TRIVIAL_ARCHIVE(float)
202 CPPCMS_TRIVIAL_ARCHIVE(double)
203 CPPCMS_TRIVIAL_ARCHIVE(long double)
204
205
206 namespace cppcms {
207
208 template<typename T,int size>
209 struct archive_traits<T [size]>
210 {
211 static void save(T const d[size],archive &a)
212 {
213 for(int i=0;i<size;i++)
214 archive_traits<T>::save(d[i],a);
215 }
216 static void load(T d[size],archive &a)
217 {
218 for(int i=0;i<size;i++)
219 archive_traits<T>::load(d[i],a);
220 }
221 };
222
223 template<typename F,typename S>
224 struct archive_traits<std::pair<F,S> >
225 {
226 static void save(std::pair<F,S> const &d,archive &a)
227 {
228 archive_traits<F>::save(d.first,a);
229 archive_traits<S>::save(d.second,a);
230 }
231 static void load(std::pair<F,S> &d,archive &a)
232 {
233 archive_traits<F>::load(d.first,a);
234 archive_traits<S>::load(d.second,a);
235 }
236 };
237
238 template<>
239 struct archive_traits<json::value> {
240 static void save(json::value const &v,archive &a)
241 {
242 std::ostringstream ss;
243 v.save(ss);
244 std::string s=ss.str();
245 a.write_chunk(s.c_str(),s.size());
246 }
247 static void load(json::value &v,archive &a)
248 {
249 std::istringstream ss;
250 ss.str(a.read_chunk_as_string());
251 if(!v.load(ss,true)) {
252 throw archive_error("Invalid json");
253 }
254 }
255 };
256
257 namespace details {
258
259 template<typename T>
260 void archive_save_container(T const &v,archive &a)
261 {
262 typename T::const_iterator it;
263 typedef typename T::value_type value_type;
264 size_t n=v.size();
265 archive_traits<size_t>::save(n,a);
266 for(it=v.begin();it!=v.end();++it) {
267 archive_traits<value_type>::save(*it,a);
268 }
269 }
270
271 template<typename T>
272 void archive_load_container(T &v,archive &a)
273 {
274 size_t n;
275 archive_traits<size_t>::load(n,a);
276 v.clear();
277 std::insert_iterator<T> it(v,v.begin());
278 typedef typename T::value_type value_type;
279 for(size_t i=0;i<n;i++) {
280 value_type tmp;
281 archive_traits<value_type>::load(tmp,a);
282 *it++ = tmp;
283 }
284 }
285 } // details
286
287
288
289 }
290
291 #define CPPCMS_CONTAINER_ARCHIVE2(Type) \
292 namespace cppcms { \
293 template<typename V1,typename V2> \
294 struct archive_traits<Type<V1,V2> > \
295 { \
296 typedef Type<V1,V2> cont; \
297 static void save(cont const &d,archive &a) \
298 { \
299 details::archive_save_container<cont>(d,a); \
300 } \
301 static void load(cont &v,archive &a) \
302 { \
303 size_t n; \
304 archive_traits<size_t>::load(n,a); \
305 v.clear(); \
306 typedef std::pair<V1,V2> pair_type; \
307 for(size_t i=0;i<n;i++) { \
308 pair_type tmp; \
309 archive_traits<pair_type>::load(tmp,a); \
310 v.insert(tmp); \
311 } \
312 } \
313 }; \
314 } /* cppcms */
315
316 #define CPPCMS_CONTAINER_ARCHIVE(Type) \
317 namespace cppcms { \
318 template<typename V> \
319 struct archive_traits<Type<V> > \
320 { \
321 static void save(Type<V> const &d,archive &a) \
322 { \
323 details::archive_save_container<Type<V> >(d,a); \
324 } \
325 static void load(Type<V> &d,archive &a) \
326 { \
327 details::archive_load_container<Type<V> >(d,a); \
328 } \
329 }; \
330 } /* cppcms */
331
332 CPPCMS_CONTAINER_ARCHIVE(std::vector)
333 CPPCMS_CONTAINER_ARCHIVE(std::list)
334 CPPCMS_CONTAINER_ARCHIVE2(std::map)
335 CPPCMS_CONTAINER_ARCHIVE2(std::multimap)
336 CPPCMS_CONTAINER_ARCHIVE(std::set)
337 CPPCMS_CONTAINER_ARCHIVE(std::multiset)
338
339 #define CPPCMS_ARCHIVE_SMART_POINTER(SmartPtr) \
340 namespace cppcms { \
341 template<typename V> \
342 struct archive_traits<SmartPtr<V> > { \
343 typedef SmartPtr<V> pointer; \
344 static void save(pointer const &d,archive &a) \
345 { \
346 char empty = d.get() == 0; \
347 a.write_chunk(&empty,1); \
348 if(!empty) { \
349 archive_traits<V>::save(*d,a); \
350 } \
351 } \
352 static void load(pointer &d,archive &a) \
353 { \
354 char empty; \
355 a.read_chunk(&empty,1); \
356 if(empty) { \
357 d.reset(); \
358 } \
359 else { \
360 d.reset(new V()); \
361 archive_traits<V>::load(*d,a); \
362 } \
363 } \
364 }; \
365 } /* cppcms */
366
367
368 #define CPPCMS_ARCHIVE_INTRUSIVE_POINTER(SmartPtr) \
369 namespace cppcms { \
370 template<typename V> \
371 struct archive_traits<SmartPtr<V> > { \
372 typedef SmartPtr<V> pointer; \
373 static void save(pointer const &d,archive &a) \
374 { \
375 char empty = d.get() == 0; \
376 a.write_chunk(&empty,1); \
377 if(!empty) { \
378 archive_traits<V>::save(*d,a); \
379 } \
380 } \
381 static void load(pointer &d,archive &a) \
382 { \
383 char empty; \
384 a.read_chunk(&empty,1); \
385 if(empty) { \
386 d = 0; \
387 } \
388 else { \
389 d = new V(); \
390 archive_traits<V>::load(*d,a); \
391 } \
392 } \
393 }; \
394 } /* cppcms */
395
396
397
398
399 CPPCMS_ARCHIVE_SMART_POINTER(booster::shared_ptr)
400 CPPCMS_ARCHIVE_SMART_POINTER(booster::hold_ptr)
401 CPPCMS_ARCHIVE_SMART_POINTER(booster::copy_ptr)
402 CPPCMS_ARCHIVE_SMART_POINTER(booster::clone_ptr)
403 CPPCMS_ARCHIVE_SMART_POINTER(std::auto_ptr)
404 CPPCMS_ARCHIVE_INTRUSIVE_POINTER(booster::intrusive_ptr)
405
406
407
409
410
411 #endif
booster::locale::flags::value_type
value_type
Definition: formatting.h:85
cppcms
This is the namespace where all CppCMS functionality is placed.
Definition: application.h:19
cppcms::operator>>
archive & operator>>(archive &a, Archivable &object)
Definition: serialization_classes.h:186
cppcms::operator&
archive & operator&(archive &a, Archivable &object)
Definition: serialization_classes.h:163
cppcms::archive_traits::load
static void load(Object &d, archive &a)
cppcms::archive::write_chunk
void write_chunk(void const *begin, size_t len)
booster::shared_ptr
Definition: log.h:25
cppcms::archive_traits::save
static void save(Object const &d, archive &a)
cppcms::archive::read_chunk
void read_chunk(void *begin, size_t len)
cppcms::operator<<
archive & operator<<(archive &a, Archivable const &object)
Definition: serialization_classes.h:176
booster
Booster library namespace. The library that implements Boost Like API in ABI backward compatible way...
Definition: application.h:23