nlib
JsonStreamParser.h
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
13  *--------------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_MSGPACK_JSONSTREAMPARSER_H_
17 #define INCLUDE_NN_NLIB_MSGPACK_JSONSTREAMPARSER_H_
18 
19 #include <float.h>
20 
21 #include "nn/nlib/UniquePtr.h"
22 #include "nn/nlib/Swap.h"
24 
25 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
26 #undef NLIB_VIS_PUBLIC
27 #define NLIB_VIS_PUBLIC NLIB_WINEXPORT
28 #endif
29 NLIB_NAMESPACE_BEGIN
30 class InputStream;
31 class TextReader;
32 namespace msgpack {
33 
35  enum Format {
36  kFormatAdaptive = 0,
37  kFormatJson,
38  kFormatMsgpack,
39  FORMAT_ADAPTIVE = kFormatAdaptive,
40  FORMAT_JSON = kFormatJson,
41  FORMAT_MSGPACK = kFormatMsgpack
42  };
44  size_t max_map_size;
46  size_t max_depth;
47  Format format;
48  bool strict;
50  max_array_size(8192), max_map_size(256), token_buffer_size(2048), max_depth(7),
51  format(kFormatAdaptive), strict(false) {}
52 };
53 
55  public:
56  enum Event {
57  kNone = -1,
58  kEventNull = 1,
73  kEventBinary, // msgpack only
74  kEventExt, // msgpack only
76  NONE = kNone,
77  EVENT_NULL = kEventNull,
78  EVENT_TRUE = kEventTrue,
79  EVENT_FALSE = kEventFalse,
80  EVENT_STRING = kEventString,
81  EVENT_NUMBER_INT32 = kEventNumberInt32,
82  EVENT_NUMBER_UINT32 = kEventNumberUint32,
83  EVENT_NUMBER_INT64 = kEventNumberInt64,
84  EVENT_NUMBER_UINT64 = kEventNumberUint64,
85  EVENT_NUMBER_FLOAT = kEventNumberFloat,
86  EVENT_NUMBER_DOUBLE = kEventNumberDouble,
87  EVENT_START_ARRAY = kEventStartArray,
88  EVENT_END_ARRAY = kEventEndArray,
89  EVENT_START_MAP = kEventStartMap,
90  EVENT_END_MAP = kEventEndMap,
91  EVENT_KEY_NAME = kEventKeyName,
92  EVENT_BINARY = kEventBinary,
93  EVENT_EXT = kEventExt,
94  EVENT_END_DOCUMENT = kEventEndDocument
95  };
96  enum Error {
97  kOk = 0,
98  kErrorColon,
99  kErrorComma,
100  kErrorQuote,
101  kErrorKeyTooLong,
102  kErrorNumberTooLong,
103  kErrorArrayTooBig,
104  kErrorMapTooBig,
105  kErrorCharacter,
106  kErrorNumberRange,
107  kErrorDepth,
108  kErrorToken,
109  kErrorStream,
110  ERROR_OK = kOk,
111  ERROR_COLON = kErrorColon,
112  ERROR_COMMA = kErrorComma,
113  ERROR_QUOTE = kErrorQuote,
114  ERROR_KEY_TOOLONG = kErrorKeyTooLong,
115  ERROR_NUMBER_TOOLONG = kErrorNumberTooLong,
116  ERROR_ARRAY_TOOBIG = kErrorArrayTooBig,
117  ERROR_MAP_TOOBIG = kErrorMapTooBig,
118  ERROR_CHARACTER = kErrorCharacter,
119  ERROR_NUMBER_RANGE = kErrorNumberRange,
120  ERROR_DEPTH = kErrorDepth,
121  ERROR_TOKEN = kErrorToken,
122  ERROR_STREAM = kErrorStream
123  };
124  struct Token {
127  union {
128  size_t size;
129  int64_t i64;
130  uint64_t u64;
131  double f64;
132  int32_t i32;
133  uint32_t u32;
134  float f32;
135  } number;
137  int8_t ext; // for kEventExt
138  };
139 
140  public:
141  static errno_t Parse(JsonStreamParser* parser, UniquePtr<MpObject>& obj, // NOLINT
142  bool peek) NLIB_NOEXCEPT NLIB_NONNULL_1;
144  return Parse(parser, obj, false);
145  }
146  static errno_t Parse(UniquePtr<MpObject>& obj, const void* data, size_t n, // NOLINT
147  const JsonStreamParserSettings& settings)
149  static errno_t Parse(UniquePtr<MpObject>& obj, const void* data, size_t n) NLIB_NOEXCEPT { // NOLINT
150  JsonStreamParserSettings settings;
151  return Parse(obj, data, n, settings);
152  }
153  static errno_t Parse(UniquePtr<MpObject>& obj, const nlib_utf8_t* str, // NOLINT
154  const JsonStreamParserSettings& settings) NLIB_NOEXCEPT {
155  size_t n = nlib_strlen(str);
156  if (settings.format == JsonStreamParserSettings::kFormatJson) {
157  return Parse(obj, str, n, settings);
158  } else {
159  JsonStreamParserSettings settings_ = settings;
160  settings_.format = JsonStreamParserSettings::kFormatJson;
161  return Parse(obj, str, n, settings_);
162  }
163  }
164  static errno_t Parse(UniquePtr<MpObject>& obj, const nlib_utf8_t* str) NLIB_NOEXCEPT { // NOLINT
165  JsonStreamParserSettings settings;
166  return Parse(obj, str, settings);
167  }
168 
169  static errno_t ToInt32(const Token& token, int32_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
170  static errno_t ToUint32(const Token& token, uint32_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
171  static errno_t ToInt64(const Token& token, int64_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
172  static errno_t ToUint64(const Token& token, uint64_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
173  static errno_t ToFloat(const Token& token, float* number) NLIB_NOEXCEPT NLIB_NONNULL;
174  static errno_t ToDouble(const Token& token, double* number) NLIB_NOEXCEPT NLIB_NONNULL;
175 
178  NLIB_MOVE_MEMBER_HELPER_1(JsonStreamParser, prv_);
179  errno_t Init(const JsonStreamParserSettings& settings) NLIB_NOEXCEPT;
180  errno_t Init() NLIB_NOEXCEPT {
182  return this->Init(settings);
183  }
184  errno_t Open(InputStream* stream) NLIB_NOEXCEPT NLIB_NONNULL;
185  errno_t Open(TextReader* reader) NLIB_NOEXCEPT NLIB_NONNULL;
186  errno_t Close() NLIB_NOEXCEPT;
187  Error GetError() const NLIB_NOEXCEPT;
188  bool HasNext() const NLIB_NOEXCEPT;
189  Event Next() NLIB_NOEXCEPT;
190  bool Skip() NLIB_NOEXCEPT;
191  int GetLine() const NLIB_NOEXCEPT;
192  int GetColumn() const NLIB_NOEXCEPT;
193  const Token& GetToken() const NLIB_NOEXCEPT { return token_; }
194  NLIB_SAFE_BOOL(JsonStreamParser, error_ == kOk);
195  void swap(JsonStreamParser& rhs) NLIB_NOEXCEPT {
196  using std::swap;
197  swap(prv_, rhs.prv_);
198  swap(error_, rhs.error_);
199  swap(token_, rhs.token_);
200  }
201 
202  private:
203  NLIB_VIS_HIDDEN Error ReadString() NLIB_NOEXCEPT;
204  NLIB_VIS_HIDDEN Error ReadNumber() NLIB_NOEXCEPT;
206  NLIB_VIS_HIDDEN Event NextMsgpack() NLIB_NOEXCEPT;
207  NLIB_VIS_HIDDEN Event NextMsgpackVal() NLIB_NOEXCEPT;
208 
209  struct JsonStreamParserPrivate;
210  JsonStreamParserPrivate* prv_;
211  Error error_;
212  Token token_;
214 };
215 
216 inline errno_t JsonStreamParser::ToInt32(const Token& token, int32_t* number) NLIB_NOEXCEPT {
217  NLIB_EINVAL_IFNULL(number);
218  switch (token.event) {
219  case kEventNumberInt32:
220  *number = token.number.i32;
221  break;
222  case kEventNumberUint32:
223  *number = static_cast<int32_t>(token.number.u32);
224  if (token.number.u32 > INT32_MAX) return ERANGE;
225  break;
226  case kEventNumberInt64:
227  *number = static_cast<int32_t>(token.number.i64);
228  if (token.number.i64 > INT32_MAX ||
229  token.number.i64 < INT32_MIN) return ERANGE;
230  break;
231  case kEventNumberUint64:
232  *number = static_cast<int32_t>(token.number.u64);
233  if (token.number.u64 > INT32_MAX) return ERANGE;
234  break;
235  case kEventNumberFloat:
236  *number = static_cast<int32_t>(token.number.f32);
237  if (token.number.f32 > static_cast<float>(INT32_MAX) ||
238  token.number.f32 < static_cast<float>(INT32_MIN))
239  return ERANGE;
240  return EDOM;
241  case kEventNumberDouble:
242  *number = static_cast<int32_t>(token.number.f64);
243  if (token.number.f64 > static_cast<double>(INT32_MAX) ||
244  token.number.f64 < static_cast<double>(INT32_MIN))
245  return ERANGE;
246  return EDOM;
247  default:
248  return EINVAL;
249  }
250  return 0;
251 }
252 
253 inline errno_t JsonStreamParser::ToUint32(const Token& token, uint32_t* number) NLIB_NOEXCEPT {
254  NLIB_EINVAL_IFNULL(number);
255  switch (token.event) {
256  case kEventNumberInt32:
257  *number = static_cast<uint32_t>(token.number.i32);
258  if (token.number.i32 < 0) return ERANGE;
259  break;
260  case kEventNumberUint32:
261  *number = token.number.u32;
262  break;
263  case kEventNumberInt64:
264  *number = static_cast<uint32_t>(token.number.i64);
265  if (token.number.i64 > UINT32_MAX ||
266  token.number.i64 < 0) return ERANGE;
267  break;
268  case kEventNumberUint64:
269  *number = static_cast<uint32_t>(token.number.u64);
270  if (token.number.u64 > UINT32_MAX) return ERANGE;
271  break;
272  case kEventNumberFloat:
273  *number = static_cast<uint32_t>(token.number.f32);
274  if (token.number.f32 > static_cast<float>(UINT32_MAX) ||
275  token.number.f32 < 0.f)
276  return ERANGE;
277  return EDOM;
278  case kEventNumberDouble:
279  *number = static_cast<uint32_t>(token.number.f64);
280  if (token.number.f64 > static_cast<double>(UINT32_MAX) ||
281  token.number.f64 < 0.0)
282  return ERANGE;
283  return EDOM;
284  default:
285  return EINVAL;
286  }
287  return 0;
288 }
289 
290 inline errno_t JsonStreamParser::ToInt64(const Token& token, int64_t* number) NLIB_NOEXCEPT {
291  NLIB_EINVAL_IFNULL(number);
292  switch (token.event) {
293  case JsonStreamParser::kEventNumberInt32:
294  *number = token.number.i32;
295  break;
296  case JsonStreamParser::kEventNumberUint32:
297  *number = static_cast<int64_t>(token.number.u32);
298  break;
299  case JsonStreamParser::kEventNumberInt64:
300  *number = token.number.i64;
301  break;
302  case JsonStreamParser::kEventNumberUint64:
303  *number = static_cast<int64_t>(token.number.u64);
304  if (token.number.u64 > INT64_MAX) return ERANGE;
305  break;
306  case kEventNumberFloat:
307  *number = static_cast<int64_t>(token.number.f32);
308  if (token.number.f32 > static_cast<float>(INT64_MAX) ||
309  token.number.f32 < static_cast<float>(INT64_MIN))
310  return ERANGE;
311  return EDOM;
312  case kEventNumberDouble:
313  *number = static_cast<int64_t>(token.number.f64);
314  if (token.number.f64 > static_cast<double>(INT64_MAX) ||
315  token.number.f64 < static_cast<double>(INT64_MIN))
316  return ERANGE;
317  return EDOM;
318  default:
319  return EINVAL;
320  }
321  return 0;
322 }
323 
324 inline errno_t JsonStreamParser::ToUint64(const Token& token, uint64_t* number) NLIB_NOEXCEPT {
325  NLIB_EINVAL_IFNULL(number);
326  switch (token.event) {
327  case kEventNumberInt32:
328  *number = static_cast<uint64_t>(token.number.i32);
329  if (token.number.i32 < 0) return ERANGE;
330  break;
331  case kEventNumberUint32:
332  *number = token.number.u32;
333  break;
334  case kEventNumberInt64:
335  *number = static_cast<uint64_t>(token.number.i64);
336  if (token.number.i64 < 0) return ERANGE;
337  break;
338  case kEventNumberUint64:
339  *number = token.number.u64;
340  break;
341  case kEventNumberFloat:
342  *number = static_cast<uint64_t>(token.number.f32);
343  if (token.number.f32 > static_cast<float>(UINT64_MAX) ||
344  token.number.f32 < 0.f)
345  return ERANGE;
346  return EDOM;
347  case kEventNumberDouble:
348  *number = static_cast<uint64_t>(token.number.f64);
349  if (token.number.f64 > static_cast<double>(UINT64_MAX) ||
350  token.number.f64 < 0.0)
351  return ERANGE;
352  return EDOM;
353  default:
354  return EINVAL;
355  }
356  return 0;
357 }
358 
359 inline errno_t JsonStreamParser::ToFloat(const Token& token, float* number) NLIB_NOEXCEPT {
360  NLIB_EINVAL_IFNULL(number);
361  switch (token.event) {
362  case kEventNumberInt32:
363  *number = static_cast<float>(token.number.i32);
364  if (token.number.i32 > 16777215 || token.number.i32 < -16777215)
365  return EDOM;
366  break;
367  case kEventNumberUint32:
368  *number = static_cast<float>(token.number.u32);
369  if (token.number.u32 > 16777215)
370  return EDOM;
371  break;
372  case kEventNumberInt64:
373  *number = static_cast<float>(token.number.i64);
374  if (token.number.i64 > 16777215 || token.number.i64 < -16777215)
375  return EDOM;
376  break;
377  case kEventNumberUint64:
378  *number = static_cast<float>(token.number.u64);
379  if (token.number.u64 > 16777215)
380  return EDOM;
381  break;
382  case kEventNumberFloat:
383  *number = token.number.f32;
384  break;
385  case kEventNumberDouble:
386  *number = static_cast<float>(token.number.f32);
387  if (token.number.f64 < FLT_MIN ||
388  token.number.f64 > FLT_MAX)
389  return ERANGE;
390  else
391  return EDOM;
392  default:
393  return EINVAL;
394  }
395  return 0;
396 }
397 
398 inline errno_t JsonStreamParser::ToDouble(const Token& token, double* number) NLIB_NOEXCEPT {
399  NLIB_EINVAL_IFNULL(number);
400  switch (token.event) {
401  case kEventNumberInt32:
402  *number = static_cast<double>(token.number.i32);
403  break;
404  case kEventNumberUint32:
405  *number = static_cast<double>(token.number.u32);
406  break;
407  case kEventNumberInt64:
408  *number = static_cast<double>(token.number.i64);
409  if (token.number.i64 > 9007199254740991LL ||
410  token.number.i64 < -9007199254740991LL)
411  return EDOM;
412  break;
413  case kEventNumberUint64:
414  *number = static_cast<double>(token.number.u64);
415  if (token.number.u64 > 9007199254740991ULL)
416  return EDOM;
417  break;
418  case kEventNumberFloat:
419  *number = token.number.f32;
420  break;
421  case kEventNumberDouble:
422  *number = token.number.f64;
423  break;
424  default:
425  return EINVAL;
426  }
427  return 0;
428 }
429 
430 } // namespace msgpack
431 NLIB_NAMESPACE_END
432 NLIB_DEFINE_STD_SWAP(::nlib_ns::msgpack::JsonStreamParser)
433 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
434 #undef NLIB_VIS_PUBLIC
435 #define NLIB_VIS_PUBLIC NLIB_WINIMPORT
436 #endif
437 
438 #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...
Extended data has been read (msgpack only).
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Definition: Config.h:163
#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:178
#define NLIB_NONNULL_1
Indicates that you cannot specify NULL for the first argument.
A uint64_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...
nlib_utf8_t * buf
Stores strings or binary data.
UniquePtr owns the pointer, and when it goes out of scope, the pointer is released by the destructor ...
Definition: UniquePtr.h:109
Defines that class that is corresponding to std::unique_ptr.
An int32_t type integer has been read.
#define NLIB_VIS_HIDDEN
Symbols for functions and classes are not made available outside of the library.
Definition: Platform_unix.h:88
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:89
Event event
The event returned by Next().
#define NLIB_NONNULL_2
Indicates that you cannot specify NULL for the second argument.
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:33
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:29
An associative array key has been read.
A uint32_t type integer has been read.
static errno_t Parse(UniquePtr< MpObject > &obj, const nlib_utf8_t *str, const JsonStreamParserSettings &settings) noexcept
Creates MpObject by parsing JSON.
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:99
JSON or msgpack has finished (A return value of Next() when HasNext() returns false).
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
Definition: Config.h:93
bool token_toobig
When the event is kEventString and the token is too large, stores a non-zero value. In this case, a null string is set to buf.
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.
A string other than an associative array key has been read.
static errno_t Parse(UniquePtr< MpObject > &obj, const nlib_utf8_t *str) noexcept
Runs Parse(obj, str, settings) with the default JsonStreamParserSettings settings specified...
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:229
int8_t ext
When the event is kEventExt, stores a data type 8-bit value.
An int64_t type integer has been read.
errno_t Init() noexcept
Initializes the parser using the default settings.
Binary data has been read (msgpack only).
size_t max_depth
Specifies the maximum value for the depth of array or associative array. The default is 7...
The associative array has finished.
Format format
Decides how formats are determined when parsing. The default is kFormatAdaptive.
#define NLIB_NONNULL
Indicates that you cannot specify NULL for all arguments.
A float type floating-point number has been read.
char nlib_utf8_t
Defines char with a typedef. Indicates that it is a UTF-8 string.
Definition: Platform.h:300
int errno_t
Indicates with an int-type typedef that a POSIX error value is returned as the return value...
Definition: NMalloc.h:37