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 : namespace boost {
15 : namespace urls {
16 : namespace grammar {
17 :
18 : namespace detail {
19 :
20 : //------------------------------------------------
21 :
22 : // https://lemire.me/blog/2020/04/30/for-case-insensitive-string-comparisons-avoid-char-by-char-functions/
23 : // https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/blob/master/2020/04/30/tolower.cpp
24 :
25 : bool
26 HIT 8 : ci_is_equal(
27 : core::string_view s0,
28 : core::string_view s1) noexcept
29 : {
30 8 : auto n = s0.size();
31 8 : auto p1 = s0.data();
32 8 : auto p2 = s1.data();
33 : char a, b;
34 : // fast loop
35 13 : while(n--)
36 : {
37 10 : a = *p1++;
38 10 : b = *p2++;
39 10 : if(a != b)
40 5 : goto slow;
41 : }
42 3 : return true;
43 : do
44 : {
45 8 : a = *p1++;
46 8 : b = *p2++;
47 13 : slow:
48 26 : if( to_lower(a) !=
49 13 : to_lower(b))
50 MIS 0 : return false;
51 : }
52 HIT 13 : while(n--);
53 5 : return true;
54 : }
55 :
56 : //------------------------------------------------
57 :
58 : bool
59 5 : ci_is_less(
60 : core::string_view s0,
61 : core::string_view s1) noexcept
62 : {
63 5 : auto p1 = s0.data();
64 5 : auto p2 = s1.data();
65 5 : auto n = s0.size() < s1.size()
66 5 : ? s0.size() : s1.size();
67 18 : while(n--)
68 : {
69 15 : auto c1 = to_lower(*p1++);
70 15 : auto c2 = to_lower(*p2++);
71 15 : if(c1 != c2)
72 2 : return c1 < c2;
73 : }
74 3 : return s0.size() < s1.size();
75 : }
76 :
77 : } // detail
78 :
79 : //------------------------------------------------
80 :
81 : int
82 21 : ci_compare(
83 : core::string_view s0,
84 : core::string_view s1) noexcept
85 : {
86 : int bias;
87 : std::size_t n;
88 42 : if( s0.size() <
89 21 : s1.size())
90 : {
91 2 : bias = -1;
92 2 : n = s0.size();
93 : }
94 : else
95 : {
96 38 : if( s0.size() >
97 19 : s1.size())
98 2 : bias = 1;
99 : else
100 17 : bias = 0;
101 19 : n = s1.size();
102 : }
103 21 : auto it0 = s0.data();
104 21 : auto it1 = s1.data();
105 38 : while(n--)
106 : {
107 : auto c0 =
108 29 : to_lower(*it0++);
109 : auto c1 =
110 29 : to_lower(*it1++);
111 29 : if(c0 == c1)
112 17 : continue;
113 12 : if(c0 < c1)
114 8 : return -1;
115 4 : return 1;
116 : }
117 9 : return bias;
118 : }
119 :
120 : //------------------------------------------------
121 :
122 : std::size_t
123 18 : ci_digest(
124 : core::string_view s) noexcept
125 : {
126 : // Only 4 and 8 byte sizes are supported
127 : static_assert(
128 : sizeof(std::size_t) == 4 ||
129 : sizeof(std::size_t) == 8, "");
130 18 : constexpr std::size_t prime = (
131 : sizeof(std::size_t) == 8) ?
132 : 0x100000001B3ULL :
133 : 0x01000193UL;
134 18 : constexpr std::size_t hash0 = (
135 : sizeof(std::size_t) == 8) ?
136 : 0xcbf29ce484222325ULL :
137 : 0x811C9DC5UL;
138 18 : auto hash = hash0;
139 18 : auto p = s.data();
140 18 : auto n = s.size();
141 56 : for(;n--;++p)
142 : {
143 : // VFALCO NOTE Consider using a lossy
144 : // to_lower which works 4 or 8 chars at a time.
145 38 : hash = (to_lower(*p) ^ hash) * prime;
146 : }
147 18 : return hash;
148 : }
149 :
150 : } // grammar
151 : } // urls
152 : } // boost
153 :
|