libdballe  9.14
json.h
1 #ifndef DBALLE_CORE_JSON_H
2 #define DBALLE_CORE_JSON_H
3 
4 #include <dballe/core/fwd.h>
5 #include <dballe/types.h>
6 #include <istream>
7 #include <ostream>
8 #include <vector>
9 #include <wreport/var.h>
10 #include <wreport/varinfo.h>
11 
12 namespace dballe {
13 namespace core {
14 
15 struct JSONParseException : public std::runtime_error
16 {
17  using std::runtime_error::runtime_error;
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> void add_ostream(const T& val)
71  {
72  val_head();
73  out << val;
74  }
75 
76  void add_number(const std::string& val);
77  void add_level(const Level& val);
78  void add_trange(const Trange& val);
79  void add_datetime(const Datetime& val);
80  void add_datetimerange(const DatetimeRange& val);
81  void add_coords(const Coords& val);
82  void add_ident(const Ident& val);
83  void add_report(const Report& 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 Report& val) { add_report(val); }
105  void add(const wreport::Var& val) { add_var(val); }
106  void add(const Station& s) { add_station(s); }
107  void add(const DBStation& s) { add_dbstation(s); }
108  void add(const Values& v) { add_values(v); }
109  void add(const DBValues& v) { add_dbvalues(v); }
110 
111  template <typename T> void add(const char* a, T b)
112  {
113  add_cstring(a);
114  add(b);
115  }
116 
117  template <typename T> void add_list(const T& val)
118  {
119  start_list();
120  for (const auto& i : val)
121  add(i);
122  end_list();
123  }
124 };
125 
130 {
131 public:
132  virtual ~JSONReader() {}
133 
134  virtual void on_start_list() = 0;
135  virtual void on_end_list() = 0;
136 
137  virtual void on_start_mapping() = 0;
138  virtual void on_end_mapping() = 0;
139 
140  virtual void on_add_null() = 0;
141  virtual void on_add_bool(bool val) = 0;
142  virtual void on_add_int(int val) = 0;
143  virtual void on_add_double(double val) = 0;
144  virtual void on_add_string(const std::string& val) = 0;
145 
146  // Parse a stream
147  void parse(std::istream& in);
148 };
149 
150 namespace json {
151 
152 enum Element {
153  JSON_OBJECT,
154  JSON_ARRAY,
155  JSON_STRING,
156  JSON_NUMBER,
157  JSON_TRUE,
158  JSON_FALSE,
159  JSON_NULL,
160 };
161 
162 struct Stream
163 {
164  std::istream& in;
165 
166  Stream(std::istream& in) : in(in) {}
167 
169  void expect_token(const char* token);
170 
172  void skip_spaces();
173 
175  template <typename T> T parse_unsigned()
176  {
177  T res = 0;
178  while (true)
179  {
180  int c = in.peek();
181  if (c >= '0' and c <= '9')
182  res = res * 10 + in.get() - '0';
183  else
184  break;
185  }
186  skip_spaces();
187  return res;
188  }
189 
191  template <typename T> T parse_signed()
192  {
193  if (in.peek() == '-')
194  {
195  in.get();
196  return -parse_unsigned<T>();
197  }
198  else
199  return parse_unsigned<T>();
200  }
201 
203  double parse_double();
204 
211  std::tuple<std::string, bool> parse_number();
212 
214  std::string parse_string();
215 
218 
221 
224 
226  Ident parse_ident();
227 
229  Level parse_level();
230 
233 
236 
239 
240  template <typename T> inline T parse()
241  {
243  }
244 
246  void parse_array(std::function<void()> on_element);
247 
249  void parse_object(std::function<void(const std::string& key)> on_value);
250 
253  Element identify_next();
254 };
255 
256 template <> inline std::string Stream::parse() { return parse_string(); }
257 template <> inline Coords Stream::parse() { return parse_coords(); }
258 template <> inline Station Stream::parse() { return parse_station(); }
259 template <> inline DBStation Stream::parse() { return parse_dbstation(); }
260 template <> inline Ident Stream::parse() { return parse_ident(); }
261 template <> inline Level Stream::parse() { return parse_level(); }
262 template <> inline Trange Stream::parse() { return parse_trange(); }
263 template <> inline Datetime Stream::parse() { return parse_datetime(); }
264 template <> inline DatetimeRange Stream::parse()
265 {
266  return parse_datetimerange();
267 }
268 
269 } // namespace json
270 
271 } // namespace core
272 } // namespace dballe
273 #endif
Common base types used by most of DB-All.e code.
Definition: json.h:162
Coords parse_coords()
Parse a Coords object.
Station information.
Definition: types.h:878
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:175
Coordinates.
Definition: types.h:371
Information on how a value has been sampled or computed with regards to time.
Definition: types.h:688
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:229
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:750
Range of datetimes.
Definition: types.h:296
JSON sax-like parser.
Definition: json.h:129
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:191
Date and time.
Definition: types.h:163
std::string parse_string()
Parse a string from the start of the stream.
JSON serializer.
Definition: json.h:29
A report name.
Definition: types.h:815
Level parse_level()
Parse a Level object.
Definition: types.h:939
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:215
Trange parse_trange()
Parse a Trange object.
void reset()
Reset the serializer state, to cancel the current output and prepare for a new one.