3 #ifndef INCLUDE_NN_NLIB_MSGPACK_MPOBJECT_H_
4 #define INCLUDE_NN_NLIB_MSGPACK_MPOBJECT_H_
12 #include "nn/nlib/Swap.h"
16 #ifdef NLIB_CXX11_STDLIB_ARRAY
20 #ifdef NLIB_CXX11_STDLIB_UNORDERED
21 #include <unordered_map>
24 #ifdef NLIB_CXX11_STDLIB_TUPLE
28 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
29 #undef NLIB_VIS_PUBLIC
30 #define NLIB_VIS_PUBLIC NLIB_WINEXPORT
98 return NLIB_LIKELY(0 == this->GetArrayItem(n, &obj)) ? obj : NULL;
102 return NLIB_LIKELY(0 == this->GetArrayItem(n, &obj)) ? obj : NULL;
105 NLIB_ASSERT(this->IsArray());
106 NLIB_ASSERT(n < m_Size);
107 return (*m_Via.ary)[n];
115 MpObject* p = this->GetArrayItem(n);
121 MpObject* p = this->GetMapItem(key);
127 MpObject* p = this->GetMapItem(str);
131 MpObject* AppendArrayItem() NLIB_NOEXCEPT;
137 NLIB_MOVE_MEMBER_HELPER_1(
MpObject, m_Type);
142 MyBox<T, typename IsIntegral<T>::type,
typename IsSigned<T>::type>::Construct(
this, x);
151 if (m_Type == RAW)
return m_Via.raw;
152 if (
NLIB_LIKELY(m_Type == RAW_INLINE))
return &m_Raw14Data;
156 if (m_Type == RAW)
return m_Via.raw;
157 if (
NLIB_LIKELY(m_Type == RAW_INLINE))
return &m_Raw14Data;
167 template <u
int32_t n>
169 template <
class T, u
int32_t n>
171 #ifdef NLIB_CXX11_STDLIB_ARRAY
172 template <
class T,
size_t n>
177 return MyBox<T, typename IsIntegral<T>::type,
typename IsSigned<T>::type>
::Box(
this, v);
182 template <
class T,
size_t n>
184 return this->
Unbox(&a[0], n);
186 #ifdef NLIB_CXX11_STDLIB_ARRAY
187 template <
class T,
size_t n>
189 return this->
Unbox(reinterpret_cast<T*>(&*a.begin()), n);
194 return this->
Unbox(&str[0], n);
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);
214 MyBox<T, typename IsIntegral<T>::type,
typename IsSigned<T>::type>::Assign(
this, x);
221 swap(m_Type, rhs.m_Type);
222 swap(m_Raw14Size, rhs.m_Raw14Size);
223 swap(m_Raw14Data, rhs.m_Raw14Data);
225 swap(m_Size, rhs.m_Size);
226 swap(m_Via.u64, rhs.m_Via.u64);
240 RAW_INLINE = 0x80 | RAW,
241 BOOLEAN_FALSE = 0x00 | BOOLEAN,
242 BOOLEAN_TRUE = 0x80 | BOOLEAN
245 return static_cast<ObjectType>(m_Type & 0x7F);
248 return (m_Type != RAW_INLINE) ? m_Size : m_Raw14Size;
250 bool IsNil() const NLIB_NOEXCEPT {
return GetType() == NIL; }
251 bool IsBoolean() const NLIB_NOEXCEPT {
return GetType() == BOOLEAN; }
254 return tp == UINT64 || tp == INT64;
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; }
264 template <
class T,
class IS_INTEGRAL,
class IS_SIGNED>
268 if (!v)
return EINVAL;
271 static void Assign(MpObject* This,
const T& x);
272 static void Construct(MpObject* This,
const T& x);
274 void ReleaseIfNeeded() NLIB_NOEXCEPT {
275 if (m_Type >= RAW && m_Type <= MAP) ReleaseIfNeeded_();
277 void ReleaseIfNeeded_() NLIB_NOEXCEPT;
287 friend
NLIB_VIS_PUBLIC bool operator==(const MpObject& lhs, const MpObject& rhs);
297 NLIB_MOVE_MEMBER_HELPER_2(MpObjectKv, first, second);
298 void swap(MpObjectKv& rhs) NLIB_NOEXCEPT {
299 first.
swap(rhs.first);
300 second.
swap(rhs.second);
308 struct MpObject::MyBox<nil, FalseType, FalseType> {
309 static errno_t Box(MpObject* This, nil v) NLIB_NOEXCEPT {
311 This->ReleaseIfNeeded();
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; }
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);
326 static errno_t Unbox(
const MpObject* This,
bool* v) NLIB_NOEXCEPT {
327 if (This->m_Type == BOOLEAN_FALSE) {
330 }
else if (
NLIB_LIKELY(This->m_Type == BOOLEAN_TRUE)) {
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);
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;
351 static errno_t Unbox(
const MpObject* This, T* v) NLIB_NOEXCEPT {
353 if (This->m_Type == INT64) {
354 *v =
static_cast<T
>(This->m_Via.i64);
357 *v =
static_cast<T
>(This->m_Via.u64);
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;
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;
378 static errno_t Unbox(
const MpObject* This, T* v) NLIB_NOEXCEPT {
380 if (This->m_Type == INT64) {
381 *v =
static_cast<T
>(This->m_Via.i64);
384 *v =
static_cast<T
>(This->m_Via.u64);
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;
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;
405 static errno_t Unbox(
const MpObject* This,
float* v) NLIB_NOEXCEPT {
407 switch (This->m_Type) {
409 *v = This->m_Via.f32;
412 *v =
static_cast<float>(This->m_Via.f64);
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;
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;
435 static errno_t Unbox(
const MpObject* This,
double* v) NLIB_NOEXCEPT {
437 switch (This->m_Type) {
439 *v = This->m_Via.f32;
442 *v = This->m_Via.f64;
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;
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());
466 static errno_t Unbox(
const MpObject* This, std::string* str) NLIB_NOEXCEPT {
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; }
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());
485 for (uint32_t i = 0; i < n; ++i) {
486 e = (*tmp.m_Via.ary)[i].
Box(vec[i]);
492 static errno_t Unbox(
const MpObject* This, std::vector<T, ALLOC>* vec) {
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) {
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();
510 errno_t e = tmp.InitArray(static_cast<uint32_t>(n));
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);
520 static errno_t Unbox(
const MpObject* This, Nlist<T, ALLOC>* vec) {
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();
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) {
540 e = (*tmp.m_Via.ary)[0].
Box(p.first);
542 e = (*tmp.m_Via.ary)[1].
Box(p.second);
547 static errno_t Unbox(
const MpObject* This, std::pair<T1, T2>* p) {
552 e = (*This->m_Via.ary)[0].
Unbox(&p->first);
554 e = (*This->m_Via.ary)[1].
Unbox(&p->second);
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 > {
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);
568 template<
size_t N,
class HEAD,
class ...TAIL>
569 static errno_t BoxHelper(MpObject* tmp,
const HEAD& head, TAIL&... tail) {
572 return BoxHelper<N + 1, TAIL...>(tmp, tail...);
574 template<
size_t N,
class HEAD>
575 static errno_t UnboxHelper(
const MpObject* This, HEAD& head) {
576 return (*This->m_Via.ary)[N].Unbox(&head);
578 template<
size_t N,
class HEAD,
class ...TAIL>
579 static errno_t UnboxHelper(
const MpObject* This, HEAD& head, TAIL&... tail) {
582 return UnboxHelper<N + 1, TAIL...>(This, tail...);
584 template<
int ...>
struct seq {};
585 template<
int N,
int ...S>
struct gens : gens<N - 1, N - 1, S...> {};
587 struct gens<0, S...> {
588 typedef seq<S...> type;
591 static errno_t Box(MpObject* tmp, seq<S...>,
const std::tuple<Args...>& p) {
592 return BoxHelper<0>(tmp, std::get<S>(p)...);
595 static errno_t Unbox(
const MpObject* This, seq<S...>, std::tuple<Args...>& p) {
596 return UnboxHelper<0>(This, std::get<S>(p)...);
600 static errno_t Box(MpObject* This,
const std::tuple<Args...>& p) {
601 size_t count = std::tuple_size<std::tuple<Args...> >::value;
603 errno_t e = tmp.InitArray(static_cast<uint32_t>(count));
605 typedef typename gens<
sizeof...(Args)>::type MySeq;
606 e =
Box(&tmp, MySeq(), p);
611 static errno_t Unbox(
const MpObject* This, std::tuple<Args...>* p) {
614 if (
NLIB_UNLIKELY(This->m_Size != std::tuple_size<std::tuple<Args...> >::value))
616 typedef typename gens<
sizeof...(Args)>::type MySeq;
617 return Unbox(This, MySeq(), *p);
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());
631 typename maptype::const_iterator it;
632 typename maptype::const_iterator it_end = m.end();
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);
638 e = kv.second.Box(it->second);
644 static errno_t Unbox(
const MpObject* This, std::map<K, V, Pr, Alloc>* m) {
648 for (uint32_t i = 0; i < This->m_Size; ++i) {
651 const MpObjectKv& kv = (*This->m_Via.mp)[i];
653 e = kv.first.Unbox(&key);
655 e = kv.second.Unbox(&value);
657 NLIB_TRY { (*m)[NLIB_MOVE(key)] = NLIB_MOVE(value); }
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());
674 typename maptype::const_iterator it;
675 typename maptype::const_iterator it_end = m.end();
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);
681 e = kv.second.Box(it->second);
687 static errno_t Unbox(
const MpObject* This, std::unordered_map<K, V, Hash, Pr, Alloc>* m) {
691 for (uint32_t i = 0; i < This->m_Size; ++i) {
694 const MpObjectKv& kv = (*This->m_Via.mp)[i];
696 e = kv.first.Unbox(&key);
698 e = kv.second.Unbox(&value);
700 NLIB_TRY { (*m)[NLIB_MOVE(key)] = NLIB_MOVE(value); }
710 return lhs.first == rhs.first && lhs.second == rhs.second;
713 return !(lhs == rhs);
716 return !(lhs == rhs);
719 template <u
int32_t n>
724 nlib_memcpy(this->GetRaw(), nn, reinterpret_cast<const void*>(&str[0]), nn);
728 template <
class T, u
int32_t n>
733 for (uint32_t i = 0; i < n; ++i) {
734 e = (*tmp.m_Via.ary)[i].
Box(vec[i]);
741 #ifdef NLIB_CXX11_STDLIB_ARRAY
742 template <
class T,
size_t n>
747 for (uint32_t i = 0; i < n; ++i) {
748 e = (*tmp.m_Via.ary)[i].
Box(vec[i]);
758 NLIB_EINVAL_IFNULL(a);
762 for (uint32_t i = 0; i < m_Size; ++i) {
772 NLIB_DEFINE_STD_SWAP(::nlib_ns::msgpack::MpObject)
773 NLIB_DEFINE_STD_SWAP(::
nlib_ns::msgpack::MpObjectKv)
775 #if defined(_MSC_VER) && defined(nx_msgpack_EXPORTS)
776 #undef NLIB_VIS_PUBLIC
777 #define NLIB_VIS_PUBLIC NLIB_WINIMPORT
780 #endif // INCLUDE_NN_NLIB_MSGPACK_MPOBJECT_H_
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
非負整数型を表します。内部表現はuint64_tです。
浮動小数型を表します。内部表現はdoubleです。
uint32_t GetSize() const noexcept
配列や連想配列やRawデータ(文字列)の場合にそのサイズを返します。
bool IsMap() const noexcept
格納されている値が連想配列であるかどうかを調べます。
MpObject & operator[](size_t n)
配列である場合に配列の要素への参照を返します。
MpObjectKv() noexcept
デフォルトコンストラクタです。
#define NLIB_CATCH(x)
例外が有効なときはcatch(x), そうでなければif (true)が定義されます。
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
bool IsArray() const noexcept
格納されている値が配列であるかどうかを調べます。
bool IsBoolean() const noexcept
格納されている値が真偽値であるかどうかを調べます。
~MpObject() noexcept
デストラクタです。
errno_t Unbox(char(&str)[n]) const noexcept
Unbox(T (&a)[n]) を御覧ください。
MpObject * SwapArrayItem(size_t n, MpObject *obj) noexcept
obj の内容と配列内のオブジェクトの内容を交換します。
#define NLIB_TRY
例外が有効なときはtry, そうでなければif (true)が定義されます。
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価ならば、trueを返します。
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価でなければ、trueを返します。
errno_t Box(const T &v)
オブジェクトをボックス化します。
const void * GetRaw() const
GetRaw()と同様です。
MessagePack又はJSONを読み込むことで作成されるオブジェクトです。
bool IsRaw() const noexcept
格納されている値がバイト列(文字列)であるかどうかを調べます。
MpObject & operator=(const T &x)
値をMpObjectに代入します。
MpObject second
値となるオブジェクトです。
std::vectorに似ていますが、コピーできないオブジェクトを格納可能なクラスが定義されています。 ...
ObjectType
MpObjectに格納されているオブジェクトの型情報です。
連想配列を表します。内部ではMpObjectのペアの列として表現されています。
配列を表します。内部ではMpObjectの列として表現されています。
errno_t InitArray(uint32_t n) noexcept
オブジェクトをn 個の要素を持つ配列として初期化します。
errno_t Unbox(const MpObject *obj, T *v)
この関数テンプレートを特殊化してユーザー型のアンボックス化を定義することが可能です。 ...
void swap(MpObject &rhs) noexcept
オブジェクトの中身をスワップします。
bool IsNil() const noexcept
格納されている値ががnilであるかどうかを調べます。
共通して使われる機能やプラットフォームへの依存度が高い機能が実装されます。 nlib Platform APIs も御覧...
MpObject * SwapMapItem(const std::string &key, MpObject *obj) noexcept
obj の内容と連想配列内のオブジェクトの内容を交換します。
MpObject(const T &x)
T型のオブジェクトをボックス化するコンストラクタです。
~MpObjectKv() noexcept
デストラクタです。
bool IsInteger() const noexcept
格納されている値が整数値であるかどうかを調べます。
ObjectType GetType() const noexcept
オブジェクトの型を返します。
std::vectorに似た、コピーコンストラクタを持たないオブジェクトを格納可能なコンテナ類似クラスです。 ...
errno_t Unbox(T v) const
オブジェクトをアンボックス化します。
nlib_i64_t i64
nlib_i64_tがtypedefされています。
bool IsDouble() const noexcept
格納されている値が倍精度浮動小数点型であるかどうかを調べます。
strlen, strcpy等を安全に使えるようにラップしています。
MpObject first
キーとなるオブジェクトです。
MpObject * SwapMapItem(const char *str, MpObject *obj) noexcept
obj の内容と連想配列内のオブジェクトの内容を交換します。
MpObject * GetArrayItem(size_t n) noexcept
インデックスを指定して配列内のオブジェクトを取得します。
MpObject型のキーと値のペアです。連想配列を格納するために利用されます。
bool IsFloat() const noexcept
格納されている値が単精度浮動小数点型であるかどうかを調べます。
MessagePackのnil, 及びJSONのnullに対応するクラスです。
void swap(MpObjectKv &rhs) noexcept
オブジェクトの中身をスワップします。
errno_t Unbox(T(&a)[n]) const
オブジェクトの値をアンボックス化します。
void * GetRaw()
オブジェクトからバイト列を取得します。
errno_t Box(MpObject *obj, const T &v)
この関数テンプレートを特殊化してユーザー型のボックス化を定義することが可能です。
const MpObject * GetArrayItem(size_t n) const noexcept
GetArrayItem(size_t n) と同様です。