Zserio C++ runtime library  1.0.0
Built for Zserio 2.13.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), m_observer(observer)
111  {}
112 
119  bool parse()
120  {
121  if (m_tokenizer.getToken() == JsonToken::BEGIN_OF_FILE)
122  m_tokenizer.next();
123 
124  if (m_tokenizer.getToken() == JsonToken::END_OF_FILE)
125  return true;
126 
127  parseElement();
128 
129  return m_tokenizer.getToken() == JsonToken::END_OF_FILE;
130  }
131 
137  size_t getLine() const
138  {
139  return m_tokenizer.getLine();
140  }
141 
147  size_t getColumn() const
148  {
149  return m_tokenizer.getColumn();
150  }
151 
152 private:
153  void parseElement();
154  void parseObject();
155  void parseMembers();
156  void parseMember();
157  void parseArray();
158  void parseElements();
159 
160  void parseValue();
161  void visitValue() const;
162 
163  void checkToken(JsonToken token);
164  void consumeToken(JsonToken token);
165  JsonParserException createUnexpectedTokenException(Span<const JsonToken> expecting) const;
166 
167  static const std::array<JsonToken, 3> ELEMENT_TOKENS;
168 
169  BasicJsonTokenizer<ALLOC> m_tokenizer;
170  IObserver& m_observer;
171 };
172 
173 template <typename ALLOC>
174 const std::array<JsonToken, 3> BasicJsonParser<ALLOC>::ELEMENT_TOKENS = {
178 };
179 
180 template <typename ALLOC>
182 {
183  JsonToken token = m_tokenizer.getToken();
184 
185  if (token == JsonToken::BEGIN_ARRAY)
186  parseArray();
187  else if (token == JsonToken::BEGIN_OBJECT)
188  parseObject();
189  else if (token == JsonToken::VALUE)
190  parseValue();
191  else
192  throw createUnexpectedTokenException(ELEMENT_TOKENS);
193 }
194 
195 template <typename ALLOC>
197 {
198  consumeToken(JsonToken::BEGIN_OBJECT);
199  m_observer.beginObject();
200 
201  if (m_tokenizer.getToken() == JsonToken::VALUE)
202  parseMembers();
203 
204  consumeToken(JsonToken::END_OBJECT);
205  m_observer.endObject();
206 }
207 
208 template <typename ALLOC>
210 {
211  parseMember();
212  while (m_tokenizer.getToken() == JsonToken::ITEM_SEPARATOR)
213  {
214  m_tokenizer.next();
215  parseMember();
216  }
217 }
218 
219 template <typename ALLOC>
221 {
222  checkToken(JsonToken::VALUE);
223  const AnyHolder<ALLOC>& key = m_tokenizer.getValue();
224  if (!key.template isType<string<ALLOC>>())
225  {
226  throw JsonParserException("JsonParser:") << getLine() << ":" << getColumn() <<
227  ": Key must be a string value!";
228  }
229  m_observer.visitKey(key.template get<string<ALLOC>>());
230  m_tokenizer.next();
231 
232  consumeToken(JsonToken::KEY_SEPARATOR);
233 
234  parseElement();
235 }
236 
237 template <typename ALLOC>
239 {
240  consumeToken(JsonToken::BEGIN_ARRAY);
241  m_observer.beginArray();
242 
243  if (std::find(ELEMENT_TOKENS.begin(), ELEMENT_TOKENS.end(), m_tokenizer.getToken()) != ELEMENT_TOKENS.end())
244  parseElements();
245 
246  consumeToken(JsonToken::END_ARRAY);
247  m_observer.endArray();
248 }
249 
250 template <typename ALLOC>
252 {
253  parseElement();
254  while (m_tokenizer.getToken() == JsonToken::ITEM_SEPARATOR)
255  {
256  m_tokenizer.next();
257  parseElement();
258  }
259 }
260 
261 template <typename ALLOC>
263 {
264  visitValue();
265  m_tokenizer.next();
266 }
267 
268 template <typename ALLOC>
270 {
271  const AnyHolder<ALLOC>& value = m_tokenizer.getValue();
272 
273  if (value.template isType<std::nullptr_t>())
274  {
275  m_observer.visitValue(nullptr);
276  }
277  else if (value.template isType<bool>())
278  {
279  m_observer.visitValue(value.template get<bool>());
280  }
281  else if (value.template isType<int64_t>())
282  {
283  m_observer.visitValue(value.template get<int64_t>());
284  }
285  else if (value.template isType<uint64_t>())
286  {
287  m_observer.visitValue(value.template get<uint64_t>());
288  }
289  else if (value.template isType<double>())
290  {
291  m_observer.visitValue(value.template get<double>());
292  }
293  else
294  {
295  m_observer.visitValue(value.template get<string<ALLOC>>());
296  }
297 }
298 
299 template <typename ALLOC>
301 {
302  if (m_tokenizer.getToken() != token)
303  throw createUnexpectedTokenException({{token}});
304 }
305 
306 template <typename ALLOC>
308 {
309  checkToken(token);
310  m_tokenizer.next();
311 }
312 
313 template <typename ALLOC>
315  Span<const JsonToken> expecting) const
316 {
317  JsonParserException error("JsonParser:");
318  error << getLine() << ":" << getColumn() << ": unexpected token: " << m_tokenizer.getToken();
319  if (expecting.size() == 1)
320  {
321  error << ", expecting " << expecting[0] << "!";
322  }
323  else
324  {
325  error << ", expecting one of [";
326  for (size_t i = 0; i < expecting.size(); ++i)
327  {
328  if (i > 0)
329  error << ", ";
330  error << expecting[i];
331  }
332  error << "]!";
333  }
334  return error;
335 }
336 
339 
340 } // namespace
341 
342 #endif // ZSERIO_JSON_PARSER_H_INC
size_t getColumn() const
Definition: JsonParser.h:147
size_t getLine() const
Definition: JsonParser.h:137
constexpr size_type size() const noexcept
Definition: Span.h:276
virtual void visitValue(std::nullptr_t nullValue)=0
std::basic_string< char, std::char_traits< char >, RebindAlloc< ALLOC, char >> string
Definition: String.h:16
BasicJsonParser(std::istream &in, IObserver &observer, const ALLOC &allocator=ALLOC())
Definition: JsonParser.h:109
virtual void visitKey(StringView key)=0