diff --git a/Makefile b/Makefile index 1e1217880..cdb53a0c5 100644 --- a/Makefile +++ b/Makefile @@ -256,7 +256,7 @@ fuzzing-stop: ########################################################################## # call cppcheck on the main header file -cppcheck: +cppcheck: $(AMALGAMATED_FILE) cppcheck --enable=warning --inconclusive --force --std=c++11 $(AMALGAMATED_FILE) --error-exitcode=1 # compile and check with Clang Static Analyzer diff --git a/doc/examples/meta.output b/doc/examples/meta.output index 3c4bf3230..2c4fc1982 100644 --- a/doc/examples/meta.output +++ b/doc/examples/meta.output @@ -4,7 +4,7 @@ "family": "clang", "version": "9.0.0 (clang-900.0.39.2)" }, - "copyright": "(C) 2013-2017 Niels Lohmann", + "copyright": "(C) 2013-2018 Niels Lohmann", "name": "JSON for Modern C++", "platform": "apple", "url": "https://github.com/nlohmann/json", diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index e20763c4a..687b6de9f 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -93,7 +93,7 @@ class binary_reader get(); } - if (JSON_UNLIKELY(current != std::char_traits::eof())) + if (JSON_UNLIKELY(current != end_of_file)) { return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input")); } @@ -126,8 +126,7 @@ class binary_reader { switch (get_char ? get() : current) { - // EOF - case std::char_traits::eof(): + case end_of_file: return unexpect_eof(); // Integer 0x00..0x17 (0..23) @@ -453,8 +452,7 @@ class binary_reader { switch (get()) { - // EOF - case std::char_traits::eof(): + case end_of_file: return unexpect_eof(); // positive fixint @@ -1420,7 +1418,7 @@ class binary_reader { switch (prefix) { - case std::char_traits::eof(): // EOF + case end_of_file: return unexpect_eof(); case 'T': // true @@ -1651,7 +1649,7 @@ class binary_reader */ bool unexpect_eof() const { - if (JSON_UNLIKELY(current == std::char_traits::eof())) + if (JSON_UNLIKELY(current == end_of_file)) { return sax->parse_error(chars_read, "", parse_error::create(110, chars_read, "unexpected end of input")); } @@ -1673,7 +1671,7 @@ class binary_reader input_adapter_t ia = nullptr; /// the current character - int current = std::char_traits::eof(); + int current = end_of_file; /// the number of characters read std::size_t chars_read = 0; diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index d1c7fea11..c724ed2b0 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -105,7 +105,7 @@ class input_buffer_adapter : public input_adapter_protocol return std::char_traits::to_int_type(*(cursor++)); } - return std::char_traits::eof(); + return end_of_file; } private: @@ -152,7 +152,7 @@ class wide_string_input_adapter : public input_adapter_protocol if (current_wchar == str.size()) { - utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes[0] = end_of_file; utf8_bytes_filled = 1; } else @@ -208,7 +208,7 @@ class wide_string_input_adapter : public input_adapter_protocol if (current_wchar == str.size()) { - utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes[0] = end_of_file; utf8_bytes_filled = 1; } else diff --git a/include/nlohmann/detail/input/lexer.hpp b/include/nlohmann/detail/input/lexer.hpp index 3fb790689..8b5ad39b4 100644 --- a/include/nlohmann/detail/input/lexer.hpp +++ b/include/nlohmann/detail/input/lexer.hpp @@ -235,7 +235,7 @@ class lexer switch (get()) { // end of file while parsing string - case std::char_traits::eof(): + case end_of_file: { error_message = "invalid string: missing closing quote"; return token_type::parse_error; @@ -1089,7 +1089,7 @@ scan_number_done: current = ia->get_character(); } - if (JSON_LIKELY(current != std::char_traits::eof())) + if (JSON_LIKELY(current != end_of_file)) { token_string.push_back(std::char_traits::to_char_type(current)); } @@ -1108,7 +1108,7 @@ scan_number_done: { next_unget = true; --chars_read; - if (JSON_LIKELY(current != std::char_traits::eof())) + if (JSON_LIKELY(current != end_of_file)) { assert(token_string.size() != 0); token_string.pop_back(); @@ -1285,7 +1285,7 @@ scan_number_done: // end of input (the null byte is needed when parsing from // string literals) case '\0': - case std::char_traits::eof(): + case end_of_file: return token_type::end_of_input; // error @@ -1300,7 +1300,7 @@ scan_number_done: detail::input_adapter_t ia = nullptr; /// the current character - std::char_traits::int_type current = std::char_traits::eof(); + std::char_traits::int_type current = end_of_file; /// whether the next get() call should just return current bool next_unget = false; diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index e67522186..0dae7a5b6 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -4,13 +4,15 @@ // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them // exclude unsupported compilers -#if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif -#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" +#ifndef NLOHMANN_JSON_SKIP_COMPILER_CHECK + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif #endif #endif diff --git a/include/nlohmann/detail/meta.hpp b/include/nlohmann/detail/meta.hpp index b251afb64..5bb14cd5c 100644 --- a/include/nlohmann/detail/meta.hpp +++ b/include/nlohmann/detail/meta.hpp @@ -25,6 +25,8 @@ namespace detail // helpers // ///////////// +static constexpr std::char_traits::int_type end_of_file = std::char_traits::eof(); + template struct is_basic_json : std::false_type {}; NLOHMANN_BASIC_JSON_TPL_DECLARATION diff --git a/include/nlohmann/detail/output/serializer.hpp b/include/nlohmann/detail/output/serializer.hpp index 19ab9894a..c0f817766 100644 --- a/include/nlohmann/detail/output/serializer.hpp +++ b/include/nlohmann/detail/output/serializer.hpp @@ -414,7 +414,7 @@ class serializer else { // we finish reading, but do not accept: string was incomplete - std::string sn(3,'\0'); + std::string sn(3, '\0'); snprintf(&sn[0], sn.size(), "%.2X", static_cast(s.back())); JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); } diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp index f5b93632f..232df49f8 100644 --- a/include/nlohmann/json.hpp +++ b/include/nlohmann/json.hpp @@ -316,7 +316,7 @@ class basic_json { basic_json result; - result["copyright"] = "(C) 2013-2017 Niels Lohmann"; + result["copyright"] = "(C) 2013-2018 Niels Lohmann"; result["name"] = "JSON for Modern C++"; result["url"] = "https://github.com/nlohmann/json"; result["version"]["string"] = diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 2b387a8b6..3568007a5 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -119,13 +119,15 @@ using json = basic_json<>; // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them // exclude unsupported compilers -#if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif -#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" +#ifndef NLOHMANN_JSON_SKIP_COMPILER_CHECK + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif #endif #endif @@ -259,6 +261,8 @@ namespace detail // helpers // ///////////// +static constexpr std::char_traits::int_type end_of_file = std::char_traits::eof(); + template struct is_basic_json : std::false_type {}; NLOHMANN_BASIC_JSON_TPL_DECLARATION @@ -1699,7 +1703,7 @@ class input_buffer_adapter : public input_adapter_protocol return std::char_traits::to_int_type(*(cursor++)); } - return std::char_traits::eof(); + return end_of_file; } private: @@ -1746,7 +1750,7 @@ class wide_string_input_adapter : public input_adapter_protocol if (current_wchar == str.size()) { - utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes[0] = end_of_file; utf8_bytes_filled = 1; } else @@ -1802,7 +1806,7 @@ class wide_string_input_adapter : public input_adapter_protocol if (current_wchar == str.size()) { - utf8_bytes[0] = std::char_traits::eof(); + utf8_bytes[0] = end_of_file; utf8_bytes_filled = 1; } else @@ -1973,10 +1977,8 @@ class input_adapter #include // localeconv #include // size_t #include // strtof, strtod, strtold, strtoll, strtoull +#include // snprintf #include // initializer_list -#include // hex, uppercase -#include // setw, setfill -#include // stringstream #include // char_traits, string #include // vector @@ -2209,7 +2211,7 @@ class lexer switch (get()) { // end of file while parsing string - case std::char_traits::eof(): + case end_of_file: { error_message = "invalid string: missing closing quote"; return token_type::parse_error; @@ -3063,7 +3065,7 @@ scan_number_done: current = ia->get_character(); } - if (JSON_LIKELY(current != std::char_traits::eof())) + if (JSON_LIKELY(current != end_of_file)) { token_string.push_back(std::char_traits::to_char_type(current)); } @@ -3082,7 +3084,7 @@ scan_number_done: { next_unget = true; --chars_read; - if (JSON_LIKELY(current != std::char_traits::eof())) + if (JSON_LIKELY(current != end_of_file)) { assert(token_string.size() != 0); token_string.pop_back(); @@ -3146,10 +3148,9 @@ scan_number_done: if ('\x00' <= c and c <= '\x1F') { // escape control characters - std::stringstream ss; - ss << "(c) << ">"; - result += ss.str(); + char cs[9]; + snprintf(cs, 9, "", c); + result += cs; } else { @@ -3260,7 +3261,7 @@ scan_number_done: // end of input (the null byte is needed when parsing from // string literals) case '\0': - case std::char_traits::eof(): + case end_of_file: return token_type::end_of_input; // error @@ -3275,7 +3276,7 @@ scan_number_done: detail::input_adapter_t ia = nullptr; /// the current character - std::char_traits::int_type current = std::char_traits::eof(); + std::char_traits::int_type current = end_of_file; /// whether the next get() call should just return current bool next_unget = false; @@ -5619,12 +5620,10 @@ class output_adapter #include // ldexp #include // size_t #include // uint8_t, uint16_t, uint32_t, uint64_t +#include // snprintf #include // memcpy -#include // setw, setfill -#include // hex #include // back_inserter #include // numeric_limits -#include // stringstream #include // char_traits, string #include // make_pair, move @@ -5713,7 +5712,7 @@ class binary_reader get(); } - if (JSON_UNLIKELY(current != std::char_traits::eof())) + if (JSON_UNLIKELY(current != end_of_file)) { return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read, "expected end of input")); } @@ -5746,8 +5745,7 @@ class binary_reader { switch (get_char ? get() : current) { - // EOF - case std::char_traits::eof(): + case end_of_file: return unexpect_eof(); // Integer 0x00..0x17 (0..23) @@ -6073,8 +6071,7 @@ class binary_reader { switch (get()) { - // EOF - case std::char_traits::eof(): + case end_of_file: return unexpect_eof(); // positive fixint @@ -7040,7 +7037,7 @@ class binary_reader { switch (prefix) { - case std::char_traits::eof(): // EOF + case end_of_file: return unexpect_eof(); case 'T': // true @@ -7271,7 +7268,7 @@ class binary_reader */ bool unexpect_eof() const { - if (JSON_UNLIKELY(current == std::char_traits::eof())) + if (JSON_UNLIKELY(current == end_of_file)) { return sax->parse_error(chars_read, "", parse_error::create(110, chars_read, "unexpected end of input")); } @@ -7283,9 +7280,9 @@ class binary_reader */ std::string get_token_string() const { - std::stringstream ss; - ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << current; - return ss.str(); + char cr[3]; + snprintf(cr, 3, "%.2X", current); + return std::string{cr}; } private: @@ -7293,7 +7290,7 @@ class binary_reader input_adapter_t ia = nullptr; /// the current character - int current = std::char_traits::eof(); + int current = end_of_file; /// the number of characters read std::size_t chars_read = 0; @@ -8272,11 +8269,8 @@ class binary_writer #include // size_t, ptrdiff_t #include // uint8_t #include // snprintf -#include // setfill -#include // next #include // numeric_limits #include // string -#include // stringstream #include // is_same // #include @@ -9753,9 +9747,9 @@ class serializer case UTF8_REJECT: // decode found invalid UTF-8 byte { - std::stringstream ss; - ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast(byte); - JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + ss.str())); + std::string sn(3, '\0'); + snprintf(&sn[0], sn.size(), "%.2X", byte); + JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); } default: // decode found yet incomplete multi-byte code point @@ -9781,9 +9775,9 @@ class serializer else { // we finish reading, but do not accept: string was incomplete - std::stringstream ss; - ss << std::setw(2) << std::uppercase << std::setfill('0') << std::hex << static_cast(static_cast(s.back())); - JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + ss.str())); + std::string sn(3, '\0'); + snprintf(&sn[0], sn.size(), "%.2X", static_cast(s.back())); + JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); } } @@ -11060,7 +11054,7 @@ class basic_json { basic_json result; - result["copyright"] = "(C) 2013-2017 Niels Lohmann"; + result["copyright"] = "(C) 2013-2018 Niels Lohmann"; result["name"] = "JSON for Modern C++"; result["url"] = "https://github.com/nlohmann/json"; result["version"]["string"] = diff --git a/test/src/unit-conversions.cpp b/test/src/unit-conversions.cpp index 79ccf6810..0e1a4874c 100644 --- a/test/src/unit-conversions.cpp +++ b/test/src/unit-conversions.cpp @@ -1093,9 +1093,9 @@ TEST_CASE("value conversion") SECTION("superfluous entries") { - json j8 = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}; - m2 = j8.get>(); - CHECK(m == m2); + json j8 = {{0, 1, 2}, {1, 2, 3}, {2, 3, 4}}; + m2 = j8.get>(); + CHECK(m == m2); } } diff --git a/test/src/unit-inspection.cpp b/test/src/unit-inspection.cpp index 4c03cf968..e50c7338e 100644 --- a/test/src/unit-inspection.cpp +++ b/test/src/unit-inspection.cpp @@ -317,8 +317,8 @@ TEST_CASE("object inspection") SECTION("round trips") { for (const auto& s : - {"3.141592653589793", "1000000000000000010E5" - }) + {"3.141592653589793", "1000000000000000010E5" + }) { json j1 = json::parse(s); std::string s1 = j1.dump(); diff --git a/test/src/unit-meta.cpp b/test/src/unit-meta.cpp index db03453ad..0e28c2674 100644 --- a/test/src/unit-meta.cpp +++ b/test/src/unit-meta.cpp @@ -39,7 +39,7 @@ TEST_CASE("version information") json j = json::meta(); CHECK(j["name"] == "JSON for Modern C++"); - CHECK(j["copyright"] == "(C) 2013-2017 Niels Lohmann"); + CHECK(j["copyright"] == "(C) 2013-2018 Niels Lohmann"); CHECK(j["url"] == "https://github.com/nlohmann/json"); CHECK(j["version"] == json( {