Skip to content

Commit 0a81688

Browse files
hash fix
1 parent 53012d2 commit 0a81688

File tree

1 file changed

+83
-41
lines changed

1 file changed

+83
-41
lines changed

sdk/include/opentelemetry/sdk/metrics/view/attributes_processor.h

Lines changed: 83 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,59 +22,109 @@ namespace metrics
2222

2323
using MetricAttributes = opentelemetry::sdk::metrics::FilteredOrderedAttributeMap;
2424

25+
/**
26+
* Generic FNV hash implementation
27+
*/
28+
29+
template <typename Ty, size_t s>
30+
struct fnv_magic_prime_number
31+
{
32+
static constexpr const Ty value = 0x01000193U;
33+
};
34+
35+
template <typename Ty>
36+
struct fnv_magic_prime_number<Ty, 8>
37+
{
38+
static constexpr const Ty value = 0x100000001b3ULL;
39+
};
40+
41+
template <typename Ty, size_t s>
42+
struct fnv_magic_offset_basis
43+
{
44+
static constexpr const Ty value = 0x811C9DC5U;
45+
46+
static constexpr Ty fix(Ty hval) { return hval; }
47+
};
48+
49+
template <typename Ty>
50+
struct fnv_magic_offset_basis<Ty, 8>
51+
{
52+
static constexpr const Ty value = 0xCBF29CE484222325ULL;
53+
54+
static constexpr Ty fix(Ty hval) { return hval ^ (hval >> 32); }
55+
};
56+
57+
template <typename Ty>
58+
Ty fnv_n_buf(const void *buf, size_t len, Ty hval = fnv_magic_offset_basis<Ty, sizeof(Ty)>::value)
59+
{
60+
const unsigned char *bp = reinterpret_cast<const unsigned char *>(buf);
61+
const unsigned char *be = bp + len;
62+
Ty mn = fnv_magic_prime_number<Ty, sizeof(Ty)>::value;
63+
64+
while (bp < be)
65+
{
66+
hval *= mn;
67+
hval ^= static_cast<Ty>(*bp++);
68+
}
69+
70+
return fnv_magic_offset_basis<Ty, sizeof(Ty)>::fix(hval);
71+
}
72+
73+
template <typename Ty>
74+
Ty fnv_n_buf_a(const void *buf, size_t len, Ty hval = fnv_magic_offset_basis<Ty, sizeof(Ty)>::value)
75+
{
76+
const unsigned char *bp = reinterpret_cast<const unsigned char *>(buf);
77+
const unsigned char *be = bp + len;
78+
Ty mn = fnv_magic_prime_number<Ty, sizeof(Ty)>::value;
79+
80+
while (bp < be)
81+
{
82+
hval ^= static_cast<Ty>(*bp++);
83+
hval *= mn;
84+
}
85+
86+
return fnv_magic_offset_basis<Ty, sizeof(Ty)>::fix(hval);
87+
}
88+
2589
/**
2690
* Hash and equality for nostd::string_view, enabling safe use in unordered_map
2791
* without requiring null termination.
2892
*/
93+
2994
struct StringViewHash
3095
{
31-
#if __cplusplus >= 202002L
32-
// enable heterogenous lookup in C++20+
96+
#if defined(OPENTELEMETRY_STL_VERSION)
97+
# if OPENTELEMETRY_STL_VERSION >= 2020
3398
using is_transparent = void;
99+
# endif
34100
#endif
35101

36102
std::size_t operator()(const std::string &s) const noexcept
37103
{
38-
return std::hash<std::string>{}(s);
104+
return fnv_n_buf_a<std::size_t>(s.data(), s.size());
39105
}
40106

41107
std::size_t operator()(opentelemetry::nostd::string_view sv) const noexcept
42108
{
43-
#if __cplusplus >= 202002L
44-
return std::hash<opentelemetry::nostd::string_view>{}(
45-
opentelemetry::nostd::string_view{sv.data(), sv.size()});
46-
#else
47-
// pre-C++20 fallback: materialize to std::string
48-
return std::hash<std::string>{}(std::string{sv.data(), sv.size()});
49-
#endif
109+
return fnv_n_buf_a<std::size_t>(sv.data(), sv.size());
50110
}
51111
};
52112

53113
struct StringViewEqual
54114
{
55-
#if __cplusplus >= 202002L
115+
#if defined(OPENTELEMETRY_STL_VERSION)
116+
# if OPENTELEMETRY_STL_VERSION >= 2020
56117
using is_transparent = void;
118+
# endif
57119
#endif
58120

59-
bool operator()(const std::string &lhs, const std::string &rhs) const noexcept
60-
{
61-
return lhs == rhs;
62-
}
63-
64-
bool operator()(const std::string &lhs, opentelemetry::nostd::string_view rhs) const noexcept
65-
{
66-
return lhs.size() == rhs.size() && std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
67-
}
68-
69-
bool operator()(opentelemetry::nostd::string_view lhs, const std::string &rhs) const noexcept
121+
template <typename Lhs, typename Rhs>
122+
bool operator()(const Lhs &lhs, const Rhs &rhs) const noexcept
70123
{
71-
return lhs.size() == rhs.size() && std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
72-
}
124+
opentelemetry::nostd::string_view lsv(lhs.data(), lhs.size());
125+
opentelemetry::nostd::string_view rsv(rhs.data(), rhs.size());
73126

74-
bool operator()(opentelemetry::nostd::string_view lhs,
75-
opentelemetry::nostd::string_view rhs) const noexcept
76-
{
77-
return lhs.size() == rhs.size() && std::memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;
127+
return lsv.size() == rsv.size() && std::memcmp(lsv.data(), rsv.data(), lsv.size()) == 0;
78128
}
79129
};
80130

@@ -83,23 +133,15 @@ struct StringViewEqual
83133
* Falls back to std::string construction on libc++ (macOS) and pre-c++20,
84134
* but uses direct lookup on libstdc++ (Linux).
85135
*/
86-
inline auto find_hetero(
87-
const std::unordered_map<std::string, bool, StringViewHash, StringViewEqual> &map,
88-
opentelemetry::nostd::string_view key)
89-
{
90-
#if defined(_LIBCPP_VERSION) || __cplusplus < 202002L
91-
return map.find(std::string(key));
92-
#else
93-
return map.find(key);
94-
#endif
95-
}
96136

97-
inline auto find_hetero(std::unordered_map<std::string, bool, StringViewHash, StringViewEqual> &map,
98-
opentelemetry::nostd::string_view key)
137+
template <typename MapType>
138+
inline auto find_hetero(MapType &&map, opentelemetry::nostd::string_view key)
99139
{
100-
#if defined(_LIBCPP_VERSION) || __cplusplus < 202002L
140+
#if defined(_LIBCPP_VERSION) || \
141+
(defined(OPENTELEMETRY_STL_VERSION) && OPENTELEMETRY_STL_VERSION < 2020)
101142
return map.find(std::string(key));
102143
#else
144+
// libstdc++ + C++20: heterogeneous lookup works
103145
return map.find(key);
104146
#endif
105147
}

0 commit comments

Comments
 (0)