00001
00002
00003
00004
00005
00006
00008 #ifndef CPPCMS_ARCHIVE_TRAITS_H
00009 #define CPPCMS_ARCHIVE_TRAITS_H
00010
00011 #include <cppcms/serialization_classes.h>
00012 #include <cppcms/json.h>
00013
00014 #include <booster/shared_ptr.h>
00015 #include <booster/intrusive_ptr.h>
00016 #include <booster/hold_ptr.h>
00017 #include <booster/clone_ptr.h>
00018 #include <booster/copy_ptr.h>
00019
00020 #include <booster/traits/enable_if.h>
00021 #include <booster/traits/is_base_of.h>
00022
00023 #include <memory>
00024 #include <iterator>
00025 #include <map>
00026 #include <vector>
00027 #include <list>
00028 #include <set>
00029 #include <sstream>
00030
00032
00033 namespace cppcms {
00034
00035
00036 template<typename S>
00037 struct archive_traits<S,typename booster::enable_if<booster::is_base_of<serializable_base,S> >::type > {
00038 static void save(serializable_base const &d,archive &a)
00039 {
00040 d.save(a);
00041 }
00042 static void load(serializable_base &d,archive &a)
00043 {
00044 d.load(a);
00045 }
00046 };
00047
00048 template<typename T>
00049 struct archive_traits<T const> {
00050 static void save(T const &o,archive &a)
00051 {
00052 archive_traits<T>::save(o,a);
00053 }
00054 static void load(T &o,archive &a)
00055 {
00056 archive_traits<T>::load(o,a);
00057 }
00058 };
00059
00060 template<>
00061 struct archive_traits<std::string> {
00062 static void save(std::string const &o,archive &a)
00063 {
00064 a.write_chunk(o.c_str(),o.size());
00065 }
00066 static void load(std::string &o,archive &a)
00067 {
00068 std::string res = a.read_chunk_as_string();
00069 res.swap(o);
00070 }
00071 };
00072
00073 namespace details {
00074
00075 struct pod_data {
00076 void *pointer;
00077 size_t len;
00078 };
00079
00080 struct const_pod_data {
00081 void const *pointer;
00082 size_t len;
00083 };
00084
00085 inline archive &operator<<(archive &a,const_pod_data const &d)
00086 {
00087 a.write_chunk(d.pointer,d.len);
00088 return a;
00089 }
00090
00091
00092 inline archive &operator&(archive &a,pod_data const &d)
00093 {
00094 if(a.mode()==archive::load_from_archive)
00095 a.read_chunk(d.pointer,d.len);
00096 else
00097 a.write_chunk(d.pointer,d.len);
00098 return a;
00099 }
00100 inline archive &operator<<(archive &a,pod_data const &d)
00101 {
00102 a.write_chunk(d.pointer,d.len);
00103 return a;
00104 }
00105 inline archive &operator>>(archive &a,pod_data const &d)
00106 {
00107 a.read_chunk(d.pointer,d.len);
00108 return a;
00109 }
00110
00111 }
00112
00113 template<typename T>
00114 details::pod_data as_pod(T &v)
00115 {
00116 details::pod_data d = { &v , sizeof(v) };
00117 return d;
00118 }
00119
00120 template<typename T>
00121 details::const_pod_data as_pod(T const &v)
00122 {
00123 details::const_pod_data d = { &v , sizeof(v) };
00124 return d;
00125 }
00126
00127 }
00128
00129
00130 #define CPPCMS_TRIVIAL_ARCHIVE(Type) \
00131 namespace cppcms { \
00132 template<> \
00133 struct archive_traits<std::vector<Type> > { \
00134 typedef std::vector<Type> vec; \
00135 static void save(vec const &v,archive &a) \
00136 { \
00137 void const *p=0; \
00138 size_t len= \
00139 v.size()*sizeof(Type); \
00140 if(!v.empty()) \
00141 p=&v.front(); \
00142 a.write_chunk(p,len); \
00143 } \
00144 static void load(vec &v,archive &a) \
00145 { \
00146 size_t n=a.next_chunk_size() / \
00147 sizeof(Type); \
00148 v.clear(); \
00149 v.resize(n); \
00150 void *p=0; \
00151 if(!v.empty()) \
00152 p=&v.front(); \
00153 a.read_chunk(p,n*sizeof(Type)); \
00154 } \
00155 }; \
00156 \
00157 template<int n> \
00158 struct archive_traits<Type[n]> { \
00159 static void save(Type const d[n],archive &a) \
00160 { \
00161 a.write_chunk(&d[0],sizeof(Type)*n); \
00162 } \
00163 static void load(Type d[n],archive &a) \
00164 { \
00165 a.read_chunk(&d[0],sizeof(Type)*n); \
00166 } \
00167 }; \
00168 template<int n> \
00169 struct archive_traits<Type const [n]> { \
00170 static void save(Type const d[n],archive &a) \
00171 { \
00172 a.write_chunk(&d[0],sizeof(Type)*n); \
00173 } \
00174 }; \
00175 \
00176 template<> \
00177 struct archive_traits<Type> { \
00178 static void save(Type const d,archive &a) \
00179 { \
00180 a.write_chunk(&d,sizeof(d)); \
00181 } \
00182 static void load(Type &d,archive &a) \
00183 { \
00184 a.read_chunk(&d,sizeof(d)); \
00185 } \
00186 }; \
00187 }
00188
00189 CPPCMS_TRIVIAL_ARCHIVE(char)
00190 CPPCMS_TRIVIAL_ARCHIVE(signed char)
00191 CPPCMS_TRIVIAL_ARCHIVE(unsigned char)
00192 CPPCMS_TRIVIAL_ARCHIVE(signed short)
00193 CPPCMS_TRIVIAL_ARCHIVE(unsigned short)
00194 CPPCMS_TRIVIAL_ARCHIVE(signed int)
00195 CPPCMS_TRIVIAL_ARCHIVE(unsigned int)
00196 CPPCMS_TRIVIAL_ARCHIVE(signed long)
00197 CPPCMS_TRIVIAL_ARCHIVE(unsigned long)
00198 CPPCMS_TRIVIAL_ARCHIVE(signed long long)
00199 CPPCMS_TRIVIAL_ARCHIVE(unsigned long long)
00200 CPPCMS_TRIVIAL_ARCHIVE(wchar_t)
00201 CPPCMS_TRIVIAL_ARCHIVE(float)
00202 CPPCMS_TRIVIAL_ARCHIVE(double)
00203 CPPCMS_TRIVIAL_ARCHIVE(long double)
00204
00205
00206 namespace cppcms {
00207
00208 template<typename T,int size>
00209 struct archive_traits<T [size]>
00210 {
00211 static void save(T const d[size],archive &a)
00212 {
00213 for(int i=0;i<size;i++)
00214 archive_traits<T>::save(d[i],a);
00215 }
00216 static void load(T d[size],archive &a)
00217 {
00218 for(int i=0;i<size;i++)
00219 archive_traits<T>::load(d[i],a);
00220 }
00221 };
00222
00223 template<typename F,typename S>
00224 struct archive_traits<std::pair<F,S> >
00225 {
00226 static void save(std::pair<F,S> const &d,archive &a)
00227 {
00228 archive_traits<F>::save(d.first,a);
00229 archive_traits<S>::save(d.second,a);
00230 }
00231 static void load(std::pair<F,S> &d,archive &a)
00232 {
00233 archive_traits<F>::load(d.first,a);
00234 archive_traits<S>::load(d.second,a);
00235 }
00236 };
00237
00238 template<>
00239 struct archive_traits<json::value> {
00240 static void save(json::value const &v,archive &a)
00241 {
00242 std::ostringstream ss;
00243 v.save(ss);
00244 std::string s=ss.str();
00245 a.write_chunk(s.c_str(),s.size());
00246 }
00247 static void load(json::value &v,archive &a)
00248 {
00249 std::istringstream ss;
00250 ss.str(a.read_chunk_as_string());
00251 if(!v.load(ss,true)) {
00252 throw archive_error("Invalid json");
00253 }
00254 }
00255 };
00256
00257 namespace details {
00258
00259 template<typename T>
00260 void archive_save_container(T const &v,archive &a)
00261 {
00262 typename T::const_iterator it;
00263 typedef typename T::value_type value_type;
00264 size_t n=v.size();
00265 archive_traits<size_t>::save(n,a);
00266 for(it=v.begin();it!=v.end();++it) {
00267 archive_traits<value_type>::save(*it,a);
00268 }
00269 }
00270
00271 template<typename T>
00272 void archive_load_container(T &v,archive &a)
00273 {
00274 size_t n;
00275 archive_traits<size_t>::load(n,a);
00276 v.clear();
00277 std::insert_iterator<T> it(v,v.begin());
00278 typedef typename T::value_type value_type;
00279 for(size_t i=0;i<n;i++) {
00280 value_type tmp;
00281 archive_traits<value_type>::load(tmp,a);
00282 *it++ = tmp;
00283 }
00284 }
00285 }
00286
00287
00288
00289 }
00290
00291 #define CPPCMS_CONTAINER_ARCHIVE2(Type) \
00292 namespace cppcms { \
00293 template<typename V1,typename V2> \
00294 struct archive_traits<Type<V1,V2> > \
00295 { \
00296 typedef Type<V1,V2> cont; \
00297 static void save(cont const &d,archive &a) \
00298 { \
00299 details::archive_save_container<cont>(d,a); \
00300 } \
00301 static void load(cont &v,archive &a) \
00302 { \
00303 size_t n; \
00304 archive_traits<size_t>::load(n,a); \
00305 v.clear(); \
00306 typedef std::pair<V1,V2> pair_type; \
00307 for(size_t i=0;i<n;i++) { \
00308 pair_type tmp; \
00309 archive_traits<pair_type>::load(tmp,a); \
00310 v.insert(tmp); \
00311 } \
00312 } \
00313 }; \
00314 }
00315
00316 #define CPPCMS_CONTAINER_ARCHIVE(Type) \
00317 namespace cppcms { \
00318 template<typename V> \
00319 struct archive_traits<Type<V> > \
00320 { \
00321 static void save(Type<V> const &d,archive &a) \
00322 { \
00323 details::archive_save_container<Type<V> >(d,a); \
00324 } \
00325 static void load(Type<V> &d,archive &a) \
00326 { \
00327 details::archive_load_container<Type<V> >(d,a); \
00328 } \
00329 }; \
00330 }
00331
00332 CPPCMS_CONTAINER_ARCHIVE(std::vector)
00333 CPPCMS_CONTAINER_ARCHIVE(std::list)
00334 CPPCMS_CONTAINER_ARCHIVE2(std::map)
00335 CPPCMS_CONTAINER_ARCHIVE2(std::multimap)
00336 CPPCMS_CONTAINER_ARCHIVE(std::set)
00337 CPPCMS_CONTAINER_ARCHIVE(std::multiset)
00338
00339 #define CPPCMS_ARCHIVE_SMART_POINTER(SmartPtr) \
00340 namespace cppcms { \
00341 template<typename V> \
00342 struct archive_traits<SmartPtr<V> > { \
00343 typedef SmartPtr<V> pointer; \
00344 static void save(pointer const &d,archive &a) \
00345 { \
00346 char empty = d.get() == 0; \
00347 a.write_chunk(&empty,1); \
00348 if(!empty) { \
00349 archive_traits<V>::save(*d,a); \
00350 } \
00351 } \
00352 static void load(pointer &d,archive &a) \
00353 { \
00354 char empty; \
00355 a.read_chunk(&empty,1); \
00356 if(empty) { \
00357 d.reset(); \
00358 } \
00359 else { \
00360 d.reset(new V()); \
00361 archive_traits<V>::load(*d,a); \
00362 } \
00363 } \
00364 }; \
00365 }
00366
00367
00368 #define CPPCMS_ARCHIVE_INTRUSIVE_POINTER(SmartPtr) \
00369 namespace cppcms { \
00370 template<typename V> \
00371 struct archive_traits<SmartPtr<V> > { \
00372 typedef SmartPtr<V> pointer; \
00373 static void save(pointer const &d,archive &a) \
00374 { \
00375 char empty = d.get() == 0; \
00376 a.write_chunk(&empty,1); \
00377 if(!empty) { \
00378 archive_traits<V>::save(*d,a); \
00379 } \
00380 } \
00381 static void load(pointer &d,archive &a) \
00382 { \
00383 char empty; \
00384 a.read_chunk(&empty,1); \
00385 if(empty) { \
00386 d = 0; \
00387 } \
00388 else { \
00389 d = new V(); \
00390 archive_traits<V>::load(*d,a); \
00391 } \
00392 } \
00393 }; \
00394 }
00395
00396
00397
00398
00399 CPPCMS_ARCHIVE_SMART_POINTER(booster::shared_ptr)
00400 CPPCMS_ARCHIVE_SMART_POINTER(booster::hold_ptr)
00401 CPPCMS_ARCHIVE_SMART_POINTER(booster::copy_ptr)
00402 CPPCMS_ARCHIVE_SMART_POINTER(booster::clone_ptr)
00403 CPPCMS_ARCHIVE_SMART_POINTER(std::auto_ptr)
00404 CPPCMS_ARCHIVE_INTRUSIVE_POINTER(booster::intrusive_ptr)
00405
00406
00407
00409
00410
00411 #endif