File: CheckSums.h

package info (click to toggle)
freeorion 0.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 194,940 kB
  • sloc: cpp: 186,508; python: 40,969; ansic: 1,164; xml: 719; makefile: 32; sh: 7
file content (120 lines) | stat: -rw-r--r-- 4,097 bytes parent folder | download
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