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