libdballe 9.6
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
12namespace dballe {
13namespace core {
14
15struct JSONParseException : public std::runtime_error {
16 using std::runtime_error::runtime_error;
17};
18
19
30{
31protected:
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
48public:
49 JSONWriter(std::ostream& out);
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{
132public:
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
152namespace json {
153
154enum 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
165struct Stream
166{
167 std::istream& in;
168
169 Stream(std::istream& in) : in(in) {}
170
172 void expect_token(const char* token);
173
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
231
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
258template<> inline std::string Stream::parse() { return parse_string(); }
259template<> inline Coords Stream::parse() { return parse_coords(); }
260template<> inline Station Stream::parse() { return parse_station(); }
261template<> inline DBStation Stream::parse() { return parse_dbstation(); }
262template<> inline Ident Stream::parse() { return parse_ident(); }
263template<> inline Level Stream::parse() { return parse_level(); }
264template<> inline Trange Stream::parse() { return parse_trange(); }
265template<> inline Datetime Stream::parse() { return parse_datetime(); }
266template<> inline DatetimeRange Stream::parse() { return parse_datetimerange(); }
267
268}
269
270}
271}
272#endif
A station identifier, that can be any string (including the empty string) or a missing value.
Definition: types.h:748
JSON sax-like parser.
Definition: json.h:131
JSON serializer.
Definition: json.h:30
void val_head()
Append whatever separator is needed (if any) before a new value.
void reset()
Reset the serializer state, to cancel the current output and prepare for a new one.
uint16_t Varcode
Coordinates.
Definition: types.h:369
Definition: types.h:851
Collection of DBValue objects, indexed by wreport::Varcode.
Definition: values.h:192
Range of datetimes.
Definition: types.h:295
Date and time.
Definition: types.h:165
Vertical level or layer.
Definition: types.h:625
Station information.
Definition: types.h:794
Information on how a value has been sampled or computed with regards to time.
Definition: types.h:687
Collection of Value objects, indexed by wreport::Varcode.
Definition: values.h:177
Definition: json.h:166
std::string parse_string()
Parse a string from the start of the stream.
DatetimeRange parse_datetimerange()
Parse a DatetimeRange object.
Coords parse_coords()
Parse a Coords object.
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_unsigned()
Parse an unsigned integer.
Definition: json.h:179
void expect_token(const char *token)
Raise a parse error if the stream does not yield this exact token.
Datetime parse_datetime()
Parse a Datetime object.
Level parse_level()
Parse a Level object.
void skip_spaces()
Consume and discard all spaces at the start of the stream.
DBStation parse_dbstation()
Parse a Coords object.
double parse_double()
Parse a double.
Element identify_next()
Identify the next element in the stream, without moving the stream position.
Ident parse_ident()
Parse an Ident object.
void parse_array(std::function< void()> on_element)
Parse a JSON array, calling on_element to parse each element.
Station parse_station()
Parse a Coords object.
std::tuple< std::string, bool > parse_number()
Parse a number, without converting it.
T parse_signed()
Parse a signed integer.
Definition: json.h:196
Trange parse_trange()
Parse a Trange object.
Common base types used by most of DB-All.e code.