Coverage Report

Created: 2024-04-30 09:35

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
        result = calcHashCode(result, element);
106
107
2
    return result;
108
2
}
109
110
/**
111
 * Calculates hash code of the given enum item using the given seed value.
112
 *
113
 * \param seedValue Seed value (current hash code).
114
 * \param enumValue Enum item for which to calculate the hash code.
115
 *
116
 * \return Calculated hash code.
117
 */
118
template <typename ENUM_TYPE>
119
inline typename std::enable_if<std::is_enum<ENUM_TYPE>::value, uint32_t>::type calcHashCode(
120
        uint32_t seedValue, ENUM_TYPE enumValue)
121
5
{
122
5
    return calcHashCode(seedValue, enumHashCode(enumValue));
123
5
}
124
125
/**
126
 * Calculates hash code of the given Zserio object (structure, choice, ...) using the given seed value.
127
 *
128
 * \param seedValue Seed value (current hash code).
129
 * \param object Object for which to calculate the hash code.
130
 *
131
 * \return Calculated hash code.
132
 */
133
template <typename OBJECT>
134
inline typename std::enable_if<!std::is_enum<OBJECT>::value && !std::is_integral<OBJECT>::value, uint32_t>::type
135
calcHashCode(uint32_t seedValue, const OBJECT& object)
136
14
{
137
14
    return calcHashCode(seedValue, object.hashCode());
138
14
}
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
inline uint32_t calcHashCode(uint32_t seedValue, const std::vector<ARRAY_ELEMENT, ALLOC>& array)
150
11
{
151
11
    uint32_t result = seedValue;
152
11
    for (const ARRAY_ELEMENT& element : array)
153
16
        result = calcHashCode(result, element);
154
155
11
    return result;
156
11
}
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
inline uint32_t calcHashCode(uint32_t seedValue, const InplaceOptionalHolder<FIELD>& optionalHolder)
170
5
{
171
5
    if (!optionalHolder)
172
1
        return calcHashCode(seedValue, 0);
173
174
4
    return calcHashCode(seedValue, *optionalHolder);
175
5
}
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
inline uint32_t calcHashCode(uint32_t seedValue, const HeapOptionalHolder<FIELD, ALLOC>& optionalHolder)
187
2
{
188
2
    if (!optionalHolder)
189
1
        return calcHashCode(seedValue, 0);
190
191
1
    return calcHashCode(seedValue, *optionalHolder);
192
2
}
193
194
} // namespace zserio
195
196
#endif // ZSERIO_HASH_CODE_UTIL_H_INC