Skip to content

Commit 0ed14de

Browse files
authored
Fixing handling of getting numeric values as doubles (#18)
* Fixing handling of getting numeric values as doubles RapidJson will allow you to convert integers to doubles, however, the type checking in rabbit disallowed this. There is a caveat for really really large numbers that you may lose precision but RapidJSON still allows it
1 parent f074dbb commit 0ed14de

File tree

2 files changed

+107
-6
lines changed

2 files changed

+107
-6
lines changed

rabbit.hpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ class basic_value_ref
595595
else if (value.is_object()) throw std::runtime_error("can not assign object directly. please use insert");
596596
}
597597

598-
template <typename OtherTraits>
598+
template <typename OtherTraits>
599599
void deep_copy(const basic_value_ref<OtherTraits>& other)
600600
{
601601
value_->CopyFrom(*other.get_native_value_pointer(), *alloc_);
@@ -680,9 +680,29 @@ class basic_value_ref
680680
RABBIT_AS_DEF(unsigned, uint, Uint)
681681
RABBIT_AS_DEF(int64_t, int64, Int64)
682682
RABBIT_AS_DEF(uint64_t, uint64, Uint64)
683-
RABBIT_AS_DEF(double, double, Double)
684683
RABBIT_AS_DEF(string_type, string, String)
685684
#undef RABBIT_AS_DEF
685+
double as_double() const
686+
{
687+
if(!is_number()){
688+
std::stringstream ss;
689+
ss << "value is not ";
690+
ss << details::type_name<double>();
691+
ss << " (which is " << which() << ")";
692+
throw type_mismatch(ss.str());
693+
}
694+
return value_->GetDouble();
695+
}
696+
697+
template <typename T>
698+
T as(typename details::enable_if< details::is_double<T> >::type* = 0) const
699+
{
700+
return as_double();
701+
}
702+
703+
704+
705+
686706

687707
private:
688708
struct as_t
@@ -1041,7 +1061,7 @@ struct basic_value_base
10411061
};
10421062

10431063
template <typename Traits, typename DefaultTag = null_tag>
1044-
class basic_value
1064+
class basic_value
10451065
: private basic_value_base<Traits>
10461066
, public basic_value_ref<Traits>
10471067
{
@@ -1086,7 +1106,7 @@ class basic_value
10861106

10871107

10881108
/*
1089-
* Tag based constructors
1109+
* Tag based constructors
10901110
*/
10911111
template <typename Tag>
10921112
basic_value(Tag tag, typename details::enable_if< details::is_tag<Tag> >::type* = 0)

test/value_test.cpp

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,8 +284,8 @@ BOOST_AUTO_TEST_SUITE(as_test) // {{{
284284
BOOST_CHECK_EQUAL(v.as<int64_t>(), 123);
285285
BOOST_CHECK_EQUAL(v.as_uint64(), 123);
286286
BOOST_CHECK_EQUAL(v.as<uint64_t>(), 123);
287-
BOOST_CHECK_THROW(v.as_double(), rabbit::type_mismatch);
288-
BOOST_CHECK_THROW(v.as<double>(), rabbit::type_mismatch);
287+
BOOST_CHECK_CLOSE(v.as_double(), 123.0, 0.00001);
288+
BOOST_CHECK_CLOSE(v.as<double>(), 123.0, 0.00001);
289289
BOOST_CHECK_THROW(v.as_string(), rabbit::type_mismatch);
290290
BOOST_CHECK_THROW(v.as<std::string>(), rabbit::type_mismatch);
291291
}
@@ -310,6 +310,28 @@ BOOST_AUTO_TEST_SUITE(as_test) // {{{
310310
BOOST_CHECK_THROW(v.as<std::string>(), rabbit::type_mismatch);
311311
}
312312

