TLA Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/boostorg/url
8 : //
9 :
10 :
11 : #include <boost/url/detail/config.hpp>
12 : #include <boost/url/grammar/ci_string.hpp>
13 :
14 : // FNV-1a (in ci_digest below) relies on modular multiplication
15 : // of unsigned values, which Clang's -fsanitize=integer flags as
16 : // overflow. Suppress the check for that function only. GCC has
17 : // no equivalent sanitizer (it does not flag unsigned overflow),
18 : // so the annotation is Clang-only — applying it on GCC produces
19 : // "attribute directive ignored" under -Werror=attributes.
20 : #if defined(__clang__) && defined(__has_attribute)
21 : # if __has_attribute(no_sanitize)
22 : # define BOOST_URL_NO_SANITIZE_INT_OVERFLOW \
23 : __attribute__((no_sanitize("unsigned-integer-overflow")))
24 : # endif
25 : #endif
26 : #ifndef BOOST_URL_NO_SANITIZE_INT_OVERFLOW
27 : # define BOOST_URL_NO_SANITIZE_INT_OVERFLOW
28 : #endif
29 :
30 : namespace boost {
31 : namespace urls {
32 : namespace grammar {
33 :
34 : namespace detail {
35 :
36 : //------------------------------------------------
37 :
38 : // https://lemire.me/blog/2020/04/30/for-case-insensitive-string-comparisons-avoid-char-by-char-functions/
39 : // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2020/04/30/tolower.cpp
40 :
41 : bool
42 HIT 8 : ci_is_equal(
43 : core::string_view s0,
44 : core::string_view s1) noexcept
45 : {
46 8 : auto n = s0.size();
47 8 : auto p1 = s0.data();
48 8 : auto p2 = s1.data();
49 : char a, b;
50 : // fast loop
51 13 : while(n != 0)
52 : {
53 10 : --n;
54 10 : a = *p1++;
55 10 : b = *p2++;
56 10 : if(a != b)
57 5 : goto slow;
58 : }
59 3 : return true;
60 : for(;;)
61 : {
62 8 : a = *p1++;
63 8 : b = *p2++;
64 13 : slow:
65 26 : if( to_lower(a) !=
66 13 : to_lower(b))
67 MIS 0 : return false;
68 HIT 13 : if(n == 0)
69 5 : break;
70 8 : --n;
71 : }
72 5 : return true;
73 : }
74 :
75 : //------------------------------------------------
76 :
77 : bool
78 5 : ci_is_less(
79 : core::string_view s0,
80 : core::string_view s1) noexcept
81 : {
82 5 : auto p1 = s0.data();
83 5 : auto p2 = s1.data();
84 5 : auto n = s0.size() < s1.size()
85 5 : ? s0.size() : s1.size();
86 18 : while(n != 0)
87 : {
88 15 : --n;
89 15 : auto c1 = to_lower(*p1++);
90 15 : auto c2 = to_lower(*p2++);
91 15 : if(c1 != c2)
92 2 : return c1 < c2;
93 : }
94 3 : return s0.size() < s1.size();
95 : }
96 :
97 : } // detail
98 :
99 : //------------------------------------------------
100 :
101 : int
102 21 : ci_compare(
103 : core::string_view s0,
104 : core::string_view s1) noexcept
105 : {
106 : int bias;
107 : std::size_t n;
108 42 : if( s0.size() <
109 21 : s1.size())
110 : {
111 2 : bias = -1;
112 2 : n = s0.size();
113 : }
114 : else
115 : {
116 38 : if( s0.size() >
117 19 : s1.size())
118 2 : bias = 1;
119 : else
120 17 : bias = 0;
121 19 : n = s1.size();
122 : }
123 21 : auto it0 = s0.data();
124 21 : auto it1 = s1.data();
125 38 : while(n != 0)
126 : {
127 29 : --n;
128 : auto c0 =
129 29 : to_lower(*it0++);
130 : auto c1 =
131 29 : to_lower(*it1++);
132 29 : if(c0 == c1)
133 17 : continue;
134 12 : if(c0 < c1)
135 8 : return -1;
136 4 : return 1;
137 : }
138 9 : return bias;
139 : }
140 :
141 : //------------------------------------------------
142 :
143 : BOOST_URL_NO_SANITIZE_INT_OVERFLOW
144 : std::size_t
145 18 : ci_digest(
146 : core::string_view s) noexcept
147 : {
148 : // Only 4 and 8 byte sizes are supported
149 : static_assert(
150 : sizeof(std::size_t) == 4 ||
151 : sizeof(std::size_t) == 8, "");
152 18 : constexpr std::size_t prime = (
153 : sizeof(std::size_t) == 8) ?
154 : 0x100000001B3ULL :
155 : 0x01000193UL;
156 18 : constexpr std::size_t hash0 = (
157 : sizeof(std::size_t) == 8) ?
158 : 0xcbf29ce484222325ULL :
159 : 0x811C9DC5UL;
160 18 : auto hash = hash0;
161 18 : auto p = s.data();
162 18 : auto n = s.size();
163 56 : for(; n != 0; --n, ++p)
164 : {
165 : // VFALCO NOTE Consider using a lossy
166 : // to_lower which works 4 or 8 chars at a time.
167 38 : hash = (to_lower(*p) ^ hash) * prime;
168 : }
169 18 : return hash;
170 : }
171 :
172 : } // grammar
173 : } // urls
174 : } // boost
175 :
|