278 lines
5.0 KiB
C++
278 lines
5.0 KiB
C++
//
|
|
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
//
|
|
// Official repository: https://github.com/boostorg/json
|
|
//
|
|
|
|
#ifndef BOOST_JSON_DETAIL_VALUE_HPP
|
|
#define BOOST_JSON_DETAIL_VALUE_HPP
|
|
|
|
#include <boost/json/kind.hpp>
|
|
#include <boost/json/storage_ptr.hpp>
|
|
#include <cstdint>
|
|
#include <limits>
|
|
#include <new>
|
|
#include <utility>
|
|
|
|
BOOST_JSON_NS_BEGIN
|
|
namespace detail {
|
|
|
|
struct key_t
|
|
{
|
|
};
|
|
|
|
#if 0
|
|
template<class T>
|
|
struct to_number_limit
|
|
: std::numeric_limits<T>
|
|
{
|
|
};
|
|
|
|
template<class T>
|
|
struct to_number_limit<T const>
|
|
: to_number_limit<T>
|
|
{
|
|
};
|
|
|
|
template<>
|
|
struct to_number_limit<long long>
|
|
{
|
|
static constexpr long long (min)() noexcept
|
|
{
|
|
return -9223372036854774784;
|
|
}
|
|
|
|
static constexpr long long (max)() noexcept
|
|
{
|
|
return 9223372036854774784;
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct to_number_limit<unsigned long long>
|
|
{
|
|
static constexpr
|
|
unsigned long long (min)() noexcept
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static constexpr
|
|
unsigned long long (max)() noexcept
|
|
{
|
|
return 18446744073709549568ULL;
|
|
}
|
|
};
|
|
#else
|
|
|
|
template<class T>
|
|
class to_number_limit
|
|
{
|
|
// unsigned
|
|
|
|
static constexpr
|
|
double min1(std::false_type)
|
|
{
|
|
return 0.0;
|
|
}
|
|
|
|
static constexpr
|
|
double max1(std::false_type)
|
|
{
|
|
return max2u(std::integral_constant<
|
|
bool, (std::numeric_limits<T>::max)() ==
|
|
UINT64_MAX>{});
|
|
}
|
|
|
|
static constexpr
|
|
double max2u(std::false_type)
|
|
{
|
|
return static_cast<double>(
|
|
(std::numeric_limits<T>::max)());
|
|
}
|
|
|
|
static constexpr
|
|
double max2u(std::true_type)
|
|
{
|
|
return 18446744073709549568.0;
|
|
}
|
|
|
|
// signed
|
|
|
|
static constexpr
|
|
double min1(std::true_type)
|
|
{
|
|
return min2s(std::integral_constant<
|
|
bool, (std::numeric_limits<T>::max)() ==
|
|
INT64_MAX>{});
|
|
}
|
|
|
|
static constexpr
|
|
double min2s(std::false_type)
|
|
{
|
|
return static_cast<double>(
|
|
(std::numeric_limits<T>::min)());
|
|
}
|
|
|
|
static constexpr
|
|
double min2s(std::true_type)
|
|
{
|
|
return -9223372036854774784.0;
|
|
}
|
|
|
|
static constexpr
|
|
double max1(std::true_type)
|
|
{
|
|
return max2s(std::integral_constant<
|
|
bool, (std::numeric_limits<T>::max)() ==
|
|
INT64_MAX>{});
|
|
}
|
|
|
|
static constexpr
|
|
double max2s(std::false_type)
|
|
{
|
|
return static_cast<double>(
|
|
(std::numeric_limits<T>::max)());
|
|
}
|
|
|
|
static constexpr
|
|
double max2s(std::true_type)
|
|
{
|
|
return 9223372036854774784.0;
|
|
}
|
|
|
|
public:
|
|
static constexpr
|
|
double (min)() noexcept
|
|
{
|
|
return min1(std::is_signed<T>{});
|
|
}
|
|
|
|
static constexpr
|
|
double (max)() noexcept
|
|
{
|
|
return max1(std::is_signed<T>{});
|
|
}
|
|
};
|
|
|
|
#endif
|
|
|
|
struct scalar
|
|
{
|
|
storage_ptr sp; // must come first
|
|
kind k; // must come second
|
|
union
|
|
{
|
|
bool b;
|
|
std::int64_t i;
|
|
std::uint64_t u;
|
|
double d;
|
|
};
|
|
|
|
explicit
|
|
scalar(storage_ptr sp_ = {}) noexcept
|
|
: sp(std::move(sp_))
|
|
, k(json::kind::null)
|
|
{
|
|
}
|
|
|
|
explicit
|
|
scalar(bool b_,
|
|
storage_ptr sp_ = {}) noexcept
|
|
: sp(std::move(sp_))
|
|
, k(json::kind::bool_)
|
|
, b(b_)
|
|
{
|
|
}
|
|
|
|
explicit
|
|
scalar(std::int64_t i_,
|
|
storage_ptr sp_ = {}) noexcept
|
|
: sp(std::move(sp_))
|
|
, k(json::kind::int64)
|
|
, i(i_)
|
|
{
|
|
}
|
|
|
|
explicit
|
|
scalar(std::uint64_t u_,
|
|
storage_ptr sp_ = {}) noexcept
|
|
: sp(std::move(sp_))
|
|
, k(json::kind::uint64)
|
|
, u(u_)
|
|
{
|
|
}
|
|
|
|
explicit
|
|
scalar(double d_,
|
|
storage_ptr sp_ = {}) noexcept
|
|
: sp(std::move(sp_))
|
|
, k(json::kind::double_)
|
|
, d(d_)
|
|
{
|
|
}
|
|
};
|
|
|
|
struct access
|
|
{
|
|
template<class Value, class... Args>
|
|
static
|
|
Value&
|
|
construct_value(Value* p, Args&&... args)
|
|
{
|
|
return *reinterpret_cast<
|
|
Value*>(::new(p) Value(
|
|
std::forward<Args>(args)...));
|
|
}
|
|
|
|
template<class KeyValuePair, class... Args>
|
|
static
|
|
KeyValuePair&
|
|
construct_key_value_pair(
|
|
KeyValuePair* p, Args&&... args)
|
|
{
|
|
return *reinterpret_cast<
|
|
KeyValuePair*>(::new(p)
|
|
KeyValuePair(
|
|
std::forward<Args>(args)...));
|
|
}
|
|
|
|
template<class Value>
|
|
static
|
|
char const*
|
|
release_key(
|
|
Value& jv,
|
|
std::size_t& len) noexcept
|
|
{
|
|
BOOST_ASSERT(jv.is_string());
|
|
jv.str_.sp_.~storage_ptr();
|
|
return jv.str_.impl_.release_key(len);
|
|
}
|
|
|
|
using index_t = std::uint32_t;
|
|
|
|
template<class KeyValuePair>
|
|
static
|
|
index_t&
|
|
next(KeyValuePair& e) noexcept
|
|
{
|
|
return e.next_;
|
|
}
|
|
|
|
template<class KeyValuePair>
|
|
static
|
|
index_t const&
|
|
next(KeyValuePair const& e) noexcept
|
|
{
|
|
return e.next_;
|
|
}
|
|
};
|
|
|
|
} // detail
|
|
BOOST_JSON_NS_END
|
|
|
|
#endif
|