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.
 
 
 
 
 
 

384 lines
8.0 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2010 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU Lesser General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU Lesser General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU Lesser General Public License
  16. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. //
  18. ///////////////////////////////////////////////////////////////////////////////
  19. #ifndef CPPCMS_JSON_H
  20. #define CPPCMS_JSON_H
  21. #include "defs.h"
  22. #include <booster/copy_ptr.h>
  23. #include <vector>
  24. #include <map>
  25. #include <string>
  26. #include <iostream>
  27. #include <typeinfo>
  28. namespace cppcms {
  29. namespace json {
  30. class value;
  31. struct null {};
  32. struct undefined {};
  33. inline bool operator==(undefined const &l,undefined const &r) {return true;}
  34. inline bool operator!=(undefined const &l,undefined const &r) {return false;}
  35. inline bool operator==(null const &l,null const &r) {return true;}
  36. inline bool operator!=(null const &l,null const &r) {return false;}
  37. typedef std::vector<value> array;
  38. typedef std::map<std::string,value> object;
  39. template<typename T>
  40. struct traits {
  41. static void set(value &v,T const &in);
  42. };
  43. typedef enum {
  44. is_undefined,
  45. is_null,
  46. is_boolean,
  47. is_number,
  48. is_string,
  49. is_object,
  50. is_array
  51. } json_type;
  52. enum {
  53. compact = 0,
  54. readable = 1
  55. };
  56. class CPPCMS_API bad_value_cast : public std::bad_cast {
  57. public:
  58. bad_value_cast();
  59. bad_value_cast(std::string const &s);
  60. bad_value_cast(std::string const &s,json_type actual);
  61. bad_value_cast(std::string const &s,json_type expected, json_type actual);
  62. virtual ~bad_value_cast() throw();
  63. virtual const char* what() const throw();
  64. private:
  65. std::string msg_;
  66. };
  67. class value;
  68. std::istream CPPCMS_API &operator>>(std::istream &in,value &v);
  69. std::ostream CPPCMS_API &operator<<(std::ostream &out,value const &v);
  70. std::ostream CPPCMS_API &operator<<(std::ostream &out,json_type);
  71. class CPPCMS_API value {
  72. public:
  73. json_type type() const;
  74. bool is_undefined() const;
  75. bool is_null() const;
  76. bool const &boolean() const;
  77. double const &number() const;
  78. std::string const &str() const;
  79. json::object const &object() const;
  80. json::array const &array() const;
  81. bool &boolean();
  82. double &number();
  83. std::string &str();
  84. json::object &object();
  85. json::array &array();
  86. void undefined();
  87. void null();
  88. void boolean(bool);
  89. void number(double );
  90. void str(std::string const &);
  91. void object(json::object const &);
  92. void array(json::array const &);
  93. template<typename T>
  94. T get_value() const
  95. {
  96. return traits<T>::get(*this);
  97. }
  98. template<typename T>
  99. void set_value(T const &v)
  100. {
  101. traits<T>::set(*this,v);
  102. }
  103. // returns empty if not found
  104. value const &find(std::string) const;
  105. // throws if not found
  106. value const &at(std::string) const;
  107. value &at(std::string);
  108. // sets
  109. void at(std::string,value const &v);
  110. template<typename T>
  111. value(T const &v)
  112. {
  113. set_value(v);
  114. }
  115. ///
  116. /// Returns the type of variable in path, if not found returns undefined
  117. ///
  118. json_type type(std::string path) const
  119. {
  120. return find(path).type();
  121. }
  122. ///
  123. /// Set value at specific path
  124. ///
  125. template<typename T>
  126. void set(std::string path,T const &v)
  127. {
  128. at(path,value(v));
  129. }
  130. std::string get(std::string path,char const *def) const
  131. {
  132. value const &v=find(path);
  133. if(v.is_undefined())
  134. return def;
  135. try {
  136. return v.get_value<std::string>();
  137. }
  138. catch(std::bad_cast const &e) {
  139. return def;
  140. }
  141. }
  142. template<typename T>
  143. T get(std::string path) const
  144. {
  145. return at(path).get_value<T>();
  146. }
  147. template<typename T>
  148. T get(std::string path,T const &def) const
  149. {
  150. value const &v=find(path);
  151. if(v.is_undefined())
  152. return def;
  153. try {
  154. return v.get_value<T>();
  155. }
  156. catch(std::bad_cast const &e) {
  157. return def;
  158. }
  159. }
  160. value &operator[](std::string name);
  161. value const &operator[](std::string name) const;
  162. value &operator[](size_t n);
  163. value const &operator[](size_t n) const;
  164. std::string save(int how=compact) const;
  165. void save(std::ostream &out,int how=compact) const;
  166. bool load(std::istream &in,bool full,int *line_number=0);
  167. bool operator==(value const &other) const;
  168. bool operator!=(value const &other) const;
  169. value(value const &other) :
  170. d(other.d)
  171. {
  172. }
  173. value const &operator=(value const &other)
  174. {
  175. d=other.d;
  176. return *this;
  177. }
  178. value()
  179. {
  180. }
  181. ~value()
  182. {
  183. }
  184. void swap(value &other)
  185. {
  186. d.swap(other.d);
  187. }
  188. private:
  189. void write(std::ostream &out,int tabs) const;
  190. void write_value(std::ostream &out,int tabs) const;
  191. struct data;
  192. struct copyable {
  193. data *operator->() { return &*d; }
  194. data &operator*() { return *d; }
  195. data const *operator->() const { return &*d; }
  196. data const &operator*() const { return *d; }
  197. copyable();
  198. copyable(copyable const &r);
  199. copyable const &operator=(copyable const &r);
  200. ~copyable();
  201. void swap(copyable &other)
  202. {
  203. d.swap(other.d);
  204. }
  205. private:
  206. booster::copy_ptr<data> d;
  207. } d;
  208. friend struct copyable;
  209. };
  210. /*****************************************************************
  211. template<typename T>
  212. struct traits {
  213. static T get(value const &v);
  214. static void set(value &v,T const &in);
  215. };
  216. *******************************************************************/
  217. template<typename T1,typename T2>
  218. struct traits<std::pair<T1,T2> > {
  219. static std::pair<T1,T2> get(value const &v)
  220. {
  221. if(v.object().size()!=2)
  222. throw bad_value_cast("Object with two members expected");
  223. std::pair<T1,T2> pair(v.get_value<T1>("first"),v.get_value<T2>("second"));
  224. return pair;
  225. }
  226. static void set(value &v,std::pair<T1,T2> const &in)
  227. {
  228. v=json::object();
  229. v.set_value("first",in.first);
  230. v.set_value("second",in.second);
  231. }
  232. };
  233. template<typename T>
  234. struct traits<std::vector<T> > {
  235. static std::vector<T> get(value const &v)
  236. {
  237. std::vector<T> result;
  238. json::array const &a=v.array();
  239. result.resize(a.size());
  240. for(unsigned i=0;i<a.size();i++)
  241. result[i]=a[i].get_value<T>();
  242. return result;
  243. }
  244. static void set(value &v,std::vector<T> const &in)
  245. {
  246. v=json::array();
  247. json::array &a=v.array();
  248. a.resize(in.size());
  249. for(unsigned i=0;i<in.size();i++)
  250. a[i].set_value(in[i]);
  251. }
  252. };
  253. #define CPPCMS_JSON_SPECIALIZE(type,method) \
  254. template<> \
  255. struct traits<type> { \
  256. static type get(value const &v) \
  257. { \
  258. return v.method(); \
  259. } \
  260. static void set(value &v,type const &in)\
  261. { \
  262. v.method(in); \
  263. } \
  264. };
  265. CPPCMS_JSON_SPECIALIZE(bool,boolean);
  266. CPPCMS_JSON_SPECIALIZE(double,number);
  267. CPPCMS_JSON_SPECIALIZE(std::string,str);
  268. CPPCMS_JSON_SPECIALIZE(json::object,object);
  269. CPPCMS_JSON_SPECIALIZE(json::array,array);
  270. #undef CPPCMS_JSON_SPECIALIZE
  271. template<>
  272. struct traits<int> {
  273. static int get(value const &v)
  274. {
  275. return static_cast<int>(v.number());
  276. }
  277. static void set(value &v,int const &in)
  278. {
  279. v.number(in);
  280. }
  281. };
  282. template<>
  283. struct traits<json::null> {
  284. static void set(value &v,json::null const &in)
  285. {
  286. v.null();
  287. }
  288. };
  289. template<int n>
  290. struct traits<char[n]> {
  291. typedef char array_type[n];
  292. static void set(value &v,array_type const &in)
  293. {
  294. v.str(in);
  295. }
  296. };
  297. template<>
  298. struct traits<char const *> {
  299. static void set(value &v,char const * const &in)
  300. {
  301. v.str(in);
  302. }
  303. };
  304. } // json
  305. } // cppcms
  306. #endif