Skip to content

Commit

Permalink
[#4] Add Variant
Browse files Browse the repository at this point in the history
  • Loading branch information
mikir committed Sep 2, 2024
1 parent a4f0b9a commit 90c1c80
Show file tree
Hide file tree
Showing 7 changed files with 1,315 additions and 0 deletions.
4 changes: 4 additions & 0 deletions runtime/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ cmake_minimum_required(VERSION 3.15.0)
project(ZserioCpp17Runtime)

set(ZSERIO_CPP17_RUNTIME_LIB_SRCS
zserio/AllocatorHolder.h
zserio/BitBuffer.h
zserio/BitFieldUtil.cpp
zserio/BitPositionUtil.h
Expand All @@ -30,14 +31,17 @@ set(ZSERIO_CPP17_RUNTIME_LIB_SRCS
zserio/ConstraintException.h
zserio/FloatUtil.cpp
zserio/FloatUtil.h
zserio/HashCodeUtil.h
zserio/RebindAlloc.h
zserio/RuntimeArch.h
zserio/SizeConvertUtil.cpp
zserio/SizeConvertUtil.h
zserio/Span.h
zserio/String.h
zserio/StringConvertUtil.h
zserio/Traits.h
zserio/Types.h
zserio/Variant.h
zserio/Vector.h
)

Expand Down
116 changes: 116 additions & 0 deletions runtime/src/zserio/AllocatorHolder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#ifndef ZSERIO_ALLOCATOR_HOLDER_H_INC
#define ZSERIO_ALLOCATOR_HOLDER_H_INC

#include <utility>

namespace zserio
{

/**
* Base class for allocator-holding classes, so that the empty base class
* optimization may happen.
*/
template <typename ALLOC>
class AllocatorHolder
{
public:
using allocator_type = ALLOC;

/**
* Empty constructor.
*/
AllocatorHolder() :
m_allocator(allocator_type())
{}

/**
* Constructor from given allocator.
*
* \param allocator Allocator to be stored.
*/
explicit AllocatorHolder(const allocator_type& allocator) :
m_allocator(allocator)
{}

/**
* Constructor from given allocator.
*
* \param allocator Allocator to be stored.
*/
explicit AllocatorHolder(allocator_type&& allocator) :
m_allocator(std::move(allocator))
{}

/**
* Method generated by default.
* \{
*/
~AllocatorHolder() = default;

AllocatorHolder(const AllocatorHolder& other) = default;
AllocatorHolder& operator=(const AllocatorHolder& other) = default;

AllocatorHolder(AllocatorHolder&& other) = default;
AllocatorHolder& operator=(AllocatorHolder&& other) = default;
/**
* \}
*/

/**
* Allocator getter.
*
* \return Copy of the stored allocator.
*/
allocator_type get_allocator() const
{
return get_allocator_ref();
}

protected:
/**
* Allocator setter.
*
* \param allocator Allocator to be copy-assigned to the stored allocator.
*/
void set_allocator(const allocator_type& allocator)
{
m_allocator = allocator;
}

/**
* Allocator setter.
*
* \param allocator Allocator to be move-assigned to the stored allocator.
*/
void set_allocator(allocator_type&& allocator)
{
m_allocator = std::move(allocator);
}

/**
* Allocator getter.
*
* \return Reference to the stored allocator.
*/
allocator_type& get_allocator_ref()
{
return m_allocator;
}

/**
* Allocator getter.
*
* \return Reference to the stored allocator.
*/
const allocator_type& get_allocator_ref() const
{
return m_allocator;
}

private:
ALLOC m_allocator;
};

} // namespace zserio

#endif // ifndef ZSERIO_ALLOCATOR_HOLDER_H_INC
147 changes: 147 additions & 0 deletions runtime/src/zserio/HashCodeUtil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
#ifndef ZSERIO_HASH_CODE_UTIL_H_INC
#define ZSERIO_HASH_CODE_UTIL_H_INC

#include <memory>
#include <string>
#include <type_traits>
#include <vector>

#include "zserio/FloatUtil.h"
#include "zserio/Types.h"

namespace zserio
{

/** Prime number for hash calculation. */
static const uint32_t HASH_PRIME_NUMBER = 37;
/** Initial seed for hash calculation. */
static const uint32_t HASH_SEED = 23;

/**
* Gets initial hash code calculated from the given seed value.
*
* \param seedValue Seed value (current hash code).
*
* \return Hash code.
*/
inline uint32_t calcHashCodeFirstTerm(uint32_t seedValue)
{
return HASH_PRIME_NUMBER * seedValue;
}

/**
* Calculates hash code of the given integral value using the given seed value.
*
* \param seedValue Seed value (current hash code).
* \param value Value for which to calculate the hash code.
*
* \return Calculated hash code.
*/
template <typename T>
inline typename std::enable_if<std::is_integral<T>::value && (sizeof(T) <= 4), uint32_t>::type calcHashCode(
uint32_t seedValue, T value)
{
return calcHashCodeFirstTerm(seedValue) + static_cast<uint32_t>(value);
}

/**
* Calculates hash code of the given integral value using the given seed value.
*
* \param seedValue Seed value (current hash code).
* \param value Value for which to calculate the hash code.
*
* \return Calculated hash code.
*/
template <typename T>
inline typename std::enable_if<std::is_integral<T>::value && (sizeof(T) > 4), uint32_t>::type calcHashCode(
uint32_t seedValue, T value)
{
const auto unsignedValue = static_cast<typename std::make_unsigned<T>::type>(value);
return calcHashCodeFirstTerm(seedValue) + static_cast<uint32_t>(unsignedValue ^ (unsignedValue >> 32U));
}

/**
* Calculates hash code of the given float value using the given seed value.
*
* \param seedValue Seed value (current hash code).
* \param value Value for which to calculate the hash code.
*
* \return Calculated hash code.
*/
inline uint32_t calcHashCode(uint32_t seedValue, float value)
{
return calcHashCode(seedValue, convertFloatToUInt32(value));
}

/**
* Calculates hash code of the given double value using the given seed value.
*
* \param seedValue Seed value (current hash code).
* \param value Value for which to calculate the hash code.
*
* \return Calculated hash code.
*/
inline uint32_t calcHashCode(uint32_t seedValue, double value)
{
return calcHashCode(seedValue, convertDoubleToUInt64(value));
}

/**
* Calculates hash code of the given string value using the given seed value.
*
* \param seedValue Seed value (current hash code).
* \param stringValue Value for which to calculate the hash code.
*
* \return Calculated hash code.
*/
template <typename ALLOC>
inline uint32_t calcHashCode(
uint32_t seedValue, const std::basic_string<char, std::char_traits<char>, ALLOC>& stringValue)
{
uint32_t result = seedValue;
for (auto element : stringValue)
{
result = calcHashCode(result, element);
}

return result;
}

/**
* Calculates hash code of the given enum item using the given seed value.
*
* \param seedValue Seed value (current hash code).
* \param enumValue Enum item for which to calculate the hash code.
*
* \return Calculated hash code.
*/
template <typename ENUM_TYPE>
inline typename std::enable_if<std::is_enum<ENUM_TYPE>::value, uint32_t>::type calcHashCode(
uint32_t seedValue, ENUM_TYPE enumValue)
{
return calcHashCode(seedValue, enumHashCode(enumValue));
}

/**
* Calculates hash code of the given Zserio array using the given seed value.
*
* \param seedValue Seed value (current hash code).
* \param array Array for which to calculate the hash code.
*
* \return Calculated hash code.
*/
template <typename ARRAY_ELEMENT, typename ALLOC>
inline uint32_t calcHashCode(uint32_t seedValue, const std::vector<ARRAY_ELEMENT, ALLOC>& array)
{
uint32_t result = seedValue;
for (const ARRAY_ELEMENT& element : array)
{
result = calcHashCode(result, element);
}

return result;
}

} // namespace zserio

#endif // ZSERIO_HASH_CODE_UTIL_H_INC
66 changes: 66 additions & 0 deletions runtime/src/zserio/Traits.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#ifndef ZSERIO_TRAITS_H_INC
#define ZSERIO_TRAITS_H_INC

#include <type_traits>

namespace zserio
{

namespace detail
{

// declval is needed because otherwise MSVC 2015 states that std::allocator<int> does NOT have allocate method!
template <typename T, typename U = decltype(std::declval<T>().allocate(0))>
struct decltype_allocate
{
using type = U;
};

template <typename T, typename U = decltype(std::declval<T>().deallocate(nullptr, 0))>
struct decltype_deallocate
{
using type = U;
};

template <typename... T>
struct make_void
{
using type = void;
};

template <typename... T>
using void_t = typename make_void<T...>::type;

} // namespace detail

/**
* Trait used to check whether the type T is an allocator.
* \{
*/
template <typename T, typename = void>
struct is_allocator : std::false_type
{};

template <typename T>
struct is_allocator<T,
detail::void_t<typename detail::decltype_allocate<T>::type,
typename detail::decltype_deallocate<T>::type>> : std::true_type
{};
/** \} */

/**
* Trait used to check whether the first type of ARGS is an allocator.
* \{
*/
template <typename... ARGS>
struct is_first_allocator : std::false_type
{};

template <typename T, typename... ARGS>
struct is_first_allocator<T, ARGS...> : is_allocator<T>
{};
/** \} */

} // namespace zserio

#endif // ifndef ZSERIO_TRAITS_H_INC
Loading

0 comments on commit 90c1c80

Please sign in to comment.