mirror of
https://github.com/fraillt/bitsery.git
synced 2026-06-08 08:13:56 +00:00
in progress of range values feature
This commit is contained in:
@@ -7,5 +7,9 @@ file(GLOB EXAMPLE_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
|
||||
FOREACH(EXAMPLE ${EXAMPLE_FILES})
|
||||
get_filename_component(EXAMPLE_NAME ${EXAMPLE} NAME_WE)
|
||||
add_executable(${EXAMPLE_NAME} ${EXAMPLE})
|
||||
|
||||
set_property(TARGET ${EXAMPLE_NAME} PROPERTY CXX_STANDARD 14)
|
||||
set_property(TARGET ${EXAMPLE_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
ENDFOREACH()
|
||||
|
||||
|
||||
@@ -72,6 +72,76 @@ struct ProcessAnyType<0> {
|
||||
template <typename S, typename T, typename std::enable_if<std::is_same<T, ObjectType>::value || std::is_same<T, const ObjectType>::value>::type* = nullptr> \
|
||||
S& serialize(S& s, T& o)
|
||||
|
||||
extern int no_symbol;
|
||||
|
||||
template <typename T>
|
||||
constexpr size_t calcRequiredBits(T min, T max) {
|
||||
(T)min != min ? throw (no_symbol) : 0;
|
||||
assert(min < max);
|
||||
size_t res{};
|
||||
for (auto diff = max - min; diff > 0; diff >>= 1)
|
||||
++res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
template <typename T, class Enable = void>
|
||||
class RangeSpec {
|
||||
public:
|
||||
|
||||
constexpr RangeSpec(T min, T max)
|
||||
:_min{min},
|
||||
_max{max},
|
||||
_bitsRequired{calcRequiredBits(_min, _max)}
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
constexpr size_t bitsRequired() const {
|
||||
return _bitsRequired;
|
||||
}
|
||||
|
||||
constexpr bool isValid(const T& v) const {
|
||||
return !(_max < v || v < _min);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
T _min;
|
||||
T _max;
|
||||
size_t _bitsRequired;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class RangeSpec<T, typename std::enable_if<std::is_enum<T>::value>::type> {
|
||||
public:
|
||||
using value_type = typename std::underlying_type<T>::type;
|
||||
constexpr RangeSpec(T min, T max):
|
||||
_min{static_cast<value_type>(min)},
|
||||
_max{static_cast<value_type>(max)},
|
||||
_bitsRequired{calcRequiredBits(_min, _max)}
|
||||
{
|
||||
|
||||
}
|
||||
constexpr size_t bitsRequired() const {
|
||||
return _bitsRequired;
|
||||
}
|
||||
constexpr bool isValid(const T& v) const {
|
||||
return !(_max < static_cast<value_type>(v) || static_cast<value_type>(v) < _min);
|
||||
}
|
||||
|
||||
T getValue(T v) const {
|
||||
//return v - _min;
|
||||
return v;
|
||||
}
|
||||
private:
|
||||
value_type _min;
|
||||
value_type _max;
|
||||
size_t _bitsRequired;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ObjectMemoryPosition {
|
||||
public:
|
||||
|
||||
@@ -49,6 +49,16 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* range
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
Deserializer& range(T& v, RangeSpec<T> r) {
|
||||
_reader.template readBits(r.valueProxy(v), r.bitsRequired());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* text overloads
|
||||
*/
|
||||
|
||||
@@ -47,6 +47,17 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* range
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
Serializer& range(const T& v, RangeSpec<T> r) {
|
||||
assert(r.isValid(v));
|
||||
_writter.template writeBits(r.value(v), r.bitsRequired());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* text overloads
|
||||
*/
|
||||
|
||||
32
tests/SerializationRangeTests.cpp
Normal file
32
tests/SerializationRangeTests.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Created by fraillt on 17.2.15.
|
||||
//
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include "SerializationTestUtils.h"
|
||||
using namespace testing;
|
||||
|
||||
TEST(Ranges, IntegralRanges) {
|
||||
constexpr RangeSpec<int> r1{0, 31};
|
||||
static_assert(r1.bitsRequired() == 5);
|
||||
EXPECT_TRUE(r1.isValid(0));
|
||||
EXPECT_TRUE(r1.isValid(15));
|
||||
EXPECT_TRUE(r1.isValid(31));
|
||||
EXPECT_FALSE(r1.isValid(-1));
|
||||
EXPECT_FALSE(r1.isValid(32));
|
||||
|
||||
constexpr RangeSpec<MyEnumClass> r2{MyEnumClass::E1, MyEnumClass::E4};
|
||||
EXPECT_TRUE(r2.isValid(MyEnumClass::E2));
|
||||
EXPECT_FALSE(r2.isValid(MyEnumClass::E5));
|
||||
|
||||
int x= 0;
|
||||
RangeSpec<int> r3{x,3};
|
||||
EXPECT_THAT(r3.bitsRequired(), Eq(2));
|
||||
|
||||
|
||||
SerializationContext ctx;
|
||||
// ctx.createSerializer().range(486, {0,900});
|
||||
// ctx.createSerializer().range(MyEnumClass::E4, {MyEnumClass::E1,MyEnumClass::E6});
|
||||
// ctx.createSerializer().range(4.5f, {0.0f,10.0f, 10});
|
||||
// ctx.createSerializer().range(4.5f, {0.0f,10.0f, 0.001f});
|
||||
}
|
||||
@@ -28,9 +28,13 @@ SERIALIZE(MyStruct1) {
|
||||
value(o.i2);
|
||||
}
|
||||
|
||||
enum class MyEnumClass {
|
||||
E1, E2, E3, E4, E5, E6
|
||||
};
|
||||
|
||||
struct MyStruct2 {
|
||||
enum MyEnum {
|
||||
V1, V2, V3
|
||||
V1, V2, V3, V4, V5, V6
|
||||
};
|
||||
|
||||
MyStruct2(MyEnum e, MyStruct1 s):e1{e}, s1{s} {}
|
||||
|
||||
Reference in New Issue
Block a user