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