ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

412 lines
9.4 KiB

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