nlib
MpObject.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_MPOBJECT_H_
17 #define INCLUDE_NN_NLIB_MSGPACK_MPOBJECT_H_
18 
19 #include <map>
20 #include <utility>
21 #include <vector>
22 
23 #include "nn/nlib/Config.h"
24 #include "nn/nlib/Swap.h"
25 #include "nn/nlib/Cstring.h"
26 #include "nn/nlib/Nlist.h"
27 
28 #ifdef NLIB_CXX11_STDLIB_ARRAY
29 #include <array> // NOLINT
30 #endif
31 
32 #ifdef NLIB_CXX11_STDLIB_UNORDERED
33 #include <unordered_map> // NOLINT
34 #endif
35 
36 #ifdef NLIB_CXX11_STDLIB_TUPLE
37 #include <tuple> // NOLINT
38 #endif
39 
40 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
41 #undef NLIB_VIS_PUBLIC
42 #define NLIB_VIS_PUBLIC NLIB_WINEXPORT
43 #endif
44 
45 NLIB_NAMESPACE_BEGIN
46 namespace msgpack {
47 
48 class MpObject;
49 
50 template <class T>
51 errno_t Box(MpObject* obj, const T& v);
52 
53 template <class T>
54 errno_t Unbox(const MpObject* obj, T* v);
55 
56 struct nil {};
57 
58 template <class T>
59 inline bool operator==(const nil& lhs, const T& rhs) NLIB_NOEXCEPT {
60  NLIB_UNUSED(lhs);
61  NLIB_UNUSED(rhs);
62  return false;
63 }
64 template <class T>
65 inline bool operator==(const T& lhs, const nil& rhs) NLIB_NOEXCEPT {
66  NLIB_UNUSED(lhs);
67  NLIB_UNUSED(rhs);
68  return false;
69 }
70 inline bool operator==(const nil& lhs, const nil& rhs) NLIB_NOEXCEPT {
71  NLIB_UNUSED(lhs);
72  NLIB_UNUSED(rhs);
73  return true;
74 }
75 template <class T>
76 inline bool operator!=(const nil& rhs, const T& lhs) NLIB_NOEXCEPT {
77  NLIB_UNUSED(lhs);
78  NLIB_UNUSED(rhs);
79  return true;
80 }
81 template <class T>
82 inline bool operator!=(const T& rhs, const nil& lhs) NLIB_NOEXCEPT {
83  NLIB_UNUSED(lhs);
84  NLIB_UNUSED(rhs);
85  return true;
86 }
87 inline bool operator!=(const nil& rhs, const nil& lhs) NLIB_NOEXCEPT {
88  NLIB_UNUSED(lhs);
89  NLIB_UNUSED(rhs);
90  return false;
91 }
92 
93 struct MpObjectKv;
94 
96  private:
97  union UnionType {
98  uint64_t u64;
99  int64_t i64;
100  float f32;
101  double f64;
102  Nlist<MpObject>* ary;
103  Nlist<MpObjectKv>* mp;
104  char* str;
105  void* binary;
106  };
107 
108  public:
110  MpObject* obj;
111  return NLIB_LIKELY(0 == this->GetArrayItem(n, &obj)) ? obj : NULL;
112  }
113  const MpObject* GetArrayItem(size_t n) const NLIB_NOEXCEPT {
114  const MpObject* obj;
115  return NLIB_LIKELY(0 == this->GetArrayItem(n, &obj)) ? obj : NULL;
116  }
117  MpObject& operator[](size_t n) {
118  NLIB_ASSERT(this->IsArray());
119  NLIB_ASSERT(n < size_);
120  return (*via_.ary)[n];
121  }
122  MpObject* GetMapItem(const char* str) NLIB_NOEXCEPT;
123  const MpObject* GetMapItem(const char* str) const NLIB_NOEXCEPT;
124  template<size_t N>
125  MpObject* GetMapItem(const char (&str)[N]) NLIB_NOEXCEPT {
126  return GetMapItem(&str[0]);
127  }
128  template<size_t N>
129  const MpObject* GetMapItem(const char (&str)[N]) const NLIB_NOEXCEPT {
130  return GetMapItem(&str[0]);
131  }
132  template<class STDSTRING>
133  const MpObject* GetMapItem(const STDSTRING& str) const NLIB_NOEXCEPT {
134  return GetMapItem(str.c_str());
135  }
136  template<class STDSTRING>
137  MpObject* GetMapItem(const STDSTRING& str) NLIB_NOEXCEPT {
138  return GetMapItem(str.c_str());
139  }
140  errno_t Resize(uint32_t n);
141  MpObject* SwapArrayItem(size_t n, MpObject* obj) NLIB_NOEXCEPT {
142  MpObject* p = this->GetArrayItem(n);
143  if (NLIB_LIKELY(p)) p->swap(*obj);
144  return p;
145  }
146  template<class STDSTRING>
147  MpObject* SwapMapItem(const STDSTRING& key, MpObject* obj) NLIB_NOEXCEPT {
148  MpObject* p = this->GetMapItem(key);
149  if (NLIB_LIKELY(p)) p->swap(*obj);
150  return p;
151  }
152  template<size_t N>
153  MpObject* SwapMapItem(const char (&str)[N], MpObject* obj) NLIB_NOEXCEPT {
154  return SwapMapItem(&str[0], obj);
155  }
156  MpObject* SwapMapItem(const char* str, MpObject* obj) NLIB_NOEXCEPT {
157  MpObject* p = this->GetMapItem(str);
158  if (NLIB_LIKELY(p)) p->swap(*obj);
159  return p;
160  }
161  MpObject* AppendArrayItem() NLIB_NOEXCEPT;
162  MpObjectKv* AppendMapItem() NLIB_NOEXCEPT;
163  NLIB_OVERRIDE_NEW;
164 
165  public:
166  MpObject() NLIB_NOEXCEPT : type_(NIL) {} // only do minimum memory access
167  ~MpObject() NLIB_NOEXCEPT { ReleaseIfNeeded(); }
168  NLIB_MOVE_MEMBER_HELPER_1(MpObject, type_);
169 
170  // NOTE: implicit call was error in gcc or clang....
171  template <class T>
172  explicit MpObject(const T& x) {
173  MyBox<T, typename IsIntegral<T>::type, typename IsSigned<T>::type>::Construct(this, x);
174  }
175  errno_t GetArrayItem(size_t n, MpObject** obj) NLIB_NOEXCEPT NLIB_NONNULL;
176  errno_t GetArrayItem(size_t n, const MpObject** obj) const NLIB_NOEXCEPT NLIB_NONNULL;
177  errno_t GetMapItem(size_t n, MpObjectKv** obj) NLIB_NOEXCEPT NLIB_NONNULL;
178  errno_t GetMapItem(size_t n, const MpObjectKv** obj) const NLIB_NOEXCEPT NLIB_NONNULL;
179  char* GetString() NLIB_NOEXCEPT {
180  if (type_ == STRING) return via_.str;
181  if (NLIB_LIKELY(type_ == STRING_INLINE)) return reinterpret_cast<char*>(&raw14data_);
182  return NULL;
183  }
184  const char* GetString() const NLIB_NOEXCEPT {
185  return const_cast<MpObject*>(this)->GetString();
186  }
187  void* GetBinary(uint32_t* n) NLIB_NOEXCEPT {
188  if (type_ == BINARY) {
189  *n = size_;
190  return via_.binary;
191  }
192  if (NLIB_LIKELY(type_ == BINARY_INLINE)) {
193  *n = raw14size_;
194  return &raw14data_;
195  }
196  return NULL;
197  }
198  const void* GetBinary(uint32_t* n) const NLIB_NOEXCEPT {
199  return const_cast<MpObject*>(this)->GetBinary(n);
200  }
201  void* GetExt(int8_t* tp, uint32_t* n) NLIB_NOEXCEPT {
202  if (type_ == EXT) {
203  *n = size_;
204  *tp = static_cast<int8_t>(raw14data_);
205  return via_.binary;
206  } else {
207  return NULL;
208  }
209  }
210  const void* GetExt(int8_t* tp, uint32_t* n) const NLIB_NOEXCEPT {
211  return const_cast<MpObject*>(this)->GetExt(tp, n);
212  }
213 
214  errno_t InitArray(uint32_t n) NLIB_NOEXCEPT;
215  errno_t InitMap(uint32_t n) NLIB_NOEXCEPT;
216  errno_t InitString(uint32_t n) NLIB_NOEXCEPT;
217  errno_t InitString(const char* str, uint32_t n) NLIB_NOEXCEPT;
218  errno_t InitString(const char* str) NLIB_NOEXCEPT {
219  uint32_t n = static_cast<uint32_t>(nlib_strlen(str));
220  return InitString(str, n);
221  }
222  errno_t InitBinary(uint32_t n) NLIB_NOEXCEPT;
223  errno_t InitBinary(const void* p, uint32_t n) NLIB_NOEXCEPT;
224  errno_t InitExt(int8_t tp, uint32_t n) NLIB_NOEXCEPT;
225  errno_t InitExt(int8_t tp, const void* p, uint32_t n) NLIB_NOEXCEPT;
226 
227  public: // Box
228  errno_t Box(const char* str) NLIB_NOEXCEPT NLIB_NONNULL;
229  template <uint32_t n>
230  errno_t Box(const char (&str)[n]) NLIB_NOEXCEPT;
231  template <class T, uint32_t n>
232  errno_t Box(const T (&vec)[n]);
233 #ifdef NLIB_CXX11_STDLIB_ARRAY
234  template <class T, size_t n>
235  errno_t Box(const std::array<T, n>& vec);
236 #endif
237  template <class T>
238  errno_t Box(const T& v) {
239  return MyBox<T, typename IsIntegral<T>::type, typename IsSigned<T>::type>::Box(this, v);
240  }
241  // Use BoxBinary(p, n) or Box(reinterpret_cast<const char*>(p)) instead
242  errno_t BoxBinary(const void* p, uint32_t n) NLIB_NOEXCEPT NLIB_NONNULL;
243  errno_t BoxExt(int8_t tp, const void* p, uint32_t n) NLIB_NOEXCEPT NLIB_NONNULL;
244 
245  public: // Unbox
246  template <class T, size_t n>
247  errno_t Unbox(T (&a)[n]) const {
248  return this->Unbox(&a[0], n);
249  }
250 #ifdef NLIB_CXX11_STDLIB_ARRAY
251  template <class T, size_t n>
252  errno_t Unbox(std::array<T, n>& a) { // NOLINT
253  return this->Unbox(reinterpret_cast<T*>(&*a.begin()), n);
254  }
255 #endif
256  template <size_t n>
257  errno_t Unbox(char (&str)[n]) const NLIB_NOEXCEPT {
258  return this->Unbox(&str[0], n);
259  }
260  template <class T>
261  errno_t Unbox(T* a, size_t n) const NLIB_NONNULL;
262  errno_t Unbox(char* str, size_t n) const NLIB_NOEXCEPT NLIB_NONNULL;
263  errno_t UnboxBinary(void* p, size_t n) const NLIB_NOEXCEPT NLIB_NONNULL;
264  errno_t UnboxExt(int8_t* tp, void* p, size_t n) const NLIB_NOEXCEPT NLIB_NONNULL;
265  template <class T>
266  errno_t Unbox(T v) const {
267  // T cannot be T* though v is only pointer type
268  // because of conflict against array types.
269  return MyBox<typename RemovePtr<T>::type,
270  typename IsIntegral<typename RemovePtr<T>::type>::type,
271  typename IsSigned<typename RemovePtr<T>::type>::type>::Unbox(this, v);
272  }
273 
274  public:
275  // You can use operator=() only for basic types(never fails).
276  // Use Box() otherwise.
277  template <class T>
278  MpObject& operator=(const T& x) {
279  MyBox<T, typename IsIntegral<T>::type, typename IsSigned<T>::type>::Assign(this, x);
280  return *this;
281  }
282 
283  MpObject* Clone() NLIB_NOEXCEPT;
284  void swap(MpObject& rhs) NLIB_NOEXCEPT { // NOLINT
285  using std::swap;
286  swap(type_, rhs.type_);
287  swap(raw14size_, rhs.raw14size_);
288  swap(raw14data_, rhs.raw14data_);
289  swap(_, rhs._);
290  swap(size_, rhs.size_);
291  swap(via_.u64, rhs.via_.u64);
292  }
293 
294  public:
295  enum ObjectType {
296  NIL = 0,
302  STRING,
305  BINARY,
306  EXT,
307  RAW = STRING,
308  STRING_INLINE = 0x80 | STRING,
309  BINARY_INLINE = 0x80 | BINARY,
310  RAW_INLINE = 0x80 | RAW,
311  BOOLEAN_FALSE = 0x00 | BOOLEAN,
312  BOOLEAN_TRUE = 0x80 | BOOLEAN
313  };
314  ObjectType GetType() const NLIB_NOEXCEPT {
315  return static_cast<ObjectType>(type_ & 0x7F);
316  }
317  uint32_t GetSize() const NLIB_NOEXCEPT {
318  if (type_ == STRING_INLINE || type_ == BINARY_INLINE)
319  return raw14size_;
320  else
321  return size_;
322  }
323  bool IsNil() const NLIB_NOEXCEPT { return GetType() == NIL; }
324  bool IsBoolean() const NLIB_NOEXCEPT { return GetType() == BOOLEAN; }
325  bool IsInteger() const NLIB_NOEXCEPT {
326  ObjectType tp = GetType();
327  return tp == UINT64 || tp == INT64;
328  }
329  bool IsFloat() const NLIB_NOEXCEPT { return GetType() == FLOAT; }
330  bool IsDouble() const NLIB_NOEXCEPT { return GetType() == DOUBLE; }
331  bool IsString() const NLIB_NOEXCEPT { return GetType() == STRING; }
332  bool IsBinary() const NLIB_NOEXCEPT { return GetType() == BINARY; }
333  bool IsExt() const NLIB_NOEXCEPT { return GetType() == EXT; }
334  bool IsArray() const NLIB_NOEXCEPT { return GetType() == ARRAY; }
335  bool IsMap() const NLIB_NOEXCEPT { return GetType() == MAP; }
336 
337  private:
338  errno_t Clone(MpObject* p) NLIB_NOEXCEPT;
339  template <class T, class IS_INTEGRAL, class IS_SIGNED>
340  struct MyBox {
341  static errno_t Box(MpObject* This, const T& v) { return ::nlib_ns::msgpack::Box(This, v); }
342  static errno_t Unbox(const MpObject* This, T* v) {
343  if (!v) return EINVAL;
345  }
346  static void Assign(MpObject* This, const T& x);
347  static void Construct(MpObject* This, const T& x);
348  };
349  void ReleaseIfNeeded() NLIB_NOEXCEPT {
350  if (type_ >= STRING && type_ <= EXT) ReleaseIfNeeded_();
351  }
352  void ReleaseIfNeeded_() NLIB_NOEXCEPT;
353 
354  private:
355  uint8_t type_;
356  uint8_t raw14size_;
357  uint8_t raw14data_;
358  uint8_t _;
359  uint32_t size_;
360  UnionType via_;
362  friend NLIB_VIS_PUBLIC bool operator==(const MpObject& lhs, const MpObject& rhs);
363 };
364 
365 struct MpObjectKv {
368 
369  public:
370  MpObjectKv() NLIB_NOEXCEPT {}
371  ~MpObjectKv() NLIB_NOEXCEPT {}
372  NLIB_MOVE_MEMBER_HELPER_2(MpObjectKv, first, second);
373  void swap(MpObjectKv& rhs) NLIB_NOEXCEPT { // NOLINT
374  first.swap(rhs.first);
375  second.swap(rhs.second);
376  }
377 
378  private:
380 };
381 
382 template <>
383 struct MpObject::MyBox<nil, FalseType, FalseType> {
384  static errno_t Box(MpObject* This, nil v) NLIB_NOEXCEPT {
385  NLIB_UNUSED(v);
386  This->ReleaseIfNeeded();
387  This->type_ = NIL;
388  return 0;
389  }
390  static void Assign(MpObject* This, nil x) NLIB_NOEXCEPT { This->Box(x); }
391  static void Construct(MpObject* This, nil) NLIB_NOEXCEPT { This->type_ = NIL; }
392 };
393 
394 template <>
395 struct MpObject::MyBox<bool, TrueType, FalseType> {
396  static errno_t Box(MpObject* This, bool v) NLIB_NOEXCEPT {
397  This->ReleaseIfNeeded();
398  This->type_ = v ? static_cast<uint8_t>(BOOLEAN_TRUE) : static_cast<uint8_t>(BOOLEAN_FALSE);
399  return 0;
400  }
401  static errno_t Unbox(const MpObject* This, bool* v) NLIB_NOEXCEPT {
402  if (This->type_ == BOOLEAN_FALSE) {
403  *v = false;
404  return 0;
405  } else if (NLIB_LIKELY(This->type_ == BOOLEAN_TRUE)) {
406  *v = true;
407  return 0;
408  }
409  *v = false; // to suppress warnings
410  return EACCES;
411  }
412  static void Assign(MpObject* This, bool x) NLIB_NOEXCEPT { This->Box(x); }
413  static void Construct(MpObject* This, bool x) NLIB_NOEXCEPT {
414  This->type_ = x ? static_cast<uint8_t>(BOOLEAN_TRUE) : static_cast<uint8_t>(BOOLEAN_FALSE);
415  }
416 };
417 
418 template <class T>
419 struct MpObject::MyBox<T, TrueType, TrueType> {
420  static errno_t Box(MpObject* This, T v) NLIB_NOEXCEPT {
421  This->ReleaseIfNeeded();
422  This->type_ = INT64;
423  This->via_.i64 = v;
424  return 0;
425  }
426  static errno_t Unbox(const MpObject* This, T* v) NLIB_NOEXCEPT {
427  if (NLIB_UNLIKELY(!v)) return EINVAL;
428  if (This->type_ == INT64) {
429  *v = static_cast<T>(This->via_.i64);
430  return 0;
431  } else if (NLIB_LIKELY(This->type_ == UINT64)) {
432  *v = static_cast<T>(This->via_.u64);
433  return 0;
434  }
435  *v = 0; // to suppress warnings
436  return EACCES;
437  }
438  static void Assign(MpObject* This, T x) NLIB_NOEXCEPT { This->Box(x); }
439  static void Construct(MpObject* This, T x) NLIB_NOEXCEPT {
440  This->type_ = INT64;
441  This->via_.i64 = x;
442  }
443 };
444 
445 template <class T>
446 struct MpObject::MyBox<T, TrueType, FalseType> {
447  static errno_t Box(MpObject* This, T v) NLIB_NOEXCEPT {
448  This->ReleaseIfNeeded();
449  This->type_ = UINT64;
450  This->via_.u64 = v;
451  return 0;
452  }
453  static errno_t Unbox(const MpObject* This, T* v) NLIB_NOEXCEPT {
454  if (NLIB_UNLIKELY(!v)) return EINVAL;
455  if (This->type_ == INT64) {
456  *v = static_cast<T>(This->via_.i64);
457  return 0;
458  } else if (NLIB_LIKELY(This->type_ == UINT64)) {
459  *v = static_cast<T>(This->via_.u64);
460  return 0;
461  }
462  *v = 0; // to suppress warnings
463  return EACCES;
464  }
465  static void Assign(MpObject* This, T x) NLIB_NOEXCEPT { This->Box(x); }
466  static void Construct(MpObject* This, T x) NLIB_NOEXCEPT {
467  This->type_ = UINT64;
468  This->via_.u64 = x;
469  }
470 };
471 
472 template <class TR1_WORKAROUND>
473 struct MpObject::MyBox<float, FalseType, TR1_WORKAROUND> {
474  static errno_t Box(MpObject* This, float v) NLIB_NOEXCEPT {
475  This->ReleaseIfNeeded();
476  This->type_ = FLOAT;
477  This->via_.f32 = v;
478  return 0;
479  }
480  static errno_t Unbox(const MpObject* This, float* v) NLIB_NOEXCEPT {
481  if (NLIB_UNLIKELY(!v)) return EINVAL;
482  switch (This->type_) {
483  case FLOAT:
484  *v = This->via_.f32;
485  break;
486  case DOUBLE:
487  *v = static_cast<float>(This->via_.f64);
488  break;
489  default:
490  *v = 0; // to suppress warnings
491  return EACCES;
492  }
493  return 0;
494  }
495  static void Assign(MpObject* This, float x) NLIB_NOEXCEPT { This->Box(x); }
496  static void Construct(MpObject* This, float x) NLIB_NOEXCEPT {
497  This->type_ = FLOAT;
498  This->via_.f32 = x;
499  }
500 };
501 
502 template <class TR1_WORKAROUND>
503 struct MpObject::MyBox<double, FalseType, TR1_WORKAROUND> {
504  static errno_t Box(MpObject* This, double v) NLIB_NOEXCEPT {
505  This->ReleaseIfNeeded();
506  This->type_ = DOUBLE;
507  This->via_.f64 = v;
508  return 0;
509  }
510  static errno_t Unbox(const MpObject* This, double* v) NLIB_NOEXCEPT {
511  if (NLIB_UNLIKELY(!v)) return EINVAL;
512  switch (This->type_) {
513  case FLOAT:
514  *v = This->via_.f32;
515  break;
516  case DOUBLE:
517  *v = This->via_.f64;
518  break;
519  default:
520  *v = 0; // to suppress warnings
521  return EACCES;
522  }
523  return 0;
524  }
525  static void Assign(MpObject* This, double x) NLIB_NOEXCEPT { This->Box(x); }
526  static void Construct(MpObject* This, double x) NLIB_NOEXCEPT {
527  This->type_ = DOUBLE;
528  This->via_.f64 = x;
529  }
530 };
531 
532 template <class STDSTRING>
533 struct MpObject::MyBox<STDSTRING, FalseType, FalseType> {
534  static errno_t Box(MpObject* This, const STDSTRING& str) NLIB_NOEXCEPT {
535  uint32_t n = static_cast<uint32_t>(str.size());
536  ErrnoT e = This->InitString(n);
537  if (NLIB_UNLIKELY(e != 0)) return e;
538  nlib_memcpy(reinterpret_cast<void*>(This->GetString()),
539  n,
540  reinterpret_cast<const void*>(&str[0]),
541  n);
542  return 0;
543  }
544  static errno_t Unbox(const MpObject* This, STDSTRING* str) NLIB_NOEXCEPT {
545  if (NLIB_UNLIKELY(!str)) return EINVAL;
546  if (NLIB_UNLIKELY(This->type_ != STRING) && NLIB_UNLIKELY(This->type_ != STRING_INLINE))
547  return EACCES;
548  const char* chr = This->GetString();
549  NLIB_TRY { (*str).assign(chr, This->GetSize()); }
550  NLIB_CATCH(std::bad_alloc&) { return ENOMEM; }
551  return 0;
552  }
553 };
554 
555 template <class T, class ALLOC>
556 struct MpObject::MyBox<std::vector<T, ALLOC>, FalseType, FalseType> {
557  static errno_t Box(MpObject* This, const std::vector<T, ALLOC>& vec) {
558  uint32_t n = static_cast<uint32_t>(vec.size());
559  MpObject tmp;
560  ErrnoT e = tmp.InitArray(n);
561  if (NLIB_UNLIKELY(e != 0)) return e;
562 
563  for (uint32_t i = 0; i < n; ++i) {
564  e = (*tmp.via_.ary)[i].Box(vec[i]);
565  if (NLIB_UNLIKELY(e != 0)) return e;
566  }
567  tmp.swap(*This);
568  return 0;
569  }
570  static errno_t Unbox(const MpObject* This, std::vector<T, ALLOC>* vec) {
571  if (NLIB_UNLIKELY(!vec)) return EINVAL;
572  if (NLIB_UNLIKELY(This->type_ != ARRAY)) return EACCES;
573  NLIB_TRY { vec->resize(This->size_); }
574  NLIB_CATCH(std::bad_alloc&) { return ENOMEM; }
575  for (uint32_t i = 0; i < This->size_; ++i) {
576  ErrnoT e = (*This->via_.ary)[i].Unbox(&(*vec)[i]);
577  if (NLIB_UNLIKELY(e != 0)) return e; // *vec NOT RESET
578  }
579  return 0;
580  }
581 };
582 
583 template <class T, class ALLOC>
584 struct MpObject::MyBox<Nlist<T, ALLOC>, FalseType, FalseType> {
585  static errno_t Box(MpObject* This, const Nlist<T, ALLOC>& vec) {
586  size_t n = vec.size();
587  MpObject tmp;
588  ErrnoT e = tmp.InitArray(static_cast<uint32_t>(n));
589  if (NLIB_UNLIKELY(e != 0)) return e;
590  typename Nlist<T, ALLOC>::const_iterator it = vec.begin();
591  for (size_t i = 0; i < n; ++it, ++i) {
592  e = (*tmp.via_.ary)[i].Box(*it);
593  if (NLIB_UNLIKELY(e != 0)) return e;
594  }
595  tmp.swap(*This);
596  return 0;
597  }
598  static errno_t Unbox(const MpObject* This, Nlist<T, ALLOC>* vec) {
599  if (NLIB_UNLIKELY(!vec)) return EINVAL;
600  if (NLIB_UNLIKELY(This->type_ != ARRAY)) return EACCES;
601  vec->clear();
602  if (NLIB_UNLIKELY(!vec->reserve(This->size_))) return ENOMEM;
603  for (uint32_t i = 0; i < This->size_; ++i) {
604  T* item = vec->push_back();
605  ErrnoT e = (*This->via_.ary)[i].Unbox(item);
606  if (NLIB_UNLIKELY(e != 0)) return e; // *vec NOT RESET
607  }
608  return 0;
609  }
610 };
611 
612 template <class T1, class T2>
613 struct MpObject::MyBox<std::pair<T1, T2>, FalseType, FalseType> {
614  static errno_t Box(MpObject* This, const std::pair<T1, T2>& p) {
615  MpObject tmp;
616  ErrnoT e = tmp.InitArray(2);
617  if (NLIB_UNLIKELY(e != 0)) return e;
618  e = (*tmp.via_.ary)[0].Box(p.first);
619  if (NLIB_UNLIKELY(e != 0)) return e;
620  e = (*tmp.via_.ary)[1].Box(p.second);
621  if (NLIB_UNLIKELY(e != 0)) return e;
622  tmp.swap(*This);
623  return 0;
624  }
625  static errno_t Unbox(const MpObject* This, std::pair<T1, T2>* p) {
626  if (NLIB_UNLIKELY(!p)) return EINVAL;
627  if (NLIB_UNLIKELY(This->type_ != ARRAY)) return EACCES;
628  if (NLIB_UNLIKELY(This->size_ != 2)) return EACCES;
629  ErrnoT e;
630  e = (*This->via_.ary)[0].Unbox(&p->first);
631  if (NLIB_UNLIKELY(e != 0)) return e; // *p NOT RESET
632  e = (*This->via_.ary)[1].Unbox(&p->second);
633  if (NLIB_UNLIKELY(e != 0)) return e; // *p NOT RESET
634  return 0;
635  }
636 };
637 
638 #if defined(NLIB_CXX11_STDLIB_TUPLE) && defined(NLIB_CXX11_VARIADIC_TEMPLATES)
639 template <class ...Args>
640 struct MpObject::MyBox<std::tuple<Args...>, FalseType, FalseType > {
641  private:
642  template<size_t N, class HEAD>
643  static errno_t BoxHelper(MpObject* tmp, const HEAD& head) {
644  return (*tmp->via_.ary)[N].Box(head);
645  }
646  template<size_t N, class HEAD, class ...TAIL>
647  static errno_t BoxHelper(MpObject* tmp, const HEAD& head, TAIL&... tail) {
648  ErrnoT e = (*tmp->via_.ary)[N].Box(head);
649  if (NLIB_UNLIKELY(e != 0)) return e;
650  return BoxHelper<N + 1, TAIL...>(tmp, tail...);
651  }
652  template<size_t N, class HEAD>
653  static errno_t UnboxHelper(const MpObject* This, HEAD& head) { // NOLINT
654  return (*This->via_.ary)[N].Unbox(&head);
655  }
656  template<size_t N, class HEAD, class ...TAIL>
657  static errno_t UnboxHelper(const MpObject* This, HEAD& head, TAIL&... tail) { // NOLINT
658  ErrnoT e = (*This->via_.ary)[N].Unbox(&head);
659  if (NLIB_UNLIKELY(e != 0)) return e;
660  return UnboxHelper<N + 1, TAIL...>(This, tail...);
661  }
662  template<int ...> struct seq {};
663  template<int N, int ...S> struct gens : gens<N - 1, N - 1, S...> {};
664  template<int ...S>
665  struct gens<0, S...> {
666  typedef seq<S...> type;
667  };
668  template<int ...S>
669  static errno_t Box(MpObject* tmp, seq<S...>, const std::tuple<Args...>& p) {
670  return BoxHelper<0>(tmp, std::get<S>(p)...);
671  }
672  template<int ...S>
673  static errno_t Unbox(const MpObject* This, seq<S...>, std::tuple<Args...>& p) { // NOLINT
674  return UnboxHelper<0>(This, std::get<S>(p)...);
675  }
676 
677  public:
678  static errno_t Box(MpObject* This, const std::tuple<Args...>& p) {
679  size_t count = std::tuple_size<std::tuple<Args...> >::value;
680  MpObject tmp;
681  ErrnoT e = tmp.InitArray(static_cast<uint32_t>(count));
682  if (NLIB_UNLIKELY(e != 0)) return e;
683  typedef typename gens<sizeof...(Args)>::type MySeq;
684  e = Box(&tmp, MySeq(), p);
685  if (NLIB_UNLIKELY(e != 0)) return e;
686  tmp.swap(*This);
687  return 0;
688  }
689  static errno_t Unbox(const MpObject* This, std::tuple<Args...>* p) {
690  if (NLIB_UNLIKELY(!p)) return EINVAL;
691  if (NLIB_UNLIKELY(This->type_ != ARRAY)) return EACCES;
692  if (NLIB_UNLIKELY(This->size_ != std::tuple_size<std::tuple<Args...> >::value))
693  return EACCES;
694  typedef typename gens<sizeof...(Args)>::type MySeq;
695  return Unbox(This, MySeq(), *p);
696  }
697 };
698 #endif
699 
700 template <class K, class V, class Pr, class Alloc>
701 struct MpObject::MyBox<std::map<K, V, Pr, Alloc>, FalseType, FalseType> {
702  static errno_t Box(MpObject* This, const std::map<K, V, Pr, Alloc>& m) {
703  typedef typename std::map<K, V, Pr, Alloc> maptype;
704  uint32_t n = static_cast<uint32_t>(m.size());
705  MpObject tmp;
706  ErrnoT e = tmp.InitMap(n);
707  if (NLIB_UNLIKELY(e != 0)) return e;
708 
709  typename maptype::const_iterator it;
710  typename maptype::const_iterator it_end = m.end();
711  uint32_t i;
712  for (i = 0, it = m.begin(); it != it_end; ++it, ++i) {
713  MpObjectKv& kv = (*tmp.via_.mp)[i];
714  e = kv.first.Box(it->first);
715  if (NLIB_UNLIKELY(e != 0)) return e;
716  e = kv.second.Box(it->second);
717  if (NLIB_UNLIKELY(e != 0)) return e;
718  }
719  tmp.swap(*This);
720  return 0;
721  }
722  static errno_t Unbox(const MpObject* This, std::map<K, V, Pr, Alloc>* m) {
723  if (NLIB_UNLIKELY(!m)) return EINVAL;
724  if (NLIB_UNLIKELY(This->type_ != MAP)) return EACCES;
725  m->clear();
726  for (uint32_t i = 0; i < This->size_; ++i) {
727  K key;
728  V value;
729  const MpObjectKv& kv = (*This->via_.mp)[i];
730  ErrnoT e;
731  e = kv.first.Unbox(&key);
732  if (NLIB_UNLIKELY(e != 0)) return e; // *m NOT RESET
733  e = kv.second.Unbox(&value);
734  if (NLIB_UNLIKELY(e != 0)) return e; // *m NOT RESET
735  NLIB_TRY { (*m)[NLIB_MOVE(key)] = NLIB_MOVE(value); }
736  NLIB_CATCH(...) { return ENOMEM; }
737  }
738  return 0;
739  }
740 };
741 
742 #ifdef NLIB_CXX11_STDLIB_UNORDERED
743 template <class K, class V, class Hash, class Pr, class Alloc>
744 struct MpObject::MyBox<std::unordered_map<K, V, Hash, Pr, Alloc>, FalseType, FalseType > {
745  static errno_t Box(MpObject* This, const std::unordered_map<K, V, Hash, Pr, Alloc>& m) {
746  typedef typename std::unordered_map<K, V, Hash, Pr, Alloc> maptype;
747  uint32_t n = static_cast<uint32_t>(m.size());
748  MpObject tmp;
749  ErrnoT e = tmp.InitMap(n);
750  if (NLIB_UNLIKELY(e != 0)) return e;
751 
752  typename maptype::const_iterator it;
753  typename maptype::const_iterator it_end = m.end();
754  uint32_t i;
755  for (i = 0, it = m.begin(); it != it_end; ++it, ++i) {
756  MpObjectKv& kv = (*tmp.via_.mp)[i];
757  e = kv.first.Box(it->first);
758  if (NLIB_UNLIKELY(e != 0)) return e;
759  e = kv.second.Box(it->second);
760  if (NLIB_UNLIKELY(e != 0)) return e;
761  }
762  tmp.swap(*This);
763  return 0;
764  }
765  static errno_t Unbox(const MpObject* This, std::unordered_map<K, V, Hash, Pr, Alloc>* m) {
766  if (NLIB_UNLIKELY(!m)) return EINVAL;
767  if (NLIB_UNLIKELY(This->type_ != MAP)) return EACCES;
768  m->clear();
769  for (uint32_t i = 0; i < This->size_; ++i) {
770  K key;
771  V value;
772  const MpObjectKv& kv = (*This->via_.mp)[i];
773  ErrnoT e;
774  e = kv.first.Unbox(&key);
775  if (NLIB_UNLIKELY(e != 0)) return e; // *m NOT RESET
776  e = kv.second.Unbox(&value);
777  if (NLIB_UNLIKELY(e != 0)) return e; // *m NOT RESET
778  NLIB_TRY { (*m)[NLIB_MOVE(key)] = NLIB_MOVE(value); }
779  NLIB_CATCH(...) { return ENOMEM; }
780  }
781  return 0;
782  }
783 };
784 #endif
785 
786 NLIB_VIS_PUBLIC bool operator==(const MpObject& lhs, const MpObject& rhs);
787 inline bool operator==(const MpObjectKv& lhs, const MpObjectKv& rhs) NLIB_NOEXCEPT {
788  return lhs.first == rhs.first && lhs.second == rhs.second;
789 }
790 inline bool operator!=(const MpObject& lhs, const MpObject& rhs) NLIB_NOEXCEPT {
791  return !(lhs == rhs);
792 }
793 inline bool operator!=(const MpObjectKv& lhs, const MpObjectKv& rhs) NLIB_NOEXCEPT {
794  return !(lhs == rhs);
795 }
796 
797 template <uint32_t n>
798 errno_t MpObject::Box(const char (&str)[n]) NLIB_NOEXCEPT {
799  uint32_t nn = static_cast<uint32_t>(nlib_strlen(str));
800  ErrnoT e = this->InitString(nn);
801  if (NLIB_UNLIKELY(e != 0)) return e;
802  nlib_memcpy(this->GetString(), nn, reinterpret_cast<const void*>(&str[0]), nn);
803  return 0;
804 }
805 
806 template <class T, uint32_t n>
807 errno_t MpObject::Box(const T (&vec)[n]) {
808  MpObject tmp;
809  ErrnoT e = tmp.InitArray(n);
810  if (NLIB_UNLIKELY(e != 0)) return e;
811  for (uint32_t i = 0; i < n; ++i) {
812  e = (*tmp.via_.ary)[i].Box(vec[i]);
813  if (NLIB_UNLIKELY(e != 0)) return e;
814  }
815  this->swap(tmp);
816  return 0;
817 }
818 
819 #ifdef NLIB_CXX11_STDLIB_ARRAY
820 template <class T, size_t n>
821 errno_t MpObject::Box(const std::array<T, n>& vec) {
822  MpObject tmp;
823  ErrnoT e = tmp.InitArray(n);
824  if (NLIB_UNLIKELY(e != 0)) return e;
825  for (uint32_t i = 0; i < n; ++i) {
826  e = (*tmp.via_.ary)[i].Box(vec[i]);
827  if (NLIB_UNLIKELY(e != 0)) return e;
828  }
829  this->swap(tmp);
830  return 0;
831 }
832 #endif
833 
834 template <class T>
835 errno_t MpObject::Unbox(T* a, size_t n) const {
836  NLIB_EINVAL_IFNULL(a);
837  if (NLIB_UNLIKELY(n == 0)) return EINVAL;
838  if (NLIB_UNLIKELY(type_ != ARRAY)) return EACCES;
839  if (NLIB_UNLIKELY(n != size_)) return ERANGE;
840  for (uint32_t i = 0; i < size_; ++i) {
841  ErrnoT e = (*via_.ary)[i].Unbox(&a[i]);
842  if (NLIB_UNLIKELY(e != 0)) return e;
843  }
844  return 0;
845 }
846 
847 } // namespace msgpack
848 NLIB_NAMESPACE_END
849 
850 NLIB_DEFINE_STD_SWAP(::nlib_ns::msgpack::MpObject)
851 NLIB_DEFINE_STD_SWAP(::nlib_ns::msgpack::MpObjectKv)
852 
853 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
854 #undef NLIB_VIS_PUBLIC
855 #define NLIB_VIS_PUBLIC NLIB_WINIMPORT
856 #endif
857 
858 #endif // INCLUDE_NN_NLIB_MSGPACK_MPOBJECT_H_
非負整数型を表します。内部表現はuint64_tです。
Definition: MpObject.h:298
整数型を表します。内部表現はint64_tです。
Definition: MpObject.h:299
char * GetString() noexcept
オブジェクトから文字列を取得します。
Definition: MpObject.h:179
浮動小数型を表します。内部表現はdoubleです。
Definition: MpObject.h:301
errno_t Unbox(T v) const
オブジェクトをアンボックス化します。
Definition: MpObject.h:266
bool IsString() const noexcept
格納されている値が文字列であるかどうかを調べます。
Definition: MpObject.h:331
bool IsMap() const noexcept
格納されている値が連想配列であるかどうかを調べます。
Definition: MpObject.h:335
MpObject & operator[](size_t n)
配列である場合に配列の要素への参照を返します。
Definition: MpObject.h:117
MpObjectKv() noexcept
デフォルトコンストラクタです。
Definition: MpObject.h:370
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
Definition: Config.h:158
errno_t InitString(const char *str) noexcept
オブジェクトを文字列として初期化します。
Definition: MpObject.h:218
Definition: Base64.h:21
MpObject() noexcept
デフォルトコンストラクタです。nil型に設定されます。
Definition: MpObject.h:166
~MpObject() noexcept
デストラクタです。
Definition: MpObject.h:167
const void * GetExt(int8_t *tp, uint32_t *n) const noexcept
オブジェクトから拡張データ型を取得します。
Definition: MpObject.h:210
iterator begin() noexcept
コンテナの先頭を指す反復子を返します。
Definition: Nlist.h:454
const MpObject * GetArrayItem(size_t n) const noexcept
GetArrayItem(size_t n) と同様です。
Definition: MpObject.h:113
MpObject * SwapArrayItem(size_t n, MpObject *obj) noexcept
obj の内容と配列内のオブジェクトの内容を交換します。
Definition: MpObject.h:141
const void * GetBinary(uint32_t *n) const noexcept
オブジェクトからバイナリを取得します。
Definition: MpObject.h:198
#define NLIB_UNLIKELY(x)
条件xが偽になる傾向が高いことをコンパイラに示します。
Definition: Platform_unix.h:98
const char * GetString() const noexcept
オブジェクトから文字列を取得します。
Definition: MpObject.h:184
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価ならば、trueを返します。
Definition: NMalloc.h:123
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価でなければ、trueを返します。
Definition: NMalloc.h:128
errno_t Box(const T &v)
オブジェクトをボックス化します。
Definition: MpObject.h:238
BaseType::const_iterator const_iterator
読み取り専用フォワードイテレータ
Definition: Nlist.h:371
#define NLIB_VIS_PUBLIC
関数やクラス等のシンボルをライブラリの外部に公開します。
Definition: Platform_unix.h:87
MessagePack又はJSONを読み込むことで作成されるオブジェクトです。
Definition: MpObject.h:95
pointer push_back()
末尾に要素を追加してデフォルトコンストラクタで初期化します。
Definition: Nlist.h:390
MpObject & operator=(const T &x)
値をMpObjectに代入します。
Definition: MpObject.h:278
MpObject second
値となるオブジェクトです。
Definition: MpObject.h:367
std::vectorに似ていますが、コピーできないオブジェクトを格納可能なクラスが定義されています。 ...
ObjectType
MpObjectに格納されているオブジェクトの型情報です。
Definition: MpObject.h:295
bool IsExt() const noexcept
格納されている値が拡張データであるかどうかを調べます。
Definition: MpObject.h:333
連想配列を表します。内部ではMpObjectのペアの列として表現されています。
Definition: MpObject.h:304
配列を表します。内部ではMpObjectの列として表現されています。
Definition: MpObject.h:303
errno_t InitArray(uint32_t n) noexcept
オブジェクトをn 個の要素を持つ配列として初期化します。
void clear() noexcept
コンテナをクリアします。
Definition: Nlist.h:428
MpObject * SwapMapItem(const STDSTRING &key, MpObject *obj) noexcept
obj の内容と連想配列内のオブジェクトの内容を交換します。
Definition: MpObject.h:147
errno_t Unbox(const MpObject *obj, T *v)
この関数テンプレートを特殊化してユーザー型のアンボックス化を定義することが可能です。 ...
bool IsNil() const noexcept
格納されている値ががnilであるかどうかを調べます。
Definition: MpObject.h:323
void swap(MpObject &rhs) noexcept
オブジェクトの中身をスワップします。
Definition: MpObject.h:284
#define NLIB_LIKELY(x)
条件xが真になる傾向が高いことをコンパイラに示します。
Definition: Platform_unix.h:97
#define NLIB_CATCH(x)
例外が有効なときはcatch(x), そうでなければif (true)が定義されます。
Definition: Config.h:124
errno_t InitString(uint32_t n) noexcept
オブジェクトを文字列として初期化します。
errno_tをラップするクラスです。Visual Studioのデバッガ上での表示を改善します。
Definition: Config.h:487
static errno_t nlib_memcpy(void *s1, size_t s1max, const void *s2, size_t n)
N1078のmemcpy_sに相当する実装です。
Definition: Platform.h:3251
#define NLIB_TRY
例外が有効なときはtry, そうでなければif (true)が定義されます。
Definition: Config.h:123
ObjectType GetType() const noexcept
オブジェクトの型を返します。
Definition: MpObject.h:314
bool IsArray() const noexcept
格納されている値が配列であるかどうかを調べます。
Definition: MpObject.h:334
errno_t Unbox(char(&str)[n]) const noexcept
Unbox(T (&a)[n]) を御覧ください。
Definition: MpObject.h:257
MpObject(const T &x)
T型のオブジェクトをボックス化するコンストラクタです。
Definition: MpObject.h:172
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Config.h:99
const MpObject * GetMapItem(const STDSTRING &str) const noexcept
GetMapItem(const STDSTRING& str) と同様です。
Definition: MpObject.h:133
開発環境別の設定が書かれるファイルです。
~MpObjectKv() noexcept
デストラクタです。
Definition: MpObject.h:371
bool reserve(size_type n) noexcept
n 個の要素のためのメモリをアロケート済みにします。
Definition: Nlist.h:674
uint32_t GetSize() const noexcept
配列や連想配列や文字列やバイナリの場合にそのサイズを返します。
Definition: MpObject.h:317
std::vectorに似た、コピーコンストラクタを持たないオブジェクトを格納可能なコンテナ類似クラスです。 ...
Definition: Nlist.h:32
size_type size() const noexcept
格納されている要素の個数を返します。
Definition: Nlist.h:378
size_t nlib_strlen(const char *s)
内部でstrlen()を呼び出します。独自の実装が動作する場合もあります。
bool IsBoolean() const noexcept
格納されている値が真偽値であるかどうかを調べます。
Definition: MpObject.h:324
void * GetBinary(uint32_t *n) noexcept
オブジェクトからバイナリを取得します。
Definition: MpObject.h:187
strlen, strcpy等を安全に使えるようにラップしています。
void * GetExt(int8_t *tp, uint32_t *n) noexcept
オブジェクトから拡張データ型を取得します。
Definition: MpObject.h:201
bool IsFloat() const noexcept
格納されている値が単精度浮動小数点型であるかどうかを調べます。
Definition: MpObject.h:329
MpObject first
キーとなるオブジェクトです。
Definition: MpObject.h:366
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
Definition: Config.h:224
MpObject * GetMapItem(const STDSTRING &str) noexcept
文字列を指定して連想配列内のオブジェクトを取得します。
Definition: MpObject.h:137
MpObject * SwapMapItem(const char *str, MpObject *obj) noexcept
obj の内容と連想配列内のオブジェクトの内容を交換します。
Definition: MpObject.h:156
errno_t InitMap(uint32_t n) noexcept
オブジェクトをn個の要素を持つ連想配列として初期化します。
MpObject * GetArrayItem(size_t n) noexcept
インデックスを指定して配列内のオブジェクトを取得します。
Definition: MpObject.h:109
bool IsDouble() const noexcept
格納されている値が倍精度浮動小数点型であるかどうかを調べます。
Definition: MpObject.h:330
MpObject型のキーと値のペアです。連想配列を格納するために利用されます。
Definition: MpObject.h:365
MessagePackのnil, 及びJSONのnullに対応するクラスです。
Definition: MpObject.h:56
void swap(MpObjectKv &rhs) noexcept
オブジェクトの中身をスワップします。
Definition: MpObject.h:373
#define NLIB_NONNULL
全ての引数にNULLを指定することができないことを示します。
bool IsInteger() const noexcept
格納されている値が整数値であるかどうかを調べます。
Definition: MpObject.h:325
bool IsBinary() const noexcept
格納されている値がバイナリであるかどうかを調べます。
Definition: MpObject.h:332
errno_t Box(const char *str) noexcept
文字列をボックス化します。
真偽値型を表します。内部表現はboolです。
Definition: MpObject.h:297
errno_t Unbox(T(&a)[n]) const
オブジェクトの値をアンボックス化します。
Definition: MpObject.h:247
errno_t Box(MpObject *obj, const T &v)
この関数テンプレートを特殊化してユーザー型のボックス化を定義することが可能です。
浮動小数型を表します。内部表現はfloatです。
Definition: MpObject.h:300
int errno_t
intのtypedefで、戻り値としてPOSIXのエラー値を返すことを示します。
Definition: NMalloc.h:37