From 26cdbe0564146834a68dda9ecd0c19d20efe159e Mon Sep 17 00:00:00 2001 From: KeXu001 Date: Wed, 8 Dec 2021 01:17:17 -0500 Subject: [PATCH] Fix workflows cppcheck (#2) * change parser template args order * amalgamate for previous commit * add newlines at end of file * incremental changes * incremental changes * incremental changes * incremental changes * incremental changes (code style) * incremental changes * incremental changes amalgamate * incremental changes (code style) * add missing include guards * incremental changes (code style) * incremental changes (code style) * incremental changes (amalgamate) * incremental changes * incremental changes * code style change * clean up includes * try using vector_of_uint8_t * add missing include * add missing include * add missing includes * add comment --- include/nlohmann/detail/input/lexer.hpp | 2 +- include/nlohmann/detail/input/numerizer.hpp | 20 +- include/nlohmann/detail/input/parser.hpp | 2 +- .../nlohmann/detail/output/denumerizer.hpp | 110 ++++++--- include/nlohmann/detail/output/serializer.hpp | 2 - include/nlohmann/json.hpp | 12 +- include/nlohmann/json_fwd.hpp | 30 ++- single_include/nlohmann/json.hpp | 222 +++++++++++------- 8 files changed, 250 insertions(+), 150 deletions(-) diff --git a/include/nlohmann/detail/input/lexer.hpp b/include/nlohmann/detail/input/lexer.hpp index 9b2dc4fa6..27561a048 100644 --- a/include/nlohmann/detail/input/lexer.hpp +++ b/include/nlohmann/detail/input/lexer.hpp @@ -11,9 +11,9 @@ #include // vector #include +#include #include #include -#include namespace nlohmann { diff --git a/include/nlohmann/detail/input/numerizer.hpp b/include/nlohmann/detail/input/numerizer.hpp index de92c0823..1c2a0ba89 100644 --- a/include/nlohmann/detail/input/numerizer.hpp +++ b/include/nlohmann/detail/input/numerizer.hpp @@ -1,11 +1,16 @@ +#pragma once + +#include // uint64_t, int64_t #include // strtof, strtod, strtold, strtoll, strtoull +#include + namespace nlohmann { namespace detail { - + struct numerizer { JSON_HEDLEY_NON_NULL(2) @@ -25,20 +30,19 @@ struct numerizer { f = std::strtold(str, endptr); } - + JSON_HEDLEY_NON_NULL(2) - static unsigned long long int strtoull(const char* str, char** endptr, int base) + static uint64_t strtoull(const char* str, char** endptr, int base) { return std::strtoull(str, endptr, base); } - + JSON_HEDLEY_NON_NULL(2) - static long long int strtoll(const char* str, char** endptr, int base) + static int64_t strtoll(const char* str, char** endptr, int base) { return std::strtoll(str, endptr, base); } }; - -} -} \ No newline at end of file +} // namespace detail +} // namespace nlohmann diff --git a/include/nlohmann/detail/input/parser.hpp b/include/nlohmann/detail/input/parser.hpp index 70ea6cdb7..969c43232 100644 --- a/include/nlohmann/detail/input/parser.hpp +++ b/include/nlohmann/detail/input/parser.hpp @@ -48,7 +48,7 @@ using parser_callback_t = This class implements a recursive descent parser. */ -template class LexerType, typename BasicJsonType, typename InputAdapterType> +template class LexerType> class parser { using number_integer_t = typename BasicJsonType::number_integer_t; diff --git a/include/nlohmann/detail/output/denumerizer.hpp b/include/nlohmann/detail/output/denumerizer.hpp index 56147ed92..508aaba01 100644 --- a/include/nlohmann/detail/output/denumerizer.hpp +++ b/include/nlohmann/detail/output/denumerizer.hpp @@ -1,19 +1,18 @@ +#pragma once #include // reverse, remove, fill, find, none_of #include // array #include // localeconv, lconv #include // labs, isfinite, isnan, signbit #include // size_t, ptrdiff_t -#include // uint8_t #include // snprintf #include // numeric_limits -#include // string, char_traits -#include // setfill, setw -#include // stringstream -#include // is_same -#include // move +#include // char_traits +#include +#include +#include namespace nlohmann { @@ -21,9 +20,15 @@ namespace detail { struct denumerizer -{ +{ using number_buffer_t = std::array; - + + /*! + @brief count digits + Count the number of decimal (base 10) digits for an input unsigned integer. + @param[in] x unsigned integer number to count its digits + @return number of decimal digits + */ template static unsigned int count_digits(number_unsigned_t x) noexcept { @@ -46,23 +51,53 @@ struct denumerizer { return n_digits + 3; } - x = x / 10000u; + x = static_cast(x / 10000u); n_digits += 4; } } - - template ::type> - static number_unsigned_t remove_sign(number_integral_t x) noexcept + + /* + * Overload to make the compiler happy while it is instantiating + * dump_integer for number_unsigned_t. + * Must never be called. + */ + template ::value, int> = 0> + static number_unsigned_t remove_sign(number_unsigned_t x) noexcept { - JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return x; // LCOV_EXCL_LINE + } + + /* + * Helper function for dump_integer + * + * This function takes a negative signed integer and returns its absolute + * value as unsigned integer. The plus/minus shuffling is necessary as we can + * not directly remove the sign of an arbitrary signed integer as the + * absolute values of INT_MIN and INT_MAX are usually not the same. See + * #1708 for details. + */ + template ::value, int> = 0, + typename number_unsigned_t = + typename std::make_unsigned::type> + static number_unsigned_t remove_sign(number_integer_t x) noexcept + { + JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) return static_cast(-(x + 1)) + 1; } - + + /*! + @brief dump an integer + Dump a given integer to output stream @a o. + @param[in] x integer number (signed or unsigned) to dump + */ template ::type> + typename number_unsigned_t = typename std::make_unsigned< + number_integral_t>::type> static void dump_integer(OutputAdapterType& o, number_integral_t x) { static constexpr std::array, 100> digits_to_99 @@ -87,7 +122,7 @@ struct denumerizer o->write_character('0'); return; } - + number_buffer_t number_buffer{{}}; // use a pointer to fill the buffer @@ -142,11 +177,15 @@ struct denumerizer o->write_characters(number_buffer.data(), n_chars); } - - + + /*! + @brief dump a floating-point number + Dump a given floating-point number to output stream @a o. + @param[in] x floating-point number to dump + */ template ::value, int> = 0> + detail::enable_if_t< + std::is_floating_point::value, int> = 0> static void dump_float(OutputAdapterType& o, number_float_t x) { // NaN / inf @@ -167,31 +206,31 @@ struct denumerizer dump_float(o, x, std::integral_constant()); } - + template ::value, int> = 0> + detail::enable_if_t< + std::is_floating_point::value, int> = 0> static void dump_float(OutputAdapterType& o, number_float_t x, std::true_type /*is_ieee_single_or_double*/) { number_buffer_t number_buffer{{}}; - + auto* begin = number_buffer.data(); auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); o->write_characters(begin, static_cast(end - begin)); } - + template ::value, int> = 0> + detail::enable_if_t< + std::is_floating_point::value, int> = 0> static void dump_float(OutputAdapterType& o, number_float_t x, std::false_type /*is_ieee_single_or_double*/) { number_buffer_t number_buffer{{}}; - + const std::lconv* loc(std::localeconv()); const char thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->thousands_sep))); const char decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->decimal_point))); - + // get number of digits for a float -> text -> float round-trip static constexpr auto d = std::numeric_limits::max_digits10; @@ -240,8 +279,7 @@ struct denumerizer o->write_characters(".0", 2); } } - }; - -} -} \ No newline at end of file + +} // namespace detail +} // namespace nlohmann diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index 55391c8c8..60638d73e 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -14,10 +14,8 @@ #include // is_same #include // move -#include #include #include -#include #include #include #include diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index ce2f51b53..62e9e6af0 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -179,9 +179,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template friend struct detail::external_constructor; friend ::nlohmann::json_pointer; - template + template class> friend class ::nlohmann::detail::parser; - friend ::nlohmann::detail::serializer; + template + friend class ::nlohmann::detail::serializer; template friend class ::nlohmann::detail::iter_impl; template @@ -202,14 +203,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec using lexer = ::nlohmann::detail::lexer_base; template - static ::nlohmann::detail::parser parser( + static ::nlohmann::detail::parser parser( InputAdapterType adapter, detail::parser_callback_tcb = nullptr, const bool allow_exceptions = true, - const bool ignore_comments = false - ) + const bool ignore_comments = false) { - return ::nlohmann::detail::parser(std::move(adapter), + return ::nlohmann::detail::parser(std::move(adapter), std::move(cb), allow_exceptions, ignore_comments); } diff --git a/include/nlohmann/json_fwd.hpp b/include/nlohmann/json_fwd.hpp index da1e92479..58df84d59 100644 --- a/include/nlohmann/json_fwd.hpp +++ b/include/nlohmann/json_fwd.hpp @@ -41,21 +41,29 @@ class serializer; template using basic_serializer = serializer; -} +} // namespace detail -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, +// temporary workaround: use a typedef to avoid cppcheck alarm in basic_json template class declaration +using vector_of_uint8_t = std::vector; + +template + class ObjectType = std::map, + template + class ArrayType = std::vector, + class StringType = std::string, + class BooleanType = bool, class NumberIntegerType = std::int64_t, class NumberUnsignedType = std::uint64_t, class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector, - template class LexerType = detail::basic_lexer, - template class SerializerType = detail::basic_serializer> + template + class AllocatorType = std::allocator, + template + class JSONSerializer = adl_serializer, + class BinaryType = vector_of_uint8_t, + template + class LexerType = detail::basic_lexer, + template + class SerializerType = detail::basic_serializer> class basic_json; /*! diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 6cd8381fa..b6713c3c1 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -3453,21 +3453,29 @@ class serializer; template using basic_serializer = serializer; -} +} // namespace detail -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, +// temporary workaround: use a typedef to avoid cppcheck alarm in basic_json template class declaration +using vector_of_uint8_t = std::vector; + +template + class ObjectType = std::map, + template + class ArrayType = std::vector, + class StringType = std::string, + class BooleanType = bool, class NumberIntegerType = std::int64_t, class NumberUnsignedType = std::uint64_t, class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector, - template class LexerType = detail::basic_lexer, - template class SerializerType = detail::basic_serializer> + template + class AllocatorType = std::allocator, + template + class JSONSerializer = adl_serializer, + class BinaryType = vector_of_uint8_t, + template + class LexerType = detail::basic_lexer, + template + class SerializerType = detail::basic_serializer> class basic_json; /*! @@ -6660,19 +6668,21 @@ class json_sax_acceptor // #include -// #include +// #include + + + +#include // uint64_t, int64_t +#include // strtof, strtod, strtold, strtoll, strtoull // #include -// #include - -#include // strtof, strtod, strtold, strtoll, strtoull namespace nlohmann { namespace detail { - + struct numerizer { JSON_HEDLEY_NON_NULL(2) @@ -6692,23 +6702,27 @@ struct numerizer { f = std::strtold(str, endptr); } - + JSON_HEDLEY_NON_NULL(2) - static unsigned long long int strtoull(const char* str, char** endptr, int base) + static uint64_t strtoull(const char* str, char** endptr, int base) { return std::strtoull(str, endptr, base); } - + JSON_HEDLEY_NON_NULL(2) - static long long int strtoll(const char* str, char** endptr, int base) + static int64_t strtoll(const char* str, char** endptr, int base) { return std::strtoll(str, endptr, base); } }; - -} -} +} // namespace detail +} // namespace nlohmann + +// #include + +// #include + namespace nlohmann { @@ -11023,7 +11037,7 @@ using parser_callback_t = This class implements a recursive descent parser. */ -template class LexerType, typename BasicJsonType, typename InputAdapterType> +template class LexerType> class parser { using number_integer_t = typename BasicJsonType::number_integer_t; @@ -15370,6 +15384,29 @@ class binary_writer #include // is_same #include // move +// #include + +// #include + +// #include + +// #include + +// #include + +// #include + + + +#include // reverse, remove, fill, find, none_of +#include // array +#include // localeconv, lconv +#include // labs, isfinite, isnan, signbit +#include // size_t, ptrdiff_t +#include // snprintf +#include // numeric_limits +#include // char_traits + // #include @@ -16483,35 +16520,10 @@ char* to_chars(char* first, const char* last, FloatType value) } // namespace detail } // namespace nlohmann -// #include - // #include // #include -// #include - -// #include - -// #include - -// #include - - -#include // reverse, remove, fill, find, none_of -#include // array -#include // localeconv, lconv -#include // labs, isfinite, isnan, signbit -#include // size_t, ptrdiff_t -#include // uint8_t -#include // snprintf -#include // numeric_limits -#include // string, char_traits -#include // setfill, setw -#include // stringstream -#include // is_same -#include // move - namespace nlohmann { @@ -16519,9 +16531,15 @@ namespace detail { struct denumerizer -{ +{ using number_buffer_t = std::array; - + + /*! + @brief count digits + Count the number of decimal (base 10) digits for an input unsigned integer. + @param[in] x unsigned integer number to count its digits + @return number of decimal digits + */ template static unsigned int count_digits(number_unsigned_t x) noexcept { @@ -16544,23 +16562,53 @@ struct denumerizer { return n_digits + 3; } - x = x / 10000u; + x = static_cast(x / 10000u); n_digits += 4; } } - - template ::type> - static number_unsigned_t remove_sign(number_integral_t x) noexcept + + /* + * Overload to make the compiler happy while it is instantiating + * dump_integer for number_unsigned_t. + * Must never be called. + */ + template ::value, int> = 0> + static number_unsigned_t remove_sign(number_unsigned_t x) noexcept { - JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) + JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE + return x; // LCOV_EXCL_LINE + } + + /* + * Helper function for dump_integer + * + * This function takes a negative signed integer and returns its absolute + * value as unsigned integer. The plus/minus shuffling is necessary as we can + * not directly remove the sign of an arbitrary signed integer as the + * absolute values of INT_MIN and INT_MAX are usually not the same. See + * #1708 for details. + */ + template ::value, int> = 0, + typename number_unsigned_t = + typename std::make_unsigned::type> + static number_unsigned_t remove_sign(number_integer_t x) noexcept + { + JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); // NOLINT(misc-redundant-expression) return static_cast(-(x + 1)) + 1; } - + + /*! + @brief dump an integer + Dump a given integer to output stream @a o. + @param[in] x integer number (signed or unsigned) to dump + */ template ::type> + typename number_unsigned_t = typename std::make_unsigned< + number_integral_t>::type> static void dump_integer(OutputAdapterType& o, number_integral_t x) { static constexpr std::array, 100> digits_to_99 @@ -16585,7 +16633,7 @@ struct denumerizer o->write_character('0'); return; } - + number_buffer_t number_buffer{{}}; // use a pointer to fill the buffer @@ -16640,11 +16688,15 @@ struct denumerizer o->write_characters(number_buffer.data(), n_chars); } - - + + /*! + @brief dump a floating-point number + Dump a given floating-point number to output stream @a o. + @param[in] x floating-point number to dump + */ template ::value, int> = 0> + detail::enable_if_t< + std::is_floating_point::value, int> = 0> static void dump_float(OutputAdapterType& o, number_float_t x) { // NaN / inf @@ -16665,31 +16717,31 @@ struct denumerizer dump_float(o, x, std::integral_constant()); } - + template ::value, int> = 0> + detail::enable_if_t< + std::is_floating_point::value, int> = 0> static void dump_float(OutputAdapterType& o, number_float_t x, std::true_type /*is_ieee_single_or_double*/) { number_buffer_t number_buffer{{}}; - + auto* begin = number_buffer.data(); auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); o->write_characters(begin, static_cast(end - begin)); } - + template ::value, int> = 0> + detail::enable_if_t< + std::is_floating_point::value, int> = 0> static void dump_float(OutputAdapterType& o, number_float_t x, std::false_type /*is_ieee_single_or_double*/) { number_buffer_t number_buffer{{}}; - + const std::lconv* loc(std::localeconv()); const char thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->thousands_sep))); const char decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->decimal_point))); - + // get number of digits for a float -> text -> float round-trip static constexpr auto d = std::numeric_limits::max_digits10; @@ -16738,11 +16790,11 @@ struct denumerizer o->write_characters(".0", 2); } } - }; - -} -} + +} // namespace detail +} // namespace nlohmann + namespace nlohmann { @@ -17764,9 +17816,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec template friend struct detail::external_constructor; friend ::nlohmann::json_pointer; - template + template class> friend class ::nlohmann::detail::parser; - friend ::nlohmann::detail::serializer; + template + friend class ::nlohmann::detail::serializer; template friend class ::nlohmann::detail::iter_impl; template @@ -17787,14 +17840,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec using lexer = ::nlohmann::detail::lexer_base; template - static ::nlohmann::detail::parser parser( + static ::nlohmann::detail::parser parser( InputAdapterType adapter, detail::parser_callback_tcb = nullptr, const bool allow_exceptions = true, - const bool ignore_comments = false - ) + const bool ignore_comments = false) { - return ::nlohmann::detail::parser(std::move(adapter), + return ::nlohmann::detail::parser(std::move(adapter), std::move(cb), allow_exceptions, ignore_comments); }