nlib
JsonStreamParser.h
1 
2 /*---------------------------------------------------------------------------*
3 
4  Project: CrossRoad
5  Copyright (C)2012-2016 Nintendo. All rights reserved.
6 
7  These coded instructions, statements, and computer programs contain
8  proprietary information of Nintendo of America Inc. and/or Nintendo
9  Company Ltd., and are protected by Federal copyright law. They may
10  not be disclosed to third parties or copied or duplicated in any form,
11  in whole or in part, without the prior written consent of Nintendo.
12 
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"
23 
24 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
25 #undef NLIB_VIS_PUBLIC
26 #define NLIB_VIS_PUBLIC NLIB_WINEXPORT
27 #endif
28 NLIB_NAMESPACE_BEGIN
29 class InputStream;
30 class TextReader;
31 namespace msgpack {
32 
34  enum Format {
35  FORMAT_ADAPTIVE = 0,
36  FORMAT_JSON,
37  FORMAT_MSGPACK
38  };
40  size_t max_map_size;
42  size_t max_depth;
43  Format format;
44  bool strict;
46  max_array_size(8192), max_map_size(256), token_buffer_size(2048), max_depth(7),
47  format(FORMAT_ADAPTIVE), strict(false) {}
48 };
49 
51  public:
52  enum Event {
53  NONE = -1,
54  EVENT_NULL = 1,
69  EVENT_BINARY, // msgpack only
70  EVENT_EXT, // msgpack only
71  EVENT_END_DOCUMENT
72  };
73  enum Error {
74  ERROR_OK = 0,
75  ERROR_COLON,
76  ERROR_COMMA,
77  ERROR_QUOTE,
78  ERROR_KEY_TOOLONG,
79  ERROR_NUMBER_TOOLONG,
80  ERROR_ARRAY_TOOBIG,
81  ERROR_MAP_TOOBIG,
82  ERROR_CHARACTER,
83  ERROR_NUMBER_RANGE,
84  ERROR_DEPTH,
85  ERROR_TOKEN,
86  ERROR_STREAM
87  };
88  struct Token {
90  char* buf;
91  union {
92  size_t size;
93  int64_t i64;
94  uint64_t u64;
95  double f64;
96  int32_t i32;
97  uint32_t u32;
98  float f32;
99  } number;
101  int8_t ext; // for EVENT_EXT
102  };
103 
104  public:
105  static errno_t Parse(JsonStreamParser* parser, UniquePtr<MpObject>& obj, // NOLINT
106  bool peek) NLIB_NOEXCEPT NLIB_NONNULL_1;
108  return Parse(parser, obj, false);
109  }
110  static errno_t Parse(UniquePtr<MpObject>& obj, const void* data, size_t n, // NOLINT
111  const JsonStreamParserSettings& settings)
113  static errno_t Parse(UniquePtr<MpObject>& obj, const void* data, size_t n) NLIB_NOEXCEPT { // NOLINT
114  JsonStreamParserSettings settings;
115  return Parse(obj, data, n, settings);
116  }
117  static errno_t Parse(UniquePtr<MpObject>& obj, const char* str, // NOLINT
118  const JsonStreamParserSettings& settings) NLIB_NOEXCEPT {
119  size_t n = nlib_strlen(str);
120  if (settings.format == JsonStreamParserSettings::FORMAT_JSON) {
121  return Parse(obj, str, n, settings);
122  } else {
123  JsonStreamParserSettings settings_ = settings;
124  settings_.format = JsonStreamParserSettings::FORMAT_JSON;
125  return Parse(obj, str, n, settings_);
126  }
127  }
128  static errno_t Parse(UniquePtr<MpObject>& obj, const char* str) NLIB_NOEXCEPT { // NOLINT
129  JsonStreamParserSettings settings;
130  return Parse(obj, str, settings);
131  }
132 
133  static errno_t ToInt32(const Token& token, int32_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
134  static errno_t ToUint32(const Token& token, uint32_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
135  static errno_t ToInt64(const Token& token, int64_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
136  static errno_t ToUint64(const Token& token, uint64_t* number) NLIB_NOEXCEPT NLIB_NONNULL;
137  static errno_t ToFloat(const Token& token, float* number) NLIB_NOEXCEPT NLIB_NONNULL;
138  static errno_t ToDouble(const Token& token, double* number) NLIB_NOEXCEPT NLIB_NONNULL;
139 
142  errno_t Init(const JsonStreamParserSettings& settings) NLIB_NOEXCEPT;
143  errno_t Init() NLIB_NOEXCEPT {
145  return this->Init(settings);
146  }
147  errno_t Open(InputStream* stream) NLIB_NOEXCEPT NLIB_NONNULL;
148  errno_t Open(TextReader* reader) NLIB_NOEXCEPT NLIB_NONNULL;
149  errno_t Close() NLIB_NOEXCEPT;
150  Error GetError() const NLIB_NOEXCEPT;
151  bool HasNext() const NLIB_NOEXCEPT;
152  Event Next() NLIB_NOEXCEPT;
153  bool Skip() NLIB_NOEXCEPT;
154  int GetLine() const NLIB_NOEXCEPT;
155  int GetColumn() const NLIB_NOEXCEPT;
156  const Token& GetToken() const NLIB_NOEXCEPT { return token_; }
157  NLIB_SAFE_BOOL(JsonStreamParser, error_ == ERROR_OK);
158 
159  private:
160  NLIB_VIS_HIDDEN Error ReadString() NLIB_NOEXCEPT;
161  NLIB_VIS_HIDDEN Error ReadNumber() NLIB_NOEXCEPT;
163  NLIB_VIS_HIDDEN Event NextMsgpack() NLIB_NOEXCEPT;
164  NLIB_VIS_HIDDEN Event NextMsgpackVal() NLIB_NOEXCEPT;
165 
166  struct JsonStreamParserPrivate;
167  JsonStreamParserPrivate* prv_;
168  Error error_;
169  Token token_;
170 };
171 
172 inline errno_t JsonStreamParser::ToInt32(const Token& token, int32_t* number) NLIB_NOEXCEPT {
173  NLIB_EINVAL_IFNULL(number);
174  switch (token.event) {
175  case EVENT_NUMBER_INT32:
176  *number = token.number.i32;
177  break;
178  case EVENT_NUMBER_UINT32:
179  *number = static_cast<int32_t>(token.number.u32);
180  if (token.number.u32 > INT32_MAX) return ERANGE;
181  break;
182  case EVENT_NUMBER_INT64:
183  *number = static_cast<int32_t>(token.number.i64);
184  if (token.number.i64 > INT32_MAX ||
185  token.number.i64 < INT32_MIN) return ERANGE;
186  break;
187  case EVENT_NUMBER_UINT64:
188  *number = static_cast<int32_t>(token.number.u64);
189  if (token.number.u64 > INT32_MAX) return ERANGE;
190  break;
191  case EVENT_NUMBER_FLOAT:
192  *number = static_cast<int32_t>(token.number.f32);
193  if (token.number.f32 > static_cast<float>(INT32_MAX) ||
194  token.number.f32 < static_cast<float>(INT32_MIN))
195  return ERANGE;
196  return EDOM;
197  case EVENT_NUMBER_DOUBLE:
198  *number = static_cast<int32_t>(token.number.f64);
199  if (token.number.f64 > static_cast<double>(INT32_MAX) ||
200  token.number.f64 < static_cast<double>(INT32_MIN))
201  return ERANGE;
202  return EDOM;
203  default:
204  return EINVAL;
205  }
206  return 0;
207 }
208 
209 inline errno_t JsonStreamParser::ToUint32(const Token& token, uint32_t* number) NLIB_NOEXCEPT {
210  NLIB_EINVAL_IFNULL(number);
211  switch (token.event) {
212  case EVENT_NUMBER_INT32:
213  *number = static_cast<uint32_t>(token.number.i32);
214  if (token.number.i32 < 0) return ERANGE;
215  break;
216  case EVENT_NUMBER_UINT32:
217  *number = token.number.u32;
218  break;
219  case EVENT_NUMBER_INT64:
220  *number = static_cast<uint32_t>(token.number.i64);
221  if (token.number.i64 > UINT32_MAX ||
222  token.number.i64 < 0) return ERANGE;
223  break;
224  case EVENT_NUMBER_UINT64:
225  *number = static_cast<uint32_t>(token.number.u64);
226  if (token.number.u64 > UINT32_MAX) return ERANGE;
227  break;
228  case EVENT_NUMBER_FLOAT:
229  *number = static_cast<uint32_t>(token.number.f32);
230  if (token.number.f32 > static_cast<float>(UINT32_MAX) ||
231  token.number.f32 < 0.f)
232  return ERANGE;
233  return EDOM;
234  case EVENT_NUMBER_DOUBLE:
235  *number = static_cast<uint32_t>(token.number.f64);
236  if (token.number.f64 > static_cast<double>(UINT32_MAX) ||
237  token.number.f64 < 0.0)
238  return ERANGE;
239  return EDOM;
240  default:
241  return EINVAL;
242  }
243  return 0;
244 }
245 
246 inline errno_t JsonStreamParser::ToInt64(const Token& token, int64_t* number) NLIB_NOEXCEPT {
247  NLIB_EINVAL_IFNULL(number);
248  switch (token.event) {
249  case JsonStreamParser::EVENT_NUMBER_INT32:
250  *number = token.number.i32;
251  break;
252  case JsonStreamParser::EVENT_NUMBER_UINT32:
253  *number = static_cast<int64_t>(token.number.u32);
254  break;
255  case JsonStreamParser::EVENT_NUMBER_INT64:
256  *number = token.number.i64;
257  break;
258  case JsonStreamParser::EVENT_NUMBER_UINT64:
259  *number = static_cast<int64_t>(token.number.u64);
260  if (token.number.u64 > INT64_MAX) return ERANGE;
261  break;
262  case EVENT_NUMBER_FLOAT:
263  *number = static_cast<int64_t>(token.number.f32);
264  if (token.number.f32 > static_cast<float>(INT64_MAX) ||
265  token.number.f32 < static_cast<float>(INT64_MIN))
266  return ERANGE;
267  return EDOM;
268  case EVENT_NUMBER_DOUBLE:
269  *number = static_cast<int64_t>(token.number.f64);
270  if (token.number.f64 > static_cast<double>(INT64_MAX) ||
271  token.number.f64 < static_cast<double>(INT64_MIN))
272  return ERANGE;
273  return EDOM;
274  default:
275  return EINVAL;
276  }
277  return 0;
278 }
279 
280 inline errno_t JsonStreamParser::ToUint64(const Token& token, uint64_t* number) NLIB_NOEXCEPT {
281  NLIB_EINVAL_IFNULL(number);
282  switch (token.event) {
283  case EVENT_NUMBER_INT32:
284  *number = static_cast<uint64_t>(token.number.i32);
285  if (token.number.i32 < 0) return ERANGE;
286  break;
287  case EVENT_NUMBER_UINT32:
288  *number = token.number.u32;
289  break;
290  case EVENT_NUMBER_INT64:
291  *number = static_cast<uint64_t>(token.number.i64);
292  if (token.number.i64 < 0) return ERANGE;
293  break;
294  case EVENT_NUMBER_UINT64:
295  *number = token.number.u64;
296  break;
297  case EVENT_NUMBER_FLOAT:
298  *number = static_cast<uint64_t>(token.number.f32);
299  if (token.number.f32 > static_cast<float>(UINT64_MAX) ||
300  token.number.f32 < 0.f)
301  return ERANGE;
302  return EDOM;
303  case EVENT_NUMBER_DOUBLE:
304  *number = static_cast<uint64_t>(token.number.f64);
305  if (token.number.f64 > static_cast<double>(UINT64_MAX) ||
306  token.number.f64 < 0.0)
307  return ERANGE;
308  return EDOM;
309  default:
310  return EINVAL;
311  }
312  return 0;
313 }
314 
315 inline errno_t JsonStreamParser::ToFloat(const Token& token, float* number) NLIB_NOEXCEPT {
316  NLIB_EINVAL_IFNULL(number);
317  switch (token.event) {
318  case EVENT_NUMBER_INT32:
319  *number = static_cast<float>(token.number.i32);
320  if (token.number.i32 > 16777215 || token.number.i32 < -16777215)
321  return EDOM;
322  break;
323  case EVENT_NUMBER_UINT32:
324  *number = static_cast<float>(token.number.u32);
325  if (token.number.u32 > 16777215)
326  return EDOM;
327  break;
328  case EVENT_NUMBER_INT64:
329  *number = static_cast<float>(token.number.i64);
330  if (token.number.i64 > 16777215 || token.number.i64 < -16777215)
331  return EDOM;
332  break;
333  case EVENT_NUMBER_UINT64:
334  *number = static_cast<float>(token.number.u64);
335  if (token.number.u64 > 16777215)
336  return EDOM;
337  break;
338  case EVENT_NUMBER_FLOAT:
339  *number = token.number.f32;
340  break;
341  case EVENT_NUMBER_DOUBLE:
342  *number = static_cast<float>(token.number.f32);
343  if (token.number.f64 < FLT_MIN ||
344  token.number.f64 > FLT_MAX)
345  return ERANGE;
346  else
347  return EDOM;
348  default:
349  return EINVAL;
350  }
351  return 0;
352 }
353 
354 inline errno_t JsonStreamParser::ToDouble(const Token& token, double* number) NLIB_NOEXCEPT {
355  NLIB_EINVAL_IFNULL(number);
356  switch (token.event) {
357  case EVENT_NUMBER_INT32:
358  *number = static_cast<double>(token.number.i32);
359  break;
360  case EVENT_NUMBER_UINT32:
361  *number = static_cast<double>(token.number.u32);
362  break;
363  case EVENT_NUMBER_INT64:
364  *number = static_cast<double>(token.number.i64);
365  if (token.number.i64 > 9007199254740991LL ||
366  token.number.i64 < -9007199254740991LL)
367  return EDOM;
368  break;
369  case EVENT_NUMBER_UINT64:
370  *number = static_cast<double>(token.number.u64);
371  if (token.number.u64 > 9007199254740991ULL)
372  return EDOM;
373  break;
374  case EVENT_NUMBER_FLOAT:
375  *number = token.number.f32;
376  break;
377  case EVENT_NUMBER_DOUBLE:
378  *number = token.number.f64;
379  break;
380  default:
381  return EINVAL;
382  }
383  return 0;
384 }
385 
386 } // namespace msgpack
387 NLIB_NAMESPACE_END
388 
389 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
390 #undef NLIB_VIS_PUBLIC
391 #define NLIB_VIS_PUBLIC NLIB_WINIMPORT
392 #endif
393 
394 #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:173
#define NLIB_NONNULL_1
Indicates that you cannot specify NULL for the first argument.
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:109
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:86
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:87
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.
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: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
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:99
#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 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:224
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.
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:37