Zserio C++ runtime library  1.2.0
Built for Zserio 2.16.0
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 "zserio/AnyHolder.h"
5 #include "zserio/JsonDecoder.h"
6 #include "zserio/JsonTokenizer.h"
7 #include "zserio/Span.h"
8 
9 namespace zserio
10 {
11 
17 template <typename ALLOC = std::allocator<uint8_t>>
19 {
20 public:
24  class IObserver
25  {
26  public:
30  virtual ~IObserver() = default;
31 
35  virtual void beginObject() = 0;
36 
40  virtual void endObject() = 0;
41 
45  virtual void beginArray() = 0;
46 
50  virtual void endArray() = 0;
51 
57  virtual void visitKey(StringView key) = 0;
58 
64  virtual void visitValue(std::nullptr_t nullValue) = 0;
65 
71  virtual void visitValue(bool boolValue) = 0;
72 
78  virtual void visitValue(int64_t intValue) = 0;
79 
85  virtual void visitValue(uint64_t uintValue) = 0;
86 
92  virtual void visitValue(double doubleValue) = 0;
93 
99  virtual void visitValue(StringView stringValue) = 0;
100  };
101 
109  BasicJsonParser(std::istream& in, IObserver& observer, const ALLOC& allocator = ALLOC()) :
110  m_tokenizer(in, allocator),
111  m_observer(observer)
112  {}
113 
120  bool parse()
121  {
122  if (m_tokenizer.getToken() == JsonToken::BEGIN_OF_FILE)
123  {
124  m_tokenizer.next();
125  }
126 
127  if (m_tokenizer.getToken() == JsonToken::END_OF_FILE)
128  {
129  return true;
130  }
131 
132  parseElement();
133 
134  return m_tokenizer.getToken() == JsonToken::END_OF_FILE;
135  }
136 
142  size_t getLine() const
143  {
144  return m_tokenizer.getLine();
145  }
146 
152  size_t getColumn() const
153  {
154  return m_tokenizer.getColumn();
155  }
156 
157 private:
158  void parseElement();
159  void parseObject();
160  void parseMembers();
161  void parseMember();
162  void parseArray();
163  void parseElements();
164 
165  void parseValue();
166  void visitValue() const;
167 
168  void checkToken(JsonToken token);
169  void consumeToken(JsonToken token);
170  JsonParserException createUnexpectedTokenException(Span<const JsonToken> expecting) const;
171 
172  static const std::array<JsonToken, 3> ELEMENT_TOKENS;
173 
174  BasicJsonTokenizer<ALLOC> m_tokenizer;
175  IObserver& m_observer;
176 };
177 
178 template <typename ALLOC>
179 const std::array<JsonToken, 3> BasicJsonParser<ALLOC>::ELEMENT_TOKENS = {
181 
182 template <typename ALLOC>
183 void BasicJsonParser<ALLOC>::parseElement()
184 {
185  JsonToken token = m_tokenizer.getToken();
186 
187  if (token == JsonToken::BEGIN_ARRAY)
188  {
189  parseArray();
190  }
191  else if (token == JsonToken::BEGIN_OBJECT)
192  {
193  parseObject();
194  }
195  else if (token == JsonToken::VALUE)
196  {
197  parseValue();
198  }
199  else
200  {
201  throw createUnexpectedTokenException(ELEMENT_TOKENS);
202  }
203 }
204 
205 template <typename ALLOC>
206 void BasicJsonParser<ALLOC>::parseObject()
207 {
208  consumeToken(JsonToken::BEGIN_OBJECT);
209  m_observer.beginObject();
210 
211  if (m_tokenizer.getToken() == JsonToken::VALUE)
212  {
213  parseMembers();
214  }
215 
216  consumeToken(JsonToken::END_OBJECT);
217  m_observer.endObject();
218 }
219 
220 template <typename ALLOC>
221 void BasicJsonParser<ALLOC>::parseMembers()
222 {
223  parseMember();
224  while (m_tokenizer.getToken() == JsonToken::ITEM_SEPARATOR)
225  {
226  m_tokenizer.next();
227  parseMember();
228  }
229 }
230 
231 template <typename ALLOC>
232 void BasicJsonParser<ALLOC>::parseMember()
233 {
234  checkToken(JsonToken::VALUE);
235  const AnyHolder<ALLOC>& key = m_tokenizer.getValue();
236  if (!key.template isType<string<ALLOC>>())
237  {
238  throw JsonParserException("JsonParser:")
239  << getLine() << ":" << getColumn() << ": Key must be a string value!";
240  }
241  m_observer.visitKey(key.template get<string<ALLOC>>());
242  m_tokenizer.next();
243 
244  consumeToken(JsonToken::KEY_SEPARATOR);
245 
246  parseElement();
247 }
248 
249 template <typename ALLOC>
250 void BasicJsonParser<ALLOC>::parseArray()
251 {
252  consumeToken(JsonToken::BEGIN_ARRAY);
253  m_observer.beginArray();
254 
255  if (std::find(ELEMENT_TOKENS.begin(), ELEMENT_TOKENS.end(), m_tokenizer.getToken()) != ELEMENT_TOKENS.end())
256  {
257  parseElements();
258  }
259 
260  consumeToken(JsonToken::END_ARRAY);
261  m_observer.endArray();
262 }
263 
264 template <typename ALLOC>
265 void BasicJsonParser<ALLOC>::parseElements()
266 {
267  parseElement();
268  while (m_tokenizer.getToken() == JsonToken::ITEM_SEPARATOR)
269  {
270  m_tokenizer.next();
271  parseElement();
272  }
273 }
274 
275 template <typename ALLOC>
276 void BasicJsonParser<ALLOC>::parseValue()
277 {
278  visitValue();
279  m_tokenizer.next();
280 }
281 
282 template <typename ALLOC>
283 void BasicJsonParser<ALLOC>::visitValue() const
284 {
285  const AnyHolder<ALLOC>& value = m_tokenizer.getValue();
286 
287  if (value.template isType<std::nullptr_t>())
288  {
289  m_observer.visitValue(nullptr);
290  }
291  else if (value.template isType<bool>())
292  {
293  m_observer.visitValue(value.template get<bool>());
294  }
295  else if (value.template isType<int64_t>())
296  {
297  m_observer.visitValue(value.template get<int64_t>());
298  }
299  else if (value.template isType<uint64_t>())
300  {
301  m_observer.visitValue(value.template get<uint64_t>());
302  }
303  else if (value.template isType<double>())
304  {
305  m_observer.visitValue(value.template get<double>());
306  }
307  else
308  {
309  m_observer.visitValue(value.template get<string<ALLOC>>());
310  }
311 }
312 
313 template <typename ALLOC>
314 void BasicJsonParser<ALLOC>::checkToken(JsonToken token)
315 {
316  if (m_tokenizer.getToken() != token)
317  {
318  throw createUnexpectedTokenException({{token}});
319  }
320 }
321 
322 template <typename ALLOC>
323 void BasicJsonParser<ALLOC>::consumeToken(JsonToken token)
324 {
325  checkToken(token);
326  m_tokenizer.next();
327 }
328 
329 template <typename ALLOC>
330 JsonParserException BasicJsonParser<ALLOC>::createUnexpectedTokenException(
331  Span<const JsonToken> expecting) const
332 {
333  JsonParserException error("JsonParser:");
334  error << getLine() << ":" << getColumn() << ": unexpected token: " << m_tokenizer.getToken();
335  if (expecting.size() == 1)
336  {
337  error << ", expecting " << expecting[0] << "!";
338  }
339  else
340  {
341  error << ", expecting one of [";
342  for (size_t i = 0; i < expecting.size(); ++i)
343  {
344  if (i > 0)
345  {
346  error << ", ";
347  }
348  error << expecting[i];
349  }
350  error << "]!";
351  }
352  return error;
353 }
354 
357 
358 } // namespace zserio
359 
360 #endif // ZSERIO_JSON_PARSER_H_INC
virtual void visitValue(uint64_t uintValue)=0
virtual void visitValue(int64_t intValue)=0
virtual void visitKey(StringView key)=0
virtual void visitValue(std::nullptr_t nullValue)=0
virtual void visitValue(double doubleValue)=0
virtual void visitValue(StringView stringValue)=0
virtual void visitValue(bool boolValue)=0
size_t getLine() const
Definition: JsonParser.h:142
size_t getColumn() const
Definition: JsonParser.h:152
BasicJsonParser(std::istream &in, IObserver &observer, const ALLOC &allocator=ALLOC())
Definition: JsonParser.h:109