libdballe  9.11
json.h
1 #ifndef DBALLE_CORE_JSON_H
2 #define DBALLE_CORE_JSON_H
3 
4 #include <wreport/varinfo.h>
5 #include <wreport/var.h>
6 #include <dballe/types.h>
7 #include <dballe/core/fwd.h>
8 #include <vector>
9 #include <ostream>
10 #include <istream>
11 
12 namespace dballe {
13 namespace core {
14 
15 struct JSONParseException : public std::runtime_error {
16  using std::runtime_error::runtime_error;
17 };
18 
19 
30 {
31 protected:
32  enum State {
33  LIST_FIRST,
34  LIST,
35  MAPPING_KEY_FIRST,
36  MAPPING_KEY,
37  MAPPING_VAL,
38  };
39  std::ostream& out;
40  std::vector<State> stack;
41 
43  void val_head();
44 
45  void jputc(char c);
46  void jputs(const char* s);
47 
48 public:
49  JSONWriter(std::ostream& out);
50  ~JSONWriter();
51 
56  void reset();
57 
58  void start_list();
59  void end_list();
60 
61  void start_mapping();
62  void end_mapping();
63 
64  void add_null();
65  void add_bool(bool val);
66  void add_int(int val);
67  void add_double(double val);
68  void add_cstring(const char* val);
69  void add_string(const std::string& val);
70  template<typename T>
71  void add_ostream(const T& val)
72  {
73  val_head();
74  out << val;
75  }
76 
77  void add_number(const std::string& val);
78  void add_level(const Level& val);
79  void add_trange(const Trange& val);
80  void add_datetime(const Datetime& val);
81  void add_datetimerange(const DatetimeRange& val);
82  void add_coords(const Coords& val);
83  void add_ident(const Ident& val);
84  void add_var(const wreport::Var& val);
85  void add_station(const Station& s);
86  void add_dbstation(const DBStation& s);
87  void add_values(const Values& values);
88  void add_dbvalues(const DBValues& values);
89  void add_break();
90 
91  void add(const std::string& val) { add_string(val); }
92  void add(const char* val) { add_cstring(val); }
93  void add(double val) { add_double(val); }
94  void add(int val) { add_int(val); }
95  void add(bool val) { add_bool(val); }
96  void add(size_t val) { add_ostream(val); }
97  void add(wreport::Varcode val) { add_int(val); }
98  void add(const Level& val) { add_level(val); }
99  void add(const Trange& val) { add_trange(val); }
100  void add(const Datetime& val) { add_datetime(val); }
101  void add(const DatetimeRange& val) { add_datetimerange(val); }
102  void add(const Coords& val) { add_coords(val); }
103  void add(const Ident& val) { add_ident(val); }
104  void add(const wreport::Var& val) { add_var(val); }
105  void add(const Station& s) { add_station(s); }
106  void add(const DBStation& s) { add_dbstation(s); }
107  void add(const Values& v) { add_values(v); }
108  void add(const DBValues& v) { add_dbvalues(v); }
109 
110  template<typename T>
111  void add(const char* a, T b)
112  {
113  add_cstring(a);
114  add(b);
115  }
116 
117  template<typename T>
118  void add_list(const T& val)
119  {
120  start_list();
121  for (const auto& i : val)
122  add(i);
123  end_list();
124  }
125 };
126 
131 {
132 public:
133  virtual ~JSONReader() {}
134 
135  virtual void on_start_list() = 0;
136  virtual void on_end_list() = 0;
137 
138  virtual void on_start_mapping() = 0;
139  virtual void on_end_mapping() = 0;
140 
141  virtual void on_add_null() = 0;
142  virtual void on_add_bool(bool val) = 0;
143  virtual void on_add_int(int val) = 0;
144  virtual void on_add_double(double val) = 0;
145  virtual void on_add_string(const std::string& val) = 0;
146 
147  // Parse a stream
148  void parse(std::istream& in);
149 };
150 
151 
152 namespace json {
153 
154 enum Element
155 {
156  JSON_OBJECT,
157  JSON_ARRAY,
158  JSON_STRING,
159  JSON_NUMBER,
160  JSON_TRUE,
161  JSON_FALSE,
162  JSON_NULL,
163 };
164 
165 struct Stream
166 {
167  std::istream& in;
168 
169  Stream(std::istream& in) : in(in) {}
170 
172  void expect_token(const char* token);
173 
175  void skip_spaces();
176 
178  template<typename T>
180  {
181  T res = 0;
182  while (true)
183  {
184  int c = in.peek();
185  if (c >= '0' and c <= '9')
186  res = res * 10 + in.get() - '0';
187  else
188  break;
189  }
190  skip_spaces();
191  return res;
192  }
193 
195  template<typename T>
197  {
198  if (in.peek() == '-')
199  {
200  in.get();
201  return -parse_unsigned<T>();
202  } else
203  return parse_unsigned<T>();
204  }
205 
207  double parse_double();
208 
215  std::tuple<std::string, bool> parse_number();
216 
218  std::string parse_string();
219 
222 
225 
228 
230  Ident parse_ident();
231 
233  Level parse_level();
234 
237 
240 
243 
244  template<typename T>
245  inline T parse() { throw wreport::error_unimplemented(); }
246 
248  void parse_array(std::function<void()> on_element);
249 
251  void parse_object(std::function<void(const std::string& key)> on_value);
252 
255  Element identify_next();
256 };
257 
258 template<> inline std::string Stream::parse() { return parse_string(); }
259 template<> inline Coords Stream::parse() { return parse_coords(); }
260 template<> inline Station Stream::parse() { return parse_station(); }
261 template<> inline DBStation Stream::parse() { return parse_dbstation(); }
262 template<> inline Ident Stream::parse() { return parse_ident(); }
263 template<> inline Level Stream::parse() { return parse_level(); }
264 template<> inline Trange Stream::parse() { return parse_trange(); }
265 template<> inline Datetime Stream::parse() { return parse_datetime(); }
266 template<> inline DatetimeRange Stream::parse() { return parse_datetimerange(); }
267 
268 }
269 
270 }
271 }
272 #endif
Common base types used by most of DB-All.e code.
Definition: json.h:165
Coords parse_coords()
Parse a Coords object.
Station information.
Definition: types.h:793
double parse_double()
Parse a double.
void expect_token(const char *token)
Raise a parse error if the stream does not yield this exact token.
T parse_unsigned()
Parse an unsigned integer.
Definition: json.h:179
Coordinates.
Definition: types.h:368
Information on how a value has been sampled or computed with regards to time.
Definition: types.h:686
void skip_spaces()
Consume and discard all spaces at the start of the stream.
Datetime parse_datetime()
Parse a Datetime object.
Definition: cmdline.h:18
Collection of DBValue objects, indexed by wreport::Varcode.
Definition: values.h:191
Vertical level or layer.
Definition: types.h:624
A station identifier, that can be any string (including the empty string) or a missing value...
Definition: types.h:747
uint16_t Varcode
Range of datetimes.
Definition: types.h:294
JSON sax-like parser.
Definition: json.h:130
DBStation parse_dbstation()
Parse a Coords object.
Station parse_station()
Parse a Coords object.
void val_head()
Append whatever separator is needed (if any) before a new value.
void parse_object(std::function< void(const std::string &key)> on_value)
Parse a JSON object, calling on_value to parse each value.
T parse_signed()
Parse a signed integer.
Definition: json.h:196
Date and time.
Definition: types.h:164
std::string parse_string()
Parse a string from the start of the stream.
JSON serializer.
Definition: json.h:29
Level parse_level()
Parse a Level object.
Definition: types.h:850
Element identify_next()
Identify the next element in the stream, without moving the stream position.
Ident parse_ident()
Parse an Ident object.
std::tuple< std::string, bool > parse_number()
Parse a number, without converting it.
void parse_array(std::function< void()> on_element)
Parse a JSON array, calling on_element to parse each element.
DatetimeRange parse_datetimerange()
Parse a DatetimeRange object.
Collection of Value objects, indexed by wreport::Varcode.
Definition: values.h:176
Trange parse_trange()
Parse a Trange object.
void reset()
Reset the serializer state, to cancel the current output and prepare for a new one.