CppCMS
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  {
53  }
54  static void load(T &o,archive &a)
55  {
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();
266  for(it=v.begin();it!=v.end();++it) {
268  }
269  }
270 
271  template<typename T>
272  void archive_load_container(T &v,archive &a)
273  {
274  size_t n;
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;
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
value_type
Definition: formatting.h:85
This is the namespace where all CppCMS functionality is placed.
Definition: application.h:19
archive & operator>>(archive &a, Archivable &object)
Definition: serialization_classes.h:186
archive & operator&(archive &a, Archivable &object)
Definition: serialization_classes.h:163
static void load(Object &d, archive &a)
void write_chunk(void const *begin, size_t len)
Definition: log.h:25
static void save(Object const &d, archive &a)
void read_chunk(void *begin, size_t len)
archive & operator<<(archive &a, Archivable const &object)
Definition: serialization_classes.h:176
Booster library namespace. The library that implements Boost Like API in ABI backward compatible way...
Definition: application.h:23