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.
 
 
 
 
 
 

780 lines
20 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_JSON_H
  9. #define CPPCMS_JSON_H
  10. #include <cppcms/defs.h>
  11. #include <cppcms/string_key.h>
  12. #include <booster/copy_ptr.h>
  13. #include <booster/backtrace.h>
  14. #include <vector>
  15. #include <map>
  16. #include <string>
  17. #include <iostream>
  18. #include <limits>
  19. namespace cppcms {
  20. ///
  21. /// \brief This namespace includes all JSON parsing and formatting related classes and functions
  22. ///
  23. namespace json {
  24. class value;
  25. ///
  26. /// \brief Special object that is convertible to null json value
  27. ///
  28. struct null {};
  29. ///
  30. /// \brief Special object that is convertible to undefined json value
  31. ///
  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. ///
  38. /// \brief The json::array - std::vector of json::value's
  39. ///
  40. typedef std::vector<value> array;
  41. ///
  42. /// \brief The json::object - std::map of json::value's
  43. ///
  44. typedef std::map<string_key,value> object;
  45. #ifdef CPPCMS_DOXYGEN_DOCS
  46. ///
  47. /// \brief The type traits schema for converting json values to/from orinary objects
  48. /// i.e. serialization from JSON to C++ object
  49. ///
  50. template<typename T>
  51. struct traits {
  52. ///
  53. /// Convert json value \a v to an object of type T and return it
  54. ///
  55. static T get(value const &v);
  56. ///
  57. /// Convert an object \a in to a json::value \a v
  58. ///
  59. static void set(value &v,T const &in);
  60. };
  61. #else
  62. template<typename T>
  63. struct traits;
  64. #endif
  65. ///
  66. /// The type of json value
  67. ///
  68. typedef enum {
  69. is_undefined, ///< Undefined value
  70. is_null, ///< null value
  71. is_boolean, ///< boolean value
  72. is_number, ///< numeric value
  73. is_string, ///< string value
  74. is_object, ///< object value
  75. is_array ///< array value
  76. } json_type;
  77. enum {
  78. compact = 0, ///< Print JSON values in most compact format
  79. readable = 1 ///< Print JSON values in human readable format (with identention)
  80. };
  81. ///
  82. /// \brief The error that is thrown in case of bad conversion of json::value to ordinary value
  83. ///
  84. /// When implementing json::traits for complex classes you are expected to throw this exception
  85. /// in case of invalid formatting
  86. ///
  87. class CPPCMS_API bad_value_cast : public booster::bad_cast {
  88. public:
  89. bad_value_cast();
  90. bad_value_cast(std::string const &s);
  91. bad_value_cast(std::string const &s,json_type actual);
  92. bad_value_cast(std::string const &s,json_type expected, json_type actual);
  93. virtual ~bad_value_cast() throw();
  94. virtual const char* what() const throw();
  95. private:
  96. std::string msg_;
  97. };
  98. class value;
  99. ///
  100. /// Read json object from input stream
  101. ///
  102. std::istream CPPCMS_API &operator>>(std::istream &in,value &v);
  103. ///
  104. /// Write json object to output stream
  105. ///
  106. std::ostream CPPCMS_API &operator<<(std::ostream &out,value const &v);
  107. ///
  108. /// Write human readable representation of json_type
  109. ///
  110. std::ostream CPPCMS_API &operator<<(std::ostream &out,json_type);
  111. ///
  112. /// \brief This class is central representation of json objects.
  113. ///
  114. /// It can be a value from any type
  115. /// including scalar, object, array and undefined
  116. ///
  117. class CPPCMS_API value {
  118. public:
  119. ///
  120. /// Get the type of the value
  121. ///
  122. json_type type() const;
  123. ///
  124. /// Returns true if type()==json::is_undefined
  125. ///
  126. bool is_undefined() const;
  127. ///
  128. /// Returns true if type()==json::is_null
  129. ///
  130. bool is_null() const;
  131. ///
  132. /// Convert value to boolean, throws bad_value_cast if value's type is not boolean
  133. ///
  134. bool const &boolean() const;
  135. ///
  136. /// Convert value to double, throws bad_value_cast if value's type is not number
  137. ///
  138. double const &number() const;
  139. ///
  140. /// Convert value to strng, throws bad_value_cast if value's type is not string
  141. ///
  142. std::string const &str() const;
  143. ///
  144. /// Convert value to json::object, throws bad_value_cast if value's type is not object
  145. ///
  146. json::object const &object() const;
  147. ///
  148. /// Convert value to json::array, throws bad_value_cast if value's type is not array
  149. ///
  150. json::array const &array() const;
  151. ///
  152. /// Get reference to bool variable that represents this value, throws bad_value_cast if type is invalid
  153. ///
  154. bool &boolean();
  155. ///
  156. /// Get reference to double variable that represents this value, throws bad_value_cast if type is invalid
  157. ///
  158. double &number();
  159. ///
  160. /// Get reference to string variable that represents this value, throws bad_value_cast if type is invalid
  161. ///
  162. std::string &str();
  163. ///
  164. /// Get reference to object variable that represents this value, throws bad_value_cast if type is invalid
  165. ///
  166. json::object &object();
  167. ///
  168. /// Get reference to array variable that represents this value, throws bad_value_cast if type is invalid
  169. ///
  170. json::array &array();
  171. ///
  172. /// Set value to undefined type
  173. ///
  174. void undefined();
  175. ///
  176. /// Set value to null type
  177. ///
  178. void null();
  179. ///
  180. /// Set value to boolean type and assign it
  181. ///
  182. void boolean(bool);
  183. ///
  184. /// Set value to numeric type and assign it
  185. ///
  186. void number(double );
  187. ///
  188. /// Set value to string type and assign it
  189. ///
  190. void str(std::string const &);
  191. ///
  192. /// Set value to object type and assign it
  193. ///
  194. void object(json::object const &);
  195. ///
  196. /// Set value to array type and assign it
  197. ///
  198. void array(json::array const &);
  199. ///
  200. /// Convert the value to type T, using json::traits, throws bad_value_cast if conversion is not possible
  201. ///
  202. template<typename T>
  203. T get_value() const
  204. {
  205. return traits<T>::get(*this);
  206. }
  207. ///
  208. /// Convert the object \a v of type T to the value
  209. ///
  210. template<typename T>
  211. void set_value(T const &v)
  212. {
  213. traits<T>::set(*this,v);
  214. }
  215. ///
  216. /// Searches a value in the path \a path
  217. ///
  218. /// For example if the json::value represents { "x" : { "y" : 10 } }, then find("x.y") would return
  219. /// a reference to value that hold a number 10, find("x") returns a reference to a value
  220. /// that holds an object { "y" : 10 } and find("foo") would return value of undefined type.
  221. ///
  222. value const &find(std::string const &path) const;
  223. ///
  224. /// Searches a value in the path \a path
  225. ///
  226. /// For example if the json::value represents { "x" : { "y" : 10 } }, then find("x.y") would return
  227. /// a reference to value that hold a number 10, find("x") returns a reference to a value
  228. /// that holds an object { "y" : 10 } and find("foo") would return value of undefined type.
  229. ///
  230. value const &find(char const *path) const;
  231. ///
  232. /// Searches a value in the path \a path, if not found throw bad_value_cast.
  233. ///
  234. /// For example if the json::value represents { "x" : { "y" : 10 } }, then find("x.y") would return
  235. /// a reference to value that hold a number 10, find("x") returns a reference to a value
  236. /// that holds an object { "y" : 10 } and find("foo") throws
  237. ///
  238. value const &at(std::string const &path) const;
  239. ///
  240. /// Searches a value in the path \a path, if not found throw bad_value_cast.
  241. ///
  242. /// For example if the json::value represents { "x" : { "y" : 10 } }, then find("x.y") would return
  243. /// a reference to value that hold a number 10, find("x") returns a reference to a value
  244. /// that holds an object { "y" : 10 } and find("foo") throws
  245. ///
  246. value const &at(char const *path) const;
  247. ///
  248. /// Searches a value in the path \a path, if not found throw bad_value_cast.
  249. ///
  250. /// For example if the json::value represents { "x" : { "y" : 10 } }, then find("x.y") would return
  251. /// a reference to value that hold a number 10, find("x") returns a reference to a value
  252. /// that holds an object { "y" : 10 } and find("foo") throws
  253. ///
  254. value &at(std::string const &path);
  255. ///
  256. /// Searches a value in the path \a path, if not found throw bad_value_cast.
  257. ///
  258. /// For example if the json::value represents { "x" : { "y" : 10 } }, then find("x.y") would return
  259. /// a reference to value that hold a number 10, find("x") returns a reference to a value
  260. /// that holds an object { "y" : 10 } and find("foo") throws
  261. ///
  262. value &at(char const *path);
  263. ///
  264. /// Sets the value \a v at the path \a path, if the path invalid, creates it.
  265. ///
  266. void at(std::string const &path,value const &v);
  267. ///
  268. /// Sets the value \a v at the path \a path, if the path invalid, creates it.
  269. ///
  270. void at(char const *path,value const &v);
  271. ///
  272. /// Creates a value from and object \a v of type T
  273. ///
  274. template<typename T>
  275. value(T const &v)
  276. {
  277. set_value(v);
  278. }
  279. ///
  280. /// Returns the type of variable in path, if not found returns undefined
  281. ///
  282. /// Same as find(path).type()
  283. ///
  284. json_type type(std::string const &path) const
  285. {
  286. return find(path).type();
  287. }
  288. ///
  289. /// Returns the type of variable in path, if not found returns undefined
  290. ///
  291. /// Same as find(path).type()
  292. ///
  293. json_type type(char const *path) const
  294. {
  295. return find(path).type();
  296. }
  297. ///
  298. /// Convert an object \a v of type T to a value at specific path, same as at(path,value(v))
  299. ///
  300. template<typename T>
  301. void set(std::string const &path,T const &v)
  302. {
  303. at(path,value(v));
  304. }
  305. ///
  306. /// Convert an object \a v of type T to a value at specific path, same as at(path,value(v))
  307. ///
  308. template<typename T>
  309. void set(char const *path,T const &v)
  310. {
  311. at(path,value(v));
  312. }
  313. ///
  314. /// Get a string value from a path \a path. If the path is not invalid or the object
  315. /// is not of type string at this path, returns \a def instead
  316. ///
  317. std::string get(std::string const &path,char const *def) const
  318. {
  319. value const &v=find(path);
  320. if(v.is_undefined())
  321. return def;
  322. try {
  323. return v.get_value<std::string>();
  324. }
  325. catch(std::bad_cast const &e) {
  326. return def;
  327. }
  328. }
  329. ///
  330. /// Get a string value from a path \a path. If the path is not invalid or the object
  331. /// is not of type string at this path, returns \a def instead
  332. ///
  333. std::string get(char const *path,char const *def) const
  334. {
  335. value const &v=find(path);
  336. if(v.is_undefined())
  337. return def;
  338. try {
  339. return v.get_value<std::string>();
  340. }
  341. catch(std::bad_cast const &e) {
  342. return def;
  343. }
  344. }
  345. ///
  346. /// Get an object of type T from the path \a path. Throws bad_value_cast if such path does not
  347. /// exists of conversion can't be done
  348. ///
  349. template<typename T>
  350. T get(std::string const &path) const
  351. {
  352. return at(path).get_value<T>();
  353. }
  354. ///
  355. /// Get an object of type T from the path \a path. Throws bad_value_cast if such path does not
  356. /// exists of conversion can't be done
  357. ///
  358. template<typename T>
  359. T get(char const *path) const
  360. {
  361. return at(path).get_value<T>();
  362. }
  363. ///
  364. /// Get an object of type T from the path \a path. Returns \a def if such path does not
  365. /// exists of conversion can't be done
  366. ///
  367. template<typename T>
  368. T get(char const *path,T const &def) const
  369. {
  370. value const &v=find(path);
  371. if(v.is_undefined())
  372. return def;
  373. try {
  374. return v.get_value<T>();
  375. }
  376. catch(std::bad_cast const &e) {
  377. return def;
  378. }
  379. }
  380. ///
  381. /// Get an object of type T from the path \a path. Returns \a def if such path does not
  382. /// exists of conversion can't be done
  383. ///
  384. template<typename T>
  385. T get(std::string const &path,T const &def) const
  386. {
  387. value const &v=find(path);
  388. if(v.is_undefined())
  389. return def;
  390. try {
  391. return v.get_value<T>();
  392. }
  393. catch(std::bad_cast const &e) {
  394. return def;
  395. }
  396. }
  397. ///
  398. /// Returns a reference to the node \a name of the value.
  399. /// For value = {"x",10} and name == "x" return a value that holds 10.
  400. ///
  401. /// If value is not object it's type set to object.
  402. /// If such node does not exits, it is created with undefined value
  403. ///
  404. value &operator[](std::string const &name);
  405. ///
  406. /// Returns reference to the node \a name of the value.
  407. /// For value = {"x",10} and name == "x" return a value that holds 10.
  408. ///
  409. /// If value is not object or such node does not exits, throws bad_value_cast
  410. ///
  411. value const &operator[](std::string const &name) const;
  412. ///
  413. /// Returns a reference to \a n 'th entry of the array. If the value is not an array it is reset to array,
  414. /// of the array is too small it is resized to size of at least n+1
  415. ///
  416. value &operator[](size_t n);
  417. ///
  418. /// Returns a reference to \a n 'th entry of array, if the value is not array or n is too big, throws
  419. /// bad_value_cast
  420. ///
  421. value const &operator[](size_t n) const;
  422. ///
  423. /// Convert a value to std::string, if \a how has value \a readable it is converted with indentation
  424. ///
  425. std::string save(int how=compact) const;
  426. ///
  427. /// Write a value to std::ostream, if \a how has value \a readable it is converted with indentation
  428. ///
  429. void save(std::ostream &out,int how=compact) const;
  430. ///
  431. /// Read a value from std::istream.
  432. ///
  433. /// Note: only JSON object and JSON array are considered valid values
  434. ///
  435. /// \param in the std::istream used to read the data
  436. /// \param full require EOF once the object is read, otherwise consider it as syntax error
  437. /// \param line_number return a number of the line where syntax error occurred
  438. /// \result returns true if the value was read successfully, otherwise returns false to indicate a syntax error.
  439. ///
  440. bool load(std::istream &in,bool full,int *line_number=0);
  441. ///
  442. /// Read a value from character range
  443. ///
  444. /// Note: only JSON object and JSON array are considered valid values
  445. ///
  446. /// \param begin - begin of the text range, at the end points to the end of parsed range
  447. /// \param end - end of the text range
  448. /// \param full require EOF once the object is read, otherwise consider it as syntax error
  449. /// \param line_number return a number of the line where syntax error occurred
  450. /// \result returns true if the value was read successfully, otherwise returns false to indicate a syntax error.
  451. ///
  452. /// \ver{v1_2}
  453. bool load(char const *&begin,char const *end,bool full,int *line_number=0);
  454. ///
  455. /// Compare two values objects, return true if they are same
  456. ///
  457. bool operator==(value const &other) const;
  458. ///
  459. /// Compare two values objects, return false if they are same
  460. ///
  461. bool operator!=(value const &other) const;
  462. ///
  463. /// Copy constructor
  464. ///
  465. value(value const &other) :
  466. d(other.d)
  467. {
  468. }
  469. ///
  470. /// Assignment operator
  471. ///
  472. value const &operator=(value const &other)
  473. {
  474. d=other.d;
  475. return *this;
  476. }
  477. ///
  478. /// Default value - creates a value of undefined type
  479. ///
  480. value()
  481. {
  482. }
  483. ///
  484. /// Destructor
  485. ///
  486. ~value()
  487. {
  488. }
  489. ///
  490. /// Swaps two values, does not throw.
  491. ///
  492. void swap(value &other)
  493. {
  494. d.swap(other.d);
  495. }
  496. private:
  497. void write(std::ostream &out,int tabs) const;
  498. void write_value(std::ostream &out,int tabs) const;
  499. struct _data;
  500. struct CPPCMS_API copyable {
  501. _data *operator->() { return &*d; }
  502. _data &operator*() { return *d; }
  503. _data const *operator->() const { return &*d; }
  504. _data const &operator*() const { return *d; }
  505. copyable();
  506. copyable(copyable const &r);
  507. copyable const &operator=(copyable const &r);
  508. ~copyable();
  509. void swap(copyable &other)
  510. {
  511. d.swap(other.d);
  512. }
  513. private:
  514. booster::copy_ptr<_data> d;
  515. } d;
  516. friend struct copyable;
  517. };
  518. ///
  519. /// Convert UTF-8 string to JSON string, i.e. a sring foo is converted to "foo",
  520. /// a string bar"baz is converted to "bar\"baz"
  521. ///
  522. /// \ver{v1_2}
  523. std::string CPPCMS_API to_json(std::string const &utf);
  524. ///
  525. /// Convert UTF-8 string to JSON string, i.e. a sring foo is converted to "foo",
  526. /// a string bar"baz is converted to "bar\"baz"
  527. ///
  528. /// \ver{v1_2}
  529. std::string CPPCMS_API to_json(char const *begin,char const *end);
  530. ///
  531. /// Convert UTF-8 string to JSON string, i.e. a sring foo is converted to "foo",
  532. /// a string bar"baz is converted to "bar\"baz"
  533. ///
  534. /// \ver{v1_2}
  535. void CPPCMS_API to_json(char const *begin,char const *end,std::ostream &out);
  536. //
  537. /// Convert UTF-8 string to JSON string, i.e. a sring foo is converted to "foo",
  538. /// a string bar"baz is converted to "bar\"baz"
  539. ///
  540. /// \ver{v1_2}
  541. void CPPCMS_API to_json(std::string const &str,std::ostream &out);
  542. /// \cond INTERNAL
  543. template<typename T1,typename T2>
  544. struct traits<std::pair<T1,T2> > {
  545. static std::pair<T1,T2> get(value const &v)
  546. {
  547. if(v.object().size()!=2)
  548. throw bad_value_cast("Object with two members expected");
  549. std::pair<T1,T2> pair(v.get_value<T1>("first"),v.get_value<T2>("second"));
  550. return pair;
  551. }
  552. static void set(value &v,std::pair<T1,T2> const &in)
  553. {
  554. v=json::object();
  555. v.set_value("first",in.first);
  556. v.set_value("second",in.second);
  557. }
  558. };
  559. template<typename T>
  560. struct traits<std::vector<T> > {
  561. static std::vector<T> get(value const &v)
  562. {
  563. std::vector<T> result;
  564. json::array const &a=v.array();
  565. result.resize(a.size());
  566. for(unsigned i=0;i<a.size();i++)
  567. result[i]=a[i].get_value<T>();
  568. return result;
  569. }
  570. static void set(value &v,std::vector<T> const &in)
  571. {
  572. v=json::array();
  573. json::array &a=v.array();
  574. a.resize(in.size());
  575. for(unsigned i=0;i<in.size();i++)
  576. a[i].set_value(in[i]);
  577. }
  578. };
  579. #define CPPCMS_JSON_SPECIALIZE(type,method) \
  580. template<> \
  581. struct traits<type> { \
  582. static type get(value const &v) \
  583. { \
  584. return v.method(); \
  585. } \
  586. static void set(value &v,type const &in)\
  587. { \
  588. v.method(in); \
  589. } \
  590. };
  591. CPPCMS_JSON_SPECIALIZE(bool,boolean);
  592. CPPCMS_JSON_SPECIALIZE(double,number);
  593. CPPCMS_JSON_SPECIALIZE(std::string,str);
  594. CPPCMS_JSON_SPECIALIZE(json::object,object);
  595. CPPCMS_JSON_SPECIALIZE(json::array,array);
  596. #undef CPPCMS_JSON_SPECIALIZE
  597. #define CPPCMS_JSON_SPECIALIZE_INT(type) \
  598. template<> \
  599. struct traits<type> { \
  600. static type get(value const &v) \
  601. { \
  602. type res=static_cast<type>(v.number()); \
  603. if(res!=v.number()) \
  604. throw bad_value_cast(); \
  605. return res; \
  606. } \
  607. static void set(value &v,type const &in) \
  608. { \
  609. if(std::numeric_limits<type>::digits > \
  610. std::numeric_limits<double>::digits \
  611. && static_cast<double>(in)!=in) \
  612. { \
  613. throw bad_value_cast(); \
  614. } \
  615. v.number(static_cast<double>(in)); \
  616. } \
  617. };
  618. CPPCMS_JSON_SPECIALIZE_INT(char)
  619. CPPCMS_JSON_SPECIALIZE_INT(unsigned char)
  620. CPPCMS_JSON_SPECIALIZE_INT(signed char)
  621. CPPCMS_JSON_SPECIALIZE_INT(wchar_t)
  622. CPPCMS_JSON_SPECIALIZE_INT(short)
  623. CPPCMS_JSON_SPECIALIZE_INT(unsigned short)
  624. CPPCMS_JSON_SPECIALIZE_INT(int)
  625. CPPCMS_JSON_SPECIALIZE_INT(unsigned int)
  626. CPPCMS_JSON_SPECIALIZE_INT(long)
  627. CPPCMS_JSON_SPECIALIZE_INT(unsigned long)
  628. CPPCMS_JSON_SPECIALIZE_INT(long long)
  629. CPPCMS_JSON_SPECIALIZE_INT(unsigned long long)
  630. #undef CPPCMS_JSON_SPECIALIZE_INT
  631. template<>
  632. struct traits<float> {
  633. static float get(value const &v)
  634. {
  635. double r=v.number();
  636. if( r < (-std::numeric_limits<float>::max()) // actually should be C++11 lowest, but it should be under IEEE float lowest()=-max()
  637. || std::numeric_limits<float>::max() < r )
  638. {
  639. throw bad_value_cast();
  640. }
  641. return static_cast<float>(r);
  642. }
  643. static void set(value &v,float const &in)
  644. {
  645. v.number(in);
  646. }
  647. };
  648. template<>
  649. struct traits<long double> {
  650. static long double get(value const &v)
  651. {
  652. return v.number();
  653. }
  654. static void set(value &v,long double const &in)
  655. {
  656. if( in < -std::numeric_limits<double>::max() // should actually be std::numeric_limits<float>::lowest() but it is ==-max()
  657. || std::numeric_limits<double>::max() < in )
  658. {
  659. throw bad_value_cast();
  660. }
  661. v.number(static_cast<double>(in));
  662. }
  663. };
  664. template<>
  665. struct traits<json::null> {
  666. static void set(value &v,json::null const &/*in*/)
  667. {
  668. v.null();
  669. }
  670. };
  671. template<int n>
  672. struct traits<char[n]> {
  673. typedef char vtype[n];
  674. static void set(value &v,vtype const &in)
  675. {
  676. v.str(in);
  677. }
  678. };
  679. template<int n>
  680. struct traits<char const [n]> {
  681. typedef char const vtype[n];
  682. static void set(value &v,vtype const &in)
  683. {
  684. v.str(in);
  685. }
  686. };
  687. template<>
  688. struct traits<char const *> {
  689. static void set(value &v,char const * const &in)
  690. {
  691. v.str(in);
  692. }
  693. };
  694. /// \endcond
  695. } // json
  696. } // cppcms
  697. #endif