313+
BOOST_AUTO_TEST_CASE(double_from_int_test)
314+
{
315+
rabbit::value v(123);
316+
317+
BOOST_CHECK_THROW(v.as_bool(), rabbit::type_mismatch);
318+
BOOST_CHECK_THROW(v.as<bool>(), rabbit::type_mismatch);
319+
BOOST_CHECK_EQUAL(v.as_int(), 123);
320+
BOOST_CHECK_EQUAL(v.as<int>(), 123);
321+
BOOST_CHECK_EQUAL(v.as_uint(), 123);
322+
BOOST_CHECK_EQUAL(v.as<unsigned>(), 123);
323+
BOOST_CHECK_EQUAL(v.as_int64(), 123);
324+
BOOST_CHECK_EQUAL(v.as<int64_t>(), 123);
325+
BOOST_CHECK_EQUAL(v.as_uint64(), 123);
326+
BOOST_CHECK_EQUAL(v.as<uint64_t>(), 123);
327+
BOOST_CHECK_CLOSE(v.as_double(), 123.0, 0.00001);
328+
BOOST_CHECK_CLOSE(v.as<double>(), 123.0, 0.00001);
329+
BOOST_CHECK_THROW(v.as_string(), rabbit::type_mismatch);
330+
BOOST_CHECK_THROW(v.as<std::string>(), rabbit::type_mismatch);
331+
}
332+
333+
334+
313335
BOOST_AUTO_TEST_CASE(string_test)
314336
{
315337
rabbit::value v("str");
@@ -572,4 +594,63 @@ BOOST_AUTO_TEST_CASE(value_insert_string){
572594

573595
BOOST_CHECK(v["xyz"].as_string() == "abcde");
574596

597+
}
598+
599+
600+
601+
BOOST_AUTO_TEST_CASE(rabbit_number_is_and_as_compared_to_rapid){
602+
{
603+
rabbit::value v(123);
604+
BOOST_CHECK_EQUAL(v.is_int(), v.get_native_value_pointer()->IsInt());
605+
BOOST_CHECK_EQUAL(v.is_uint(), v.get_native_value_pointer()->IsUint());
606+
BOOST_CHECK_EQUAL(v.is_int64(), v.get_native_value_pointer()->IsInt64());
607+
BOOST_CHECK_EQUAL(v.is_uint64(), v.get_native_value_pointer()->IsUint64());
608+
BOOST_CHECK_EQUAL(v.is_double(), v.get_native_value_pointer()->IsDouble());
609+
610+
BOOST_CHECK_EQUAL(v.as_int(), v.get_native_value_pointer()->GetInt());
611+
BOOST_CHECK_EQUAL(v.as_uint(), v.get_native_value_pointer()->GetUint());
612+
BOOST_CHECK_EQUAL(v.as_int64(), v.get_native_value_pointer()->GetInt64());
613+
BOOST_CHECK_EQUAL(v.as_uint64(), v.get_native_value_pointer()->GetUint64());
614+
BOOST_CHECK_EQUAL(v.as_double(), v.get_native_value_pointer()->GetDouble());
615+
}
616+
617+
{
618+
rabbit::value v(4294967295);
619+
BOOST_CHECK_EQUAL(v.is_int(), v.get_native_value_pointer()->IsInt());
620+
BOOST_CHECK_EQUAL(v.is_uint(), v.get_native_value_pointer()->IsUint());
621+
BOOST_CHECK_EQUAL(v.is_int64(), v.get_native_value_pointer()->IsInt64());
622+
BOOST_CHECK_EQUAL(v.is_uint64(), v.get_native_value_pointer()->IsUint64());
623+
BOOST_CHECK_EQUAL(v.is_double(), v.get_native_value_pointer()->IsDouble());
624+
625+
BOOST_CHECK_EQUAL(v.as_uint(), v.get_native_value_pointer()->GetUint());
626+
BOOST_CHECK_EQUAL(v.as_int64(), v.get_native_value_pointer()->GetInt64());
627+
BOOST_CHECK_EQUAL(v.as_uint64(), v.get_native_value_pointer()->GetUint64());
628+
BOOST_CHECK_EQUAL(v.as_double(), v.get_native_value_pointer()->GetDouble());
629+
}
630+
631+
632+
{
633+
rabbit::value v(9223372036854775807);
634+
BOOST_CHECK_EQUAL(v.is_int(), v.get_native_value_pointer()->IsInt());
635+
BOOST_CHECK_EQUAL(v.is_uint(), v.get_native_value_pointer()->IsUint());
636+
BOOST_CHECK_EQUAL(v.is_int64(), v.get_native_value_pointer()->IsInt64());
637+
BOOST_CHECK_EQUAL(v.is_uint64(), v.get_native_value_pointer()->IsUint64());
638+
BOOST_CHECK_EQUAL(v.is_double(), v.get_native_value_pointer()->IsDouble());
639+
640+
BOOST_CHECK_EQUAL(v.as_int64(), v.get_native_value_pointer()->GetInt64());
641+
BOOST_CHECK_EQUAL(v.as_uint64(), v.get_native_value_pointer()->GetUint64());
642+
BOOST_CHECK_EQUAL(v.as_double(), v.get_native_value_pointer()->GetDouble());
643+
}
644+
645+
{
646+
rabbit::value v(static_cast<uint64_t>(9223372036854775808ULL));
647+
BOOST_CHECK_EQUAL(v.is_int(), v.get_native_value_pointer()->IsInt());
648+
BOOST_CHECK_EQUAL(v.is_uint(), v.get_native_value_pointer()->IsUint());
649+
BOOST_CHECK_EQUAL(v.is_int64(), v.get_native_value_pointer()->IsInt64());
650+
BOOST_CHECK_EQUAL(v.is_uint64(), v.get_native_value_pointer()->IsUint64());
651+
BOOST_CHECK_EQUAL(v.is_double(), v.get_native_value_pointer()->IsDouble());
652+
653+
BOOST_CHECK_EQUAL(v.as_uint64(), v.get_native_value_pointer()->GetUint64());
654+
BOOST_CHECK_EQUAL(v.as_double(), v.get_native_value_pointer()->GetDouble());
655+
}
575656
}

0 commit comments

Comments
 (0)