nlib
MpObject.h
Go to the documentation of this file.
1 
2 #pragma once
3 #ifndef INCLUDE_NN_NLIB_MSGPACK_MPOBJECT_H_
4 #define INCLUDE_NN_NLIB_MSGPACK_MPOBJECT_H_
5 
6 #include <map>
7 #include <utility>
8 #include <vector>
9 
10 #include "nn/nlib/Config.h"
11 #include "nn/nlib/Swap.h"
12 #include "nn/nlib/Cstring.h"
13 #include "nn/nlib/Nlist.h"
14 
15 #ifdef NLIB_CXX11_STDLIB_ARRAY
16 #include <array> // NOLINT
17 #endif
18 
19 #ifdef NLIB_CXX11_STDLIB_UNORDERED
20 #include <unordered_map> // NOLINT
21 #endif
22 
23 #ifdef NLIB_CXX11_STDLIB_TUPLE
24 #include <tuple> // NOLINT
25 #endif
26 
27 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
28 #undef NLIB_VIS_PUBLIC
29 #define NLIB_VIS_PUBLIC NLIB_WINEXPORT
30 #endif
31 
32 NLIB_NAMESPACE_BEGIN
33 namespace msgpack {
34 
35 class MpObject;
36 
37 template <class T>
38 errno_t Box(MpObject* obj, const T& v);
39 
40 template <class T>
41 errno_t Unbox(const MpObject* obj, T* v);
42 
43 struct nil {};
44 
45 template <class T>
46 inline bool operator==(const nil& lhs, const T& rhs) NLIB_NOEXCEPT {
47  NLIB_UNUSED(lhs);
48  NLIB_UNUSED(rhs);
49  return false;
50 }
51 template <class T>
52 inline bool operator==(const T& lhs, const nil& rhs) NLIB_NOEXCEPT {
53  NLIB_UNUSED(lhs);
54  NLIB_UNUSED(rhs);
55  return false;
56 }
57 inline bool operator==(const nil& lhs, const nil& rhs) NLIB_NOEXCEPT {
58  NLIB_UNUSED(lhs);
59  NLIB_UNUSED(rhs);
60  return true;
61 }
62 template <class T>
63 inline bool operator!=(const nil& rhs, const T& lhs) NLIB_NOEXCEPT {
64  NLIB_UNUSED(lhs);
65  NLIB_UNUSED(rhs);
66  return true;
67 }
68 template <class T>
69 inline bool operator!=(const T& rhs, const nil& lhs) NLIB_NOEXCEPT {
70  NLIB_UNUSED(lhs);
71  NLIB_UNUSED(rhs);
72  return true;
73 }
74 inline bool operator!=(const nil& rhs, const nil& lhs) NLIB_NOEXCEPT {
75  NLIB_UNUSED(lhs);
76  NLIB_UNUSED(rhs);
77  return false;
78 }
79 
80 struct MpObjectKv;
81 
83  private:
84  union UnionType {
85  uint64_t u64;
86  int64_t i64;
87  float f32;
88  double f64;
89  Nlist<MpObject>* ary;
91  char* str;
92  void* binary;
93  };
94 
95  public:
97  MpObject* obj;
98  return NLIB_LIKELY(0 == this->GetArrayItem(n, &obj)) ? obj : NULL;
99  }
100  const MpObject* GetArrayItem(size_t n) const NLIB_NOEXCEPT {
101  const MpObject* obj;
102  return NLIB_LIKELY(0 == this->GetArrayItem(n, &obj)) ? obj : NULL;
103  }
104  MpObject& operator[](size_t n) {
105  NLIB_ASSERT(this->IsArray());
106  NLIB_ASSERT(n < size_);
107  return (*via_.ary)[n];
108  }
109  MpObject* GetMapItem(const char* str) NLIB_NOEXCEPT;
110  const MpObject* GetMapItem(const char* str) const NLIB_NOEXCEPT;
111  template<size_t N>
112  MpObject* GetMapItem(const char (&str)[N]) NLIB_NOEXCEPT {
113  return GetMapItem(&str[0]);
114  }
115  template<size_t N>
116  const MpObject* GetMapItem(const char (&str)[N]) const NLIB_NOEXCEPT {
117  return GetMapItem(&str[0]);
118  }
119  template<class STDSTRING>
120  const MpObject* GetMapItem(const STDSTRING& str) const NLIB_NOEXCEPT {
121  return GetMapItem(str.c_str());
122  }
123  template<class STDSTRING>
124  MpObject* GetMapItem(const STDSTRING& str) NLIB_NOEXCEPT {
125  return GetMapItem(str.c_str());
126  }
127  errno_t Resize(uint32_t n);
128  MpObject* SwapArrayItem(size_t n, MpObject* obj) NLIB_NOEXCEPT {
129  MpObject* p = this->GetArrayItem(n);
130  if (NLIB_LIKELY(p)) p->swap(*obj);
131  return p;
132  }
133  template<class STDSTRING>
134  MpObject* SwapMapItem(const STDSTRING& key, MpObject* obj) NLIB_NOEXCEPT {
135  MpObject* p = this->GetMapItem(key);
136  if (NLIB_LIKELY(p)) p->swap(*obj);
137  return p;
138  }
139  template<size_t N>
140  MpObject* SwapMapItem(const char (&str)[N], MpObject* obj) NLIB_NOEXCEPT {
141  return SwapMapItem(&str[0], obj);
142  }
143  MpObject* SwapMapItem(const char* str, MpObject* obj) NLIB_NOEXCEPT {
144  MpObject* p = this->GetMapItem(str);
145  if (NLIB_LIKELY(p)) p->swap(*obj);
146  return p;
147  }
148  MpObject* AppendArrayItem() NLIB_NOEXCEPT;
149  MpObjectKv* AppendMapItem() NLIB_NOEXCEPT;
150  NLIB_OVERRIDE_NEW;
151 
152  public:
153  MpObject() NLIB_NOEXCEPT : type_(NIL) {} // only do minimum memory access
154  ~MpObject() NLIB_NOEXCEPT { ReleaseIfNeeded(); }
155  NLIB_MOVE_MEMBER_HELPER_1(MpObject, type_);
156 
157  // NOTE: implicit call was error in gcc or clang....
158  template <class T>
159  explicit MpObject(const T& x) {
160  MyBox<T, typename IsIntegral<T>::type, typename IsSigned<T>::type>::Construct(this, x);
161  }
162  errno_t GetArrayItem(size_t n, MpObject** obj) NLIB_NOEXCEPT NLIB_NONNULL;
163  errno_t GetArrayItem(size_t n, const MpObject** obj) const NLIB_NOEXCEPT NLIB_NONNULL;
164  errno_t GetMapItem(size_t n, MpObjectKv** obj) NLIB_NOEXCEPT NLIB_NONNULL;
165  errno_t GetMapItem(size_t n, const MpObjectKv** obj) const NLIB_NOEXCEPT NLIB_NONNULL;
166  char* GetString() NLIB_NOEXCEPT {
167  if (type_ == STRING) return via_.str;
168  if (NLIB_LIKELY(type_ == STRING_INLINE)) return reinterpret_cast<char*>(&raw14data_);
169  return NULL;
170  }
171  const char* GetString() const NLIB_NOEXCEPT {
172  return const_cast<MpObject*>(this)->GetString();
173  }
174  void* GetBinary(uint32_t* n) NLIB_NOEXCEPT {
175  if (type_ == BINARY) {
176  *n = size_;
177  return via_.binary;
178  }
179  if (NLIB_LIKELY(type_ == BINARY_INLINE)) {
180  *n = raw14size_;
181  return &raw14data_;
182  }
183  return NULL;
184  }
185  const void* GetBinary(uint32_t* n) const NLIB_NOEXCEPT {
186  return const_cast<MpObject*>(this)->GetBinary(n);
187  }
188  void* GetExt(int8_t* tp, uint32_t* n) NLIB_NOEXCEPT {
189  if (type_ == EXT) {
190  *n = size_;
191  *tp = static_cast<int8_t>(raw14data_);
192  return via_.binary;
193  } else {
194  return NULL;
195  }
196  }
197  const void* GetExt(int8_t* tp, uint32_t* n) const NLIB_NOEXCEPT {
198  return const_cast<MpObject*>(this)->GetExt(tp, n);
199  }
200 
201  errno_t InitArray(uint32_t n) NLIB_NOEXCEPT;
202  errno_t InitMap(uint32_t n) NLIB_NOEXCEPT;
203  errno_t InitString(uint32_t n) NLIB_NOEXCEPT;
204  errno_t InitString(const char* str, uint32_t n) NLIB_NOEXCEPT;
205  errno_t InitString(const char* str) NLIB_NOEXCEPT {
206  uint32_t n = static_cast<uint32_t>(nlib_strlen(str));
207  return InitString(str, n);
208  }
209  errno_t InitBinary(uint32_t n) NLIB_NOEXCEPT;
210  errno_t InitBinary(const void* p, uint32_t n) NLIB_NOEXCEPT;
211  errno_t InitExt(int8_t tp, uint32_t n) NLIB_NOEXCEPT;
212  errno_t InitExt(int8_t tp, const void* p, uint32_t n) NLIB_NOEXCEPT;
213 
214  public: // Box
215  errno_t Box(const char* str) NLIB_NOEXCEPT NLIB_NONNULL;
216  template <uint32_t n>
217  errno_t Box(const char (&str)[n]) NLIB_NOEXCEPT;
218  template <class T, uint32_t n>
219  errno_t Box(const T (&vec)[n]);
220 #ifdef NLIB_CXX11_STDLIB_ARRAY
221  template <class T, size_t n>
222  errno_t Box(const std::array<T, n>& vec);
223 #endif
224  template <class T>
225  errno_t Box(const T& v) {
226  return MyBox<T, typename IsIntegral<T>::type, typename IsSigned<T>::type>::Box(this, v);
227  }
228  // Use BoxBinary(p, n) or Box(reinterpret_cast<const char*>(p)) instead
229  errno_t BoxBinary(const void* p, uint32_t n) NLIB_NOEXCEPT NLIB_NONNULL;
230  errno_t BoxExt(int8_t tp, const void* p, uint32_t n) NLIB_NOEXCEPT NLIB_NONNULL;
231 
232  public: // Unbox
233  template <class T, size_t n>
234  errno_t Unbox(T (&a)[n]) const {
235  return this->Unbox(&a[0], n);
236  }
237 #ifdef NLIB_CXX11_STDLIB_ARRAY
238  template <class T, size_t n>
239  errno_t Unbox(std::array<T, n>& a) { // NOLINT
240  return this->Unbox(reinterpret_cast<T*>(&*a.begin()), n);
241  }
242 #endif
243  template <size_t n>
244  errno_t Unbox(char (&str)[n]) const NLIB_NOEXCEPT {
245  return this->Unbox(&str[0], n);
246  }
247  template <class T>
248  errno_t Unbox(T* a, size_t n) const NLIB_NONNULL;
249  errno_t Unbox(char* str, size_t n) const NLIB_NOEXCEPT NLIB_NONNULL;
250  errno_t UnboxBinary(void* p, size_t n) const NLIB_NOEXCEPT NLIB_NONNULL;
251  errno_t UnboxExt(int8_t* tp, void* p, size_t n) const NLIB_NOEXCEPT NLIB_NONNULL;
252  template <class T>
253  errno_t Unbox(T v) const {
254  // T cannot be T* though v is only pointer type
255  // because of conflict against array types.
256  return MyBox<typename RemovePtr<T>::type,
257  typename IsIntegral<typename RemovePtr<T>::type>::type,
258  typename IsSigned<typename RemovePtr<T>::type>::type>::Unbox(this, v);
259  }
260 
261  public:
262  // You can use operator=() only for basic types(never fails).
263  // Use Box() otherwise.
264  template <class T>
265  MpObject& operator=(const T& x) {
266  MyBox<T, typename IsIntegral<T>::type, typename IsSigned<T>::type>::Assign(this, x);
267  return *this;
268  }
269 
270  MpObject* Clone() NLIB_NOEXCEPT;
271  void swap(MpObject& rhs) NLIB_NOEXCEPT { // NOLINT
272  using std::swap;
273  swap(type_, rhs.type_);
274  swap(raw14size_, rhs.raw14size_);
275  swap(raw14data_, rhs.raw14data_);
276  swap(_, rhs._);
277  swap(size_, rhs.size_);
278  swap(via_.u64, rhs.via_.u64);
279  }
280 
281  public:
282  enum ObjectType {
283  NIL = 0,
289  STRING,
292  BINARY,
293  EXT,
294  RAW = STRING,
295  STRING_INLINE = 0x80 | STRING,
296  BINARY_INLINE = 0x80 | BINARY,
297  RAW_INLINE = 0x80 | RAW,
298  BOOLEAN_FALSE = 0x00 | BOOLEAN,
299  BOOLEAN_TRUE = 0x80 | BOOLEAN
300  };
301  ObjectType GetType() const NLIB_NOEXCEPT {
302  return static_cast<ObjectType>(type_ & 0x7F);
303  }
304  uint32_t GetSize() const NLIB_NOEXCEPT {
305  if (type_ == STRING_INLINE || type_ == BINARY_INLINE)
306  return raw14size_;
307  else
308  return size_;
309  }
310  bool IsNil() const NLIB_NOEXCEPT { return GetType() == NIL; }
311  bool IsBoolean() const NLIB_NOEXCEPT { return GetType() == BOOLEAN; }
312  bool IsInteger() const NLIB_NOEXCEPT {
313  ObjectType tp = GetType();
314  return tp == UINT64 || tp == INT64;
315  }
316  bool IsFloat() const NLIB_NOEXCEPT { return GetType() == FLOAT; }
317  bool IsDouble() const NLIB_NOEXCEPT { return GetType() == DOUBLE; }
318  bool IsString() const NLIB_NOEXCEPT { return GetType() == STRING; }
319  bool IsBinary() const NLIB_NOEXCEPT { return GetType() == BINARY; }
320  bool IsExt() const NLIB_NOEXCEPT { return GetType() == EXT; }
321  bool IsArray() const NLIB_NOEXCEPT { return GetType() == ARRAY; }
322  bool IsMap() const NLIB_NOEXCEPT { return GetType() == MAP; }
323 
324  private:
325  errno_t Clone(MpObject* p) NLIB_NOEXCEPT;
326  template <class T, class IS_INTEGRAL, class IS_SIGNED>
327  struct MyBox {
328  static errno_t Box(MpObject* This, const T& v) { return ::nlib_ns::msgpack::Box(This, v); }
329  static errno_t Unbox(const MpObject* This, T* v) {
330  if (!v) return EINVAL;
332  }
333  static void Assign(MpObject* This, const T& x);
334  static void Construct(MpObject* This, const T& x);
335  };
336  void ReleaseIfNeeded() NLIB_NOEXCEPT {
337  if (type_ >= STRING && type_ <= EXT) ReleaseIfNeeded_();
338  }
339  void ReleaseIfNeeded_() NLIB_NOEXCEPT;
340 
341  private:
342  uint8_t type_;
343  uint8_t raw14size_;
344  uint8_t raw14data_;
345  uint8_t _;
346  uint32_t size_;
347  UnionType via_;
349  friend NLIB_VIS_PUBLIC bool operator==(const MpObject& lhs, const MpObject& rhs);
350 };
351 
352 struct MpObjectKv {
355 
356  public:
357  MpObjectKv() NLIB_NOEXCEPT {}
358  ~MpObjectKv() NLIB_NOEXCEPT {}
359  NLIB_MOVE_MEMBER_HELPER_2(MpObjectKv, first, second);
360  void swap(MpObjectKv& rhs) NLIB_NOEXCEPT { // NOLINT
361  first.swap(rhs.first);
362  second.swap(rhs.second);
363  }
364 
365  private:
367 };
368 
369 template <>
370 struct MpObject::MyBox<nil, FalseType, FalseType> {
371  static errno_t Box(MpObject* This, nil v) NLIB_NOEXCEPT {
372  NLIB_UNUSED(v);
373  This->ReleaseIfNeeded();
374  This->type_ = NIL;
375  return 0;
376  }
377  static void Assign(MpObject* This, nil x) NLIB_NOEXCEPT { This->Box(x); }
378  static void Construct(MpObject* This, nil) NLIB_NOEXCEPT { This->type_ = NIL; }
379 };
380 
381 template <>
382 struct MpObject::MyBox<bool, TrueType, FalseType> {
383  static errno_t Box(MpObject* This, bool v) NLIB_NOEXCEPT {
384  This->ReleaseIfNeeded();
385  This->type_ = v ? static_cast<uint8_t>(BOOLEAN_TRUE) : static_cast<uint8_t>(BOOLEAN_FALSE);
386  return 0;
387  }
388  static errno_t Unbox(const MpObject* This, bool* v) NLIB_NOEXCEPT {
389  if (This->type_ == BOOLEAN_FALSE) {
390  *v = false;
391  return 0;
392  } else if (NLIB_LIKELY(This->type_ == BOOLEAN_TRUE)) {
393  *v = true;
394  return 0;
395  }
396  *v = false; // to suppress warnings
397  return EACCES;
398  }
399  static void Assign(MpObject* This, bool x) NLIB_NOEXCEPT { This->Box(x); }
400  static void Construct(MpObject* This, bool x) NLIB_NOEXCEPT {
401  This->type_ = x ? static_cast<uint8_t>(BOOLEAN_TRUE) : static_cast<uint8_t>(BOOLEAN_FALSE);
402  }
403 };
404 
405 template <class T>
406 struct MpObject::MyBox<T, TrueType, TrueType> {
407  static errno_t Box(MpObject* This, T v) NLIB_NOEXCEPT {
408  This->ReleaseIfNeeded();
409  This->type_ = INT64;
410  This->via_.i64 = v;
411  return 0;
412  }
413  static errno_t Unbox(const MpObject* This, T* v) NLIB_NOEXCEPT {
414  if (NLIB_UNLIKELY(!v)) return EINVAL;
415  if (This->type_ == INT64) {
416  *v = static_cast<T>(This->via_.i64);
417  return 0;
418  } else if (NLIB_LIKELY(This->type_ == UINT64)) {
419  *v = static_cast<T>(This->via_.u64);
420  return 0;
421  }
422  *v = 0; // to suppress warnings
423  return EACCES;
424  }
425  static void Assign(MpObject* This, T x) NLIB_NOEXCEPT { This->Box(x); }
426  static void Construct(MpObject* This, T x) NLIB_NOEXCEPT {
427  This->type_ = INT64;
428  This->via_.i64 = x;
429  }
430 };
431 
432 template <class T>
433 struct MpObject::MyBox<T, TrueType, FalseType> {
434  static errno_t Box(MpObject* This, T v) NLIB_NOEXCEPT {
435  This->ReleaseIfNeeded();
436  This->type_ = UINT64;
437  This->via_.u64 = v;
438  return 0;
439  }
440  static errno_t Unbox(const MpObject* This, T* v) NLIB_NOEXCEPT {
441  if (NLIB_UNLIKELY(!v)) return EINVAL;
442  if (This->type_ == INT64) {
443  *v = static_cast<T>(This->via_.i64);
444  return 0;
445  } else if (NLIB_LIKELY(This->type_ == UINT64)) {
446  *v = static_cast<T>(This->via_.u64);
447  return 0;
448  }
449  *v = 0; // to suppress warnings
450  return EACCES;
451  }
452  static void Assign(MpObject* This, T x) NLIB_NOEXCEPT { This->Box(x); }
453  static void Construct(MpObject* This, T x) NLIB_NOEXCEPT {
454  This->type_ = UINT64;
455  This->via_.u64 = x;
456  }
457 };
458 
459 template <class TR1_WORKAROUND>
460 struct MpObject::MyBox<float, FalseType, TR1_WORKAROUND> {
461  static errno_t Box(MpObject* This, float v) NLIB_NOEXCEPT {
462  This->ReleaseIfNeeded();
463  This->type_ = FLOAT;
464  This->via_.f32 = v;
465  return 0;
466  }
467  static errno_t Unbox(const MpObject* This, float* v) NLIB_NOEXCEPT {
468  if (NLIB_UNLIKELY(!v)) return EINVAL;
469  switch (This->type_) {
470  case FLOAT:
471  *v = This->via_.f32;
472  break;
473  case DOUBLE:
474  *v = static_cast<float>(This->via_.f64);
475  break;
476  default:
477  *v = 0; // to suppress warnings
478  return EACCES;
479  }
480  return 0;
481  }
482  static void Assign(MpObject* This, float x) NLIB_NOEXCEPT { This->Box(x); }
483  static void Construct(MpObject* This, float x) NLIB_NOEXCEPT {
484  This->type_ = FLOAT;
485  This->via_.f32 = x;
486  }
487 };
488 
489 template <class TR1_WORKAROUND>
490 struct MpObject::MyBox<double, FalseType, TR1_WORKAROUND> {
491  static errno_t Box(MpObject* This, double v) NLIB_NOEXCEPT {
492  This->ReleaseIfNeeded();
493  This->type_ = DOUBLE;
494  This->via_.f64 = v;
495  return 0;
496  }
497  static errno_t Unbox(const MpObject* This, double* v) NLIB_NOEXCEPT {
498  if (NLIB_UNLIKELY(!v)) return EINVAL;
499  switch (This->type_) {
500  case FLOAT:
501  *v = This->via_.f32;
502  break;
503  case DOUBLE:
504  *v = This->via_.f64;
505  break;
506  default:
507  *v = 0; // to suppress warnings
508  return EACCES;
509  }
510  return 0;
511  }
512  static void Assign(MpObject* This, double x) NLIB_NOEXCEPT { This->Box(x); }
513  static void Construct(MpObject* This, double x) NLIB_NOEXCEPT {
514  This->type_ = DOUBLE;
515  This->via_.f64 = x;
516  }
517 };
518 
519 template <class STDSTRING>
520 struct MpObject::MyBox<STDSTRING, FalseType, FalseType> {
521  static errno_t Box(MpObject* This, const STDSTRING& str) NLIB_NOEXCEPT {
522  uint32_t n = static_cast<uint32_t>(str.size());
523  ErrnoT e = This->InitString(n);
524  if (NLIB_UNLIKELY(e != 0)) return e;
525  nlib_memcpy(reinterpret_cast<void*>(This->GetString()),
526  n,
527  reinterpret_cast<const void*>(&str[0]),
528  n);
529  return 0;
530  }
531  static errno_t Unbox(const MpObject* This, STDSTRING* str) NLIB_NOEXCEPT {
532  if (NLIB_UNLIKELY(!str)) return EINVAL;
533  if (NLIB_UNLIKELY(This->type_ != STRING) && NLIB_UNLIKELY(This->type_ != STRING_INLINE))
534  return EACCES;
535  const char* chr = This->GetString();
536  NLIB_TRY { (*str).assign(chr, This->GetSize()); }
537  NLIB_CATCH(std::bad_alloc&) { return ENOMEM; }
538  return 0;
539  }
540 };
541 
542 template <class T, class ALLOC>
543 struct MpObject::MyBox<std::vector<T, ALLOC>, FalseType, FalseType> {
544  static errno_t Box(MpObject* This, const std::vector<T, ALLOC>& vec) {
545  uint32_t n = static_cast<uint32_t>(vec.size());
546  MpObject tmp;
547  ErrnoT e = tmp.InitArray(n);
548  if (NLIB_UNLIKELY(e != 0)) return e;
549 
550  for (uint32_t i = 0; i < n; ++i) {
551  e = (*tmp.via_.ary)[i].Box(vec[i]);
552  if (NLIB_UNLIKELY(e != 0)) return e;
553  }
554  tmp.swap(*This);
555  return 0;
556  }
557  static errno_t Unbox(const MpObject* This, std::vector<T, ALLOC>* vec) {
558  if (NLIB_UNLIKELY(!vec)) return EINVAL;
559  if (NLIB_UNLIKELY(This->type_ != ARRAY)) return EACCES;
560  NLIB_TRY { vec->resize(This->size_); }
561  NLIB_CATCH(std::bad_alloc&) { return ENOMEM; }
562  for (uint32_t i = 0; i < This->size_; ++i) {
563  ErrnoT e = (*This->via_.ary)[i].Unbox(&(*vec)[i]);
564  if (NLIB_UNLIKELY(e != 0)) return e; // *vec NOT RESET
565  }
566  return 0;
567  }
568 };
569 
570 template <class T, class ALLOC>
571 struct MpObject::MyBox<Nlist<T, ALLOC>, FalseType, FalseType> {
572  static errno_t Box(MpObject* This, const Nlist<T, ALLOC>& vec) {
573  size_t n = vec.size();
574  MpObject tmp;
575  ErrnoT e = tmp.InitArray(static_cast<uint32_t>(n));
576  if (NLIB_UNLIKELY(e != 0)) return e;
577  typename Nlist<T, ALLOC>::const_iterator it = vec.begin();
578  for (size_t i = 0; i < n; ++it, ++i) {
579  e = (*tmp.via_.ary)[i].Box(*it);
580  if (NLIB_UNLIKELY(e != 0)) return e;
581  }
582  tmp.swap(*This);
583  return 0;
584  }
585  static errno_t Unbox(const MpObject* This, Nlist<T, ALLOC>* vec) {
586  if (NLIB_UNLIKELY(!vec)) return EINVAL;
587  if (NLIB_UNLIKELY(This->type_ != ARRAY)) return EACCES;
588  vec->clear();
589  if (NLIB_UNLIKELY(!vec->reserve(This->size_))) return ENOMEM;
590  for (uint32_t i = 0; i < This->size_; ++i) {
591  T* item = vec->push_back();
592  ErrnoT e = (*This->via_.ary)[i].Unbox(item);
593  if (NLIB_UNLIKELY(e != 0)) return e; // *vec NOT RESET
594  }
595  return 0;
596  }
597 };
598 
599 template <class T1, class T2>
600 struct MpObject::MyBox<std::pair<T1, T2>, FalseType, FalseType> {
601  static errno_t Box(MpObject* This, const std::pair<T1, T2>& p) {
602  MpObject tmp;
603  ErrnoT e = tmp.InitArray(2);
604  if (NLIB_UNLIKELY(e != 0)) return e;
605  e = (*tmp.via_.ary)[0].Box(p.first);
606  if (NLIB_UNLIKELY(e != 0)) return e;
607  e = (*tmp.via_.ary)[1].Box(p.second);
608  if (NLIB_UNLIKELY(e != 0)) return e;
609  tmp.swap(*This);
610  return 0;
611  }
612  static errno_t Unbox(const MpObject* This, std::pair<T1, T2>* p) {
613  if (NLIB_UNLIKELY(!p)) return EINVAL;
614  if (NLIB_UNLIKELY(This->type_ != ARRAY)) return EACCES;
615  if (NLIB_UNLIKELY(This->size_ != 2)) return EACCES;
616  ErrnoT e;
617  e = (*This->via_.ary)[0].Unbox(&p->first);
618  if (NLIB_UNLIKELY(e != 0)) return e; // *p NOT RESET
619  e = (*This->via_.ary)[1].Unbox(&p->second);
620  if (NLIB_UNLIKELY(e != 0)) return e; // *p NOT RESET
621  return 0;
622  }
623 };
624 
625 #if defined(NLIB_CXX11_STDLIB_TUPLE) && defined(NLIB_CXX11_VARIADIC_TEMPLATES)
626 template <class ...Args>
627 struct MpObject::MyBox<std::tuple<Args...>, FalseType, FalseType > {
628  private:
629  template<size_t N, class HEAD>
630  static errno_t BoxHelper(MpObject* tmp, const HEAD& head) {
631  return (*tmp->via_.ary)[N].Box(head);
632  }
633  template<size_t N, class HEAD, class ...TAIL>
634  static errno_t BoxHelper(MpObject* tmp, const HEAD& head, TAIL&... tail) {
635  ErrnoT e = (*tmp->via_.ary)[N].Box(head);
636  if (NLIB_UNLIKELY(e != 0)) return e;
637  return BoxHelper<N + 1, TAIL...>(tmp, tail...);
638  }
639  template<size_t N, class HEAD>
640  static errno_t UnboxHelper(const MpObject* This, HEAD& head) { // NOLINT
641  return (*This->via_.ary)[N].Unbox(&head);
642  }
643  template<size_t N, class HEAD, class ...TAIL>
644  static errno_t UnboxHelper(const MpObject* This, HEAD& head, TAIL&... tail) { // NOLINT
645  ErrnoT e = (*This->via_.ary)[N].Unbox(&head);
646  if (NLIB_UNLIKELY(e != 0)) return e;
647  return UnboxHelper<N + 1, TAIL...>(This, tail...);
648  }
649  template<int ...> struct seq {};
650  template<int N, int ...S> struct gens : gens<N - 1, N - 1, S...> {};
651  template<int ...S>
652  struct gens<0, S...> {
653  typedef seq<S...> type;
654  };
655  template<int ...S>
656  static errno_t Box(MpObject* tmp, seq<S...>, const std::tuple<Args...>& p) {
657  return BoxHelper<0>(tmp, std::get<S>(p)...);
658  }
659  template<int ...S>
660  static errno_t Unbox(const MpObject* This, seq<S...>, std::tuple<Args...>& p) { // NOLINT
661  return UnboxHelper<0>(This, std::get<S>(p)...);
662  }
663 
664  public:
665  static errno_t Box(MpObject* This, const std::tuple<Args...>& p) {
666  size_t count = std::tuple_size<std::tuple<Args...> >::value;
667  MpObject tmp;
668  ErrnoT e = tmp.InitArray(static_cast<uint32_t>(count));
669  if (NLIB_UNLIKELY(e != 0)) return e;
670  typedef typename gens<sizeof...(Args)>::type MySeq;
671  e = Box(&tmp, MySeq(), p);
672  if (NLIB_UNLIKELY(e != 0)) return e;
673  tmp.swap(*This);
674  return 0;
675  }
676  static errno_t Unbox(const MpObject* This, std::tuple<Args...>* p) {
677  if (NLIB_UNLIKELY(!p)) return EINVAL;
678  if (NLIB_UNLIKELY(This->type_ != ARRAY)) return EACCES;
679  if (NLIB_UNLIKELY(This->size_ != std::tuple_size<std::tuple<Args...> >::value))
680  return EACCES;
681  typedef typename gens<sizeof...(Args)>::type MySeq;
682  return Unbox(This, MySeq(), *p);
683  }
684 };
685 #endif
686 
687 template <class K, class V, class Pr, class Alloc>
688 struct MpObject::MyBox<std::map<K, V, Pr, Alloc>, FalseType, FalseType> {
689  static errno_t Box(MpObject* This, const std::map<K, V, Pr, Alloc>& m) {
690  typedef typename std::map<K, V, Pr, Alloc> maptype;
691  uint32_t n = static_cast<uint32_t>(m.size());
692  MpObject tmp;
693  ErrnoT e = tmp.InitMap(n);
694  if (NLIB_UNLIKELY(e != 0)) return e;
695 
696  typename maptype::const_iterator it;
697  typename maptype::const_iterator it_end = m.end();
698  uint32_t i;
699  for (i = 0, it = m.begin(); it != it_end; ++it, ++i) {
700  MpObjectKv& kv = (*tmp.via_.mp)[i];
701  e = kv.first.Box(it->first);
702  if (NLIB_UNLIKELY(e != 0)) return e;
703  e = kv.second.Box(it->second);
704  if (NLIB_UNLIKELY(e != 0)) return e;
705  }
706  tmp.swap(*This);
707  return 0;
708  }
709  static errno_t Unbox(const MpObject* This, std::map<K, V, Pr, Alloc>* m) {
710  if (NLIB_UNLIKELY(!m)) return EINVAL;
711  if (NLIB_UNLIKELY(This->type_ != MAP)) return EACCES;
712  m->clear();
713  for (uint32_t i = 0; i < This->size_; ++i) {
714  K key;
715  V value;
716  const MpObjectKv& kv = (*This->via_.mp)[i];
717  ErrnoT e;
718  e = kv.first.Unbox(&key);
719  if (NLIB_UNLIKELY(e != 0)) return e; // *m NOT RESET
720  e = kv.second.Unbox(&value);
721  if (NLIB_UNLIKELY(e != 0)) return e; // *m NOT RESET
722  NLIB_TRY { (*m)[NLIB_MOVE(key)] = NLIB_MOVE(value); }
723  NLIB_CATCH(...) { return ENOMEM; }
724  }
725  return 0;
726  }
727 };
728 
729 #ifdef NLIB_CXX11_STDLIB_UNORDERED
730 template <class K, class V, class Hash, class Pr, class Alloc>
731 struct MpObject::MyBox<std::unordered_map<K, V, Hash, Pr, Alloc>, FalseType, FalseType > {
732  static errno_t Box(MpObject* This, const std::unordered_map<K, V, Hash, Pr, Alloc>& m) {
733  typedef typename std::unordered_map<K, V, Hash, Pr, Alloc> maptype;
734  uint32_t n = static_cast<uint32_t>(m.size());
735  MpObject tmp;
736  ErrnoT e = tmp.InitMap(n);
737  if (NLIB_UNLIKELY(e != 0)) return e;
738 
739  typename maptype::const_iterator it;
740  typename maptype::const_iterator it_end = m.end();
741  uint32_t i;
742  for (i = 0, it = m.begin(); it != it_end; ++it, ++i) {
743  MpObjectKv& kv = (*tmp.via_.mp)[i];
744  e = kv.first.Box(it->first);
745  if (NLIB_UNLIKELY(e != 0)) return e;
746  e = kv.second.Box(it->second);
747  if (NLIB_UNLIKELY(e != 0)) return e;
748  }
749  tmp.swap(*This);
750  return 0;
751  }
752  static errno_t Unbox(const MpObject* This, std::unordered_map<K, V, Hash, Pr, Alloc>* m) {
753  if (NLIB_UNLIKELY(!m)) return EINVAL;
754  if (NLIB_UNLIKELY(This->type_ != MAP)) return EACCES;
755  m->clear();
756  for (uint32_t i = 0; i < This->size_; ++i) {
757  K key;
758  V value;
759  const MpObjectKv& kv = (*This->via_.mp)[i];
760  ErrnoT e;
761  e = kv.first.Unbox(&key);
762  if (NLIB_UNLIKELY(e != 0)) return e; // *m NOT RESET
763  e = kv.second.Unbox(&value);
764  if (NLIB_UNLIKELY(e != 0)) return e; // *m NOT RESET
765  NLIB_TRY { (*m)[NLIB_MOVE(key)] = NLIB_MOVE(value); }
766  NLIB_CATCH(...) { return ENOMEM; }
767  }
768  return 0;
769  }
770 };
771 #endif
772 
773 NLIB_VIS_PUBLIC bool operator==(const MpObject& lhs, const MpObject& rhs);
774 inline bool operator==(const MpObjectKv& lhs, const MpObjectKv& rhs) NLIB_NOEXCEPT {
775  return lhs.first == rhs.first && lhs.second == rhs.second;
776 }
777 inline bool operator!=(const MpObject& lhs, const MpObject& rhs) NLIB_NOEXCEPT {
778  return !(lhs == rhs);
779 }
780 inline bool operator!=(const MpObjectKv& lhs, const MpObjectKv& rhs) NLIB_NOEXCEPT {
781  return !(lhs == rhs);
782 }
783 
784 template <uint32_t n>
785 errno_t MpObject::Box(const char (&str)[n]) NLIB_NOEXCEPT {
786  uint32_t nn = static_cast<uint32_t>(nlib_strlen(str));
787  ErrnoT e = this->InitString(nn);
788  if (NLIB_UNLIKELY(e != 0)) return e;
789  nlib_memcpy(this->GetString(), nn, reinterpret_cast<const void*>(&str[0]), nn);
790  return 0;
791 }
792 
793 template <class T, uint32_t n>
794 errno_t MpObject::Box(const T (&vec)[n]) {
795  MpObject tmp;
796  ErrnoT e = tmp.InitArray(n);
797  if (NLIB_UNLIKELY(e != 0)) return e;
798  for (uint32_t i = 0; i < n; ++i) {
799  e = (*tmp.via_.ary)[i].Box(vec[i]);
800  if (NLIB_UNLIKELY(e != 0)) return e;
801  }
802  this->swap(tmp);
803  return 0;
804 }
805 
806 #ifdef NLIB_CXX11_STDLIB_ARRAY
807 template <class T, size_t n>
808 errno_t MpObject::Box(const std::array<T, n>& vec) {
809  MpObject tmp;
810  ErrnoT e = tmp.InitArray(n);
811  if (NLIB_UNLIKELY(e != 0)) return e;
812  for (uint32_t i = 0; i < n; ++i) {
813  e = (*tmp.via_.ary)[i].Box(vec[i]);
814  if (NLIB_UNLIKELY(e != 0)) return e;
815  }
816  this->swap(tmp);
817  return 0;
818 }
819 #endif
820 
821 template <class T>
822 errno_t MpObject::Unbox(T* a, size_t n) const {
823  NLIB_EINVAL_IFNULL(a);
824  if (NLIB_UNLIKELY(n == 0)) return EINVAL;
825  if (NLIB_UNLIKELY(type_ != ARRAY)) return EACCES;
826  if (NLIB_UNLIKELY(n != size_)) return ERANGE;
827  for (uint32_t i = 0; i < size_; ++i) {
828  ErrnoT e = (*via_.ary)[i].Unbox(&a[i]);
829  if (NLIB_UNLIKELY(e != 0)) return e;
830  }
831  return 0;
832 }
833 
834 } // namespace msgpack
835 NLIB_NAMESPACE_END
836 
837 NLIB_DEFINE_STD_SWAP(::nlib_ns::msgpack::MpObject)
838 NLIB_DEFINE_STD_SWAP(::nlib_ns::msgpack::MpObjectKv)
839 
840 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
841 #undef NLIB_VIS_PUBLIC
842 #define NLIB_VIS_PUBLIC NLIB_WINIMPORT
843 #endif
844 
845 #endif // INCLUDE_NN_NLIB_MSGPACK_MPOBJECT_H_
Represents an unsigned integer type. The internal representation is uint64_t.
Definition: MpObject.h:285
Represents an integer type. The internal representation is int64_t.
Definition: MpObject.h:286
char * GetString() noexcept
Gets a string from an object.
Definition: MpObject.h:166
Represents a floating point type. The internal representation is double.
Definition: MpObject.h:288
errno_t Unbox(T v) const
Unboxes the object.
Definition: MpObject.h:253
bool IsString() const noexcept
Determines whether the stored value is a string.
Definition: MpObject.h:318
bool IsMap() const noexcept
Determines whether the stored value is an associative array.
Definition: MpObject.h:322
MpObject & operator[](size_t n)
For an array, returns a reference to an element of the array.
Definition: MpObject.h:104
MpObjectKv() noexcept
Instantiates the object with default parameters (default constructor).
Definition: MpObject.h:357
#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:145
errno_t InitString(const char *str) noexcept
Initializes the object as a string.
Definition: MpObject.h:205
Definition: Base64.h:8
MpObject() noexcept
Instantiates the object with default parameters (default constructor). Set to the nil type...
Definition: MpObject.h:153
~MpObject() noexcept
Destructor.
Definition: MpObject.h:154
const void * GetExt(int8_t *tp, uint32_t *n) const noexcept
Gets an extended data type from an object.
Definition: MpObject.h:197
iterator begin() noexcept
Returns the iterator pointing to the beginning of the container.
Definition: Nlist.h:441
const MpObject * GetArrayItem(size_t n) const noexcept
The same as GetArrayItem(size_t n).
Definition: MpObject.h:100
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:128
const void * GetBinary(uint32_t *n) const noexcept
Gets binary from an object.
Definition: MpObject.h:185
#define NLIB_UNLIKELY(x)
Indicates to the compiler that condition x is likely to be false.
Definition: Platform_unix.h:72
const char * GetString() const noexcept
Gets a string from an object.
Definition: MpObject.h:171
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are equal.
Definition: NMalloc.h:110
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are not equal.
Definition: NMalloc.h:115
errno_t Box(const T &v)
Boxes the object.
Definition: MpObject.h:225
BaseType::const_iterator const_iterator
Read-only forward iterator.
Definition: Nlist.h:358
#define NLIB_VIS_PUBLIC
Symbols for functions and classes are made available outside of the library.
Definition: Platform_unix.h:61
Object created when MessagePack or JSON is read.
Definition: MpObject.h:82
pointer push_back()
Adds an element to the end and initializes it with the default constructor.
Definition: Nlist.h:377
MpObject & operator=(const T &x)
The value is passed into MpObject.
Definition: MpObject.h:265
MpObject second
Object used as a value.
Definition: MpObject.h:354
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:282
bool IsExt() const noexcept
Determines whether the stored value is extended data.
Definition: MpObject.h:320
Represents an associative array. The internal representation is an array of MpObject pairs...
Definition: MpObject.h:291
Represents an array. The internal representation is an array of MpObject.
Definition: MpObject.h:290
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:415
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:134
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:310
void swap(MpObject &rhs) noexcept
Swaps the content of the object.
Definition: MpObject.h:271
#define NLIB_LIKELY(x)
Indicates to the compiler that condition x is likely to be true.
Definition: Platform_unix.h:71
#define NLIB_CATCH(x)
Defines catch(x) if exceptions are enabled. If not, defines if (true).
Definition: Config.h:111
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:474
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:3170
#define NLIB_TRY
Defines try if exceptions are enabled. If not, defines if (true).
Definition: Config.h:110
ObjectType GetType() const noexcept
Returns the object type.
Definition: MpObject.h:301
bool IsArray() const noexcept
Determines whether the stored value is an array.
Definition: MpObject.h:321
errno_t Unbox(char(&str)[n]) const noexcept
See Unbox(T (&a)[n]).
Definition: MpObject.h:244
MpObject(const T &x)
The constructor for boxing a T-type object.
Definition: MpObject.h:159
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:86
const MpObject * GetMapItem(const STDSTRING &str) const noexcept
The same as GetMapItem(const STDSTRING& str).
Definition: MpObject.h:120
A file that contains the configuration information for each development environment.
~MpObjectKv() noexcept
Destructor.
Definition: MpObject.h:358
bool reserve(size_type n) noexcept
Allocates memory for n number of elements.
Definition: Nlist.h:661
uint32_t GetSize() const noexcept
Returns the size of the array, associative array, string, or binary.
Definition: MpObject.h:304
A container-like class similar to std::vector that can store objects that do not have copy constructo...
Definition: Nlist.h:19
size_type size() const noexcept
Returns the number of stored elements.
Definition: Nlist.h:365
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:311
void * GetBinary(uint32_t *n) noexcept
Gets binary from an object.
Definition: MpObject.h:174
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:188
bool IsFloat() const noexcept
Determines whether the stored value is a single precision float.
Definition: MpObject.h:316
MpObject first
Object used as a key.
Definition: MpObject.h:353
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:211
MpObject * GetMapItem(const STDSTRING &str) noexcept
Specifies a string and gets the object in the associative array.
Definition: MpObject.h:124
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:143
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:96
bool IsDouble() const noexcept
Determines whether the stored value is a double.
Definition: MpObject.h:317
A pair consisting of an MpObject-type key and value. Used to store an associative array...
Definition: MpObject.h:352
Class that corresponds to nil in MessagePack and null in JSON.
Definition: MpObject.h:43
void swap(MpObjectKv &rhs) noexcept
Swaps the content of the object.
Definition: MpObject.h:360
#define NLIB_NONNULL
Indicates that you cannot specify NULL for all arguments.
Definition: Platform_unix.h:76
bool IsInteger() const noexcept
Determines whether the stored value is an integer.
Definition: MpObject.h:312
bool IsBinary() const noexcept
Determines whether the stored value is binary.
Definition: MpObject.h:319
errno_t Box(const char *str) noexcept
Boxes the string.
Represents a boolean type. The internal representation is a bool.
Definition: MpObject.h:284
errno_t Unbox(T(&a)[n]) const
Unboxes the object value.
Definition: MpObject.h:234
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:287
int errno_t
Indicates with an int-type typedef that a POSIX error value is returned as the return value...
Definition: NMalloc.h:24