5MP Motion Camera JPEG Image and Movie Catcher  1.1.1.1
A CGI interface to capture and display pictures and movies using OpenCV.
jsonxx.h
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset: 4; -*-
2 
3 // Author: Hong Jiang <hong@hjiang.net>
4 // Contributors:
5 // Sean Middleditch <sean@middleditch.us>
6 // rlyeh <https://github.com/r-lyeh>
7 
8 #pragma once
9 
10 #include <cstddef>
11 #include <cassert>
12 #include <iostream>
13 #include <map>
14 #include <vector>
15 #include <string>
16 #include <sstream>
17 
18 // jsonxx versioning: major.minor-extra where
19 // major = { number }
20 // minor = { number }
21 // extra = { 'a':alpha, 'b':beta, 'rc': release candidate, 'r': release, 's':stable }
22 #define JSONXX_MAJOR "0"
23 #define JSONXX_MINOR "22"
24 #define JSONXX_EXTRA "a"
25 #define JSONXX_VERSION JSONXX_MAJOR "." JSONXX_MINOR "-" JSONXX_EXTRA
26 #define JSONXX_XML_TAG "<!-- generated by jsonxx " JSONXX_VERSION " -->"
27 
28 #if __cplusplus > 199711L
29 #define JSONXX_COMPILER_HAS_CXX11 1
30 #elif defined(_MSC_VER) && _MSC_VER > 1700
31 #define JSONXX_COMPILER_HAS_CXX11 1
32 #else
33 #define JSONXX_COMPILER_HAS_CXX11 0
34 #endif
35 
36 #ifdef _MSC_VER
37 // disable the C4127 warning if using VC, see http://stackoverflow.com/a/12042515
38 #define JSONXX_ASSERT(...) \
39  do { \
40  __pragma(warning(push)) __pragma(warning(disable:4127)) \
41  if( jsonxx::Assertions ) \
42  __pragma(warning(pop)) \
43  jsonxx::assertion(__FILE__,__LINE__,#__VA_ARGS__,bool(__VA_ARGS__)); \
44  __pragma(warning(push)) __pragma(warning(disable:4127)) \
45  } while(0) \
46  __pragma(warning(pop))
47 #else
48 #define JSONXX_ASSERT(...) do { if( jsonxx::Assertions ) \
49  jsonxx::assertion(__FILE__,__LINE__,#__VA_ARGS__,bool(__VA_ARGS__)); } while(0)
50 #endif
51 
52 namespace jsonxx {
53 
54 // FIXME(hjiang): Those should really be dynamic.
55 // Settings
56 enum Settings {
57  // constants
58  Enabled = true,
59  Disabled = false,
60  Permissive = true,
61  Strict = false,
62  // values
63  Parser = Strict, // permissive or strict parsing
64  UnquotedKeys = Disabled, // support of unquoted keys
65  Assertions = Disabled // enabled or disabled assertions (these asserts work both in DEBUG and RELEASE builds)
66 };
67 
68 #ifdef _MSC_VER
69 #pragma warning(push)
70 #pragma warning(disable:4127)
71 #endif
72 inline bool parser_is_strict() { return Parser == Strict; }
73 inline bool parser_is_permissive() { return Parser == Permissive; }
74 inline bool unquoted_keys_are_enabled() { return UnquotedKeys == Enabled; }
75 #ifdef _MSC_VER
76 #pragma warning(pop)
77 #endif
78 
79 // Constants for .write() and .xml() methods
80 enum Format {
81  JSON = 0, // JSON output
82  JSONx = 1, // XML output, JSONx format. see http://goo.gl/I3cxs
83  JXML = 2, // XML output, JXML format. see https://github.com/r-lyeh/JXML
84  JXMLex = 3, // XML output, JXMLex format. see https://github.com/r-lyeh/JXMLex
85  TaggedXML = 4 // XML output, tagged XML format. see https://github.com/hjiang/jsonxx/issues/12
86 };
87 
88 // Types
89 typedef long double Number;
90 typedef bool Boolean;
91 typedef std::string String;
92 struct Null {};
93 class Value;
94 class Object;
95 class Array;
96 
97 // Identity meta-function
98 template <typename T>
99 struct identity {
100  typedef T type;
101 };
102 
103 // Tools
104 bool validate( const std::string &input );
105 bool validate( std::istream &input );
106 std::string reformat( const std::string &input );
107 std::string reformat( std::istream &input );
108 std::string xml( const std::string &input, unsigned format = JSONx );
109 std::string xml( std::istream &input, unsigned format = JSONx );
110 
111 // Detail
112 void assertion( const char *file, int line, const char *expression, bool result );
113 
114 // A JSON Object
115 class Object {
116  public:
117  Object();
118  ~Object();
119 
120  template <typename T>
121  bool has(const std::string& key) const;
122 
123  // Always call has<>() first. If the key doesn't exist, consider
124  // the behavior undefined.
125  template <typename T>
126  T& get(const std::string& key);
127  template <typename T>
128  const T& get(const std::string& key) const;
129 
130  template <typename T>
131  const T& get(const std::string& key, const typename identity<T>::type& default_value) const;
132 
133  size_t size() const;
134  bool empty() const;
135 
136  const std::map<std::string, Value*>& kv_map() const;
137  std::string json() const;
138  std::string xml( unsigned format = JSONx, const std::string &header = std::string(), const std::string &attrib = std::string() ) const;
139  std::string write( unsigned format ) const;
140 
141  void reset();
142  bool parse(std::istream &input);
143  bool parse(const std::string &input);
144  typedef std::map<std::string, Value*> container;
145  void import( const Object &other );
146  void import( const std::string &key, const Value &value );
147  Object &operator<<(const Value &value);
148  Object &operator<<(const Object &value);
149  Object &operator=(const Object &value);
150  Object(const Object &other);
151  Object(const std::string &key, const Value &value);
152  template<size_t N>
153  Object(const char (&key)[N], const Value &value) {
154  import(key,value);
155  }
156  template<typename T>
157  Object &operator<<(const T &value);
158 
159  protected:
160  static bool parse(std::istream& input, Object& object);
161  container value_map_;
162  std::string odd;
163 };
164 
165 class Array {
166  public:
167  Array();
168  ~Array();
169 
170  size_t size() const;
171  bool empty() const;
172 
173  template <typename T>
174  bool has(unsigned int i) const;
175 
176  template <typename T>
177  T& get(unsigned int i);
178  template <typename T>
179  const T& get(unsigned int i) const;
180 
181  template <typename T>
182  const T& get(unsigned int i, const typename identity<T>::type& default_value) const;
183 
184  const std::vector<Value*>& values() const {
185  return values_;
186  }
187  std::string json() const;
188  std::string xml( unsigned format = JSONx, const std::string &header = std::string(), const std::string &attrib = std::string() ) const;
189 
190  std::string write( unsigned format ) const { return format == JSON ? json() : xml(format); }
191  void reset();
192  bool parse(std::istream &input);
193  bool parse(const std::string &input);
194  typedef std::vector<Value*> container;
195  void append(const Array &other);
196  void append(const Value &value) { import(value); }
197  void import(const Array &other);
198  void import(const Value &value);
199  Array &operator<<(const Array &other);
200  Array &operator<<(const Value &value);
201  Array &operator=(const Array &other);
202  Array &operator=(const Value &value);
203  Array(const Array &other);
204  Array(const Value &value);
205  protected:
206  static bool parse(std::istream& input, Array& array);
207  container values_;
208 };
209 
210 // A value could be a number, an array, a string, an object, a
211 // boolean, or null
212 class Value {
213  public:
214 
215  Value();
216  ~Value() { reset(); }
217  void reset();
218 
219  template<typename T>
220  void import( const T & ) {
221  reset();
222  type_ = INVALID_;
223  // debug
224  // std::cout << "[WARN] No support for " << typeid(t).name() << std::endl;
225  }
226  void import( const bool &b ) {
227  reset();
228  type_ = BOOL_;
229  bool_value_ = b;
230  }
231 #define $number(TYPE) \
232  void import( const TYPE &n ) { \
233  reset(); \
234  type_ = NUMBER_; \
235  number_value_ = static_cast<long double>(n); \
236  }
237  $number( char )
238  $number( int )
239  $number( long )
240  $number( long long )
241  $number( unsigned char )
242  $number( unsigned int )
243  $number( unsigned long )
244  $number( unsigned long long )
245  $number( float )
246  $number( double )
247  $number( long double )
248 #undef $number
249 #if JSONXX_COMPILER_HAS_CXX11 > 0
250  void import( const std::nullptr_t & ) {
251  reset();
252  type_ = NULL_;
253  }
254 #endif
255  void import( const Null & ) {
256  reset();
257  type_ = NULL_;
258  }
259  void import( const String &s ) {
260  reset();
261  type_ = STRING_;
262  *( string_value_ = new String() ) = s;
263  }
264  void import( const Array &a ) {
265  reset();
266  type_ = ARRAY_;
267  *( array_value_ = new Array() ) = a;
268  }
269  void import( const Object &o ) {
270  reset();
271  type_ = OBJECT_;
272  *( object_value_ = new Object() ) = o;
273  }
274  void import( const Value &other ) {
275  if (this != &other)
276  switch (other.type_) {
277  case NULL_:
278  import( Null() );
279  break;
280  case BOOL_:
281  import( other.bool_value_ );
282  break;
283  case NUMBER_:
284  import( other.number_value_ );
285  break;
286  case STRING_:
287  import( *other.string_value_ );
288  break;
289  case ARRAY_:
290  import( *other.array_value_ );
291  break;
292  case OBJECT_:
293  import( *other.object_value_ );
294  break;
295  case INVALID_:
296  type_ = INVALID_;
297  break;
298  default:
299  JSONXX_ASSERT( !"not implemented" );
300  }
301  }
302  template<typename T>
303  Value &operator <<( const T &t ) {
304  import(t);
305  return *this;
306  }
307  template<typename T>
308  Value &operator =( const T &t ) {
309  reset();
310  import(t);
311  return *this;
312  }
313  Value(const Value &other);
314  template<typename T>
315  Value( const T&t ) : type_(INVALID_) { import(t); }
316  template<size_t N>
317  Value( const char (&t)[N] ) : type_(INVALID_) { import( std::string(t) ); }
318 
319  bool parse(std::istream &input);
320  bool parse(const std::string &input);
321 
322  template<typename T>
323  bool is() const;
324  template<typename T>
325  T& get();
326  template<typename T>
327  const T& get() const;
328 
329  bool empty() const;
330 
331  public:
332  enum {
339  INVALID_
340  } type_;
341  union {
343  String* string_value_;
344  Boolean bool_value_;
347  };
348 
349 protected:
350  static bool parse(std::istream& input, Value& value);
351 };
352 
353 template <typename T>
354 bool Array::has(unsigned int i) const {
355  if (i >= size()) {
356  return false;
357  } else {
358  Value* v = values_.at(i);
359  return v->is<T>();
360  }
361 }
362 
363 template <typename T>
364 T& Array::get(unsigned int i) {
365  JSONXX_ASSERT(i < size());
366  Value* v = values_.at(i);
367  return v->get<T>();
368 }
369 
370 template <typename T>
371 const T& Array::get(unsigned int i) const {
372  JSONXX_ASSERT(i < size());
373  const Value* v = values_.at(i);
374  return v->get<T>();
375 }
376 
377 template <typename T>
378 const T& Array::get(unsigned int i, const typename identity<T>::type& default_value) const {
379  if(has<T>(i)) {
380  const Value* v = values_.at(i);
381  return v->get<T>();
382  } else {
383  return default_value;
384  }
385 }
386 
387 template <typename T>
388 bool Object::has(const std::string& key) const {
389  container::const_iterator it(value_map_.find(key));
390  return it != value_map_.end() && it->second->is<T>();
391 }
392 
393 template <typename T>
394 T& Object::get(const std::string& key) {
395  JSONXX_ASSERT(has<T>(key));
396  return value_map_.find(key)->second->get<T>();
397 }
398 
399 template <typename T>
400 const T& Object::get(const std::string& key) const {
401  JSONXX_ASSERT(has<T>(key));
402  return value_map_.find(key)->second->get<T>();
403 }
404 
405 template <typename T>
406 const T& Object::get(const std::string& key, const typename identity<T>::type& default_value) const {
407  if (has<T>(key)) {
408  return value_map_.find(key)->second->get<T>();
409  } else {
410  return default_value;
411  }
412 }
413 
414 template<>
415 inline bool Value::is<Value>() const {
416  return true;
417 }
418 
419 template<>
420 inline bool Value::is<Null>() const {
421  return type_ == NULL_;
422 }
423 
424 template<>
425 inline bool Value::is<Boolean>() const {
426  return type_ == BOOL_;
427 }
428 
429 template<>
430 inline bool Value::is<String>() const {
431  return type_ == STRING_;
432 }
433 
434 template<>
435 inline bool Value::is<Number>() const {
436  return type_ == NUMBER_;
437 }
438 
439 template<>
440 inline bool Value::is<Array>() const {
441  return type_ == ARRAY_;
442 }
443 
444 template<>
445 inline bool Value::is<Object>() const {
446  return type_ == OBJECT_;
447 }
448 
449 template<>
450 inline Value& Value::get<Value>() {
451  return *this;
452 }
453 
454 template<>
455 inline const Value& Value::get<Value>() const {
456  return *this;
457 }
458 
459 template<>
460 inline bool& Value::get<Boolean>() {
461  JSONXX_ASSERT(is<Boolean>());
462  return bool_value_;
463 }
464 
465 template<>
466 inline std::string& Value::get<String>() {
467  JSONXX_ASSERT(is<String>());
468  return *string_value_;
469 }
470 
471 template<>
472 inline Number& Value::get<Number>() {
473  JSONXX_ASSERT(is<Number>());
474  return number_value_;
475 }
476 
477 template<>
478 inline Array& Value::get<Array>() {
479  JSONXX_ASSERT(is<Array>());
480  return *array_value_;
481 }
482 
483 template<>
484 inline Object& Value::get<Object>() {
485  JSONXX_ASSERT(is<Object>());
486  return *object_value_;
487 }
488 
489 template<>
490 inline const Boolean& Value::get<Boolean>() const {
491  JSONXX_ASSERT(is<Boolean>());
492  return bool_value_;
493 }
494 
495 template<>
496 inline const String& Value::get<String>() const {
497  JSONXX_ASSERT(is<String>());
498  return *string_value_;
499 }
500 
501 template<>
502 inline const Number& Value::get<Number>() const {
503  JSONXX_ASSERT(is<Number>());
504  return number_value_;
505 }
506 
507 template<>
508 inline const Array& Value::get<Array>() const {
509  JSONXX_ASSERT(is<Array>());
510  return *array_value_;
511 }
512 
513 template<>
514 inline const Object& Value::get<Object>() const {
515  JSONXX_ASSERT(is<Object>());
516  return *object_value_;
517 }
518 
519 template<typename T>
520 inline Object &Object::operator<<(const T &value) {
521  *this << Value(value);
522  return *this;
523 }
524 
525 } // namespace jsonxx
526 
527 std::ostream& operator<<(std::ostream& stream, const jsonxx::Value& v);
528 std::ostream& operator<<(std::ostream& stream, const jsonxx::Object& v);
529 std::ostream& operator<<(std::ostream& stream, const jsonxx::Array& v);
Object(const char(&key)[N], const Value &value)
Definition: jsonxx.h:153
std::string xml(std::istream &input, unsigned format)
Definition: jsonxx.cc:970
long double Number
Definition: jsonxx.h:89
Value(const char(&t)[N])
Definition: jsonxx.h:317
bool unquoted_keys_are_enabled()
Definition: jsonxx.h:74
T & get(const std::string &key)
Definition: jsonxx.h:394
std::vector< Value * > container
Definition: jsonxx.h:194
Definition: jsonxx.h:212
Definition: jsonxx.h:61
Definition: jsonxx.h:92
String * string_value_
Definition: jsonxx.h:343
$number(char) $number(int) $number(long) $number(long long) $number(unsigned char) $number(unsigned int) $number(unsigned long) $number(unsigned long long) $number(float) $number(double) $number(long double) $ void import(const Null &)
Definition: jsonxx.h:237
Definition: jsonxx.h:334
Definition: jsonxx.h:60
T type
Definition: jsonxx.h:100
bool has(const std::string &key) const
Definition: jsonxx.h:388
Boolean bool_value_
Definition: jsonxx.h:344
Value(const T &t)
Definition: jsonxx.h:315
Definition: jsonxx.h:337
Definition: jsonxx.h:65
#define JSONXX_ASSERT(...)
Definition: jsonxx.h:48
Definition: jsonxx.h:59
std::map< std::string, Value * > container
Definition: jsonxx.h:144
Definition: jsonxx.h:115
Definition: jsonxx.h:85
Format
Definition: jsonxx.h:80
bool parser_is_permissive()
Definition: jsonxx.h:73
container value_map_
Definition: jsonxx.h:161
bool has(unsigned int i) const
Definition: jsonxx.h:354
Definition: jsonxx.h:165
std::string write(unsigned format) const
Definition: jsonxx.h:190
Definition: jsonxx.h:64
Definition: jsonxx.h:82
Definition: jsonxx.h:58
bool validate(std::istream &input)
Definition: jsonxx.cc:910
Definition: jsonxx.h:336
Definition: jsonxx.h:63
const std::vector< Value * > & values() const
Definition: jsonxx.h:184
Array * array_value_
Definition: jsonxx.h:345
Object * object_value_
Definition: jsonxx.h:346
std::string odd
Definition: jsonxx.h:162
Definition: jsonxx.h:83
container values_
Definition: jsonxx.h:207
Object & operator<<(const Value &value)
Definition: jsonxx.cc:1044
std::ostream & operator<<(std::ostream &stream, const jsonxx::Value &v)
Definition: jsonxx.cc:469
bool Boolean
Definition: jsonxx.h:90
Settings
Definition: jsonxx.h:56
Definition: jsonxx.h:333
std::string reformat(std::istream &input)
Definition: jsonxx.cc:940
bool is() const
Definition: jsonxx.h:338
Definition: jsonxx.h:335
void assertion(const char *file, int line, const char *expression, bool result)
Definition: jsonxx.cc:27
Definition: jsonxx.h:81
~Value()
Definition: jsonxx.h:216
Definition: jsonxx.h:99
Definition: jsonxx.h:84
Definition: jsonxx.cc:39
void append(const Value &value)
Definition: jsonxx.h:196
bool parser_is_strict()
Definition: jsonxx.h:72
Number number_value_
Definition: jsonxx.h:342
T & get(unsigned int i)
Definition: jsonxx.h:364
std::string String
Definition: jsonxx.h:91