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
トークンを格納するバッファのサイズを指定します。デフォルトは2048で512が最小の値です。 ...
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
Definition: Config.h:173
#define NLIB_NONNULL_1
1番目の引数にNULLを指定することができないことを示します。
int32_t型の整数を読み込みました。
bool strict
0以外を設定した場合、より厳密にエラーチェックを行います。デフォルトは0です。
constexpr JsonStreamParserSettings() noexcept
デフォルトコンストラクタです。各データメンバにデフォルト値を設定します。
int64_t型の整数を読み込みました。
char * buf
文字列やバイナリデータが格納されます。
バイナリデータを読み込みました(msgpackのみ)。
UniquePtrはポインタの所有権を保持し、UniquePtrがスコープから出るときにデストラクタでポインタをDELで指...
Definition: UniquePtr.h:109
std::unique_ptrに相当するクラスが定義されています。
#define NLIB_VIS_HIDDEN
関数やクラス等のシンボルをライブラリの外部に公開しません。
Definition: Platform_unix.h:86
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:87
拡張データを読み込みました(msgpackのみ)。
Event event
Next()によって返されたイベント
#define NLIB_NONNULL_2
2番目の引数にNULLを指定することができないことを示します。
連想配列のキー以外の文字列を読み込みました。
uint64_t型の整数を読み込みました。
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
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Config.h:99
連想配列が開始しました。
uint32_t型の整数を読み込みました。
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
Definition: Config.h:93
bool token_toobig
イベントがEVENT_STRINGかつトークンが大きすぎた場合に、0以外の値が格納されます。この場合bufにはヌル文...
float型の浮動小数点数を読み込みました。
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 char *str, const JsonStreamParserSettings &settings) noexcept
JSONをパースして、MpObjectを作成します。
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
Definition: Config.h:224
int8_t ext
イベントがEVENT_EXTだった場合に、データ型に関する8ビットの値が格納されます。
errno_t Init() noexcept
デフォルト設定でパーサーの初期化を行います。
連想配列が終了しました。
static errno_t Parse(UniquePtr< MpObject > &obj, const char *str) noexcept
JsonStreamParserSettingsのデフォルト設定でParse(obj, str, settingsを実行します。
size_t max_depth
配列や連想配列の深さの最大値を指定します。デフォルトは7です。
Format format
パースする際のフォーマット判定をどのように行うかを決定します。デフォルトはFORMAT_ADAPTIVEです。 ...
#define NLIB_NONNULL
全ての引数にNULLを指定することができないことを示します。
連想配列のキーを読み込みました。
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:37