Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c13ecd5344 | ||
|
0f1f5052bf | ||
|
e3aace6dac | ||
|
039c97694d | ||
|
23496a3abf | ||
|
bffa18b46e | ||
|
de4933e093 | ||
|
aba37d001e | ||
|
b6d0a4ab30 | ||
|
2c231f9567 | ||
|
7fbcae2679 | ||
|
3aa4c0b827 | ||
|
612f326052 | ||
|
0c4e6aa2cd |
6
Makefile
6
Makefile
@ -468,7 +468,7 @@ cppcheck:
|
||||
clang_analyze:
|
||||
rm -fr clang_analyze_build
|
||||
mkdir clang_analyze_build
|
||||
cd clang_analyze_build ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja -DJSON_BuildTests=On
|
||||
cd clang_analyze_build ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja -DJSON_BuildTests=On -DJSON_MultipleHeaders=On
|
||||
cd clang_analyze_build ; \
|
||||
$(COMPILER_DIR)/scan-build \
|
||||
-enable-checker alpha.core.BoolAssignment,alpha.core.CallAndMessageUnInitRefArg,alpha.core.CastSize,alpha.core.CastToStruct,alpha.core.Conversion,alpha.core.DynamicTypeChecker,alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,alpha.core.SizeofPtr,alpha.core.StackAddressAsyncEscape,alpha.core.TestAfterDivZero,alpha.deadcode.UnreachableCode,core.builtin.BuiltinFunctions,core.builtin.NoReturnFunctions,core.CallAndMessage,core.DivideZero,core.DynamicTypePropagation,core.NonnilStringConstants,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,core.VLASize,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.SelfAssignment,deadcode.DeadStores,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull \
|
||||
@ -490,7 +490,7 @@ clang_tidy:
|
||||
pvs_studio:
|
||||
rm -fr pvs_studio_build
|
||||
mkdir pvs_studio_build
|
||||
cd pvs_studio_build ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On
|
||||
cd pvs_studio_build ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On -DJSON_MultipleHeaders=On
|
||||
cd pvs_studio_build ; pvs-studio-analyzer analyze -j 10
|
||||
cd pvs_studio_build ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
|
||||
open pvs_studio_build/pvs/index.html
|
||||
@ -499,7 +499,7 @@ pvs_studio:
|
||||
infer:
|
||||
rm -fr infer_build
|
||||
mkdir infer_build
|
||||
cd infer_build ; infer compile -- cmake .. ; infer run -- make -j 4
|
||||
cd infer_build ; infer compile -- cmake .. -DJSON_MultipleHeaders=On ; infer run -- make -j 4
|
||||
|
||||
# call OCLint <http://oclint.org> static analyzer
|
||||
oclint:
|
||||
|
@ -34,7 +34,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||
|
||||
// overloads for basic_json template parameters
|
||||
template < typename BasicJsonType, typename ArithmeticType,
|
||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||
enable_if_t < (std::is_arithmetic<ArithmeticType>::value || is_128_bit_integral<ArithmeticType>::value)&&
|
||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||
int > = 0 >
|
||||
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||
#include <nlohmann/detail/input/position_t.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
@ -918,6 +919,68 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
f = std::strtold(str, endptr);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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' && * p <= '9')
|
||||
{
|
||||
val = (10U * val) + static_cast<number_unsigned_t>((*p - '0'));
|
||||
p++;
|
||||
}
|
||||
|
||||
if (str_end != nullptr)
|
||||
{
|
||||
*str_end = const_cast<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 = const_cast<char*>(p);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief scan a number literal
|
||||
|
||||
@ -1242,7 +1305,7 @@ scan_number_done:
|
||||
// try to parse integers first and fall back to floats
|
||||
if (number_type == token_type::value_unsigned)
|
||||
{
|
||||
const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
|
||||
const auto x = strtoull(token_buffer.data(), &endptr, is_64_bit<number_unsigned_t>());
|
||||
|
||||
// we checked the number format before
|
||||
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||
@ -1258,7 +1321,7 @@ scan_number_done:
|
||||
}
|
||||
else if (number_type == token_type::value_integer)
|
||||
{
|
||||
const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
|
||||
const auto x = strtoll(token_buffer.data(), &endptr, is_64_bit<number_integer_t>());
|
||||
|
||||
// we checked the number format before
|
||||
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||
|
@ -327,6 +327,16 @@ template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||
struct is_constructible_array_type
|
||||
: is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
|
||||
|
||||
// true for types with up to 64 bit
|
||||
template<typename NumberType>
|
||||
struct is_64_bit : std::integral_constant < bool, (sizeof(NumberType) <= 8) >
|
||||
{};
|
||||
|
||||
// true for types with at least 64 bit that con be convert from 64 bit integers
|
||||
template<typename NumberType>
|
||||
struct is_128_bit_integral : std::integral_constant < bool, (((std::is_signed<NumberType>::value&& std::is_convertible<std::int64_t, NumberType>::value) || (std::is_unsigned<NumberType>::value&& std::is_convertible<std::uint64_t, NumberType>::value))&& !is_64_bit<NumberType>::value) >
|
||||
{};
|
||||
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType,
|
||||
typename = void>
|
||||
struct is_compatible_integer_type_impl : std::false_type {};
|
||||
@ -349,6 +359,16 @@ struct is_compatible_integer_type_impl <
|
||||
RealLimits::is_signed == CompatibleLimits::is_signed;
|
||||
};
|
||||
|
||||
// second version for 128 bit integers that fail std::is_integral test
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
struct is_compatible_integer_type_impl < RealIntegerType, CompatibleNumberIntegerType,
|
||||
enable_if_t < std::is_same<RealIntegerType, CompatibleNumberIntegerType>::value&&
|
||||
!std::is_integral<CompatibleNumberIntegerType>::value&&
|
||||
is_128_bit_integral<CompatibleNumberIntegerType>::value >>
|
||||
{
|
||||
static constexpr auto value = true;
|
||||
};
|
||||
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
struct is_compatible_integer_type
|
||||
: is_compatible_integer_type_impl<RealIntegerType,
|
||||
|
@ -3142,6 +3142,14 @@ template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||
struct is_constructible_array_type
|
||||
: is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
|
||||
|
||||
template<typename NumberType>
|
||||
struct is_64_bit : std::integral_constant < bool, (sizeof(NumberType) <= 8) >
|
||||
{};
|
||||
|
||||
template<typename NumberType>
|
||||
struct is_128_bit_integral : std::integral_constant < bool, (((std::is_signed<NumberType>::value&& std::is_convertible<std::int64_t, NumberType>::value) || (std::is_unsigned<NumberType>::value&& std::is_convertible<std::uint64_t, NumberType>::value))&& !is_64_bit<NumberType>::value) >
|
||||
{};
|
||||
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType,
|
||||
typename = void>
|
||||
struct is_compatible_integer_type_impl : std::false_type {};
|
||||
@ -3164,6 +3172,16 @@ struct is_compatible_integer_type_impl <
|
||||
RealLimits::is_signed == CompatibleLimits::is_signed;
|
||||
};
|
||||
|
||||
// second version for 128 bit integers that fail std::is_integral test
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
struct is_compatible_integer_type_impl < RealIntegerType, CompatibleNumberIntegerType,
|
||||
enable_if_t < std::is_same<RealIntegerType, CompatibleNumberIntegerType>::value&&
|
||||
!std::is_integral<CompatibleNumberIntegerType>::value&&
|
||||
is_128_bit_integral<CompatibleNumberIntegerType>::value >>
|
||||
{
|
||||
static constexpr auto value = true;
|
||||
};
|
||||
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
struct is_compatible_integer_type
|
||||
: is_compatible_integer_type_impl<RealIntegerType,
|
||||
@ -3300,7 +3318,7 @@ void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||
|
||||
// overloads for basic_json template parameters
|
||||
template < typename BasicJsonType, typename ArithmeticType,
|
||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||
enable_if_t < (std::is_arithmetic<ArithmeticType>::value || is_128_bit_integral<ArithmeticType>::value)&&
|
||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||
int > = 0 >
|
||||
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||
@ -8118,6 +8136,8 @@ class binary_reader
|
||||
|
||||
// #include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
// #include <nlohmann/detail/meta/type_traits.hpp>
|
||||
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
@ -9023,6 +9043,68 @@ class lexer : public lexer_base<BasicJsonType>
|
||||
f = std::strtold(str, endptr);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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' && * p <= '9')
|
||||
{
|
||||
val = (10U * val) + static_cast<number_unsigned_t>((*p - '0'));
|
||||
p++;
|
||||
}
|
||||
|
||||
if (str_end != nullptr)
|
||||
{
|
||||
*str_end = const_cast<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 = const_cast<char*>(p);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief scan a number literal
|
||||
|
||||
@ -9347,7 +9429,7 @@ scan_number_done:
|
||||
// try to parse integers first and fall back to floats
|
||||
if (number_type == token_type::value_unsigned)
|
||||
{
|
||||
const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
|
||||
const auto x = strtoull(token_buffer.data(), &endptr, is_64_bit<number_unsigned_t>());
|
||||
|
||||
// we checked the number format before
|
||||
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||
@ -9363,7 +9445,7 @@ scan_number_done:
|
||||
}
|
||||
else if (number_type == token_type::value_integer)
|
||||
{
|
||||
const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
|
||||
const auto x = strtoll(token_buffer.data(), &endptr, is_64_bit<number_integer_t>());
|
||||
|
||||
// we checked the number format before
|
||||
JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
|
||||
|
@ -94,6 +94,7 @@ endif()
|
||||
set(files
|
||||
src/unit-algorithms.cpp
|
||||
src/unit-allocator.cpp
|
||||
src/unit-alt-number.cpp
|
||||
src/unit-alt-string.cpp
|
||||
src/unit-assert_macro.cpp
|
||||
src/unit-bson.cpp
|
||||
|
129
test/src/unit-alt-number.cpp
Normal file
129
test/src/unit-alt-number.cpp
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 3.8.0
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright (c) 2018 Vitaliy Manushkin <agri@akamo.info>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
TEST_CASE("Alternative number types")
|
||||
{
|
||||
SECTION("8 bit integers")
|
||||
{
|
||||
using json8 = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int8_t, std::uint8_t>;
|
||||
|
||||
SECTION("unsigned")
|
||||
{
|
||||
std::uint8_t unsigned_max = 255;
|
||||
json8 j_unsigned_max = json8::parse("255");
|
||||
CHECK(j_unsigned_max.is_number_unsigned());
|
||||
CHECK(j_unsigned_max.dump() == "255");
|
||||
CHECK((j_unsigned_max.get<std::uint8_t>() == unsigned_max));
|
||||
CHECK(json8::parse(j_unsigned_max.dump()) == j_unsigned_max);
|
||||
|
||||
json8 j_overflow = json8::parse("256");
|
||||
CHECK(j_overflow.is_number_float());
|
||||
CHECK(j_overflow.dump() == "256.0");
|
||||
}
|
||||
|
||||
SECTION("signed")
|
||||
{
|
||||
std::int8_t signed_min = -128;
|
||||
json8 j_signed_min = json8::parse("-128");
|
||||
CHECK(j_signed_min.is_number_integer());
|
||||
CHECK(j_signed_min.dump() == "-128");
|
||||
CHECK((j_signed_min.get<std::int8_t>() == signed_min));
|
||||
CHECK(json8::parse(j_signed_min.dump()) == j_signed_min);
|
||||
|
||||
json8 j_underflow = json8::parse("-129");
|
||||
CHECK(j_underflow.is_number_float());
|
||||
CHECK(j_underflow.dump() == "-129.0");
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("16 bit integers")
|
||||
{
|
||||
using json16 = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int16_t, std::uint16_t>;
|
||||
|
||||
SECTION("unsigned")
|
||||
{
|
||||
std::uint16_t unsigned_max = 65535;
|
||||
json16 j_unsigned_max = json16::parse("65535");
|
||||
CHECK(j_unsigned_max.is_number_unsigned());
|
||||
CHECK(j_unsigned_max.dump() == "65535");
|
||||
CHECK((j_unsigned_max.get<std::uint16_t>() == unsigned_max));
|
||||
CHECK(json16::parse(j_unsigned_max.dump()) == j_unsigned_max);
|
||||
|
||||
json16 j_overflow = json16::parse("65536");
|
||||
CHECK(j_overflow.is_number_float());
|
||||
CHECK(j_overflow.dump() == "65536.0");
|
||||
}
|
||||
|
||||
SECTION("signed")
|
||||
{
|
||||
std::int16_t signed_min = -32768;
|
||||
json16 j_signed_min = json16::parse("-32768");
|
||||
CHECK(j_signed_min.is_number_integer());
|
||||
CHECK(j_signed_min.dump() == "-32768");
|
||||
CHECK((j_signed_min.get<std::int16_t>() == signed_min));
|
||||
CHECK(json16::parse(j_signed_min.dump()) == j_signed_min);
|
||||
|
||||
json16 j_underflow = json16::parse("-32769");
|
||||
CHECK(j_underflow.is_number_float());
|
||||
CHECK(j_underflow.dump() == "-32769.0");
|
||||
}
|
||||
}
|
||||
|
||||
// 128-bit arithmetic does not work with sanitizers
|
||||
#if defined(__SIZEOF_INT128__) && !defined(__SANITIZE_ADDRESS__)
|
||||
SECTION("128 bit integers")
|
||||
{
|
||||
using json128 = nlohmann::basic_json<std::map, std::vector, std::string, bool, __int128_t, __uint128_t>;
|
||||
|
||||
SECTION("unsigned")
|
||||
{
|
||||
__uint128_t unsigned_max = (340282366920938463463.374607431768211455) * std::pow(10, 18);
|
||||
json128 j_unsigned_max = json128::parse("340282366920938463463374607431768211455");
|
||||
CHECK(j_unsigned_max.is_number_unsigned());
|
||||
CHECK(j_unsigned_max.dump() == "340282366920938463463374607431768211455");
|
||||
//CHECK((j_unsigned_max.get<__uint128_t>() == unsigned_max));
|
||||
CHECK(json128::parse(j_unsigned_max.dump()) == j_unsigned_max);
|
||||
}
|
||||
|
||||
SECTION("signed")
|
||||
{
|
||||
__int128_t signed_min = (-170141183460469231731.687303715884105728) * std::pow(10, 18);
|
||||
json128 j_signed_min = json128::parse("-170141183460469231731687303715884105728");
|
||||
CHECK(j_signed_min.is_number_integer());
|
||||
CHECK(j_signed_min.dump() == "-170141183460469231731687303715884105728");
|
||||
CHECK((j_signed_min.get<__int128_t>() == signed_min));
|
||||
CHECK(json128::parse(j_signed_min.dump()) == j_signed_min);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
Loading…
Reference in New Issue
Block a user