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