src/grammar/ci_string.cpp

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