♻️ add proper SFINAE for 64 bit check

This commit is contained in:
Niels Lohmann 2020-07-09 21:31:01 +02:00
parent 0c4e6aa2cd
commit 612f326052
No known key found for this signature in database
GPG Key ID: 7F3CEA63AE251B69
2 changed files with 150 additions and 46 deletions

View File

@ -918,20 +918,72 @@ class lexer : public lexer_base<BasicJsonType>
f = std::strtold(str, endptr);
}
template < detail::enable_if_t<sizeof(number_unsigned_t) <= 64, int> = 0>
JSON_HEDLEY_NON_NULL(2)
auto strtoull(const char* str, char** str_end) -> decltype(std::strtoull(str, str_end, 10))
template<typename NumberType>
struct is_64_bit : std::integral_constant < bool, (sizeof(NumberType) <= 8) >
{};
JSON_HEDLEY_NON_NULL(2)
unsigned long long strtoull(const char* str, char** str_end, std::true_type)
{
return std::strtoull(str, str_end, 10);
}
template < detail::enable_if_t<sizeof(number_integer_t) <= 64, int> = 0>
JSON_HEDLEY_NON_NULL(2)
auto strtoll(const char* str, char** str_end) -> decltype(std::strtoll(str, str_end, 10))
JSON_HEDLEY_NON_NULL(2)
number_unsigned_t strtoull(const char* str, char** str_end, std::false_type)
{
number_unsigned_t val = 0;
const char* p = str;
while (*p >= '0' and * p <= '9')
{
val = (10 * val) + (*p - '0');
p++;
}
if (str_end != nullptr)
{
*str_end = (char*)p;
}
return val;
}
JSON_HEDLEY_NON_NULL(2)
long long strtoll(const char* str, char** str_end, std::true_type)
{
return std::strtoll(str, str_end, 10);
}
JSON_HEDLEY_NON_NULL(2)
number_integer_t strtoll(const char* str, char** str_end, std::false_type)
{
number_integer_t val = 0;
const char* p = str;
if (*p == '-')
{
p++;
}
while (*p >= '0' and * p <= '9')
{
val = (10 * val) + (*p - '0');
p++;
}
if (*str == '-')
{
val = val * -1;
}
if (str_end != nullptr)
{
*str_end = (char*)p;
}
return val;
}
/*!
@brief scan a number literal
@ -1256,7 +1308,7 @@ scan_number_done:
// try to parse integers first and fall back to floats
if (number_type == token_type::value_unsigned)
{
const auto x = strtoull(token_buffer.data(), &endptr);
const auto x = strtoull(token_buffer.data(), &endptr, is_64_bit<number_unsigned_t>());
// we checked the number format before
assert(endptr == token_buffer.data() + token_buffer.size());
@ -1272,7 +1324,7 @@ scan_number_done:
}
else if (number_type == token_type::value_integer)
{
const auto x = strtoll(token_buffer.data(), &endptr);
const auto x = strtoll(token_buffer.data(), &endptr, is_64_bit<number_integer_t>());
// we checked the number format before
assert(endptr == token_buffer.data() + token_buffer.size());

View File

@ -9030,20 +9030,72 @@ class lexer : public lexer_base<BasicJsonType>
f = std::strtold(str, endptr);
}
template < detail::enable_if_t<sizeof(number_unsigned_t) <= 64, int> = 0>
JSON_HEDLEY_NON_NULL(2)
auto strtoull(const char* str, char** str_end) -> decltype(std::strtoull(str, str_end, 10))
template<typename NumberType>
struct is_64_bit : std::integral_constant < bool, (sizeof(NumberType) <= 8) >
{};
JSON_HEDLEY_NON_NULL(2)
unsigned long long strtoull(const char* str, char** str_end, std::true_type)
{
return std::strtoull(str, str_end, 10);
}
template < detail::enable_if_t<sizeof(number_integer_t) <= 64, int> = 0>
JSON_HEDLEY_NON_NULL(2)
auto strtoll(const char* str, char** str_end) -> decltype(std::strtoll(str, str_end, 10))
JSON_HEDLEY_NON_NULL(2)
number_unsigned_t strtoull(const char* str, char** str_end, std::false_type)
{
number_unsigned_t val = 0;
const char* p = str;
while (*p >= '0' and * p <= '9')
{
val = (10 * val) + (*p - '0');
p++;
}
if (str_end != nullptr)
{
*str_end = (char*)p;
}
return val;
}
JSON_HEDLEY_NON_NULL(2)
long long strtoll(const char* str, char** str_end, std::true_type)
{
return std::strtoll(str, str_end, 10);
}
JSON_HEDLEY_NON_NULL(2)
number_integer_t strtoll(const char* str, char** str_end, std::false_type)
{
number_integer_t val = 0;
const char* p = str;
if (*p == '-')
{
p++;
}
while (*p >= '0' and * p <= '9')
{
val = (10 * val) + (*p - '0');
p++;
}
if (*str == '-')
{
val = val * -1;
}
if (str_end != nullptr)
{
*str_end = (char*)p;
}
return val;
}
/*!
@brief scan a number literal
@ -9368,7 +9420,7 @@ scan_number_done:
// try to parse integers first and fall back to floats
if (number_type == token_type::value_unsigned)
{
const auto x = strtoull(token_buffer.data(), &endptr);
const auto x = strtoull(token_buffer.data(), &endptr, is_64_bit<number_unsigned_t>());
// we checked the number format before
assert(endptr == token_buffer.data() + token_buffer.size());
@ -9384,7 +9436,7 @@ scan_number_done:
}
else if (number_type == token_type::value_integer)
{
const auto x = strtoll(token_buffer.data(), &endptr);
const auto x = strtoll(token_buffer.data(), &endptr, is_64_bit<number_integer_t>());
// we checked the number format before
assert(endptr == token_buffer.data() + token_buffer.size());
@ -9800,7 +9852,7 @@ enum class parse_event_t : uint8_t
template<typename BasicJsonType>
using parser_callback_t =
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
std::function<bool(int depth, parse_event_t event, BasicJsonType& parsed)>;
/*!
@brief syntax analysis
@ -9817,7 +9869,7 @@ class parser
using lexer_t = lexer<BasicJsonType, InputAdapterType>;
using token_type = typename lexer_t::token_type;
public:
public:
/// a parser reading from an input adapter
explicit parser(InputAdapterType&& adapter,
const parser_callback_t<BasicJsonType> cb = nullptr,
@ -9927,7 +9979,7 @@ public:
return result;
}
private:
private:
template <typename SAX>
JSON_HEDLEY_NON_NULL(2)
bool sax_parse_internal(SAX* sax)
@ -10246,7 +10298,7 @@ private:
return error_msg;
}
private:
private:
/// callback function
const parser_callback_t<BasicJsonType> callback = nullptr;
/// the type of the last read token
@ -10469,7 +10521,7 @@ class iter_impl
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
"iter_impl only accepts (const) basic_json");
public:
public:
/// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
/// The C++ Standard has never required user-defined iterators to derive from std::iterator.
@ -10582,7 +10634,7 @@ public:
return *this;
}
private:
private:
/*!
@brief set the iterator to the first value
@pre The iterator is initialized; i.e. `m_object != nullptr`.
@ -10650,7 +10702,7 @@ private:
}
}
public:
public:
/*!
@brief return a reference to the value pointed to by the iterator
@pre The iterator is initialized; i.e. `m_object != nullptr`.
@ -11046,7 +11098,7 @@ public:
return operator*();
}
private:
private:
/// associated JSON instance
pointer m_object = nullptr;
/// the actual iterator of the associated instance
@ -11093,7 +11145,7 @@ create @ref const_reverse_iterator).
template<typename Base>
class json_reverse_iterator : public std::reverse_iterator<Base>
{
public:
public:
using difference_type = std::ptrdiff_t;
/// shortcut to the reverse iterator adapter
using base_iterator = std::reverse_iterator<Base>;
@ -11208,7 +11260,7 @@ class json_pointer
NLOHMANN_BASIC_JSON_TPL_DECLARATION
friend class basic_json;
public:
public:
/*!
@brief create JSON pointer
@ -11506,7 +11558,7 @@ public:
return reference_tokens.empty();
}
private:
private:
/*!
@param[in] s reference token to be converted into an array index
@ -12177,7 +12229,7 @@ namespace detail
template<typename BasicJsonType>
class json_ref
{
public:
public:
using value_type = BasicJsonType;
json_ref(value_type&& value)
@ -12232,7 +12284,7 @@ public:
return static_cast<value_type const*>(value_ref);
}
private:
private:
mutable value_type owned_value = nullptr;
value_type* value_ref = nullptr;
const bool is_rvalue = true;
@ -12295,7 +12347,7 @@ using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
template<typename CharType>
class output_vector_adapter : public output_adapter_protocol<CharType>
{
public:
public:
explicit output_vector_adapter(std::vector<CharType>& vec) noexcept
: v(vec)
{}
@ -12311,7 +12363,7 @@ public:
std::copy(s, s + length, std::back_inserter(v));
}
private:
private:
std::vector<CharType>& v;
};
@ -12319,7 +12371,7 @@ private:
template<typename CharType>
class output_stream_adapter : public output_adapter_protocol<CharType>
{
public:
public:
explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
: stream(s)
{}
@ -12335,7 +12387,7 @@ public:
stream.write(s, static_cast<std::streamsize>(length));
}
private:
private:
std::basic_ostream<CharType>& stream;
};
@ -12343,7 +12395,7 @@ private:
template<typename CharType, typename StringType = std::basic_string<CharType>>
class output_string_adapter : public output_adapter_protocol<CharType>
{
public:
public:
explicit output_string_adapter(StringType& s) noexcept
: str(s)
{}
@ -12359,14 +12411,14 @@ public:
str.append(s, length);
}
private:
private:
StringType& str;
};
template<typename CharType, typename StringType = std::basic_string<CharType>>
class output_adapter
{
public:
public:
output_adapter(std::vector<CharType>& vec)
: oa(std::make_shared<output_vector_adapter<CharType>>(vec)) {}
@ -12381,7 +12433,7 @@ public:
return oa;
}
private:
private:
output_adapter_t<CharType> oa = nullptr;
};
} // namespace detail
@ -12406,7 +12458,7 @@ class binary_writer
using binary_t = typename BasicJsonType::binary_t;
using number_float_t = typename BasicJsonType::number_float_t;
public:
public:
/*!
@brief create a binary writer
@ -13262,7 +13314,7 @@ public:
}
}
private:
private:
//////////
// BSON //
//////////
@ -13891,7 +13943,7 @@ private:
}
}
public:
public:
// The following to_char_type functions are implement the conversion
// between uint8_t and CharType. In case CharType is not unsigned,
// such a conversion is required to allow values greater than 128.
@ -13932,7 +13984,7 @@ public:
return x;
}
private:
private:
/// whether we can assume little endianess
const bool is_little_endian = little_endianess();
@ -15113,7 +15165,7 @@ class serializer
static constexpr std::uint8_t UTF8_ACCEPT = 0;
static constexpr std::uint8_t UTF8_REJECT = 1;
public:
public:
/*!
@param[in] s output stream to serialize to
@param[in] ichar indentation character to use
@ -15428,7 +15480,7 @@ public:
}
}
private:
private:
/*!
@brief dump escaped string
@ -15984,7 +16036,7 @@ private:
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
}
private:
private:
/// the output of the serializer
output_adapter_t<char> o = nullptr;
@ -16142,7 +16194,7 @@ class basic_json
detail::parser_callback_t<basic_json>cb = nullptr,
const bool allow_exceptions = true,
const bool ignore_comments = false
)
)
{
return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
std::move(cb), allow_exceptions, ignore_comments);
@ -24678,7 +24730,7 @@ template<>
inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
is_nothrow_move_constructible<nlohmann::json>::value and
is_nothrow_move_assignable<nlohmann::json>::value
)
)
{
j1.swap(j2);
}