/src/simdutf/fuzz/helpers/common.h
Line | Count | Source (jump to first uncovered line) |
1 | | // fuzzer helper functions |
2 | | // |
3 | | // by Paul Dreik 2024 |
4 | | |
5 | | #pragma once |
6 | | |
7 | | #include <algorithm> |
8 | | #include <charconv> |
9 | | #include <iostream> |
10 | | #include <span> |
11 | | #include <string> |
12 | | #include <tuple> |
13 | | #include <type_traits> |
14 | | #include <vector> |
15 | | |
16 | | #include "simdutf.h" |
17 | | |
18 | | #include "nameof.hpp" |
19 | | |
20 | | /// checks that the given type is a member function pointer |
21 | | template <typename T> |
22 | | concept member_function_pointer = std::is_member_function_pointer_v<T>; |
23 | | |
24 | | /// gets a list of implementations to fuzz |
25 | | inline std::span<const simdutf::implementation* const> |
26 | 31.3k | get_supported_implementations() { |
27 | 31.3k | static const auto impl = []() -> auto { |
28 | 1 | std::vector<const simdutf::implementation*> ret; |
29 | 4 | for (auto e : simdutf::get_available_implementations()) { |
30 | 4 | std::cerr << "implementation " << e->name() << " is available? " |
31 | 4 | << e->supported_by_runtime_system() << '\n'; |
32 | 4 | if (e->supported_by_runtime_system()) { |
33 | 3 | ret.push_back(e); |
34 | 3 | } |
35 | 4 | } |
36 | 1 | return ret; |
37 | 1 | }(); |
38 | 31.3k | return {impl.data(), impl.size()}; |
39 | 31.3k | } |
40 | | |
41 | | /// this should go into the library instead |
42 | 27.8k | inline bool operator!=(const simdutf::result& a, const simdutf::result& b) { |
43 | 27.8k | return a.count != b.count || a.error != b.error; |
44 | 27.8k | } |
45 | 7.52k | inline bool operator==(const simdutf::result& a, const simdutf::result& b) { |
46 | 7.52k | return a.count == b.count && a.error == b.error; |
47 | 7.52k | } |
48 | 0 | auto operator<=>(const simdutf::result& a, const simdutf::result& b) { |
49 | 0 | return std::tie(a.error, a.count) <=> std::tie(b.error, a.count); |
50 | 0 | } |
51 | | |
52 | 0 | inline std::ostream& operator<<(std::ostream& os, const simdutf::result& a) { |
53 | 0 | os << "[count=" << a.count << ", error=" << NAMEOF_ENUM(a.error) << "]"; |
54 | 0 | return os; |
55 | 0 | } |
56 | | |
57 | | template <typename Data> |
58 | | constexpr bool is_hashable = std::is_arithmetic_v<Data>; |
59 | | |
60 | | struct FNV1A_hash { |
61 | | static constexpr std::uint64_t prime = 0x00000100000001B3; |
62 | | static constexpr std::uint64_t offset = 0xcbf29ce484222325; |
63 | | |
64 | | static constexpr std::uint64_t |
65 | 20.8k | fnv1ahash_impl(std::span<const unsigned char> bytes) { |
66 | 20.8k | auto hash = offset; |
67 | | |
68 | 1.47G | for (std::uint64_t byte : bytes) { |
69 | 1.47G | hash ^= byte; |
70 | 1.47G | hash *= prime; |
71 | 1.47G | } |
72 | | |
73 | 20.8k | return hash; |
74 | 20.8k | } |
75 | 17.2k | static constexpr std::uint64_t fnv1ahash_impl(std::span<const char> bytes) { |
76 | 17.2k | auto hash = offset; |
77 | | |
78 | 501M | for (auto byte : bytes) { |
79 | 501M | hash ^= static_cast<unsigned char>(byte); |
80 | 501M | hash *= prime; |
81 | 501M | } |
82 | | |
83 | 17.2k | return hash; |
84 | 17.2k | } |
85 | | |
86 | | template <typename Basic, std::size_t N> |
87 | | requires(is_hashable<Basic> && !std::is_same_v<Basic, char> && |
88 | | !std::is_same_v<Basic, unsigned char>) |
89 | 20.8k | static constexpr std::uint64_t fnv1ahash_impl(std::span<Basic, N> data) { |
90 | 20.8k | return fnv1ahash_impl({reinterpret_cast<const unsigned char*>(data.data()), |
91 | 20.8k | data.size_bytes()}); |
92 | 20.8k | } _ZN10FNV1A_hash14fnv1ahash_implIKDsLm18446744073709551615EQaaaa11is_hashableIT_Entsr3stdE9is_same_vIS2_cEntsr3stdE9is_same_vIS2_hEEEmNSt3__14spanIS2_XT0_EEE Line | Count | Source | 89 | 13.1k | static constexpr std::uint64_t fnv1ahash_impl(std::span<Basic, N> data) { | 90 | 13.1k | return fnv1ahash_impl({reinterpret_cast<const unsigned char*>(data.data()), | 91 | 13.1k | data.size_bytes()}); | 92 | 13.1k | } |
Unexecuted instantiation: _ZN10FNV1A_hash14fnv1ahash_implIKmLm2EQaaaa11is_hashableIT_Entsr3stdE9is_same_vIS2_cEntsr3stdE9is_same_vIS2_hEEEmNSt3__14spanIS2_XT0_EEE _ZN10FNV1A_hash14fnv1ahash_implIKDiLm18446744073709551615EQaaaa11is_hashableIT_Entsr3stdE9is_same_vIS2_cEntsr3stdE9is_same_vIS2_hEEEmNSt3__14spanIS2_XT0_EEE Line | Count | Source | 89 | 7.72k | static constexpr std::uint64_t fnv1ahash_impl(std::span<Basic, N> data) { | 90 | 7.72k | return fnv1ahash_impl({reinterpret_cast<const unsigned char*>(data.data()), | 91 | 7.72k | data.size_bytes()}); | 92 | 7.72k | } |
|
93 | | |
94 | | template <typename Data> |
95 | | requires is_hashable<Data> |
96 | 38.0k | static constexpr std::uint64_t fnv1ahash_impl(const std::vector<Data>& data) { |
97 | 38.0k | return fnv1ahash_impl(std::span(data)); |
98 | 38.0k | } _ZN10FNV1A_hash14fnv1ahash_implIDiQ11is_hashableIT_EEEmRKNSt3__16vectorIS1_NS2_9allocatorIS1_EEEE Line | Count | Source | 96 | 7.72k | static constexpr std::uint64_t fnv1ahash_impl(const std::vector<Data>& data) { | 97 | 7.72k | return fnv1ahash_impl(std::span(data)); | 98 | 7.72k | } |
_ZN10FNV1A_hash14fnv1ahash_implIcQ11is_hashableIT_EEEmRKNSt3__16vectorIS1_NS2_9allocatorIS1_EEEE Line | Count | Source | 96 | 17.2k | static constexpr std::uint64_t fnv1ahash_impl(const std::vector<Data>& data) { | 97 | 17.2k | return fnv1ahash_impl(std::span(data)); | 98 | 17.2k | } |
_ZN10FNV1A_hash14fnv1ahash_implIDsQ11is_hashableIT_EEEmRKNSt3__16vectorIS1_NS2_9allocatorIS1_EEEE Line | Count | Source | 96 | 13.1k | static constexpr std::uint64_t fnv1ahash_impl(const std::vector<Data>& data) { | 97 | 13.1k | return fnv1ahash_impl(std::span(data)); | 98 | 13.1k | } |
|
99 | | |
100 | 38.0k | template <typename... Data> static std::string as_str(const Data&... data) { |
101 | 38.0k | static_assert(sizeof...(Data) > 0, "must hash with at least one argument"); |
102 | 38.0k | std::uint64_t h; |
103 | 38.0k | if constexpr (sizeof...(Data) > 1) { |
104 | 0 | const std::array hashes{fnv1ahash_impl(data)...}; |
105 | 0 | const auto s = std::span(hashes); |
106 | 0 | h = fnv1ahash_impl(s); |
107 | 38.0k | } else { |
108 | 38.0k | h = fnv1ahash_impl(data...); |
109 | 38.0k | } |
110 | 38.0k | constexpr std::size_t expected_chars = 16; |
111 | 38.0k | std::string ret(expected_chars, '0'); |
112 | 38.0k | auto c = std::to_chars(ret.data(), ret.data() + ret.size(), h, 16); |
113 | 38.0k | assert(c.ec == std::errc{}); |
114 | 38.0k | auto nwritten = c.ptr - ret.data(); |
115 | 38.0k | assert(nwritten <= expected_chars); |
116 | 38.0k | std::rotate(ret.data(), c.ptr, ret.data() + expected_chars); |
117 | 38.0k | return ret; |
118 | 38.0k | } Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > FNV1A_hash::as_str<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::span<char16_t const, 18446744073709551615ul> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::span<char16_t const, 18446744073709551615ul> const&) std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > FNV1A_hash::as_str<std::__1::vector<char32_t, std::__1::allocator<char32_t> > >(std::__1::vector<char32_t, std::__1::allocator<char32_t> > const&) Line | Count | Source | 100 | 7.72k | template <typename... Data> static std::string as_str(const Data&... data) { | 101 | 7.72k | static_assert(sizeof...(Data) > 0, "must hash with at least one argument"); | 102 | 7.72k | std::uint64_t h; | 103 | | if constexpr (sizeof...(Data) > 1) { | 104 | | const std::array hashes{fnv1ahash_impl(data)...}; | 105 | | const auto s = std::span(hashes); | 106 | | h = fnv1ahash_impl(s); | 107 | 7.72k | } else { | 108 | 7.72k | h = fnv1ahash_impl(data...); | 109 | 7.72k | } | 110 | 7.72k | constexpr std::size_t expected_chars = 16; | 111 | 7.72k | std::string ret(expected_chars, '0'); | 112 | 7.72k | auto c = std::to_chars(ret.data(), ret.data() + ret.size(), h, 16); | 113 | 7.72k | assert(c.ec == std::errc{}); | 114 | 7.72k | auto nwritten = c.ptr - ret.data(); | 115 | 7.72k | assert(nwritten <= expected_chars); | 116 | 7.72k | std::rotate(ret.data(), c.ptr, ret.data() + expected_chars); | 117 | 7.72k | return ret; | 118 | 7.72k | } |
std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > FNV1A_hash::as_str<std::__1::vector<char, std::__1::allocator<char> > >(std::__1::vector<char, std::__1::allocator<char> > const&) Line | Count | Source | 100 | 17.2k | template <typename... Data> static std::string as_str(const Data&... data) { | 101 | 17.2k | static_assert(sizeof...(Data) > 0, "must hash with at least one argument"); | 102 | 17.2k | std::uint64_t h; | 103 | | if constexpr (sizeof...(Data) > 1) { | 104 | | const std::array hashes{fnv1ahash_impl(data)...}; | 105 | | const auto s = std::span(hashes); | 106 | | h = fnv1ahash_impl(s); | 107 | 17.2k | } else { | 108 | 17.2k | h = fnv1ahash_impl(data...); | 109 | 17.2k | } | 110 | 17.2k | constexpr std::size_t expected_chars = 16; | 111 | 17.2k | std::string ret(expected_chars, '0'); | 112 | 17.2k | auto c = std::to_chars(ret.data(), ret.data() + ret.size(), h, 16); | 113 | 17.2k | assert(c.ec == std::errc{}); | 114 | 17.2k | auto nwritten = c.ptr - ret.data(); | 115 | 17.2k | assert(nwritten <= expected_chars); | 116 | 17.2k | std::rotate(ret.data(), c.ptr, ret.data() + expected_chars); | 117 | 17.2k | return ret; | 118 | 17.2k | } |
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > FNV1A_hash::as_str<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::span<char32_t const, 18446744073709551615ul> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::span<char32_t const, 18446744073709551615ul> const&) std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > FNV1A_hash::as_str<std::__1::vector<char16_t, std::__1::allocator<char16_t> > >(std::__1::vector<char16_t, std::__1::allocator<char16_t> > const&) Line | Count | Source | 100 | 13.1k | template <typename... Data> static std::string as_str(const Data&... data) { | 101 | 13.1k | static_assert(sizeof...(Data) > 0, "must hash with at least one argument"); | 102 | 13.1k | std::uint64_t h; | 103 | | if constexpr (sizeof...(Data) > 1) { | 104 | | const std::array hashes{fnv1ahash_impl(data)...}; | 105 | | const auto s = std::span(hashes); | 106 | | h = fnv1ahash_impl(s); | 107 | 13.1k | } else { | 108 | 13.1k | h = fnv1ahash_impl(data...); | 109 | 13.1k | } | 110 | 13.1k | constexpr std::size_t expected_chars = 16; | 111 | 13.1k | std::string ret(expected_chars, '0'); | 112 | 13.1k | auto c = std::to_chars(ret.data(), ret.data() + ret.size(), h, 16); | 113 | 13.1k | assert(c.ec == std::errc{}); | 114 | 13.1k | auto nwritten = c.ptr - ret.data(); | 115 | 13.1k | assert(nwritten <= expected_chars); | 116 | 13.1k | std::rotate(ret.data(), c.ptr, ret.data() + expected_chars); | 117 | 13.1k | return ret; | 118 | 13.1k | } |
Unexecuted instantiation: std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > FNV1A_hash::as_str<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::span<char const, 18446744073709551615ul> >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::span<char const, 18446744073709551615ul> const&) |
119 | | }; |
120 | | |
121 | | static_assert(FNV1A_hash::fnv1ahash_impl(std::string_view{""}) == |
122 | | 0xcbf29ce484222325); |
123 | | static_assert(FNV1A_hash::fnv1ahash_impl(std::string_view{"xyz"}) == |
124 | | 0xbff4aa198026f420); |
125 | | #if !defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE > 12 |
126 | | // work around https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113294 |
127 | | static_assert(FNV1A_hash::fnv1ahash_impl(std::string{"xyz"}) == |
128 | | 0xbff4aa198026f420); |
129 | | #endif |
130 | | static_assert(FNV1A_hash::fnv1ahash_impl(std::string_view{"\xFF"}) == |
131 | | 0xaf64724c8602eb6e); |
132 | | static_assert(FNV1A_hash::fnv1ahash_impl(std::string_view{ |
133 | | "\x01\x01\x01\x01"}) == 0xb5d0e0774c7d7499); |
134 | | static_assert(FNV1A_hash::fnv1ahash_impl(std::array<unsigned char, 4>{ |
135 | | 0x01, 0x01, 0x01, 0x01}) == 0xb5d0e0774c7d7499); |