1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
//
3  
//
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6  
//
6  
//
7  
// Official repository: https://github.com/boostorg/json
7  
// Official repository: https://github.com/boostorg/json
8  
//
8  
//
9  

9  

10  
#ifndef BOOST_JSON_DETAIL_VALUE_HPP
10  
#ifndef BOOST_JSON_DETAIL_VALUE_HPP
11  
#define BOOST_JSON_DETAIL_VALUE_HPP
11  
#define BOOST_JSON_DETAIL_VALUE_HPP
12  

12  

13  
#include <boost/json/fwd.hpp>
13  
#include <boost/json/fwd.hpp>
14  
#include <boost/json/kind.hpp>
14  
#include <boost/json/kind.hpp>
15  
#include <boost/json/storage_ptr.hpp>
15  
#include <boost/json/storage_ptr.hpp>
16  
#include <cstdint>
16  
#include <cstdint>
17  
#include <limits>
17  
#include <limits>
18  
#include <new>
18  
#include <new>
19  
#include <utility>
19  
#include <utility>
20  

20  

21  
namespace boost {
21  
namespace boost {
22  
namespace json {
22  
namespace json {
23  
namespace detail {
23  
namespace detail {
24  

24  

25  
struct key_t
25  
struct key_t
26  
{
26  
{
27  
};
27  
};
28  

28  

29  
#if 0
29  
#if 0
30  
template<class T>
30  
template<class T>
31  
struct to_number_limit
31  
struct to_number_limit
32  
    : std::numeric_limits<T>
32  
    : std::numeric_limits<T>
33  
{
33  
{
34  
};
34  
};
35  

35  

36  
template<class T>
36  
template<class T>
37  
struct to_number_limit<T const>
37  
struct to_number_limit<T const>
38  
    : to_number_limit<T>
38  
    : to_number_limit<T>
39  
{
39  
{
40  
};
40  
};
41  

41  

42  
template<>
42  
template<>
43  
struct to_number_limit<long long>
43  
struct to_number_limit<long long>
44  
{
44  
{
45  
    static constexpr long long (min)() noexcept
45  
    static constexpr long long (min)() noexcept
46  
    {
46  
    {
47  
        return -9223372036854774784;
47  
        return -9223372036854774784;
48  
    }
48  
    }
49  

49  

50  
    static constexpr long long (max)() noexcept
50  
    static constexpr long long (max)() noexcept
51  
    {
51  
    {
52  
        return 9223372036854774784;
52  
        return 9223372036854774784;
53  
    }
53  
    }
54  
};
54  
};
55  

55  

56  
template<>
56  
template<>
57  
struct to_number_limit<unsigned long long>
57  
struct to_number_limit<unsigned long long>
58  
{
58  
{
59  
    static constexpr
59  
    static constexpr
60  
    unsigned long long (min)() noexcept
60  
    unsigned long long (min)() noexcept
61  
    {
61  
    {
62  
        return 0;
62  
        return 0;
63  
    }
63  
    }
64  

64  

65  
    static constexpr
65  
    static constexpr
66  
    unsigned long long (max)() noexcept
66  
    unsigned long long (max)() noexcept
67  
    {
67  
    {
68  
        return 18446744073709549568ULL;
68  
        return 18446744073709549568ULL;
69  
    }
69  
    }
70  
};
70  
};
71  
#else
71  
#else
72  

72  

73  
template<class T>
73  
template<class T>
74  
class to_number_limit
74  
class to_number_limit
75  
{
75  
{
76  
    // unsigned
76  
    // unsigned
77  

77  

78  
    static constexpr
78  
    static constexpr
79  
    double min1(std::false_type)
79  
    double min1(std::false_type)
80  
    {
80  
    {
81  
        return 0.0;
81  
        return 0.0;
82  
    }
82  
    }
83  

83  

84  
    static constexpr
84  
    static constexpr
85  
    double max1(std::false_type)
85  
    double max1(std::false_type)
86  
    {
86  
    {
87  
        return max2u(std::integral_constant<
87  
        return max2u(std::integral_constant<
88  
            bool, (std::numeric_limits<T>::max)() ==
88  
            bool, (std::numeric_limits<T>::max)() ==
89  
            UINT64_MAX>{});
89  
            UINT64_MAX>{});
90  
    }
90  
    }
91  

91  

92  
    static constexpr
92  
    static constexpr
93  
    double max2u(std::false_type)
93  
    double max2u(std::false_type)
94  
    {
94  
    {
95  
        return static_cast<double>(
95  
        return static_cast<double>(
96  
            (std::numeric_limits<T>::max)());
96  
            (std::numeric_limits<T>::max)());
97  
    }
97  
    }
98  

98  

99  
    static constexpr
99  
    static constexpr
100  
    double max2u(std::true_type)
100  
    double max2u(std::true_type)
101  
    {
101  
    {
102  
        return 18446744073709549568.0;
102  
        return 18446744073709549568.0;
103  
    }
103  
    }
104  

104  

105  
    // signed
105  
    // signed
106  

106  

107  
    static constexpr
107  
    static constexpr
108  
    double min1(std::true_type)
108  
    double min1(std::true_type)
109  
    {
109  
    {
110  
        return min2s(std::integral_constant<
110  
        return min2s(std::integral_constant<
111  
            bool, (std::numeric_limits<T>::max)() ==
111  
            bool, (std::numeric_limits<T>::max)() ==
112  
            INT64_MAX>{});
112  
            INT64_MAX>{});
113  
    }
113  
    }
114  

114  

115  
    static constexpr
115  
    static constexpr
116  
    double min2s(std::false_type)
116  
    double min2s(std::false_type)
117  
    {
117  
    {
118  
        return static_cast<double>(
118  
        return static_cast<double>(
119  
            (std::numeric_limits<T>::min)());
119  
            (std::numeric_limits<T>::min)());
120  
    }
120  
    }
121  

121  

122  
    static constexpr
122  
    static constexpr
123  
    double min2s(std::true_type)
123  
    double min2s(std::true_type)
124  
    {
124  
    {
125  
        return -9223372036854774784.0;
125  
        return -9223372036854774784.0;
126  
    }
126  
    }
127  

127  

128  
    static constexpr
128  
    static constexpr
129  
    double max1(std::true_type)
129  
    double max1(std::true_type)
130  
    {
130  
    {
131  
        return max2s(std::integral_constant<
131  
        return max2s(std::integral_constant<
132  
            bool, (std::numeric_limits<T>::max)() ==
132  
            bool, (std::numeric_limits<T>::max)() ==
133  
            INT64_MAX>{});
133  
            INT64_MAX>{});
134  
    }
134  
    }
135  

135  

136  
    static constexpr
136  
    static constexpr
137  
    double max2s(std::false_type)
137  
    double max2s(std::false_type)
138  
    {
138  
    {
139  
        return static_cast<double>(
139  
        return static_cast<double>(
140  
            (std::numeric_limits<T>::max)());
140  
            (std::numeric_limits<T>::max)());
141  
    }
141  
    }
142  

142  

143  
    static constexpr
143  
    static constexpr
144  
    double max2s(std::true_type)
144  
    double max2s(std::true_type)
145  
    {
145  
    {
146  
        return 9223372036854774784.0;
146  
        return 9223372036854774784.0;
147  
    }
147  
    }
148  

148  

149  
public:
149  
public:
150  
    static constexpr
150  
    static constexpr
151  
    double (min)() noexcept
151  
    double (min)() noexcept
152  
    {
152  
    {
153  
        return min1(std::is_signed<T>{});
153  
        return min1(std::is_signed<T>{});
154  
    }
154  
    }
155  

155  

156  
    static constexpr
156  
    static constexpr
157  
    double (max)() noexcept
157  
    double (max)() noexcept
158  
    {
158  
    {
159  
        return max1(std::is_signed<T>{});
159  
        return max1(std::is_signed<T>{});
160  
    }
160  
    }
161  
};
161  
};
162  

162  

163  
#endif
163  
#endif
164  

164  

165  
struct scalar
165  
struct scalar
166  
{
166  
{
167  
    storage_ptr sp; // must come first
167  
    storage_ptr sp; // must come first
168  
    kind k;         // must come second
168  
    kind k;         // must come second
169  
    union
169  
    union
170  
    {
170  
    {
 
171 +
        std::nullptr_t n;
171  
        bool b;
172  
        bool b;
172  
        std::int64_t i;
173  
        std::int64_t i;
173  
        std::uint64_t u;
174  
        std::uint64_t u;
174  
        double d;
175  
        double d;
175  
    };
176  
    };
176  

177  

177  
    explicit
178  
    explicit
178  
    scalar(storage_ptr sp_ = {}) noexcept
179  
    scalar(storage_ptr sp_ = {}) noexcept
179  
        : sp(std::move(sp_))
180  
        : sp(std::move(sp_))
180  
        , k(json::kind::null)
181  
        , k(json::kind::null)
 
182 +
        , n()
181  
    {
183  
    {
182  
    }
184  
    }
183  

185  

184  
    explicit
186  
    explicit
185  
    scalar(bool b_,
187  
    scalar(bool b_,
186  
        storage_ptr sp_ = {}) noexcept
188  
        storage_ptr sp_ = {}) noexcept
187  
        : sp(std::move(sp_))
189  
        : sp(std::move(sp_))
188  
        , k(json::kind::bool_)
190  
        , k(json::kind::bool_)
189  
        , b(b_)
191  
        , b(b_)
190  
    {
192  
    {
191  
    }
193  
    }
192  

194  

193  
    explicit
195  
    explicit
194  
    scalar(std::int64_t i_,
196  
    scalar(std::int64_t i_,
195  
        storage_ptr sp_ = {}) noexcept
197  
        storage_ptr sp_ = {}) noexcept
196  
        : sp(std::move(sp_))
198  
        : sp(std::move(sp_))
197  
        , k(json::kind::int64)
199  
        , k(json::kind::int64)
198  
        , i(i_)
200  
        , i(i_)
199  
    {
201  
    {
200  
    }
202  
    }
201  

203  

202  
    explicit
204  
    explicit
203  
    scalar(std::uint64_t u_,
205  
    scalar(std::uint64_t u_,
204  
        storage_ptr sp_ = {}) noexcept
206  
        storage_ptr sp_ = {}) noexcept
205  
        : sp(std::move(sp_))
207  
        : sp(std::move(sp_))
206  
        , k(json::kind::uint64)
208  
        , k(json::kind::uint64)
207  
        , u(u_)
209  
        , u(u_)
208  
    {
210  
    {
209  
    }
211  
    }
210  

212  

211  
    explicit
213  
    explicit
212  
    scalar(double d_,
214  
    scalar(double d_,
213  
        storage_ptr sp_ = {}) noexcept
215  
        storage_ptr sp_ = {}) noexcept
214  
        : sp(std::move(sp_))
216  
        : sp(std::move(sp_))
215  
        , k(json::kind::double_)
217  
        , k(json::kind::double_)
216  
        , d(d_)
218  
        , d(d_)
217  
    {
219  
    {
218  
    }
220  
    }
219  
};
221  
};
220  

222  

221  
struct access
223  
struct access
222  
{
224  
{
223  
    template<class Value, class... Args>
225  
    template<class Value, class... Args>
224  
    static
226  
    static
225  
    Value&
227  
    Value&
226  
    construct_value(Value* p, Args&&... args)
228  
    construct_value(Value* p, Args&&... args)
227  
    {
229  
    {
228  
        return *reinterpret_cast<
230  
        return *reinterpret_cast<
229  
            Value*>(::new(p) Value(
231  
            Value*>(::new(p) Value(
230  
            std::forward<Args>(args)...));
232  
            std::forward<Args>(args)...));
231  
    }
233  
    }
232  

234  

233  
    template<class KeyValuePair, class... Args>
235  
    template<class KeyValuePair, class... Args>
234  
    static
236  
    static
235  
    KeyValuePair&
237  
    KeyValuePair&
236  
    construct_key_value_pair(
238  
    construct_key_value_pair(
237  
        KeyValuePair* p, Args&&... args)
239  
        KeyValuePair* p, Args&&... args)
238  
    {
240  
    {
239  
        return *reinterpret_cast<
241  
        return *reinterpret_cast<
240  
            KeyValuePair*>(::new(p)
242  
            KeyValuePair*>(::new(p)
241  
                KeyValuePair(
243  
                KeyValuePair(
242  
                    std::forward<Args>(args)...));
244  
                    std::forward<Args>(args)...));
243  
    }
245  
    }
244  

246  

245  
    template<class Value>
247  
    template<class Value>
246  
    static
248  
    static
247  
    char const*
249  
    char const*
248  
    release_key(
250  
    release_key(
249  
        Value& jv,
251  
        Value& jv,
250  
        std::size_t& len) noexcept
252  
        std::size_t& len) noexcept
251  
    {
253  
    {
252  
        BOOST_ASSERT(jv.is_string());
254  
        BOOST_ASSERT(jv.is_string());
253  
        jv.str_.sp_.~storage_ptr();
255  
        jv.str_.sp_.~storage_ptr();
254  
        return jv.str_.impl_.release_key(len);
256  
        return jv.str_.impl_.release_key(len);
255  
    }
257  
    }
256  

258  

257  
    using index_t = std::uint32_t;
259  
    using index_t = std::uint32_t;
258  

260  

259  
    template<class KeyValuePair>
261  
    template<class KeyValuePair>
260  
    static
262  
    static
261  
    index_t&
263  
    index_t&
262  
    next(KeyValuePair& e) noexcept
264  
    next(KeyValuePair& e) noexcept
263  
    {
265  
    {
264  
        return e.next_;
266  
        return e.next_;
265  
    }
267  
    }
266  

268  

267  
    template<class KeyValuePair>
269  
    template<class KeyValuePair>
268  
    static
270  
    static
269  
    index_t const&
271  
    index_t const&
270  
    next(KeyValuePair const& e) noexcept
272  
    next(KeyValuePair const& e) noexcept
271  
    {
273  
    {
272  
        return e.next_;
274  
        return e.next_;
 
275 +
    }
 
276 +

 
277 +
    template<class Value>
 
278 +
    static
 
279 +
    auto
 
280 +
    get_scalar(Value& jv) -> scalar&
 
281 +
    {
 
282 +
        return jv.sca_;
 
283 +
    }
 
284 +

 
285 +
    template<class Value>
 
286 +
    static
 
287 +
    auto
 
288 +
    get_scalar(Value const& jv) -> scalar const&
 
289 +
    {
 
290 +
        return jv.sca_;
273  
    }
291  
    }
274  
};
292  
};
275  

293  

276  
BOOST_JSON_DECL
294  
BOOST_JSON_DECL
277  
std::size_t
295  
std::size_t
278  
hash_value_impl( value const& jv ) noexcept;
296  
hash_value_impl( value const& jv ) noexcept;
279  

297  

280  
} // detail
298  
} // detail
281  
} // namespace json
299  
} // namespace json
282  
} // namespace boost
300  
} // namespace boost
283  

301  

284  
#endif
302  
#endif