diff --git a/include/json/value.h b/include/json/value.h index a60ca8f75..f45ab397f 100644 --- a/include/json/value.h +++ b/include/json/value.h @@ -9,6 +9,7 @@ #if !defined(JSON_IS_AMALGAMATION) #include "forwards.h" #endif // if !defined(JSON_IS_AMALGAMATION) +#include #include #include @@ -84,6 +85,29 @@ class JSON_API StaticString { const char* str_; }; +// Some Json::Value helpers in lieu of C++11 . +namespace Detail { + +template +struct IsIntegral { + enum { value = std::numeric_limits::is_integer }; +}; + +template +struct IsFloatingPoint { + enum { value = std::numeric_limits::is_specialized && + !std::numeric_limits::is_integer }; +}; + +template struct EnableIf { }; +template struct EnableIf { typedef T type; }; + +template +struct EnableIfArithmetic + : EnableIf::value || IsFloatingPoint::value, int> {}; + +} // namespace Detail + /** \brief Represents a JSON value. * * This class is a discriminated union wrapper that can represents a: @@ -210,13 +234,41 @@ Json::Value obj_value(Json::objectValue); // {} \endcode */ Value(ValueType type = nullValue); - Value(Int value); - Value(UInt value); -#if defined(JSON_HAS_INT64) - Value(Int64 value); - Value(UInt64 value); -#endif // if defined(JSON_HAS_INT64) - Value(double value); + + /** \brief Accept any arithmetic 'T'. + * + * Selected by substitution failure (sfinae) on dummy argument. + * Arithmetic means built-in integral or floating point type. + * This is currently determined with std::numeric_traits. + * Example: + * \code + * Json::Value v[] = { + * Json::Value(my_vector.size()), + * Json::Value(array_last - array_first), + * Json::Value('x'), + * Json::Value(3.14) + * }; + * \endcode + */ + template + Value(T value, typename Detail::EnableIfArithmetic::type = 0) + : allocated_(false), +#ifdef JSON_VALUE_USE_INTERNAL_MAP + itemIsUsed_(0), +#endif + comments_(0), start_(0), limit_(0) { + if (Detail::IsFloatingPoint::value) { + type_ = realValue; + value_.real_ = value; + } else if (std::numeric_limits::is_signed) { + type_ = intValue; + value_.int_ = value; + } else { + type_ = uintValue; + value_.uint_ = value; + } + } + Value(const char* value); Value(const char* beginValue, const char* endValue); /** \brief Constructs a value from a static string. diff --git a/src/lib_json/json_value.cpp b/src/lib_json/json_value.cpp index 2a0b97bbb..60c69f6c0 100644 --- a/src/lib_json/json_value.cpp +++ b/src/lib_json/json_value.cpp @@ -267,63 +267,6 @@ Value::Value(ValueType type) } } -Value::Value(UInt value) - : type_(uintValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.uint_ = value; -} - -Value::Value(Int value) - : type_(intValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.int_ = value; -} - -#if defined(JSON_HAS_INT64) -Value::Value(Int64 value) - : type_(intValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.int_ = value; -} - -Value::Value(UInt64 value) - : type_(uintValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.uint_ = value; -} -#endif // defined(JSON_HAS_INT64) - -Value::Value(double value) - : type_(realValue), allocated_(false) -#ifdef JSON_VALUE_USE_INTERNAL_MAP - , - itemIsUsed_(0) -#endif - , - comments_(0), start_(0), limit_(0) { - value_.real_ = value; -} - Value::Value(const char* value) : type_(stringValue), allocated_(true) #ifdef JSON_VALUE_USE_INTERNAL_MAP diff --git a/src/test_lib_json/main.cpp b/src/test_lib_json/main.cpp index 13fc21df5..f2f16a72f 100644 --- a/src/test_lib_json/main.cpp +++ b/src/test_lib_json/main.cpp @@ -6,6 +6,7 @@ #include "jsontest.h" #include #include +#include #include // Make numeric limits more convenient to talk about. @@ -394,6 +395,42 @@ JSONTEST_FIXTURE(ValueTest, integers) { JSONTEST_ASSERT_EQUAL(Json::uintValue, val.type()); + // A few more integral types + // special + JSONTEST_ASSERT_EQUAL(Json::booleanValue, + Json::Value(static_cast(0)).type()); + JSONTEST_ASSERT_EQUAL(Json::uintValue, + Json::Value(static_cast(0)).type()); + JSONTEST_ASSERT_EQUAL(Json::intValue, + Json::Value(static_cast(0)).type()); + // signed + JSONTEST_ASSERT_EQUAL(Json::intValue, + Json::Value(static_cast(0)).type()); + JSONTEST_ASSERT_EQUAL(Json::intValue, + Json::Value(static_cast(0)).type()); + JSONTEST_ASSERT_EQUAL(Json::intValue, + Json::Value(static_cast(0)).type()); + JSONTEST_ASSERT_EQUAL(Json::intValue, + Json::Value(static_cast(0)).type()); + // unsigned + JSONTEST_ASSERT_EQUAL(Json::uintValue, + Json::Value(static_cast(0)).type()); + JSONTEST_ASSERT_EQUAL(Json::uintValue, + Json::Value(static_cast(0)).type()); + JSONTEST_ASSERT_EQUAL(Json::uintValue, + Json::Value(static_cast(0)).type()); + JSONTEST_ASSERT_EQUAL(Json::uintValue, + Json::Value(static_cast(0)).type()); + // long long types if available +#ifdef LLONG_MAX + JSONTEST_ASSERT_EQUAL(Json::intValue, + Json::Value(static_cast(0)).type()); +#endif +#ifdef ULLONG_MAX + JSONTEST_ASSERT_EQUAL(Json::uintValue, + Json::Value(static_cast(0)).type()); +#endif + checks = IsCheck(); checks.isInt_ = true; checks.isInt64_ = true;