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
トークンを格納するバッファのサイズを指定します。デフォルトは2048で512が最小の値です。 ...
拡張データを読み込みました(msgpackのみ)。
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
Definition: Config.h:163
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
Definition: Config.h:178
#define NLIB_NONNULL_1
1番目の引数にNULLを指定することができないことを示します。
uint64_t型の整数を読み込みました。
bool strict
0以外を設定した場合、より厳密にエラーチェックを行います。デフォルトは0です。
constexpr JsonStreamParserSettings() noexcept
デフォルトコンストラクタです。各データメンバにデフォルト値を設定します。
連想配列が開始しました。
nlib_utf8_t * buf
文字列やバイナリデータが格納されます。
UniquePtrはポインタの所有権を保持し、UniquePtrがスコープから出るときにデストラクタでポインタをDELで指...
Definition: UniquePtr.h:109
std::unique_ptrに相当するクラスが定義されています。
int32_t型の整数を読み込みました。
#define NLIB_VIS_HIDDEN
関数やクラス等のシンボルをライブラリの外部に公開しません。
Definition: Platform_unix.h:88
static errno_t Parse(UniquePtr< MpObject > &obj, const void *data, size_t n) noexcept
JsonStreamParserSettingsのデフォルト設定でParse(obj, data, n, settings)を実行します。 ...
#define NLIB_VIS_PUBLIC
関数やクラス等のシンボルをライブラリの外部に公開します。
Definition: Platform_unix.h:89
Event event
Next()によって返されたイベント
#define NLIB_NONNULL_2
2番目の引数にNULLを指定することができないことを示します。
double型の浮動小数点数を読み込みました。
JsonStreamParserの設定パラメータ群を格納する構造体です。
JSON又はmsgpackをプル形式でパースするためのクラスです。
ストリームからテキストを読み込むクラスです。
Definition: TextReader.h:33
Event
JsonStreamParser::Next()及びTokenで利用される型で、パーサーが読み込んだデータに対応するイベントです。...
MessagePack, JSON及びCSVを読み込むと作成されるオブジェクトです。
size_t max_map_size
連想配列の最大サイズを指定します。デフォルトは256で16が最小の値です。
size_t max_array_size
配列の最大サイズを指定します。デフォルトは8192で16が最小の値です。
入力ストリームの基底クラスです。このクラスを実体化することはできません。
Definition: InputStream.h:29
連想配列のキーを読み込みました。
uint32_t型の整数を読み込みました。
static errno_t Parse(UniquePtr< MpObject > &obj, const nlib_utf8_t *str, const JsonStreamParserSettings &settings) noexcept
JSONをパースして、MpObjectを作成します。
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Config.h:99
JSON又はmsgpackが終了しました(HasNext()がfalseを返した場合のNext()の戻り値)。
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
Definition: Config.h:93
bool token_toobig
イベントがkEventStringかつトークンが大きすぎた場合に、0以外の値が格納されます。この場合bufにはヌル文...
static errno_t Parse(JsonStreamParser *parser, UniquePtr< MpObject > &obj) noexcept
Parse(parser, obj, false)を実行します。
const Token & GetToken() const noexcept
トークンを取得します。
size_t nlib_strlen(const char *s)
内部でstrlen()を呼び出します。独自の実装が動作する場合もあります。
パーサーが取得したトークンに関するデータが格納されています。
連想配列のキー以外の文字列を読み込みました。
static errno_t Parse(UniquePtr< MpObject > &obj, const nlib_utf8_t *str) noexcept
JsonStreamParserSettingsのデフォルト設定でParse(obj, str, settingsを実行します。
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
Definition: Config.h:229
int8_t ext
イベントがkEventExtだった場合に、データ型に関する8ビットの値が格納されます。
int64_t型の整数を読み込みました。
errno_t Init() noexcept
デフォルト設定でパーサーの初期化を行います。
バイナリデータを読み込みました(msgpackのみ)。
size_t max_depth
配列や連想配列の深さの最大値を指定します。デフォルトは7です。
連想配列が終了しました。
Format format
パースする際のフォーマット判定をどのように行うかを決定します。デフォルトはkFormatAdaptiveです。 ...
#define NLIB_NONNULL
全ての引数にNULLを指定することができないことを示します。
float型の浮動小数点数を読み込みました。
char nlib_utf8_t
charのtypedefです。文字列がUTF-8であることを示します。
Definition: Platform.h:300
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:37