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