nlib
MpObject.h
Go to the documentation of this file.
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_
Represents an unsigned integer type. The internal representation is uint64_t.
Definition: MpObject.h:298
Represents an integer type. The internal representation is int64_t.
Definition: MpObject.h:299
char * GetString() noexcept
Gets a string from an object.
Definition: MpObject.h:179
Represents a floating point type. The internal representation is double.
Definition: MpObject.h:301
errno_t Unbox(T v) const
Unboxes the object.
Definition: MpObject.h:266
bool IsString() const noexcept
Determines whether the stored value is a string.
Definition: MpObject.h:331
bool IsMap() const noexcept
Determines whether the stored value is an associative array.
Definition: MpObject.h:335
MpObject & operator[](size_t n)
For an array, returns a reference to an element of the array.
Definition: MpObject.h:117
MpObjectKv() noexcept
Instantiates the object with default parameters (default constructor).
Definition: MpObject.h:370
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Definition: Config.h:158
errno_t InitString(const char *str) noexcept
Initializes the object as a string.
Definition: MpObject.h:218
Definition: Base64.h:21
MpObject() noexcept
Instantiates the object with default parameters (default constructor). Set to the nil type...
Definition: MpObject.h:166
~MpObject() noexcept
Destructor.
Definition: MpObject.h:167
const void * GetExt(int8_t *tp, uint32_t *n) const noexcept
Gets an extended data type from an object.
Definition: MpObject.h:210
iterator begin() noexcept
Returns the iterator pointing to the beginning of the container.
Definition: Nlist.h:454
const MpObject * GetArrayItem(size_t n) const noexcept
The same as GetArrayItem(size_t n).
Definition: MpObject.h:113
MpObject * SwapArrayItem(size_t n, MpObject *obj) noexcept
Swaps the content of obj and the content of the object within an array.
Definition: MpObject.h:141
const void * GetBinary(uint32_t *n) const noexcept
Gets binary from an object.
Definition: MpObject.h:198
#define NLIB_UNLIKELY(x)
Indicates to the compiler that condition x is likely to be false.
Definition: Platform_unix.h:98
const char * GetString() const noexcept
Gets a string from an object.
Definition: MpObject.h:184
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are equal.
Definition: NMalloc.h:123
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are not equal.
Definition: NMalloc.h:128
errno_t Box(const T &v)
Boxes the object.
Definition: MpObject.h:238
BaseType::const_iterator const_iterator
Read-only forward iterator.
Definition: Nlist.h:371
#define NLIB_VIS_PUBLIC
Symbols for functions and classes are made available outside of the library.
Definition: Platform_unix.h:87
Object created when MessagePack or JSON is read.
Definition: MpObject.h:95
pointer push_back()
Adds an element to the end and initializes it with the default constructor.
Definition: Nlist.h:390
MpObject & operator=(const T &x)
The value is passed into MpObject.
Definition: MpObject.h:278
MpObject second
Object used as a value.
Definition: MpObject.h:367
Defines the class that resembles std::vector but can store objects that cannot be copied...
ObjectType
Data type of the object stored in MpObject.
Definition: MpObject.h:295
bool IsExt() const noexcept
Determines whether the stored value is extended data.
Definition: MpObject.h:333
Represents an associative array. The internal representation is an array of MpObject pairs...
Definition: MpObject.h:304
Represents an array. The internal representation is an array of MpObject.
Definition: MpObject.h:303
errno_t InitArray(uint32_t n) noexcept
Initializes as an object with an n element array.
void clear() noexcept
Clears the container.
Definition: Nlist.h:428
MpObject * SwapMapItem(const STDSTRING &key, MpObject *obj) noexcept
Swaps the content of obj and the content of the object within an associative array.
Definition: MpObject.h:147
errno_t Unbox(const MpObject *obj, T *v)
This function template can be specialized to define unboxing the user type.
bool IsNil() const noexcept
Determines whether the stored value is nil.
Definition: MpObject.h:323
void swap(MpObject &rhs) noexcept
Swaps the content of the object.
Definition: MpObject.h:284
#define NLIB_LIKELY(x)
Indicates to the compiler that condition x is likely to be true.
Definition: Platform_unix.h:97
#define NLIB_CATCH(x)
Defines catch(x) if exceptions are enabled. If not, defines if (true).
Definition: Config.h:124
errno_t InitString(uint32_t n) noexcept
Initializes the object as a string.
Class that wraps errno_t. This class improves visual representations in the Visual Studio debugger...
Definition: Config.h:487
static errno_t nlib_memcpy(void *s1, size_t s1max, const void *s2, size_t n)
An implementation corresponding to N1078 memcpy_s.
Definition: Platform.h:3251
#define NLIB_TRY
Defines try if exceptions are enabled. If not, defines if (true).
Definition: Config.h:123
ObjectType GetType() const noexcept
Returns the object type.
Definition: MpObject.h:314
bool IsArray() const noexcept
Determines whether the stored value is an array.
Definition: MpObject.h:334
errno_t Unbox(char(&str)[n]) const noexcept
See Unbox(T (&a)[n]).
Definition: MpObject.h:257
MpObject(const T &x)
The constructor for boxing a T-type object.
Definition: MpObject.h:172
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:99
const MpObject * GetMapItem(const STDSTRING &str) const noexcept
The same as GetMapItem(const STDSTRING& str).
Definition: MpObject.h:133
A file that contains the configuration information for each development environment.
~MpObjectKv() noexcept
Destructor.
Definition: MpObject.h:371
bool reserve(size_type n) noexcept
Allocates memory for n number of elements.
Definition: Nlist.h:674
uint32_t GetSize() const noexcept
Returns the size of the array, associative array, string, or binary.
Definition: MpObject.h:317
A container-like class similar to std::vector that can store objects that do not have copy constructo...
Definition: Nlist.h:32
size_type size() const noexcept
Returns the number of stored elements.
Definition: Nlist.h:378
size_t nlib_strlen(const char *s)
Internally calls strlen(). In some cases, it may operate as an independent implementation.
bool IsBoolean() const noexcept
Determines whether the stored value is a boolean.
Definition: MpObject.h:324
void * GetBinary(uint32_t *n) noexcept
Gets binary from an object.
Definition: MpObject.h:187
Wraps functions like strlen and strcpy so they can be safely used.
void * GetExt(int8_t *tp, uint32_t *n) noexcept
Gets an extended data type from an object.
Definition: MpObject.h:201
bool IsFloat() const noexcept
Determines whether the stored value is a single precision float.
Definition: MpObject.h:329
MpObject first
Object used as a key.
Definition: MpObject.h:366
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:224
MpObject * GetMapItem(const STDSTRING &str) noexcept
Specifies a string and gets the object in the associative array.
Definition: MpObject.h:137
MpObject * SwapMapItem(const char *str, MpObject *obj) noexcept
Swaps the content of obj and the content of the object within an associative array.
Definition: MpObject.h:156
errno_t InitMap(uint32_t n) noexcept
Initializes the object as an n element associative array.
MpObject * GetArrayItem(size_t n) noexcept
Specifies an index and gets the object in the array.
Definition: MpObject.h:109
bool IsDouble() const noexcept
Determines whether the stored value is a double.
Definition: MpObject.h:330
A pair consisting of an MpObject-type key and value. Used to store an associative array...
Definition: MpObject.h:365
Class that corresponds to nil in MessagePack and null in JSON.
Definition: MpObject.h:56
void swap(MpObjectKv &rhs) noexcept
Swaps the content of the object.
Definition: MpObject.h:373
#define NLIB_NONNULL
Indicates that you cannot specify NULL for all arguments.
bool IsInteger() const noexcept
Determines whether the stored value is an integer.
Definition: MpObject.h:325
bool IsBinary() const noexcept
Determines whether the stored value is binary.
Definition: MpObject.h:332
errno_t Box(const char *str) noexcept
Boxes the string.
Represents a boolean type. The internal representation is a bool.
Definition: MpObject.h:297
errno_t Unbox(T(&a)[n]) const
Unboxes the object value.
Definition: MpObject.h:247
errno_t Box(MpObject *obj, const T &v)
This function template can be specialized to define boxing the user type.
Represents a floating point type. The internal representation is float.
Definition: MpObject.h:300
int errno_t
Indicates with an int-type typedef that a POSIX error value is returned as the return value...
Definition: NMalloc.h:37