Zserio C++17 runtime library 1.3.0
Built for Zserio 2.20.0
Loading...
Searching...
No Matches
JsonParser.h
Go to the documentation of this file.
1#ifndef ZSERIO_JSON_PARSER_H_INC
2#define ZSERIO_JSON_PARSER_H_INC
3
4#include <string_view>
5
6#include "zserio/Any.h"
9#include "zserio/Span.h"
10#include "zserio/String.h"
11
12namespace zserio
13{
14
20template <typename ALLOC = std::allocator<uint8_t>>
22{
23public:
28 {
29 public:
33 virtual ~IObserver() = default;
34
38 virtual void beginObject() = 0;
39
43 virtual void endObject() = 0;
44
48 virtual void beginArray() = 0;
49
53 virtual void endArray() = 0;
54
60 virtual void visitKey(std::string_view key) = 0;
61
67 virtual void visitValue(std::nullptr_t nullValue) = 0;
68
74 virtual void visitValue(bool boolValue) = 0;
75
81 virtual void visitValue(int64_t intValue) = 0;
82
88 virtual void visitValue(uint64_t uintValue) = 0;
89
95 virtual void visitValue(double doubleValue) = 0;
96
102 virtual void visitValue(std::string_view stringValue) = 0;
103 };
104
112 BasicJsonParser(std::istream& in, IObserver& observer, const ALLOC& allocator = ALLOC()) :
113 m_tokenizer(in, allocator),
114 m_observer(observer)
115 {}
116
123 bool parse()
124 {
125 if (m_tokenizer.getToken() == JsonToken::BEGIN_OF_FILE)
126 {
127 m_tokenizer.next();
128 }
129
130 if (m_tokenizer.getToken() == JsonToken::END_OF_FILE)
131 {
132 return true;
133 }
134
135 parseElement();
136
137 return m_tokenizer.getToken() == JsonToken::END_OF_FILE;
138 }
139
145 size_t getLine() const
146 {
147 return m_tokenizer.getLine();
148 }
149
155 size_t getColumn() const
156 {
157 return m_tokenizer.getColumn();
158 }
159
160private:
161 void parseElement();
162 void parseObject();
163 void parseMembers();
164 void parseMember();
165 void parseArray();
166 void parseElements();
167
168 void parseValue();
169 void visitValue() const;
170
171 void checkToken(JsonToken token);
172 void consumeToken(JsonToken token);
173 JsonParserException createUnexpectedTokenException(Span<const JsonToken> expecting) const;
174
175 static const std::array<JsonToken, 3> ELEMENT_TOKENS;
176
177 BasicJsonTokenizer<ALLOC> m_tokenizer;
178 IObserver& m_observer;
179};
180
181template <typename ALLOC>
182const std::array<JsonToken, 3> BasicJsonParser<ALLOC>::ELEMENT_TOKENS = {
184
185template <typename ALLOC>
186void BasicJsonParser<ALLOC>::parseElement()
187{
188 JsonToken token = m_tokenizer.getToken();
189
190 if (token == JsonToken::BEGIN_ARRAY)
191 {
192 parseArray();
193 }
194 else if (token == JsonToken::BEGIN_OBJECT)
195 {
196 parseObject();
197 }
198 else if (token == JsonToken::VALUE)
199 {
200 parseValue();
201 }
202 else
203 {
204 throw createUnexpectedTokenException(ELEMENT_TOKENS);
205 }
206}
207
208template <typename ALLOC>
209void BasicJsonParser<ALLOC>::parseObject()
210{
211 consumeToken(JsonToken::BEGIN_OBJECT);
212 m_observer.beginObject();
213
214 if (m_tokenizer.getToken() == JsonToken::VALUE)
215 {
216 parseMembers();
217 }
218
219 consumeToken(JsonToken::END_OBJECT);
220 m_observer.endObject();
221}
222
223template <typename ALLOC>
224void BasicJsonParser<ALLOC>::parseMembers()
225{
226 parseMember();
227 while (m_tokenizer.getToken() == JsonToken::ITEM_SEPARATOR)
228 {
229 m_tokenizer.next();
230 parseMember();
231 }
232}
233
234template <typename ALLOC>
235void BasicJsonParser<ALLOC>::parseMember()
236{
237 checkToken(JsonToken::VALUE);
238 const BasicAny<ALLOC>& key = m_tokenizer.getValue();
239 if (!key.template isType<BasicString<RebindAlloc<ALLOC, char>>>())
240 {
241 throw JsonParserException("JsonParser:")
242 << getLine() << ":" << getColumn() << ": Key must be a string value!";
243 }
244 m_observer.visitKey(key.template get<BasicString<RebindAlloc<ALLOC, char>>>());
245 m_tokenizer.next();
246
247 consumeToken(JsonToken::KEY_SEPARATOR);
248
249 parseElement();
250}
251
252template <typename ALLOC>
253void BasicJsonParser<ALLOC>::parseArray()
254{
255 consumeToken(JsonToken::BEGIN_ARRAY);
256 m_observer.beginArray();
257
258 if (std::find(ELEMENT_TOKENS.begin(), ELEMENT_TOKENS.end(), m_tokenizer.getToken()) != ELEMENT_TOKENS.end())
259 {
260 parseElements();
261 }
262
263 consumeToken(JsonToken::END_ARRAY);
264 m_observer.endArray();
265}
266
267template <typename ALLOC>
268void BasicJsonParser<ALLOC>::parseElements()
269{
270 parseElement();
271 while (m_tokenizer.getToken() == JsonToken::ITEM_SEPARATOR)
272 {
273 m_tokenizer.next();
274 parseElement();
275 }
276}
277
278template <typename ALLOC>
279void BasicJsonParser<ALLOC>::parseValue()
280{
281 visitValue();
282 m_tokenizer.next();
283}
284
285template <typename ALLOC>
286void BasicJsonParser<ALLOC>::visitValue() const
287{
288 const BasicAny<ALLOC>& value = m_tokenizer.getValue();
289
290 if (value.template isType<std::nullptr_t>())
291 {
292 m_observer.visitValue(nullptr);
293 }
294 else if (value.template isType<bool>())
295 {
296 m_observer.visitValue(value.template get<bool>());
297 }
298 else if (value.template isType<int64_t>())
299 {
300 m_observer.visitValue(value.template get<int64_t>());
301 }
302 else if (value.template isType<uint64_t>())
303 {
304 m_observer.visitValue(value.template get<uint64_t>());
305 }
306 else if (value.template isType<double>())
307 {
308 m_observer.visitValue(value.template get<double>());
309 }
310 else
311 {
312 m_observer.visitValue(value.template get<BasicString<RebindAlloc<ALLOC, char>>>());
313 }
314}
315
316template <typename ALLOC>
317void BasicJsonParser<ALLOC>::checkToken(JsonToken token)
318{
319 if (m_tokenizer.getToken() != token)
320 {
321 throw createUnexpectedTokenException({{token}});
322 }
323}
324
325template <typename ALLOC>
326void BasicJsonParser<ALLOC>::consumeToken(JsonToken token)
327{
328 checkToken(token);
329 m_tokenizer.next();
330}
331
332template <typename ALLOC>
333JsonParserException BasicJsonParser<ALLOC>::createUnexpectedTokenException(
334 Span<const JsonToken> expecting) const
335{
336 JsonParserException error("JsonParser:");
337 error << getLine() << ":" << getColumn() << ": unexpected token: " << m_tokenizer.getToken();
338 if (expecting.size() == 1)
339 {
340 error << ", expecting " << expecting[0] << "!";
341 }
342 else
343 {
344 error << ", expecting one of [";
345 for (size_t i = 0; i < expecting.size(); ++i)
346 {
347 if (i > 0)
348 {
349 error << ", ";
350 }
351 error << expecting[i];
352 }
353 error << "]!";
354 }
355 return error;
356}
357
360
361} // namespace zserio
362
363#endif // ZSERIO_JSON_PARSER_H_INC
virtual void visitValue(uint64_t uintValue)=0
virtual void visitValue(int64_t intValue)=0
virtual void visitKey(std::string_view key)=0
virtual void visitValue(std::nullptr_t nullValue)=0
virtual void visitValue(double doubleValue)=0
virtual void visitValue(bool boolValue)=0
virtual void visitValue(std::string_view stringValue)=0
size_t getLine() const
Definition JsonParser.h:145
size_t getColumn() const
Definition JsonParser.h:155
BasicJsonParser(std::istream &in, IObserver &observer, const ALLOC &allocator=ALLOC())
Definition JsonParser.h:112
std::basic_string< char, std::char_traits< char >, ALLOC > BasicString
Definition String.h:17
decltype(auto) get(BasicVariant< ALLOC, INDEX, T... > &var)
Definition Variant.h:511