Coverage Report

Created: 2024-07-18 11:41

src/zserio/HashCodeUtil.h
Line
Count
Source
1
#ifndef ZSERIO_HASH_CODE_UTIL_H_INC
2
#define ZSERIO_HASH_CODE_UTIL_H_INC
3
4
#include <memory>
5
#include <string>
6
#include <type_traits>
7
#include <vector>
8
9
#include "zserio/Enums.h"
10
#include "zserio/FloatUtil.h"
11
#include "zserio/OptionalHolder.h"
12
#include "zserio/Types.h"
13
14
namespace zserio
15
{
16
17
/** Prime number for hash calculation. */
18
static const uint32_t HASH_PRIME_NUMBER = 37;
19
/** Initial seed for hash calculation. */
20
static const uint32_t HASH_SEED = 23;
21
22
/**
23
 * Gets initial hash code calculated from the given seed value.
24
 *
25
 * \param seedValue Seed value (current hash code).
26
 *
27
 * \return Hash code.
28
 */
29
inline uint32_t calcHashCodeFirstTerm(uint32_t seedValue)
30
74
{
31
74
    return HASH_PRIME_NUMBER * seedValue;
32
74
}
33
34
/**
35
 * Calculates hash code of the given integral value using the given seed value.
36
 *
37
 * \param seedValue Seed value (current hash code).
38
 * \param value Value for which to calculate the hash code.
39
 *
40
 * \return Calculated hash code.
41
 */
42
template <typename T>
43
inline typename std::enable_if<std::is_integral<T>::value && (sizeof(T) <= 4), uint32_t>::type calcHashCode(
44
        uint32_t seedValue, T value)
45
71
{
46
71
    return calcHashCodeFirstTerm(seedValue) + static_cast<uint32_t>(value);
47
71
}
48
49
/**
50
 * Calculates hash code of the given integral value using the given seed value.
51
 *
52
 * \param seedValue Seed value (current hash code).
53
 * \param value Value for which to calculate the hash code.
54
 *
55
 * \return Calculated hash code.
56
 */
57
template <typename T>
58
inline typename std::enable_if<std::is_integral<T>::value && (sizeof(T) > 4), uint32_t>::type calcHashCode(
59
        uint32_t seedValue, T value)
60
3
{
61
3
    const auto unsignedValue = static_cast<typename std::make_unsigned<T>::type>(value);
62
3
    return calcHashCodeFirstTerm(seedValue) + static_cast<uint32_t>(unsignedValue ^ (unsignedValue >> 32U));
63
3
}
64
65
/**
66
 * Calculates hash code of the given float value using the given seed value.
67
 *
68
 * \param seedValue Seed value (current hash code).
69
 * \param value Value for which to calculate the hash code.
70
 *
71
 * \return Calculated hash code.
72
 */
73
inline uint32_t calcHashCode(uint32_t seedValue, float value)
74
1
{
75
1
    return calcHashCode(seedValue, convertFloatToUInt32(value));
76
1
}
77
78
/**
79
 * Calculates hash code of the given double value using the given seed value.
80
 *
81
 * \param seedValue Seed value (current hash code).
82
 * \param value Value for which to calculate the hash code.
83
 *
84
 * \return Calculated hash code.
85
 */
86
inline uint32_t calcHashCode(uint32_t seedValue, double value)
87
1
{
88
1
    return calcHashCode(seedValue, convertDoubleToUInt64(value));
89
1
}
90
91
/**
92
 * Calculates hash code of the given string value using the given seed value.
93
 *
94
 * \param seedValue Seed value (current hash code).
95
 * \param stringValue Value for which to calculate the hash code.
96
 *
97
 * \return Calculated hash code.
98
 */
99
template <typename ALLOC>
100
inline uint32_t calcHashCode(
101
        uint32_t seedValue, const std::basic_string<char, std::char_traits<char>, ALLOC>& stringValue)
102
2
{
103
2
    uint32_t result = seedValue;
104
2
    for (auto element : stringValue)
105
2
    {
106
2
        result = calcHashCode(result, element);
107
2
    }
108
109
2
    return result;
110
2
}
111
112
/**
113
 * Calculates hash code of the given enum item using the given seed value.
114
 *
115
 * \param seedValue Seed value (current hash code).
116
 * \param enumValue Enum item for which to calculate the hash code.
117
 *
118
 * \return Calculated hash code.
119
 */
120
template <typename ENUM_TYPE>
121
inline typename std::enable_if<std::is_enum<ENUM_TYPE>::value, uint32_t>::type calcHashCode(
122
        uint32_t seedValue, ENUM_TYPE enumValue)
123
5
{
124
5
    return calcHashCode(seedValue, enumHashCode(enumValue));
125
5
}
126
127
/**
128
 * Calculates hash code of the given Zserio object (structure, choice, ...) using the given seed value.
129
 *
130
 * \param seedValue Seed value (current hash code).
131
 * \param object Object for which to calculate the hash code.
132
 *
133
 * \return Calculated hash code.
134
 */
135
template <typename OBJECT>
136
inline typename std::enable_if<!std::is_enum<OBJECT>::value && !std::is_integral<OBJECT>::value, uint32_t>::type
137
calcHashCode(uint32_t seedValue, const OBJECT& object)
138
14
{
139
14
    return calcHashCode(seedValue, object.hashCode());
140
14
}
141
142
/**
143
 * Calculates hash code of the given Zserio array using the given seed value.
144
 *
145
 * \param seedValue Seed value (current hash code).
146
 * \param array Array for which to calculate the hash code.
147
 *
148
 * \return Calculated hash code.
149
 */
150
template <typename ARRAY_ELEMENT, typename ALLOC>
151
inline uint32_t calcHashCode(uint32_t seedValue, const std::vector<ARRAY_ELEMENT, ALLOC>& array)
152
11
{
153
11
    uint32_t result = seedValue;
154
11
    for (const ARRAY_ELEMENT& element : array)
155
16
    {
156
16
        result = calcHashCode(result, element);
157
16
    }
158
159
11
    return result;
160
11
}
161
162
// must be last because of the two-phase lookup
163
// - we can have optional array (OptionalHolder<std::vector<T>>), but we cannot have array of optionals
164
/**
165
 * Calculates hash code of the given Zserio optional field using the given seed value.
166
 *
167
 * \param seedValue Seed value (current hash code).
168
 * \param optionalHolder Optional field for which to calculate the hash code.
169
 *
170
 * \return Calculated hash code.
171
 */
172
template <typename FIELD>
173
inline uint32_t calcHashCode(uint32_t seedValue, const InplaceOptionalHolder<FIELD>& optionalHolder)
174
5
{
175
5
    if (!optionalHolder)
176
1
    {
177
1
        return calcHashCode(seedValue, 0);
178
1
    }
179
180
4
    return calcHashCode(seedValue, *optionalHolder);
181
5
}
182
183
/**
184
 * Calculates hash code of the given Zserio optional field using the given seed value.
185
 *
186
 * \param seedValue Seed value (current hash code).
187
 * \param optionalHolder Optional field for which to calculate the hash code.
188
 *
189
 * \return Calculated hash code.
190
 */
191
template <typename FIELD, typename ALLOC>
192
inline uint32_t calcHashCode(uint32_t seedValue, const HeapOptionalHolder<FIELD, ALLOC>& optionalHolder)
193
2
{
194
2
    if (!optionalHolder)
195
1
    {
196
1
        return calcHashCode(seedValue, 0);
197
1
    }
198
199
1
    return calcHashCode(seedValue, *optionalHolder);
200
2
}
201
202
} // namespace zserio
203
204
#endif // ZSERIO_HASH_CODE_UTIL_H_INC