nlib
JsonStreamParser.h
1 
2 #pragma once
3 #ifndef INCLUDE_NN_NLIB_MSGPACK_JSONSTREAMPARSER_H_
4 #define INCLUDE_NN_NLIB_MSGPACK_JSONSTREAMPARSER_H_
5 
6 #include <float.h>
7 
8 #include "nn/nlib/UniquePtr.h"
10 
11 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
12 #undef NLIB_VIS_PUBLIC
13 #define NLIB_VIS_PUBLIC NLIB_WINEXPORT
14 #endif
15 NLIB_NAMESPACE_BEGIN
16 class InputStream;
17 class TextReader;
18 namespace msgpack {
19 
21  enum Format {
22  FORMAT_ADAPTIVE = 0,
23  FORMAT_JSON,
24  FORMAT_MSGPACK
25  };
27  size_t max_map_size;
29  size_t max_depth;
30  Format format;
31  bool strict;
33  max_array_size(8192), max_map_size(256), token_buffer_size(2048), max_depth(7),
34  format(FORMAT_ADAPTIVE), strict(false) {}
35 };
36 
38  public:
39  enum Event {
40  NONE = -1,
41  EVENT_NULL = 1,
56  EVENT_BINARY, // msgpack only
57  EVENT_EXT, // msgpack only
58  EVENT_END_DOCUMENT
59  };
60  enum Error {
61  ERROR_OK = 0,
62  ERROR_COLON,
63  ERROR_COMMA,
64  ERROR_QUOTE,
65  ERROR_KEY_TOOLONG,
66  ERROR_NUMBER_TOOLONG,
67  ERROR_ARRAY_TOOBIG,
68  ERROR_MAP_TOOBIG,
69  ERROR_CHARACTER,
70  ERROR_NUMBER_RANGE,
71  ERROR_DEPTH,
72  ERROR_TOKEN,
73  ERROR_STREAM
74  };
75  struct Token {
77  char* buf;
78  union {
79  size_t size;
80  int64_t i64;
81  uint64_t u64;
82  double f64;
83  int32_t i32;
84  uint32_t u32;
85  float f32;
86  } number;
88  int8_t ext; // for EVENT_EXT
89  };
90 
91  public:
92  static errno_t Parse(JsonStreamParser* parser, UniquePtr<MpObject>& obj, // NOLINT
93  bool peek) NLIB_NOEXCEPT NLIB_NONNULL_1;
95  return Parse(parser, obj, false);
96  }
97  static errno_t Parse(UniquePtr<MpObject>& obj, const void* data, size_t n, // NOLINT
98  const JsonStreamParserSettings& settings)
100  static errno_t Parse(UniquePtr<MpObject>& obj, const void* data, size_t n) NLIB_NOEXCEPT { // NOLINT
101  JsonStreamParserSettings settings;
102  return Parse(obj, data, n, settings);
103  }
104  static errno_t Parse(UniquePtr<MpObject>& obj, const char* str, // NOLINT
105  const JsonStreamParserSettings& settings) NLIB_NOEXCEPT {
106  size_t n = nlib_strlen(str);
107  if (settings.format == JsonStreamParserSettings::FORMAT_JSON) {
108  return Parse(obj, str, n, settings);
109  } else {
110  JsonStreamParserSettings settings_ = settings;
111  settings_.format = JsonStreamParserSettings::FORMAT_JSON;
112  return Parse(obj, str, n, settings_);
113  }
114  }
115  static errno_t Parse(UniquePtr<MpObject>& obj, const char* str) NLIB_NOEXCEPT { // NOLINT
116  JsonStreamParserSettings settings;
117  return Parse(obj, str, settings);
118  }
119 
120  static errno_t ToInt32(const Token& token, int32_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
121  static errno_t ToUint32(const Token& token, uint32_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
122  static errno_t ToInt64(const Token& token, int64_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
123  static errno_t ToUint64(const Token& token, uint64_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
124  static errno_t ToFloat(const Token& token, float* number) NLIB_NOEXCEPT NLIB_NONNULL;
125  static errno_t ToDouble(const Token& token, double* number) NLIB_NOEXCEPT NLIB_NONNULL;
126 
129  errno_t Init(const JsonStreamParserSettings& settings) NLIB_NOEXCEPT;
130  errno_t Init() NLIB_NOEXCEPT {
132  return this->Init(settings);
133  }
134  errno_t Open(InputStream* stream) NLIB_NOEXCEPT NLIB_NONNULL;
135  errno_t Open(TextReader* reader) NLIB_NOEXCEPT NLIB_NONNULL;
136  errno_t Close() NLIB_NOEXCEPT;
137  Error GetError() const NLIB_NOEXCEPT;
138  bool HasNext() const NLIB_NOEXCEPT;
139  Event Next() NLIB_NOEXCEPT;
140  bool Skip() NLIB_NOEXCEPT;
141  int GetLine() const NLIB_NOEXCEPT;
142  int GetColumn() const NLIB_NOEXCEPT;
143  const Token& GetToken() const NLIB_NOEXCEPT { return token_; }
144  NLIB_SAFE_BOOL(JsonStreamParser, error_ == ERROR_OK);
145 
146  private:
147  NLIB_VIS_HIDDEN Error ReadString() NLIB_NOEXCEPT;
148  NLIB_VIS_HIDDEN Error ReadNumber() NLIB_NOEXCEPT;
150  NLIB_VIS_HIDDEN Event NextMsgpack() NLIB_NOEXCEPT;
151  NLIB_VIS_HIDDEN Event NextMsgpackVal() NLIB_NOEXCEPT;
152 
153  struct JsonStreamParserPrivate;
154  JsonStreamParserPrivate* prv_;
155  Error error_;
156  Token token_;
157 };
158 
159 inline errno_t JsonStreamParser::ToInt32(const Token& token, int32_t* number) NLIB_NOEXCEPT {
160  NLIB_EINVAL_IFNULL(number);
161  switch (token.event) {
162  case EVENT_NUMBER_INT32:
163  *number = token.number.i32;
164  break;
165  case EVENT_NUMBER_UINT32:
166  *number = static_cast<int32_t>(token.number.u32);
167  if (token.number.u32 > INT32_MAX) return ERANGE;
168  break;
169  case EVENT_NUMBER_INT64:
170  *number = static_cast<int32_t>(token.number.i64);
171  if (token.number.i64 > INT32_MAX ||
172  token.number.i64 < INT32_MIN) return ERANGE;
173  break;
174  case EVENT_NUMBER_UINT64:
175  *number = static_cast<int32_t>(token.number.u64);
176  if (token.number.u64 > INT32_MAX) return ERANGE;
177  break;
178  case EVENT_NUMBER_FLOAT:
179  *number = static_cast<int32_t>(token.number.f32);
180  if (token.number.f32 > static_cast<float>(INT32_MAX) ||
181  token.number.f32 < static_cast<float>(INT32_MIN))
182  return ERANGE;
183  return EDOM;
184  case EVENT_NUMBER_DOUBLE:
185  *number = static_cast<int32_t>(token.number.f64);
186  if (token.number.f64 > static_cast<double>(INT32_MAX) ||
187  token.number.f64 < static_cast<double>(INT32_MIN))
188  return ERANGE;
189  return EDOM;
190  default:
191  return EINVAL;
192  }
193  return 0;
194 }
195 
196 inline errno_t JsonStreamParser::ToUint32(const Token& token, uint32_t* number) NLIB_NOEXCEPT {
197  NLIB_EINVAL_IFNULL(number);
198  switch (token.event) {
199  case EVENT_NUMBER_INT32:
200  *number = static_cast<uint32_t>(token.number.i32);
201  if (token.number.i32 < 0) return ERANGE;
202  break;
203  case EVENT_NUMBER_UINT32:
204  *number = token.number.u32;
205  break;
206  case EVENT_NUMBER_INT64:
207  *number = static_cast<uint32_t>(token.number.i64);
208  if (token.number.i64 > UINT32_MAX ||
209  token.number.i64 < 0) return ERANGE;
210  break;
211  case EVENT_NUMBER_UINT64:
212  *number = static_cast<uint32_t>(token.number.u64);
213  if (token.number.u64 > UINT32_MAX) return ERANGE;
214  break;
215  case EVENT_NUMBER_FLOAT:
216  *number = static_cast<uint32_t>(token.number.f32);
217  if (token.number.f32 > static_cast<float>(UINT32_MAX) ||
218  token.number.f32 < 0.f)
219  return ERANGE;
220  return EDOM;
221  case EVENT_NUMBER_DOUBLE:
222  *number = static_cast<uint32_t>(token.number.f64);
223  if (token.number.f64 > static_cast<double>(UINT32_MAX) ||
224  token.number.f64 < 0.0)
225  return ERANGE;
226  return EDOM;
227  default:
228  return EINVAL;
229  }
230  return 0;
231 }
232 
233 inline errno_t JsonStreamParser::ToInt64(const Token& token, int64_t* number) NLIB_NOEXCEPT {
234  NLIB_EINVAL_IFNULL(number);
235  switch (token.event) {
236  case JsonStreamParser::EVENT_NUMBER_INT32:
237  *number = token.number.i32;
238  break;
239  case JsonStreamParser::EVENT_NUMBER_UINT32:
240  *number = static_cast<int64_t>(token.number.u32);
241  break;
242  case JsonStreamParser::EVENT_NUMBER_INT64:
243  *number = token.number.i64;
244  break;
245  case JsonStreamParser::EVENT_NUMBER_UINT64:
246  *number = static_cast<int64_t>(token.number.u64);
247  if (token.number.u64 > INT64_MAX) return ERANGE;
248  break;
249  case EVENT_NUMBER_FLOAT:
250  *number = static_cast<int64_t>(token.number.f32);
251  if (token.number.f32 > static_cast<float>(INT64_MAX) ||
252  token.number.f32 < static_cast<float>(INT64_MIN))
253  return ERANGE;
254  return EDOM;
255  case EVENT_NUMBER_DOUBLE:
256  *number = static_cast<int64_t>(token.number.f64);
257  if (token.number.f64 > static_cast<double>(INT64_MAX) ||
258  token.number.f64 < static_cast<double>(INT64_MIN))
259  return ERANGE;
260  return EDOM;
261  default:
262  return EINVAL;
263  }
264  return 0;
265 }
266 
267 inline errno_t JsonStreamParser::ToUint64(const Token& token, uint64_t* number) NLIB_NOEXCEPT {
268  NLIB_EINVAL_IFNULL(number);
269  switch (token.event) {
270  case EVENT_NUMBER_INT32:
271  *number = static_cast<uint64_t>(token.number.i32);
272  if (token.number.i32 < 0) return ERANGE;
273  break;
274  case EVENT_NUMBER_UINT32:
275  *number = token.number.u32;
276  break;
277  case EVENT_NUMBER_INT64:
278  *number = static_cast<uint64_t>(token.number.i64);
279  if (token.number.i64 < 0) return ERANGE;
280  break;
281  case EVENT_NUMBER_UINT64:
282  *number = token.number.u64;
283  break;
284  case EVENT_NUMBER_FLOAT:
285  *number = static_cast<uint64_t>(token.number.f32);
286  if (token.number.f32 > static_cast<float>(UINT64_MAX) ||
287  token.number.f32 < 0.f)
288  return ERANGE;
289  return EDOM;
290  case EVENT_NUMBER_DOUBLE:
291  *number = static_cast<uint64_t>(token.number.f64);
292  if (token.number.f64 > static_cast<double>(UINT64_MAX) ||
293  token.number.f64 < 0.0)
294  return ERANGE;
295  return EDOM;
296  default:
297  return EINVAL;
298  }
299  return 0;
300 }
301 
302 inline errno_t JsonStreamParser::ToFloat(const Token& token, float* number) NLIB_NOEXCEPT {
303  NLIB_EINVAL_IFNULL(number);
304  switch (token.event) {
305  case EVENT_NUMBER_INT32:
306  *number = static_cast<float>(token.number.i32);
307  if (token.number.i32 > 16777215 || token.number.i32 < -16777215)
308  return EDOM;
309  break;
310  case EVENT_NUMBER_UINT32:
311  *number = static_cast<float>(token.number.u32);
312  if (token.number.u32 > 16777215)
313  return EDOM;
314  break;
315  case EVENT_NUMBER_INT64:
316  *number = static_cast<float>(token.number.i64);
317  if (token.number.i64 > 16777215 || token.number.i64 < -16777215)
318  return EDOM;
319  break;
320  case EVENT_NUMBER_UINT64:
321  *number = static_cast<float>(token.number.u64);
322  if (token.number.u64 > 16777215)
323  return EDOM;
324  break;
325  case EVENT_NUMBER_FLOAT:
326  *number = token.number.f32;
327  break;
328  case EVENT_NUMBER_DOUBLE:
329  *number = static_cast<float>(token.number.f32);
330  if (token.number.f64 < FLT_MIN ||
331  token.number.f64 > FLT_MAX)
332  return ERANGE;
333  else
334  return EDOM;
335  default:
336  return EINVAL;
337  }
338  return 0;
339 }
340 
341 inline errno_t JsonStreamParser::ToDouble(const Token& token, double* number) NLIB_NOEXCEPT {
342  NLIB_EINVAL_IFNULL(number);
343  switch (token.event) {
344  case EVENT_NUMBER_INT32:
345  *number = static_cast<double>(token.number.i32);
346  break;
347  case EVENT_NUMBER_UINT32:
348  *number = static_cast<double>(token.number.u32);
349  break;
350  case EVENT_NUMBER_INT64:
351  *number = static_cast<double>(token.number.i64);
352  if (token.number.i64 > 9007199254740991LL ||
353  token.number.i64 < -9007199254740991LL)
354  return EDOM;
355  break;
356  case EVENT_NUMBER_UINT64:
357  *number = static_cast<double>(token.number.u64);
358  if (token.number.u64 > 9007199254740991ULL)
359  return EDOM;
360  break;
361  case EVENT_NUMBER_FLOAT:
362  *number = token.number.f32;
363  break;
364  case EVENT_NUMBER_DOUBLE:
365  *number = token.number.f64;
366  break;
367  default:
368  return EINVAL;
369  }
370  return 0;
371 }
372 
373 } // namespace msgpack
374 NLIB_NAMESPACE_END
375 
376 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
377 #undef NLIB_VIS_PUBLIC
378 #define NLIB_VIS_PUBLIC NLIB_WINIMPORT
379 #endif
380 
381 #endif // INCLUDE_NN_NLIB_MSGPACK_JSONSTREAMPARSER_H_
size_t token_buffer_size
Specifies the size of the buffer to store tokens. The default is 2048 and the minimum value is 512...
#define NLIB_SAFE_BOOL(class_name, exp)
Defines a safe operator bool function in the class. Uses the C++11 explicit bool if it is available f...
Definition: Config.h:160
#define NLIB_NONNULL_1
Indicates that you cannot specify NULL for the first argument.
Definition: Platform_unix.h:77
An int32_t type integer has been read.
bool strict
If a value other than 0 is set, a stricter error check is performed. The default is 0...
constexpr JsonStreamParserSettings() noexcept
Instantiates the object with default parameters (default constructor). Sets each data member to the d...
An int64_t type integer has been read.
char * buf
Stores strings or binary data.
Binary data has been read (msgpack only).
UniquePtr owns the pointer, and when it goes out of scope, the pointer is released by the destructor ...
Definition: UniquePtr.h:96
Defines that class that is corresponding to std::unique_ptr.
#define NLIB_VIS_HIDDEN
Symbols for functions and classes are not made available outside of the library.
Definition: Platform_unix.h:60
static errno_t Parse(UniquePtr< MpObject > &obj, const void *data, size_t n) noexcept
Runs Parse(obj, data, n, settings) with the default JsonStreamParserSettings settings specified...
#define NLIB_VIS_PUBLIC
Symbols for functions and classes are made available outside of the library.
Definition: Platform_unix.h:61
Extended data has been read (msgpack only).
Event event
The event returned by Next().
#define NLIB_NONNULL_2
Indicates that you cannot specify NULL for the second argument.
Definition: Platform_unix.h:78
A string other than an associative array key has been read.
A double type floating-point number has been read.
Data structure used to store the JsonStreamParser settings parameters.
The class to parse JSON or msgpack in a pull manner.
The class for reading text from streams.
Definition: TextReader.h:20
Event
The type used by JsonStreamParser::Next() and Token, and the event that corresponds to the data read ...
Object created when MessagePack, JSON, or CSV is read.
size_t max_map_size
Specifies the maximum associative array size. The default is 256 and the minimum value is 16...
size_t max_array_size
Specifies the maximum array size. The default is 8192 and the minimum value is 16.
The base class for input streams. This class cannot be instantiated.
Definition: InputStream.h:16
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:86
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
Definition: Config.h:80
bool token_toobig
When the event is EVENT_STRING and the token is too large, stores a non-zero value. In this case, a null string is set to buf.
A float type floating-point number has been read.
static errno_t Parse(JsonStreamParser *parser, UniquePtr< MpObject > &obj) noexcept
Runs Parse(parser, obj, false).
const Token & GetToken() const noexcept
Gets the token.
size_t nlib_strlen(const char *s)
Internally calls strlen(). In some cases, it may operate as an independent implementation.
Stores data on the tokens obtained by the parser.
static errno_t Parse(UniquePtr< MpObject > &obj, const char *str, const JsonStreamParserSettings &settings) noexcept
Creates MpObject by parsing JSON.
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:211
int8_t ext
When the event is EVENT_EXT, stores a data type 8-bit value.
errno_t Init() noexcept
Initializes the parser using the default settings.
The associative array has finished.
static errno_t Parse(UniquePtr< MpObject > &obj, const char *str) noexcept
Runs Parse(obj, str, settings) with the default JsonStreamParserSettings settings specified...
size_t max_depth
Specifies the maximum value for the depth of array or associative array. The default is 7...
Format format
Decides how formats are determined when parsing. The default is FORMAT_ADAPTIVE.
#define NLIB_NONNULL
Indicates that you cannot specify NULL for all arguments.
Definition: Platform_unix.h:76
An associative array key has been read.
int errno_t
Indicates with an int-type typedef that a POSIX error value is returned as the return value...
Definition: NMalloc.h:24