@@ -22,59 +22,109 @@ namespace metrics
2222
2323using 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+
2994struct 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
53113struct 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