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