Skip to content

Commit

Permalink
Fix long long json serialization (#728)
Browse files Browse the repository at this point in the history
* Fix long long json serialization

* Update pod.hpp
  • Loading branch information
crazyhappygame authored Mar 14, 2022
1 parent ebef1e9 commit 45e4037
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
17 changes: 17 additions & 0 deletions include/cereal/archives/json.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,13 @@ namespace cereal
//! Saves a nullptr to the current node
void saveValue(std::nullptr_t) { itsWriter.Null(); }

template <class T> inline
typename std::enable_if<!std::is_same<T, int64_t>::value && std::is_same<T, long long>::value, void>::type
saveValue(T val) { itsWriter.Int64(val); }
template <class T> inline
typename std::enable_if<!std::is_same<T, uint64_t>::value && std::is_same<T, unsigned long long>::value, void>::type
saveValue(T val) { itsWriter.Uint64(val); }

private:
// Some compilers/OS have difficulty disambiguating the above for various flavors of longs, so we provide
// special overloads to handle these cases.
Expand Down Expand Up @@ -310,6 +317,8 @@ namespace cereal
!std::is_same<T, unsigned long>::value,
!std::is_same<T, std::int64_t>::value,
!std::is_same<T, std::uint64_t>::value,
!std::is_same<T, long long>::value,
!std::is_same<T, unsigned long long>::value,
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae> inline
void saveValue(T const & t)
{
Expand Down Expand Up @@ -659,6 +668,12 @@ namespace cereal
//! Loads a nullptr from the current node
void loadValue(std::nullptr_t&) { search(); CEREAL_RAPIDJSON_ASSERT(itsIteratorStack.back().value().IsNull()); ++itsIteratorStack.back(); }

template <class T> inline
typename std::enable_if<!std::is_same<T, int64_t>::value && std::is_same<T, long long>::value, void>::type
loadValue(T & val) { search(); val = itsIteratorStack.back().value().GetInt64(); ++itsIteratorStack.back(); }
template <class T> inline
typename std::enable_if<!std::is_same<T, uint64_t>::value && std::is_same<T, unsigned long long>::value, void>::type
loadValue(T & val) { search(); val = itsIteratorStack.back().value().GetUint64(); ++itsIteratorStack.back(); }
// Special cases to handle various flavors of long, which tend to conflict with
// the int32_t or int64_t on various compiler/OS combinations. MSVC doesn't need any of this.
#ifndef _MSC_VER
Expand Down Expand Up @@ -714,6 +729,8 @@ namespace cereal
!std::is_same<T, unsigned long>::value,
!std::is_same<T, std::int64_t>::value,
!std::is_same<T, std::uint64_t>::value,
!std::is_same<T, long long>::value,
!std::is_same<T, unsigned long long>::value,
(sizeof(T) >= sizeof(long double) || sizeof(T) >= sizeof(long long))> = traits::sfinae>
inline void loadValue(T & val)
{
Expand Down
10 changes: 10 additions & 0 deletions unittests/pod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,14 @@ TEST_CASE("json_pod")
test_pod<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
}

TEST_CASE("xml_pod_serialization")
{
test_pod_serialization<cereal::XMLInputArchive, cereal::XMLOutputArchive>();
}

TEST_CASE("json_pod_serialization")
{
test_pod_serialization<cereal::JSONInputArchive, cereal::JSONOutputArchive>();
}

TEST_SUITE_END();
68 changes: 68 additions & 0 deletions unittests/pod.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,72 @@ void test_pod()
}
}

template <class IArchive, class OArchive, class T1, class T2>
void test_pod_serialization(std::mt19937& gen)
{
T1 const o_t1 = random_value<T1>(gen);
T2 const o_t2 = o_t1;

std::ostringstream os1;
{
OArchive oar(os1);
oar(o_t1);
}

std::ostringstream os2;
{
OArchive oar(os2);
oar(o_t2);
}

CHECK_EQ(os1.str(), os2.str());

T1 i_t1 = T1();
T2 i_t2 = T2();
CHECK_EQ(os1.str(), os2.str());
std::istringstream is1(os1.str());
{
IArchive iar(is1);
iar(i_t1);
}
CHECK_EQ(o_t1, i_t1);

std::istringstream is2(os2.str());
{
IArchive iar(is2);
iar(i_t2);
}
CHECK_EQ(o_t2, i_t2);
}

template <class IArchive, class OArchive>
void test_pod_serialization()
{
std::random_device rd;
std::mt19937 gen(rd());
for (size_t i = 0; i < 100; ++i) {
test_pod_serialization<IArchive, OArchive, int8_t, int16_t>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, uint16_t>(gen);

test_pod_serialization<IArchive, OArchive, int8_t, int32_t>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, uint32_t>(gen);

test_pod_serialization<IArchive, OArchive, int8_t, int64_t>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, uint64_t>(gen);

test_pod_serialization<IArchive, OArchive, int8_t, long>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, unsigned long>(gen);

test_pod_serialization<IArchive, OArchive, int8_t, long long>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, unsigned long long>(
gen);

test_pod_serialization<IArchive, OArchive, int8_t, int>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, unsigned int>(gen);

test_pod_serialization<IArchive, OArchive, int8_t, short>(gen);
test_pod_serialization<IArchive, OArchive, uint8_t, unsigned short>(gen);
}
}

#endif // CEREAL_TEST_POD_H_

0 comments on commit 45e4037

Please sign in to comment.