/home/docs/checkouts/readthedocs.org/user_builds/ratpac/checkouts/latest/src/db/include/RAT/json.hh Source File

Ratpac-two: /home/docs/checkouts/readthedocs.org/user_builds/ratpac/checkouts/latest/src/db/include/RAT/json.hh Source File
Ratpac-two
json.hh
1 
18 #ifndef _JSON
19 #define _JSON
20 
21 #include <map>
22 #include <sstream>
23 #include <stdexcept>
24 #include <string>
25 #include <vector>
26 
27 namespace json {
28 
29 class Value;
30 class Reader;
31 class Writer;
32 
33 // types used by Value
34 typedef long int TInteger;
35 typedef unsigned long int TUInteger;
36 typedef double TReal;
37 typedef bool TBool;
38 typedef std::string TString;
39 typedef std::map<TString, Value> TObject;
40 typedef std::vector<Value> TArray;
41 
42 typedef union {
43  // basic types by value
44  TInteger integer;
45  TUInteger uinteger;
46  TReal real;
47  TBool boolean;
48  // structured types by reference
49  TString *string;
50  TObject *object;
51  TArray *array;
52 } TData;
53 
54 // type ids used by Value
55 enum Type { TINTEGER, TUINTEGER, TREAL, TBOOL, TSTRING, TOBJECT, TARRAY, TNULL };
56 
57 // JSON Value container class. Basic types (int,uint,real,bool) are stored by
58 // value, and structured types are stored by reference.
59 class Value {
60  friend class Reader;
61  friend class Writer;
62 
63  public:
64  // Default constructs null Value (this is fast)
65  inline Value() : refcount(NULL), type(TNULL) {}
66 
67  // Initilize to be of a specific type
68  inline Value(Type type_) : refcount(NULL), type(TNULL) { reset(type_); }
69 
70  // Construct values directly from basic types. These are passed by value and
71  // have no refcount.
72  explicit inline Value(TInteger integer) : refcount(NULL), type(TINTEGER) { data.integer = integer; }
73  explicit inline Value(TUInteger uinteger) : refcount(NULL), type(TUINTEGER) { data.uinteger = uinteger; }
74  explicit inline Value(TReal real) : refcount(NULL), type(TREAL) { data.real = real; }
75  explicit inline Value(TBool boolean) : refcount(NULL), type(TBOOL) { data.boolean = boolean; }
76 
77  // All these integer types... force them into our types
78  explicit inline Value(unsigned int uinteger) : refcount(NULL), type(TUINTEGER) {
79  data.uinteger = (TUInteger)uinteger;
80  }
81  explicit inline Value(int integer) : refcount(NULL), type(TINTEGER) { data.integer = (TInteger)integer; }
82 
83  // Construct structured types. These values are copied into the Value and
84  // subsequently passed by reference with refcount.
85  explicit inline Value(TString string) : refcount(new TUInteger(0)), type(TSTRING) {
86  data.string = new TString(string);
87  }
88  explicit inline Value(TObject object) : refcount(new TUInteger(0)), type(TOBJECT) {
89  data.object = new TObject(object);
90  }
91  explicit inline Value(TArray array) : refcount(new TUInteger(0)), type(TARRAY) { data.array = new TArray(array); }
92 
93  // Constructs a JSON array from a vector (assuming the compile type
94  // conversions are possible)
95  template <typename T>
96  Value(const std::vector<T> &ref) : refcount(new TUInteger(0)), type(TARRAY) {
97  const size_t size = ref.size();
98  data.array = new TArray(size);
99  for (size_t i = 0; i < size; i++) {
100  (*data.array)[i] = Value(ref[i]);
101  }
102  }
103 
104  // Copy constructor - preserves structured types and refcount tracking
105  inline Value(const Value &other) : refcount(other.refcount), type(other.type), data(other.data) { incref(); }
106 
107  // Destructor handles refcount tracking of structured types
108  inline ~Value() { decref(); }
109 
110  // Sets the lhs equal to the value (for base types) or reference (for
111  // structured types)
112  inline Value &operator=(const Value &other) {
113  decref();
114  data = other.data;
115  type = other.type;
116  refcount = other.refcount;
117  incref();
118  return *this;
119  }
120  template <typename T>
121  inline Value &operator=(const T &val) {
122  return operator=(Value(val));
123  }
124 
125  inline Value &operator[](const std::string &key) const { return getMember(key); }
126  inline Value &operator[](const size_t index) const { return getIndex(index); }
127 
128  // Initializes the state of the Value to the default for structured types or
129  // unspecified for basic types
130  void reset(Type type);
131 
132  // Sets the value to null
133  inline void reset() { reset(TNULL); }
134 
135  // Returns the type of the Value
136  inline Type getType() const { return type; }
137 
138  // Getters will throw a parser_error if the type of the Value is not the
139  // requested type
140  inline TInteger getInteger() const {
141  checkType(TINTEGER);
142  return data.integer;
143  }
144  inline TUInteger getUInteger() const {
145  checkType(TUINTEGER);
146  return data.uinteger;
147  }
148  inline TReal getReal() const {
149  checkType(TREAL);
150  return data.real;
151  }
152  inline TBool getBool() const {
153  checkType(TBOOL);
154  return data.boolean;
155  }
156  inline TString getString() const {
157  checkType(TSTRING);
158  return *data.string;
159  }
160 
161  // Returns a member of a JSON object
162  inline Value &getMember(TString key) const {
163  checkType(TOBJECT);
164  return (*data.object)[key];
165  }
166 
167  // Returns the size of a JSON array
168  inline size_t getArraySize() const {
169  checkType(TARRAY);
170  return data.array->size();
171  }
172 
173  // Returns the Value at an index in a JSON array
174  inline Value &getIndex(size_t index) const {
175  checkType(TARRAY);
176  return (*data.array)[index];
177  }
178 
179 #ifndef __CINT__
180 
181  // Templated casting functions (use these when possible / see below for
182  // default specializations)
183  template <typename T>
184  inline T cast() const {
185  throw std::runtime_error("Cannot cast Value to desired type"); // Arbitrary type casts are
186  // impossible
187  }
188 
189  // Templated vector constructing method (uses templated casters to convert
190  // types)
191  template <typename T>
192  inline std::vector<T> toVector() const {
193  const size_t size = getArraySize(); // will check that we are an array
194  std::vector<T> result(size);
195  for (size_t i = 0; i < size; i++) {
196  result[i] = (*data.array)[i].cast<T>();
197  }
198  return result;
199  }
200 
201 #endif
202 
203  // Returns a vector of all the keys in the JSON object
204  std::vector<std::string> getMembers() const;
205 
206  // Returns true if the key exists in the JSON object
207  bool isMember(std::string key) const;
208 
209  // Setters will reset the type if necessary
210  inline void setInteger(TInteger integer) {
211  checkTypeReset(TINTEGER);
212  data.integer = integer;
213  }
214  inline void setUINteger(TUInteger uinteger) {
215  checkTypeReset(TUINTEGER);
216  data.uinteger = uinteger;
217  }
218  inline void setReal(TReal real) {
219  checkTypeReset(TREAL);
220  data.real = real;
221  }
222  inline void setReal(TBool boolean) {
223  checkTypeReset(TBOOL);
224  data.boolean = boolean;
225  }
226  inline void setString(TString string) {
227  checkTypeReset(TSTRING);
228  *data.string = string;
229  }
230 
231  // Sets a member of a JSON object
232  inline void setMember(TString key, Value value) {
233  checkTypeReset(TOBJECT);
234  (*data.object)[key] = value;
235  }
236 
237  // Sets the size of a JSON array
238  inline void setArraySize(size_t size) {
239  checkTypeReset(TARRAY);
240  data.array->resize(size);
241  }
242 
243  // Sets the Value at an index in a JSON array
244  inline void setIndex(size_t index, Value value) {
245  checkTypeReset(TARRAY);
246  (*data.array)[index] = value;
247  }
248 
249  protected:
250  // Returns a string representing the given type
251  static std::string prettyType(Type type);
252 
253  // Throws a nice error message for trying to get the wrong type
254  static void wrongType(Type actual, Type requested);
255 
256  // Throws a runtime_error if the type of the Value does not match the given
257  // Type
258  inline void checkType(Type type_) const {
259  if (this->type != type_) {
260  wrongType(this->type, type_);
261  }
262  }
263 
264  // Resets the type of Value of the current type does not match the given Type
265  inline void checkTypeReset(Type type_) {
266  if (this->type != type_) reset(TOBJECT);
267  }
268 
269  // Decreases the refcount of the Value and cleans up if necessary
270  inline void decref() {
271  if (refcount && !((*refcount)--)) clean();
272  }
273 
274  // Increases the refcount of the Value if necessary
275  inline void incref() {
276  if (refcount) (*refcount)++;
277  }
278 
279  // Frees any allocated memory for this object and resets to null
280  void clean();
281 
282  // Pointer to the number of references of a structured type
283  TUInteger *refcount;
284 
285  // The current type of the Value
286  Type type;
287 
288  // Union to hold the data with minimal space requirements
289  TData data;
290 };
291 
292 #ifndef __CINT__
293 
294 // Everything can be cast to a string in one way or another
295 template <>
296 inline std::string Value::cast<std::string>() const {
297  switch (type) {
298  case TINTEGER: {
299  std::stringstream out;
300  out << data.integer;
301  return out.str();
302  }
303  case TUINTEGER: {
304  std::stringstream out;
305  out << data.uinteger;
306  return out.str();
307  }
308  case TREAL: {
309  std::stringstream out;
310  out << data.real;
311  return out.str();
312  }
313  case TBOOL:
314  return data.boolean ? "true" : "false";
315  case TNULL:
316  return "null";
317  case TSTRING:
318  return *(data.string);
319  case TARRAY: {
320  std::stringstream out;
321  out << "ARR{" << (void *)data.array << '}';
322  return out.str();
323  }
324  case TOBJECT: {
325  std::stringstream out;
326  out << "ARR{" << (void *)data.object << '}';
327  return out.str();
328  }
329  default:
330  throw std::runtime_error("Value could not be cast to string (forgotten?)");
331  }
332 }
333 
334 // Only integer Values can be cast as ints (typically 32 bits)
335 template <>
336 inline int Value::cast<int>() const {
337  switch (type) {
338  case TUINTEGER:
339  return data.uinteger; // strictly speaking this is unsafe, but does not lose
340  // precision
341  case TINTEGER:
342  return data.integer;
343  default:
344  throw std::runtime_error("Cannot cast " + prettyType(type) + " to integer");
345  }
346 }
347 
348 // All numerics can be cast to doubles
349 template <>
350 inline double Value::cast<double>() const {
351  switch (type) {
352  case TUINTEGER:
353  return data.uinteger;
354  case TINTEGER:
355  return data.integer;
356  case TREAL:
357  return data.real;
358  default:
359  throw std::runtime_error("Cannot cast " + prettyType(type) + " to double");
360  }
361 }
362 
363 // All Values are true except zero, false, and null
364 template <>
365 inline bool Value::cast<bool>() const {
366  switch (type) {
367  case TUINTEGER:
368  return data.uinteger != 0;
369  case TINTEGER:
370  return data.integer != 0;
371  case TREAL:
372  return data.real != 0.0;
373  case TNULL:
374  return false;
375  case TBOOL:
376  return data.boolean;
377  default:
378  return true;
379  }
380 }
381 
382 #endif
383 
384 // represents errors in parsing JSON values
385 class parser_error : public std::exception {
386  public:
387  parser_error(const int line_, const int pos_, std::string desc);
388  virtual ~parser_error() throw();
389  virtual const char *what() const throw();
390 
391  protected:
392  const int line, pos;
393  std::string desc, pretty;
394 };
395 
396 // parses JSON values from a stream
397 class Reader {
398  public:
399  // Reads entire stream into internal buffer immediately
400  Reader(std::istream &stream);
401 
402  // Copies the entire string into an internal buffer
403  Reader(const std::string &str);
404 
405  ~Reader();
406 
407  // Returns the next value in the stream
408  bool getValue(Value &result);
409 
410  protected:
411  // Positional data in the stream data (gets garbled during parsing)
412  char *data, *cur, *lastbr;
413  int line;
414 
415  // Converts an escaped JSON string into its literal representation
416  std::string unescapeString(std::string string);
417 
418  // Helpers to read JSON types
419  Value readNumber();
420  Value readString();
421  Value readObject();
422  Value readArray();
423 
424  void skipComment();
425 };
426 
427 // writes JSON values to a stream
428 class Writer {
429  public:
430  // Only writes to the stream when requested
431  Writer(std::ostream &stream);
432 
433  ~Writer();
434 
435  // This produces JSON compliant output at the expense of:
436  //***Unsigned integers get printed as base 10 numbers, and the next parser may
437  // truncate into signed Ultimately produces object-indented text with
438  // value-per-line mentality with arrays on a single line which is similar
439  // enough to how RATDB looks without too much effort.
440  void putValue(const Value &value, const std::string &delim = "\n");
441 
442  protected:
443  // The stream to write to
444  std::ostream &out;
445 
446  // Converts a literal string to its escaped representation
447  std::string escapeString(std::string string);
448 
449  // Helper to write a value to the stream
450  void writeValue(const Value &value, const std::string &depth = "");
451 };
452 
453 } // namespace json
454 
455 #endif
Definition: json.hh:397
Definition: json.hh:59
Definition: json.hh:428
Definition: json.hh:385
Definition: json.hh:27
Definition: json.hh:42