libdballe 9.13
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
12namespace dballe {
13namespace core {
14
15struct JSONParseException : public std::runtime_error
16{
17 using std::runtime_error::runtime_error;
18};
19
29class JSONWriter
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);
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{
131public:
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
150namespace json {
151
152enum Element {
153 JSON_OBJECT,
154 JSON_ARRAY,
155 JSON_STRING,
156 JSON_NUMBER,
157 JSON_TRUE,
158 JSON_FALSE,
159 JSON_NULL,
160};
161
162struct Stream
163{
164 std::istream& in;
165
166 Stream(std::istream& in) : in(in) {}
167
169 void expect_token(const char* token);
170
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
227
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
256template <> inline std::string Stream::parse() { return parse_string(); }
257template <> inline Coords Stream::parse() { return parse_coords(); }
258template <> inline Station Stream::parse() { return parse_station(); }
259template <> inline DBStation Stream::parse() { return parse_dbstation(); }
260template <> inline Ident Stream::parse() { return parse_ident(); }
261template <> inline Level Stream::parse() { return parse_level(); }
262template <> inline Trange Stream::parse() { return parse_trange(); }
263template <> inline Datetime Stream::parse() { return parse_datetime(); }
264template <> inline DatetimeRange Stream::parse()
265{
266 return parse_datetimerange();
267}
268
269} // namespace json
270
271} // namespace core
272} // namespace dballe
273#endif
A station identifier, that can be any string (including the empty string) or a missing value.
Definition types.h:751
A report name.
Definition types.h:816
JSON sax-like parser.
Definition json.h:130
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.
Coordinates.
Definition types.h:372
Definition types.h:940
Collection of DBValue objects, indexed by wreport::Varcode.
Definition values.h:230
Range of datetimes.
Definition types.h:297
Date and time.
Definition types.h:164
Vertical level or layer.
Definition types.h:625
Station information.
Definition types.h:879
Information on how a value has been sampled or computed with regards to time.
Definition types.h:689
Collection of Value objects, indexed by wreport::Varcode.
Definition values.h:216
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:175
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:191
Trange parse_trange()
Parse a Trange object.
Common base types used by most of DB-All.e code.