1//
2// MessagePack for C++ static resolution routine
3//
4// Copyright (C) 2008-2014 FURUHASHI Sadayuki and KONDO Takatoshi
5//
6//    Distributed under the Boost Software License, Version 1.0.
7//    (See accompanying file LICENSE_1_0.txt or copy at
8//    http://www.boost.org/LICENSE_1_0.txt)
9//
10
11#ifndef MSGPACK_OBJECT_FWD_HPP
12#define MSGPACK_OBJECT_FWD_HPP
13
14#include "msgpack/versioning.hpp"
15#include "msgpack/zone.hpp"
16#include "msgpack/object.h"
17
18#include <typeinfo>
19
20namespace msgpack {
21
22/// @cond
23MSGPACK_API_VERSION_NAMESPACE(v1) {
24/// @endcond
25
26
27namespace type {
28    enum object_type {
29        NIL                 = MSGPACK_OBJECT_NIL,
30        BOOLEAN             = MSGPACK_OBJECT_BOOLEAN,
31        POSITIVE_INTEGER    = MSGPACK_OBJECT_POSITIVE_INTEGER,
32        NEGATIVE_INTEGER    = MSGPACK_OBJECT_NEGATIVE_INTEGER,
33        FLOAT               = MSGPACK_OBJECT_FLOAT,
34#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
35        DOUBLE              = MSGPACK_OBJECT_DOUBLE, // obsolete
36#endif // MSGPACK_USE_LEGACY_NAME_AS_FLOAT
37        STR                 = MSGPACK_OBJECT_STR,
38        BIN                 = MSGPACK_OBJECT_BIN,
39        ARRAY               = MSGPACK_OBJECT_ARRAY,
40        MAP                 = MSGPACK_OBJECT_MAP,
41        EXT                 = MSGPACK_OBJECT_EXT
42    };
43}
44
45
46struct object;
47struct object_kv;
48
49struct object_array {
50    uint32_t size;
51    msgpack::object* ptr;
52};
53
54struct object_map {
55    uint32_t size;
56    msgpack::object_kv* ptr;
57};
58
59struct object_str {
60    uint32_t size;
61    const char* ptr;
62};
63
64struct object_bin {
65    uint32_t size;
66    const char* ptr;
67};
68
69struct object_ext {
70    int8_t type() const { return ptr[0]; }
71    const char* data() const { return &ptr[1]; }
72    uint32_t size;
73    const char* ptr;
74};
75
76
77#if !defined(MSGPACK_USE_CPP03)
78struct object;
79
80namespace adaptor {
81template <typename T, typename Enabler = void>
82struct as;
83} // namespace adaptor
84
85template <typename T>
86struct has_as {
87private:
88    template <typename U>
89    static auto check(U*) ->
90        typename std::is_same<
91            decltype(msgpack::adaptor::as<U>()(std::declval<msgpack::object>())),
92            T>::type;
93    template <typename>
94    static std::false_type check(...);
95public:
96    using type = decltype(check<T>(nullptr));
97    static constexpr bool value = type::value;
98};
99
100#endif // !defined(MSGPACK_USE_CPP03)
101
102/// Object class that corresponding to MessagePack format object
103/**
104 * See https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_object
105 */
106struct object {
107    union union_type {
108        bool boolean;
109        uint64_t u64;
110        int64_t  i64;
111#if defined(MSGPACK_USE_LEGACY_NAME_AS_FLOAT)
112        double   dec; // obsolete
113#endif // MSGPACK_USE_LEGACY_NAME_AS_FLOAT
114        double   f64;
115        msgpack::object_array array;
116        msgpack::object_map map;
117        msgpack::object_str str;
118        msgpack::object_bin bin;
119        msgpack::object_ext ext;
120    };
121
122    msgpack::type::object_type type;
123    union_type via;
124
125    /// Cheking nil
126    /**
127     * @return If the object is nil, then return true, else return false.
128     */
129    bool is_nil() const { return type == msgpack::type::NIL; }
130
131#if defined(MSGPACK_USE_CPP03)
132
133    /// Get value as T
134    /**
135     * If the object can't be converted to T, msgpack::type_error would be thrown.
136     * @tparam T The type you want to get.
137     * @return The converted object.
138     */
139    template <typename T>
140    T as() const;
141
142#else  // defined(MSGPACK_USE_CPP03)
143
144    /// Get value as T
145    /**
146     * If the object can't be converted to T, msgpack::type_error would be thrown.
147     * @tparam T The type you want to get.
148     * @return The converted object.
149     */
150    template <typename T>
151    typename std::enable_if<msgpack::has_as<T>::value, T>::type as() const;
152
153    /// Get value as T
154    /**
155     * If the object can't be converted to T, msgpack::type_error would be thrown.
156     * @tparam T The type you want to get.
157     * @return The converted object.
158     */
159    template <typename T>
160    typename std::enable_if<!msgpack::has_as<T>::value, T>::type as() const;
161
162#endif // defined(MSGPACK_USE_CPP03)
163
164    /// Convert the object
165    /**
166     * If the object can't be converted to T, msgpack::type_error would be thrown.
167     * @tparam T The type of v.
168     * @param v The value you want to get. `v` is output parameter. `v` is overwritten by converted value from the object.
169     * @return The reference of `v`.
170     */
171    template <typename T>
172    T& convert(T& v) const;
173
174
175#if !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
176    /// Convert the object (obsolete)
177    /**
178     * If the object can't be converted to T, msgpack::type_error would be thrown.
179     * @tparam T The type of v.
180     * @param v The pointer of the value you want to get. `v` is output parameter. `*v` is overwritten by converted value from the object.
181     * @return The pointer of `v`.
182     */
183    template <typename T>
184    T* convert(T* v) const;
185#endif // !defined(MSGPACK_DISABLE_LEGACY_CONVERT)
186
187    /// Convert the object if not nil
188    /**
189     * If the object is not nil and can't be converted to T, msgpack::type_error would be thrown.
190     * @tparam T The type of v.
191     * @param v The value you want to get. `v` is output parameter. `v` is overwritten by converted value from the object if the object is not nil.
192     * @return If the object is nil, then return false, else return true.
193     */
194    template <typename T>
195    bool convert_if_not_nil(T& v) const;
196
197    /// Default constructor. The object is set to nil.
198    object();
199
200    /// Copy constructor. Object is shallow copied.
201    object(const msgpack_object& o);
202
203    /// Construct object from T
204    /**
205     * If `v` is the type that is corresponding to MessegePack format str, bin, ext, array, or map,
206     * you need to call `object(const T& v, msgpack::zone& z)` instead of this constructor.
207     *
208     * @tparam T The type of `v`.
209     * @param v The value you want to convert.
210     */
211    template <typename T>
212    explicit object(const T& v);
213
214    /// Construct object from T
215    /**
216     * The object is constructed on the zone `z`.
217     * See https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_object
218     *
219     * @tparam T The type of `v`.
220     * @param v The value you want to convert.
221     * @param z The zone that is used by the object.
222     */
223    template <typename T>
224    object(const T& v, msgpack::zone& z);
225
226    /// Construct object from T (obsolete)
227    /**
228     * The object is constructed on the zone `z`.
229     * Use `object(const T& v, msgpack::zone& z)` instead of this constructor.
230     * See https://github.com/msgpack/msgpack-c/wiki/v1_1_cpp_object
231     *
232     * @tparam T The type of `v`.
233     * @param v The value you want to convert.
234     * @param z The pointer to the zone that is used by the object.
235     */
236    template <typename T>
237    object(const T& v, msgpack::zone* z);
238
239    template <typename T>
240    object& operator=(const T& v);
241
242    operator msgpack_object() const;
243
244    struct with_zone;
245
246private:
247    struct implicit_type;
248
249public:
250    implicit_type convert() const;
251};
252
253class type_error : public std::bad_cast { };
254
255struct object_kv {
256    msgpack::object key;
257    msgpack::object val;
258};
259
260struct object::with_zone : object {
261    with_zone(msgpack::zone& z) : zone(z) { }
262    msgpack::zone& zone;
263private:
264    with_zone();
265};
266
267/// @cond
268} // MSGPACK_API_VERSION_NAMESPACE(v1)
269/// @endcond
270
271} // namespace msgpack
272
273#endif // MSGPACK_OBJECT_FWD_HPP
274