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