-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #449 from gofractally/fracpack-chrono
Add support for std::chrono::duration.
- Loading branch information
Showing
14 changed files
with
781 additions
and
543 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
#pragma once | ||
|
||
#include <psio/fracpack.hpp> | ||
|
||
#include <chrono> | ||
|
||
namespace psio | ||
{ | ||
|
||
template <typename Rep, typename Period> | ||
struct is_packable<std::chrono::duration<Rep, Period>> : std::bool_constant<true> | ||
{ | ||
using is_p = is_packable<Rep>; | ||
using T = std::chrono::duration<Rep, Period>; | ||
|
||
static constexpr uint32_t fixed_size = is_p::fixed_size; | ||
static constexpr bool is_variable_size = is_p::is_variable_size; | ||
static constexpr bool is_optional = is_p::is_optional; | ||
static constexpr bool supports_0_offset = is_p::supports_0_offset; | ||
|
||
static bool has_value(const T& value) { return is_p::has_value(value.count()); } | ||
template <bool Verify> | ||
static bool has_value(const char* src, uint32_t pos, uint32_t end_pos) | ||
{ | ||
return is_p::template has_value<Verify>(src, pos, end_pos); | ||
} | ||
|
||
template <bool Unpack, typename F> | ||
static bool unpack_impl(F&& f, T* value) | ||
{ | ||
if constexpr (Unpack) | ||
{ | ||
Rep tmp; | ||
bool result = f(&tmp); | ||
*value = T{tmp}; | ||
return result; | ||
} | ||
else | ||
{ | ||
return f((Rep*)nullptr); | ||
} | ||
} | ||
|
||
template <typename S> | ||
static void pack(const T& value, S& stream) | ||
{ | ||
return is_p::pack(value.count(), stream); | ||
} | ||
|
||
static bool is_empty_container(const T& value) | ||
{ | ||
return is_p::is_empty_container(value.count()); | ||
} | ||
static bool is_empty_container(const char* src, uint32_t pos, uint32_t end_pos) | ||
{ | ||
return is_p::is_empty_container(src, pos, end_pos); | ||
} | ||
|
||
template <typename S> | ||
static void embedded_fixed_pack(const T& value, S& stream) | ||
{ | ||
return is_p::embedded_fixed_pack(value.count(), stream); | ||
} | ||
|
||
template <typename S> | ||
static void embedded_fixed_repack(const T& value, | ||
uint32_t fixed_pos, | ||
uint32_t heap_pos, | ||
S& stream) | ||
{ | ||
return is_p::embedded_fixed_repack(value.count(), fixed_pos, heap_pos, stream); | ||
} | ||
|
||
template <typename S> | ||
static void embedded_variable_pack(const T& value, S& stream) | ||
{ | ||
return is_p::embedded_variable_pack(value.count(), stream); | ||
} | ||
|
||
template <bool Unpack, bool Verify> | ||
[[nodiscard]] static bool unpack(T* value, | ||
bool& has_unknown, | ||
bool& known_end, | ||
const char* src, | ||
uint32_t& pos, | ||
uint32_t end_pos) | ||
{ | ||
auto orig_pos = pos; | ||
bool result = unpack_impl<Unpack>( | ||
[&](Rep* value) { | ||
return is_p::template unpack<Unpack, Verify>(value, has_unknown, known_end, src, | ||
pos, end_pos); | ||
}, | ||
value); | ||
if constexpr (Verify && (PackableValidatedObject<T> || PackableValidatedView<T>)) | ||
{ | ||
return result && user_validate<Unpack, false>(value, src, orig_pos); | ||
} | ||
return result; | ||
} | ||
|
||
template <bool Unpack, bool Verify> | ||
[[nodiscard]] static bool embedded_variable_unpack(T* value, | ||
bool& has_unknown, | ||
bool& known_end, | ||
const char* src, | ||
uint32_t& fixed_pos, | ||
uint32_t end_fixed_pos, | ||
uint32_t& heap_pos, | ||
uint32_t end_heap_pos) | ||
{ | ||
auto orig_pos = fixed_pos; | ||
bool result = unpack_impl<Unpack>( | ||
[&](Rep* value) | ||
{ | ||
return is_p::template embedded_variable_unpack<Unpack, Verify>( | ||
value, has_unknown, known_end, src, fixed_pos, end_fixed_pos, heap_pos, | ||
end_heap_pos); | ||
}, | ||
value); | ||
if constexpr (Verify && (PackableValidatedObject<T> || PackableValidatedView<T>)) | ||
{ | ||
return result && user_validate<Unpack, true>(value, src, orig_pos); | ||
} | ||
return result; | ||
} | ||
|
||
template <bool Unpack, bool Verify> | ||
[[nodiscard]] static bool embedded_unpack(T* value, | ||
bool& has_unknown, | ||
bool& known_end, | ||
const char* src, | ||
uint32_t& fixed_pos, | ||
uint32_t end_fixed_pos, | ||
uint32_t& heap_pos, | ||
uint32_t end_heap_pos) | ||
{ | ||
auto orig_pos = fixed_pos; | ||
bool result = unpack_impl<Unpack>( | ||
[&](Rep* value) | ||
{ | ||
return is_p::template embedded_unpack<Unpack, Verify>(value, has_unknown, known_end, | ||
src, fixed_pos, end_fixed_pos, | ||
heap_pos, end_heap_pos); | ||
}, | ||
value); | ||
if constexpr (Verify && (PackableValidatedObject<T> || PackableValidatedView<T>)) | ||
{ | ||
return result && user_validate < Unpack, | ||
!is_optional && is_variable_size > (value, src, orig_pos); | ||
} | ||
return result; | ||
} | ||
}; | ||
|
||
template <typename Rep, typename Period, typename Stream> | ||
void to_json(const std::chrono::duration<Rep, Period>& obj, Stream& stream) | ||
{ | ||
to_json(obj.count(), stream); | ||
} | ||
|
||
template <typename Rep, typename Period, typename Stream> | ||
void from_json(std::chrono::duration<Rep, Period>& obj, Stream& stream) | ||
{ | ||
Rep tmp; | ||
from_json(tmp, stream); | ||
obj = std::chrono::duration<Rep, Period>(tmp); | ||
} | ||
|
||
} // namespace psio |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#include "test_fracpack.hpp" | ||
|
||
TEST_CASE("roundtrip bool") | ||
{ | ||
test<bool>({false, true}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#include "test_fracpack.hpp" | ||
|
||
TEST_CASE("roundtrip char") | ||
{ | ||
test<char>({'a', 'b', 'c'}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#include <psio/chrono.hpp> | ||
|
||
#include "test_fracpack.hpp" | ||
|
||
TEST_CASE("chrono") | ||
{ | ||
test<std::chrono::nanoseconds>({std::chrono::nanoseconds(0), std::chrono::nanoseconds(1), | ||
std::chrono::nanoseconds::min(), | ||
std::chrono::nanoseconds::max()}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#include "test_fracpack.hpp" | ||
|
||
TEST_CASE("roudtrip float/double") | ||
{ | ||
test<float>({std::copysign(std::numeric_limits<float>::quiet_NaN(), -1.0f), | ||
std::copysign(std::numeric_limits<float>::signaling_NaN(), -1.0f), | ||
-std::numeric_limits<float>::infinity(), -std::numeric_limits<float>::max(), | ||
-std::numeric_limits<float>::min(), -std::numeric_limits<float>::denorm_min(), -1, | ||
-0.0f, std::numeric_limits<float>::min(), 0, 1, | ||
std::numeric_limits<float>::denorm_min(), std::numeric_limits<float>::max(), | ||
std::numeric_limits<float>::infinity(), std::numeric_limits<float>::signaling_NaN(), | ||
std::numeric_limits<float>::quiet_NaN()}); | ||
test<double>( | ||
{std::copysign(std::numeric_limits<double>::quiet_NaN(), -1.0), | ||
std::copysign(std::numeric_limits<double>::signaling_NaN(), -1.0), | ||
-std::numeric_limits<double>::infinity(), -std::numeric_limits<double>::max(), | ||
-std::numeric_limits<double>::min(), -std::numeric_limits<double>::denorm_min(), -1, -0.0, | ||
std::numeric_limits<double>::min(), 0, 1, std::numeric_limits<double>::denorm_min(), | ||
std::numeric_limits<double>::max(), std::numeric_limits<double>::infinity(), | ||
std::numeric_limits<double>::signaling_NaN(), std::numeric_limits<double>::quiet_NaN()}); | ||
} |
Oops, something went wrong.