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
トークンを格納するバッファのサイズを指定します。デフォルトは2048で512が最小の値です。 ...
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
Definition: Config.h:160
#define NLIB_NONNULL_1
1番目の引数にNULLを指定することができないことを示します。
Definition: Platform_unix.h:77
int32_t型の整数を読み込みました。
bool strict
0以外を設定した場合、より厳密にエラーチェックを行います。デフォルトは0です。
constexpr JsonStreamParserSettings() noexcept
デフォルトコンストラクタです。各データメンバにデフォルト値を設定します。
int64_t型の整数を読み込みました。
char * buf
文字列やバイナリデータが格納されます。
バイナリデータを読み込みました(msgpackのみ)。
UniquePtrはポインタの所有権を保持し、UniquePtrがスコープから出るときにデストラクタでポインタをDELで指...
Definition: UniquePtr.h:96
std::unique_ptrに相当するクラスが定義されています。
#define NLIB_VIS_HIDDEN
関数やクラス等のシンボルをライブラリの外部に公開しません。
Definition: Platform_unix.h:60
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:61
拡張データを読み込みました(msgpackのみ)。
Event event
Next()によって返されたイベント
#define NLIB_NONNULL_2
2番目の引数にNULLを指定することができないことを示します。
Definition: Platform_unix.h:78
連想配列のキー以外の文字列を読み込みました。
uint64_t型の整数を読み込みました。
double型の浮動小数点数を読み込みました。
JsonStreamParserの設定パラメータ群を格納する構造体です。
JSON又はmsgpackをプル形式でパースするためのクラスです。
ストリームからテキストを読み込むクラスです。
Definition: TextReader.h:20
Event
JsonStreamParser::Next()及びTokenで利用される型で、パーサーが読み込んだデータに対応するイベントです。...
MessagePack, JSON及びCSVを読み込むと作成されるオブジェクトです。
size_t max_map_size
連想配列の最大サイズを指定します。デフォルトは256で16が最小の値です。
size_t max_array_size
配列の最大サイズを指定します。デフォルトは8192で16が最小の値です。
入力ストリームの基底クラスです。このクラスを実体化することはできません。
Definition: InputStream.h:16
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Config.h:86
連想配列が開始しました。
uint32_t型の整数を読み込みました。
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
Definition: Config.h:80
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:211
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を指定することができないことを示します。
Definition: Platform_unix.h:76
連想配列のキーを読み込みました。
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:24