Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handling of custom containers that has a TypeDefinition #40

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions data_tamer_cpp/include/data_tamer/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

namespace DataTamer
{
using SerializeMe::has_TypeDefinition;

// Utility
inline std::chrono::nanoseconds NsecSinceEpoch()
Expand Down Expand Up @@ -73,7 +74,7 @@ class LogChannel : public std::enable_shared_from_this<LogChannel>
* @param value pointer to the value
* @return the ID to be used to unregister or enable/disable this value.
*/
template <typename T>
template <typename T, bool = true>
RegistrationID registerValue(const std::string& name, const T* value);

/**
Expand All @@ -85,7 +86,8 @@ class LogChannel : public std::enable_shared_from_this<LogChannel>
* @param value pointer to the vectors of values.
* @return the ID to be used to unregister or enable/disable the values.
*/
template <template <class, class> class Container, class T, class... TArgs>
template <template <class, class> class Container, class T, class... TArgs,
std::enable_if_t<!has_TypeDefinition<Container<T, TArgs...>>::value, bool> = true>
RegistrationID registerValue(const std::string& name,
const Container<T, TArgs...>* value);

Expand All @@ -98,7 +100,8 @@ class LogChannel : public std::enable_shared_from_this<LogChannel>
* @param value pointer to the array of values.
* @return the ID to be used to unregister or enable/disable the values.
*/
template <typename T, size_t N>
template <typename T, size_t N,
std::enable_if_t<!has_TypeDefinition<std::array<T, N>>::value, bool> = true>
RegistrationID registerValue(const std::string& name, const std::array<T, N>* value);

/**
Expand Down Expand Up @@ -259,7 +262,7 @@ inline void LogChannel::updateTypeRegistry()
}
}

template <typename T>
template <typename T, bool>
inline RegistrationID LogChannel::registerValue(const std::string& name,
const T* value_ptr)
{
Expand Down Expand Up @@ -288,7 +291,8 @@ inline RegistrationID LogChannel::registerCustomValue(const std::string& name,
return registerValueImpl(name, ValuePtr(value_ptr, serializer), serializer);
}

template <template <class, class> class Container, class T, class... TArgs>
template <template <class, class> class Container, class T, class... TArgs,
std::enable_if_t<!has_TypeDefinition<Container<T, TArgs...>>::value, bool>>
inline RegistrationID LogChannel::registerValue(const std::string& prefix,
const Container<T, TArgs...>* vect)
{
Expand All @@ -304,7 +308,8 @@ inline RegistrationID LogChannel::registerValue(const std::string& prefix,
}
}

template <typename T, size_t N>
template <typename T, size_t N,
std::enable_if_t<!has_TypeDefinition<std::array<T, N>>::value, bool>>
inline RegistrationID LogChannel::registerValue(const std::string& prefix,
const std::array<T, N>* vect)
{
Expand Down
109 changes: 62 additions & 47 deletions data_tamer_cpp/include/data_tamer/contrib/SerializeMe.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,46 +68,79 @@ using SpanBytes = Span<uint8_t>;
using SpanBytesConst = Span<uint8_t const>;
using StringSize = uint16_t;

//------------- Forward declarations of BufferSize ------------------
// Check if a Function like this is implemented:
//
// template <typename Func> std::string_view TypeDefinition(T&, Func&);

template <typename T, class = void>
struct has_TypeDefinition : std::false_type
{
};

const auto EmptyFuncion = [](const char*, void*) {};
using EmptyFunc = decltype(EmptyFuncion);

template <typename T1, typename T2>
using enable_if_same_t = std::enable_if_t<std::is_same_v<T1, T2>>;

template <typename T>
struct has_TypeDefinition<
T, enable_if_same_t<std::string_view,
decltype(TypeDefinition(std::declval<T&>(),
std::declval<EmptyFunc&>()))>>
: std::true_type
{
};

//------------- Forward declarations of BufferSize ------------------

template <typename T, bool = true>
size_t BufferSize(const T& val);

template <>
size_t BufferSize(const std::string& str);

template <class T, size_t N>
template <class T, size_t N,
std::enable_if_t<!has_TypeDefinition<std::array<T, N>>::value, bool> = true>
size_t BufferSize(const std::array<T, N>& v);

template <template <class, class> class Container, class T, class... TArgs>
template <
template <class, class> class Container, class T, class... TArgs,
std::enable_if_t<!has_TypeDefinition<Container<T, TArgs...>>::value, bool> = true>
size_t BufferSize(const Container<T, TArgs...>& vect);

//---------- Forward declarations of DeserializeFromBuffer -----------

template <typename T>
template <typename T, bool = true>
void DeserializeFromBuffer(SpanBytesConst& buffer, T& dest);

template <>
void DeserializeFromBuffer(SpanBytesConst& buffer, std::string& str);

template <class T, size_t N>
template <class T, size_t N,
std::enable_if_t<!has_TypeDefinition<std::array<T, N>>::value, bool> = true>
void DeserializeFromBuffer(SpanBytesConst& buffer, std::array<T, N>& v);

template <template <class, class> class Container, class T, class... TArgs>
template <
template <class, class> class Container, class T, class... TArgs,
std::enable_if_t<!has_TypeDefinition<Container<T, TArgs...>>::value, bool> = true>
void DeserializeFromBuffer(SpanBytesConst& buffer, Container<T, TArgs...>& dest);

//---------- Forward declarations of SerializeIntoBuffer -----------

template <typename T>
template <typename T, bool = true>
void SerializeIntoBuffer(SpanBytes& buffer, const T& value);

template <>
void SerializeIntoBuffer(SpanBytes& buffer, const std::string& str);

template <class T, size_t N>
template <class T, size_t N,
std::enable_if_t<!has_TypeDefinition<std::array<T, N>>::value, bool> = true>
void SerializeIntoBuffer(SpanBytes& buffer, const std::array<T, N>& v);

template <template <class, class> class Container, class T, class... TArgs>
template <
template <class, class> class Container, class T, class... TArgs,
std::enable_if_t<!has_TypeDefinition<Container<T, TArgs...>>::value, bool> = true>
void SerializeIntoBuffer(SpanBytes& buffer, const Container<T, TArgs...>& vect);

//-----------------------------------------------------------------------
Expand Down Expand Up @@ -150,8 +183,8 @@ inline void Span<T>::trimFront(size_t offset)
#endif // __s390x__
#if !defined(SERIALIZE_LITTLEENDIAN)
#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
#if(defined(__BIG_ENDIAN__) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
#if (defined(__BIG_ENDIAN__) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
#define SERIALIZE_LITTLEENDIAN 0
#else
#define SERIALIZE_LITTLEENDIAN 1
Expand Down Expand Up @@ -228,31 +261,6 @@ inline T EndianSwap(T t)
std::runtime_error("Problem with IndianSwap");
}
}

// Check if a Function like this is implemented:
//
// template <typename Func> std::string_view TypeDefinition(T&, Func&);

template <typename T, class = void>
struct has_TypeDefinition : std::false_type
{
};

const auto EmptyFuncion = [](const char*, void*) {};
using EmptyFunc = decltype(EmptyFuncion);

template <typename T1, typename T2>
using enable_if_same_t = std::enable_if_t<std::is_same_v<T1, T2>>;

template <typename T>
struct has_TypeDefinition<
T, enable_if_same_t<std::string_view,
decltype(TypeDefinition(std::declval<T&>(),
std::declval<EmptyFunc&>()))>>
: std::true_type
{
};

template <typename T>
inline constexpr bool is_number()
{
Expand Down Expand Up @@ -314,7 +322,7 @@ inline constexpr bool is_vector()
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

template <typename T>
template <typename T, bool>
inline size_t BufferSize(const T& val)
{
static_assert(is_number<T>() || has_TypeDefinition<T>(), "Missing TypeDefinition");
Expand All @@ -341,13 +349,15 @@ inline size_t BufferSize(const std::string& str)
return sizeof(StringSize) + str.size();
}

template <class T, size_t N>
template <class T, size_t N,
std::enable_if_t<!has_TypeDefinition<std::array<T, N>>::value, bool>>
inline size_t BufferSize(const std::array<T, N>&)
{
return BufferSize(T{}) * N;
}

template <template <class, class> class Container, class T, class... TArgs>
template <template <class, class> class Container, class T, class... TArgs,
std::enable_if_t<!has_TypeDefinition<Container<T, TArgs...>>::value, bool>>
inline size_t BufferSize(const Container<T, TArgs...>& vect)
{
if constexpr(std::is_trivially_copyable_v<T> && is_vector<Container<T, TArgs...>>())
Expand All @@ -369,7 +379,7 @@ inline size_t BufferSize(const Container<T, TArgs...>& vect)
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

template <typename T>
template <typename T, bool>
inline void DeserializeFromBuffer(SpanBytesConst& buffer, T& dest)
{
static_assert(is_number<T>() || has_TypeDefinition<T>(), "Missing TypeDefinition");
Expand Down Expand Up @@ -412,7 +422,8 @@ inline void DeserializeFromBuffer(SpanBytesConst& buffer, std::string& dest)
buffer.trimFront(size);
}

template <typename T, size_t N>
template <typename T, size_t N,
std::enable_if_t<!has_TypeDefinition<std::array<T, N>>::value, bool>>
inline void DeserializeFromBuffer(SpanBytesConst& buffer, std::array<T, N>& dest)
{
if(N * BufferSize(T{}) > buffer.size())
Expand All @@ -434,7 +445,8 @@ inline void DeserializeFromBuffer(SpanBytesConst& buffer, std::array<T, N>& dest
}
}

template <template <class, class> class Container, class T, class... TArgs>
template <template <class, class> class Container, class T, class... TArgs,
std::enable_if_t<!has_TypeDefinition<Container<T, TArgs...>>::value, bool>>
inline void DeserializeFromBuffer(SpanBytesConst& buffer, Container<T, TArgs...>& dest)
{
uint32_t num_values = 0;
Expand Down Expand Up @@ -475,7 +487,7 @@ inline void DeserializeFromBuffer(SpanBytesConst& buffer, Container<T, TArgs...>
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------

template <typename T>
template <typename T, bool>
inline void SerializeIntoBuffer(SpanBytes& buffer, T const& value)
{
static_assert(is_number<T>() || has_TypeDefinition<T>(), "Missing TypeDefinition");
Expand All @@ -488,9 +500,10 @@ inline void SerializeIntoBuffer(SpanBytes& buffer, T const& value)
throw std::runtime_error("SerializeIntoBuffer: buffer overflow");
}
#if SERIALIZE_LITTLEENDIAN == 0
*(reinterpret_cast<T*>(buffer.data())) = EndianSwap<T>(value);
T swapped = EndianSwap<T>(value);
std::memcpy(buffer.data(), &swapped, S);
#else
*(reinterpret_cast<T*>(buffer.data())) = value;
std::memcpy(buffer.data(), &value, S);
#endif
buffer.trimFront(S); // NOLINT
}
Expand Down Expand Up @@ -523,7 +536,8 @@ inline void SerializeIntoBuffer(SpanBytes& buffer, std::string const& str)
buffer.trimFront(size);
}

template <typename T, size_t N>
template <typename T, size_t N,
std::enable_if_t<!has_TypeDefinition<std::array<T, N>>::value, bool>>
inline void SerializeIntoBuffer(SpanBytes& buffer, std::array<T, N> const& vect)
{
if(N > std::numeric_limits<uint32_t>::max())
Expand Down Expand Up @@ -553,7 +567,8 @@ inline void SerializeIntoBuffer(SpanBytes& buffer, std::array<T, N> const& vect)
}
}

template <template <class, class> class Container, class T, class... TArgs>
template <template <class, class> class Container, class T, class... TArgs,
std::enable_if_t<!has_TypeDefinition<Container<T, TArgs...>>::value, bool>>
inline void SerializeIntoBuffer(SpanBytes& buffer, Container<T, TArgs...> const& vect)
{
const auto num_values = static_cast<uint32_t>(vect.size());
Expand Down
7 changes: 0 additions & 7 deletions data_tamer_cpp/include/data_tamer/custom_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,6 @@ template <typename T>
inline CustomSerializerT<T>::CustomSerializerT(std::string type_name)
: _name(std::move(type_name))
{
static_assert(!SerializeMe::container_info<T>().is_container, "Don't pass containers a "
"template type");

bool is_fixed_size = true;
GetFixedSize<T>(is_fixed_size, _fixed_size);
if(!is_fixed_size)
Expand Down Expand Up @@ -198,8 +195,6 @@ inline CustomSerializer::Ptr TypesRegistry::getSerializer()
{
static_assert(!IsNumericType<T>(), "You don't need to create a serializer for a "
"numerical type.");
static_assert(!SerializeMe::container_info<T>().is_container, "Don't pass containers "
"as template type");

std::scoped_lock lk(_mutex);
T dummy;
Expand All @@ -221,8 +216,6 @@ inline CustomSerializer::Ptr TypesRegistry::addType(const std::string& type_name
{
static_assert(!IsNumericType<T>(), "You don't need to create a serializer for a "
"numerical type.");
static_assert(!SerializeMe::container_info<T>().is_container, "Don't pass containers "
"as template type");

std::scoped_lock lk(_mutex);
if(skip_if_present && _types.count(type_name) != 0)
Expand Down
Loading
Loading