1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
#ifndef _CheckSums_h_
#define _CheckSums_h_
#include "Export.h"
#include <cmath>
#include <limits.h>
#include <memory>
#include <utility>
#include <string_view>
namespace CheckSums {
inline constexpr uint32_t CHECKSUM_MODULUS = 10000000U; // reasonably big number that should be well below UINT_MAX, which is ~4.29x10^9 for 32 bit unsigned int
static_assert(CHECKSUM_MODULUS < UINT_MAX/4);
inline constexpr bool csc_double = noexcept(noexcept(std::log10(std::abs(43.0))));
FO_COMMON_API void CheckSumCombine(uint32_t& sum, double t) noexcept(csc_double);
inline constexpr bool csc_float = noexcept(noexcept(std::log10(std::abs(43.0f))));
FO_COMMON_API void CheckSumCombine(uint32_t& sum, float t) noexcept(csc_float);
// integeral types
template <typename T> requires (std::is_signed_v<T>)
constexpr void CheckSumCombine(uint32_t& sum, T t) noexcept
{
sum += static_cast<uint32_t>(t >= 0 ? t : -t);
sum %= CHECKSUM_MODULUS;
}
template <typename T> requires (std::is_unsigned_v<T>)
constexpr void CheckSumCombine(uint32_t& sum, T t) noexcept
{
static_assert(noexcept(sum + static_cast<uint32_t>(t)) && noexcept(sum % CHECKSUM_MODULUS));
sum += static_cast<uint32_t>(t);
sum %= CHECKSUM_MODULUS;
}
template <>
constexpr void CheckSumCombine(uint32_t& sum, signed char t) noexcept
{
static_assert(noexcept(sum + static_cast<uint32_t>(static_cast<unsigned char>(t))));
static_assert(noexcept(sum % CHECKSUM_MODULUS));
sum += static_cast<uint32_t>(static_cast<unsigned char>(t));
sum %= CHECKSUM_MODULUS;
}
template <>
constexpr void CheckSumCombine(uint32_t& sum, char t) noexcept
{
if constexpr (std::is_signed_v<char>)
CheckSumCombine<signed char>(sum, t);
else
CheckSumCombine<unsigned char>(sum, t);
}
// strings
constexpr void CheckSumCombine(uint32_t& sum, std::string_view sv) noexcept {
for (auto t : sv)
CheckSumCombine(sum, t);
sum += static_cast<uint32_t>(sv.size());
sum %= CHECKSUM_MODULUS;
}
constexpr void CheckSumCombine(uint32_t& sum, const char* s) noexcept
{ CheckSumCombine(sum, std::string_view{s}); }
// classes that have GetCheckSum methods
template <typename C> //requires (requires(C c) { c.GetCheckSum(); })
void CheckSumCombine(uint32_t& sum, const C& c,
decltype(std::declval<C>().GetCheckSum())* = nullptr) noexcept(noexcept(c.GetCheckSum()))
{
sum += c.GetCheckSum();
sum %= CHECKSUM_MODULUS;
}
// enums
template <typename T> requires (std::is_enum_v<T>)
constexpr void CheckSumCombine(uint32_t& sum, T t) noexcept
{ CheckSumCombine(sum, static_cast<int>(t) + 10); }
// pointer types
template <typename T>
constexpr void CheckSumCombine(uint32_t& sum, const T* p) noexcept
{
if (p)
CheckSumCombine(sum, *p);
}
template <typename T>
void CheckSumCombine(uint32_t& sum, const typename std::shared_ptr<T>& p)
{
if (p)
CheckSumCombine(sum, *p);
}
template <typename T>
constexpr void CheckSumCombine(uint32_t& sum, const typename std::unique_ptr<T>& p)
{
if (p)
CheckSumCombine(sum, *p);
}
// pairs (including map value types)
template <typename C, typename D>
constexpr void CheckSumCombine(uint32_t& sum, const std::pair<C, D>& p)
{
CheckSumCombine(sum, p.first);
CheckSumCombine(sum, p.second);
}
// iterable containers
template <typename C> //requires (requires (C c) { c.begin(); c.end(); })
void CheckSumCombine(uint32_t& sum, const C& c,
decltype(std::declval<C>().begin())* = nullptr,
decltype(std::declval<C>().end())* = nullptr)
{
for (const auto& t : c)
CheckSumCombine(sum, t);
sum += static_cast<uint32_t>(c.size());
sum %= CHECKSUM_MODULUS;
}
}
#endif
|