GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/zserio/HashCodeUtil.h Lines: 33 33 100.0 %
Date: 2023-12-13 14:51:09 Branches: 24 43 55.8 %

Line Branch Exec Source
1
#ifndef ZSERIO_HASH_CODE_UTIL_H_INC
2
#define ZSERIO_HASH_CODE_UTIL_H_INC
3
4
#include <type_traits>
5
#include <string>
6
#include <vector>
7
#include <memory>
8
9
#include "zserio/Types.h"
10
#include "zserio/FloatUtil.h"
11
#include "zserio/Enums.h"
12
#include "zserio/OptionalHolder.h"
13
14
namespace zserio
15
{
16
    /** Prime number for hash calculation. */
17
    static const uint32_t HASH_PRIME_NUMBER = 37;
18
    /** Initial seed for hash calculation. */
19
    static const uint32_t HASH_SEED = 23;
20
21
    /**
22
     * Gets initial hash code calculated from the given seed value.
23
     *
24
     * \param seedValue Seed value (current hash code).
25
     *
26
     * \return Hash code.
27
     */
28
74
    inline uint32_t calcHashCodeFirstTerm(uint32_t seedValue)
29
    {
30
74
        return HASH_PRIME_NUMBER * seedValue;
31
    }
32
33
    /**
34
     * Calculates hash code of the given integral value using the given seed value.
35
     *
36
     * \param seedValue Seed value (current hash code).
37
     * \param value Value for which to calculate the hash code.
38
     *
39
     * \return Calculated hash code.
40
     */
41
    template<typename T>
42
    inline typename std::enable_if<std::is_integral<T>::value && (sizeof(T) <= 4), uint32_t>::type
43
71
            calcHashCode(uint32_t seedValue, T value)
44
    {
45
71
        return calcHashCodeFirstTerm(seedValue) + static_cast<uint32_t>(value);
46
    }
47
48
    /**
49
     * Calculates hash code of the given integral value using the given seed value.
50
     *
51
     * \param seedValue Seed value (current hash code).
52
     * \param value Value for which to calculate the hash code.
53
     *
54
     * \return Calculated hash code.
55
     */
56
    template<typename T>
57
    inline typename std::enable_if<std::is_integral<T>::value && (sizeof(T) > 4), uint32_t>::type
58
3
            calcHashCode(uint32_t seedValue, T value)
59
    {
60
3
        const auto unsignedValue = static_cast<typename std::make_unsigned<T>::type>(value);
61
3
        return calcHashCodeFirstTerm(seedValue) + static_cast<uint32_t>(unsignedValue ^ (unsignedValue >> 32U));
62
    }
63
64
    /**
65
     * Calculates hash code of the given float value using the given seed value.
66
     *
67
     * \param seedValue Seed value (current hash code).
68
     * \param value Value for which to calculate the hash code.
69
     *
70
     * \return Calculated hash code.
71
     */
72
1
    inline uint32_t calcHashCode(uint32_t seedValue, float value)
73
    {
74
1
        return calcHashCode(seedValue, convertFloatToUInt32(value));
75
    }
76
77
    /**
78
     * Calculates hash code of the given double value using the given seed value.
79
     *
80
     * \param seedValue Seed value (current hash code).
81
     * \param value Value for which to calculate the hash code.
82
     *
83
     * \return Calculated hash code.
84
     */
85
1
    inline uint32_t calcHashCode(uint32_t seedValue, double value)
86
    {
87
1
        return calcHashCode(seedValue, convertDoubleToUInt64(value));
88
    }
89
90
    /**
91
     * Calculates hash code of the given string value using the given seed value.
92
     *
93
     * \param seedValue Seed value (current hash code).
94
     * \param stringValue Value for which to calculate the hash code.
95
     *
96
     * \return Calculated hash code.
97
     */
98
    template <typename ALLOC>
99
2
    inline uint32_t calcHashCode(uint32_t seedValue,
100
            const std::basic_string<char, std::char_traits<char>, ALLOC>& stringValue)
101
    {
102
2
        uint32_t result = seedValue;
103
4
        for (auto element : stringValue)
104
2
            result = calcHashCode(result, element);
105
106
2
        return result;
107
    }
108
109
    /**
110
     * Calculates hash code of the given enum item using the given seed value.
111
     *
112
     * \param seedValue Seed value (current hash code).
113
     * \param enumValue Enum item for which to calculate the hash code.
114
     *
115
     * \return Calculated hash code.
116
     */
117
    template <typename ENUM_TYPE>
118
5
    inline typename std::enable_if<std::is_enum<ENUM_TYPE>::value, uint32_t>::type calcHashCode(
119
            uint32_t seedValue, ENUM_TYPE enumValue)
120
    {
121
5
        return calcHashCode(seedValue, enumHashCode(enumValue));
122
    }
123
124
    /**
125
     * Calculates hash code of the given Zserio object (structure, choice, ...) using the given seed value.
126
     *
127
     * \param seedValue Seed value (current hash code).
128
     * \param object Object for which to calculate the hash code.
129
     *
130
     * \return Calculated hash code.
131
     */
132
    template <typename OBJECT>
133
    inline
134
    typename std::enable_if<!std::is_enum<OBJECT>::value && !std::is_integral<OBJECT>::value, uint32_t>::type
135
14
    calcHashCode(uint32_t seedValue, const OBJECT& object)
136
    {
137
14
        return calcHashCode(seedValue, object.hashCode());
138
    }
139
140
    /**
141
     * Calculates hash code of the given Zserio array using the given seed value.
142
     *
143
     * \param seedValue Seed value (current hash code).
144
     * \param array Array for which to calculate the hash code.
145
     *
146
     * \return Calculated hash code.
147
     */
148
    template <typename ARRAY_ELEMENT, typename ALLOC>
149
11
    inline uint32_t calcHashCode(uint32_t seedValue, const std::vector<ARRAY_ELEMENT, ALLOC>& array)
150
    {
151
11
        uint32_t result = seedValue;
152




27
        for (const ARRAY_ELEMENT& element : array)
153



16
            result = calcHashCode(result, element);
154
155
11
        return result;
156
    }
157
158
    // must be last because of the two-phase lookup
159
    // - we can have optional array (OptionalHolder<std::vector<T>>), but we cannot have array of optionals
160
    /**
161
     * Calculates hash code of the given Zserio optional field using the given seed value.
162
     *
163
     * \param seedValue Seed value (current hash code).
164
     * \param optionalHolder Optional field for which to calculate the hash code.
165
     *
166
     * \return Calculated hash code.
167
     */
168
    template <typename FIELD>
169
5
    inline uint32_t calcHashCode(uint32_t seedValue, const InplaceOptionalHolder<FIELD>& optionalHolder)
170
    {
171


5
        if (!optionalHolder)
172
1
            return calcHashCode(seedValue, 0);
173
174
4
        return calcHashCode(seedValue, *optionalHolder);
175
    }
176
177
    /**
178
     * Calculates hash code of the given Zserio optional field using the given seed value.
179
     *
180
     * \param seedValue Seed value (current hash code).
181
     * \param optionalHolder Optional field for which to calculate the hash code.
182
     *
183
     * \return Calculated hash code.
184
     */
185
    template <typename FIELD, typename ALLOC>
186
2
    inline uint32_t calcHashCode(uint32_t seedValue, const HeapOptionalHolder<FIELD, ALLOC>& optionalHolder)
187
    {
188
2
        if (!optionalHolder)
189
1
            return calcHashCode(seedValue, 0);
190
191
1
        return calcHashCode(seedValue, *optionalHolder);
192
    }
193
194
} // namespace zserio
195
196
#endif // ZSERIO_HASH_CODE_UTIL_H_INC