|
- ///////////////////////////////////////////////////////////////////////////////
- //
- // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
- //
- // See accompanying file COPYING.TXT file for licensing details.
- //
- ///////////////////////////////////////////////////////////////////////////////
- #ifndef CPPCMS_ARCHIVE_TRAITS_H
- #define CPPCMS_ARCHIVE_TRAITS_H
-
- #include <cppcms/serialization_classes.h>
- #include <cppcms/json.h>
-
- #include <booster/shared_ptr.h>
- #include <booster/intrusive_ptr.h>
- #include <booster/hold_ptr.h>
- #include <booster/clone_ptr.h>
- #include <booster/copy_ptr.h>
-
- #include <booster/traits/enable_if.h>
- #include <booster/traits/is_base_of.h>
-
- #include <booster/auto_ptr_inc.h>
- #include <iterator>
- #include <map>
- #include <vector>
- #include <list>
- #include <set>
- #include <sstream>
-
- /// \cond internal
-
- namespace cppcms {
-
-
- template<typename S>
- struct archive_traits<S,typename booster::enable_if<booster::is_base_of<serializable_base,S> >::type > {
- static void save(serializable_base const &d,archive &a)
- {
- d.save(a);
- }
- static void load(serializable_base &d,archive &a)
- {
- d.load(a);
- }
- };
-
- template<typename T>
- struct archive_traits<T const> {
- static void save(T const &o,archive &a)
- {
- archive_traits<T>::save(o,a);
- }
- static void load(T &o,archive &a)
- {
- archive_traits<T>::load(o,a);
- }
- };
-
- template<>
- struct archive_traits<std::string> {
- static void save(std::string const &o,archive &a)
- {
- a.write_chunk(o.c_str(),o.size());
- }
- static void load(std::string &o,archive &a)
- {
- std::string res = a.read_chunk_as_string();
- res.swap(o);
- }
- };
-
- namespace details {
-
- struct pod_data {
- void *pointer;
- size_t len;
- };
-
- struct const_pod_data {
- void const *pointer;
- size_t len;
- };
-
- inline archive &operator<<(archive &a,const_pod_data const &d)
- {
- a.write_chunk(d.pointer,d.len);
- return a;
- }
-
-
- inline archive &operator&(archive &a,pod_data const &d)
- {
- if(a.mode()==archive::load_from_archive)
- a.read_chunk(d.pointer,d.len);
- else
- a.write_chunk(d.pointer,d.len);
- return a;
- }
- inline archive &operator<<(archive &a,pod_data const &d)
- {
- a.write_chunk(d.pointer,d.len);
- return a;
- }
- inline archive &operator>>(archive &a,pod_data const &d)
- {
- a.read_chunk(d.pointer,d.len);
- return a;
- }
-
- }
-
- template<typename T>
- details::pod_data as_pod(T &v)
- {
- details::pod_data d = { &v , sizeof(v) };
- return d;
- }
-
- template<typename T>
- details::const_pod_data as_pod(T const &v)
- {
- details::const_pod_data d = { &v , sizeof(v) };
- return d;
- }
-
- } // cppcms
-
-
- #define CPPCMS_TRIVIAL_ARCHIVE(Type) \
- namespace cppcms { \
- template<> \
- struct archive_traits<std::vector<Type> > { \
- typedef std::vector<Type> vec; \
- static void save(vec const &v,archive &a) \
- { \
- void const *p=0; \
- size_t len= \
- v.size()*sizeof(Type); \
- if(!v.empty()) \
- p=&v.front(); \
- a.write_chunk(p,len); \
- } \
- static void load(vec &v,archive &a) \
- { \
- size_t n=a.next_chunk_size() / \
- sizeof(Type); \
- v.clear(); \
- v.resize(n); \
- void *p=0; \
- if(!v.empty()) \
- p=&v.front(); \
- a.read_chunk(p,n*sizeof(Type)); \
- } \
- }; \
- \
- template<int n> \
- struct archive_traits<Type[n]> { \
- static void save(Type const d[n],archive &a) \
- { \
- a.write_chunk(&d[0],sizeof(Type)*n); \
- } \
- static void load(Type d[n],archive &a) \
- { \
- a.read_chunk(&d[0],sizeof(Type)*n); \
- } \
- }; \
- template<int n> \
- struct archive_traits<Type const [n]> { \
- static void save(Type const d[n],archive &a) \
- { \
- a.write_chunk(&d[0],sizeof(Type)*n); \
- } \
- }; \
- \
- template<> \
- struct archive_traits<Type> { \
- static void save(Type const d,archive &a) \
- { \
- a.write_chunk(&d,sizeof(d)); \
- } \
- static void load(Type &d,archive &a) \
- { \
- a.read_chunk(&d,sizeof(d)); \
- } \
- }; \
- } /* cppcms */
-
- CPPCMS_TRIVIAL_ARCHIVE(char)
- CPPCMS_TRIVIAL_ARCHIVE(signed char)
- CPPCMS_TRIVIAL_ARCHIVE(unsigned char)
- CPPCMS_TRIVIAL_ARCHIVE(signed short)
- CPPCMS_TRIVIAL_ARCHIVE(unsigned short)
- CPPCMS_TRIVIAL_ARCHIVE(signed int)
- CPPCMS_TRIVIAL_ARCHIVE(unsigned int)
- CPPCMS_TRIVIAL_ARCHIVE(signed long)
- CPPCMS_TRIVIAL_ARCHIVE(unsigned long)
- CPPCMS_TRIVIAL_ARCHIVE(signed long long)
- CPPCMS_TRIVIAL_ARCHIVE(unsigned long long)
- CPPCMS_TRIVIAL_ARCHIVE(wchar_t)
- CPPCMS_TRIVIAL_ARCHIVE(float)
- CPPCMS_TRIVIAL_ARCHIVE(double)
- CPPCMS_TRIVIAL_ARCHIVE(long double)
-
-
- namespace cppcms {
-
- template<typename T,int size>
- struct archive_traits<T [size]>
- {
- static void save(T const d[size],archive &a)
- {
- for(int i=0;i<size;i++)
- archive_traits<T>::save(d[i],a);
- }
- static void load(T d[size],archive &a)
- {
- for(int i=0;i<size;i++)
- archive_traits<T>::load(d[i],a);
- }
- };
-
- template<typename F,typename S>
- struct archive_traits<std::pair<F,S> >
- {
- static void save(std::pair<F,S> const &d,archive &a)
- {
- archive_traits<F>::save(d.first,a);
- archive_traits<S>::save(d.second,a);
- }
- static void load(std::pair<F,S> &d,archive &a)
- {
- archive_traits<F>::load(d.first,a);
- archive_traits<S>::load(d.second,a);
- }
- };
-
- template<>
- struct archive_traits<json::value> {
- static void save(json::value const &v,archive &a)
- {
- std::ostringstream ss;
- v.save(ss);
- std::string s=ss.str();
- a.write_chunk(s.c_str(),s.size());
- }
- static void load(json::value &v,archive &a)
- {
- std::istringstream ss;
- ss.str(a.read_chunk_as_string());
- if(!v.load(ss,true)) {
- throw archive_error("Invalid json");
- }
- }
- };
-
- namespace details {
-
- template<typename T>
- void archive_save_container(T const &v,archive &a)
- {
- typename T::const_iterator it;
- typedef typename T::value_type value_type;
- size_t n=v.size();
- archive_traits<size_t>::save(n,a);
- for(it=v.begin();it!=v.end();++it) {
- archive_traits<value_type>::save(*it,a);
- }
- }
-
- template<typename T>
- void archive_load_container(T &v,archive &a)
- {
- size_t n;
- archive_traits<size_t>::load(n,a);
- v.clear();
- std::insert_iterator<T> it(v,v.begin());
- typedef typename T::value_type value_type;
- for(size_t i=0;i<n;i++) {
- value_type tmp;
- archive_traits<value_type>::load(tmp,a);
- *it++ = tmp;
- }
- }
- } // details
-
-
-
- } /// cppcms
-
- #define CPPCMS_CONTAINER_ARCHIVE2(Type) \
- namespace cppcms { \
- template<typename V1,typename V2> \
- struct archive_traits<Type<V1,V2> > \
- { \
- typedef Type<V1,V2> cont; \
- static void save(cont const &d,archive &a) \
- { \
- details::archive_save_container<cont>(d,a); \
- } \
- static void load(cont &v,archive &a) \
- { \
- size_t n; \
- archive_traits<size_t>::load(n,a); \
- v.clear(); \
- typedef std::pair<V1,V2> pair_type; \
- for(size_t i=0;i<n;i++) { \
- pair_type tmp; \
- archive_traits<pair_type>::load(tmp,a); \
- v.insert(tmp); \
- } \
- } \
- }; \
- } /* cppcms */
-
- #define CPPCMS_CONTAINER_ARCHIVE(Type) \
- namespace cppcms { \
- template<typename V> \
- struct archive_traits<Type<V> > \
- { \
- static void save(Type<V> const &d,archive &a) \
- { \
- details::archive_save_container<Type<V> >(d,a); \
- } \
- static void load(Type<V> &d,archive &a) \
- { \
- details::archive_load_container<Type<V> >(d,a); \
- } \
- }; \
- } /* cppcms */
-
- CPPCMS_CONTAINER_ARCHIVE(std::vector)
- CPPCMS_CONTAINER_ARCHIVE(std::list)
- CPPCMS_CONTAINER_ARCHIVE2(std::map)
- CPPCMS_CONTAINER_ARCHIVE2(std::multimap)
- CPPCMS_CONTAINER_ARCHIVE(std::set)
- CPPCMS_CONTAINER_ARCHIVE(std::multiset)
-
- #define CPPCMS_ARCHIVE_SMART_POINTER(SmartPtr) \
- namespace cppcms { \
- template<typename V> \
- struct archive_traits<SmartPtr<V> > { \
- typedef SmartPtr<V> pointer; \
- static void save(pointer const &d,archive &a) \
- { \
- char empty = d.get() == 0; \
- a.write_chunk(&empty,1); \
- if(!empty) { \
- archive_traits<V>::save(*d,a); \
- } \
- } \
- static void load(pointer &d,archive &a) \
- { \
- char empty; \
- a.read_chunk(&empty,1); \
- if(empty) { \
- d.reset(); \
- } \
- else { \
- d.reset(new V()); \
- archive_traits<V>::load(*d,a); \
- } \
- } \
- }; \
- } /* cppcms */
-
-
- #define CPPCMS_ARCHIVE_INTRUSIVE_POINTER(SmartPtr) \
- namespace cppcms { \
- template<typename V> \
- struct archive_traits<SmartPtr<V> > { \
- typedef SmartPtr<V> pointer; \
- static void save(pointer const &d,archive &a) \
- { \
- char empty = d.get() == 0; \
- a.write_chunk(&empty,1); \
- if(!empty) { \
- archive_traits<V>::save(*d,a); \
- } \
- } \
- static void load(pointer &d,archive &a) \
- { \
- char empty; \
- a.read_chunk(&empty,1); \
- if(empty) { \
- d = 0; \
- } \
- else { \
- d = new V(); \
- archive_traits<V>::load(*d,a); \
- } \
- } \
- }; \
- } /* cppcms */
-
-
-
-
- CPPCMS_ARCHIVE_SMART_POINTER(booster::shared_ptr)
- CPPCMS_ARCHIVE_SMART_POINTER(booster::hold_ptr)
- CPPCMS_ARCHIVE_SMART_POINTER(booster::copy_ptr)
- CPPCMS_ARCHIVE_SMART_POINTER(booster::clone_ptr)
- CPPCMS_ARCHIVE_SMART_POINTER(std::auto_ptr)
- CPPCMS_ARCHIVE_INTRUSIVE_POINTER(booster::intrusive_ptr)
-
-
-
- /// \endcond
-
-
- #endif
|