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