Line data Source code
1 : //
2 : // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 : // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/boostorg/url
9 : //
10 :
11 : #ifndef BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
12 : #define BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
13 :
14 : #include <boost/url/detail/config.hpp>
15 : #include <boost/core/bit.hpp>
16 : #include <type_traits>
17 :
18 : #ifdef BOOST_URL_USE_SSE2
19 : # include <emmintrin.h>
20 : # include <xmmintrin.h>
21 : # ifdef _MSC_VER
22 : # include <intrin.h>
23 : # endif
24 : #endif
25 :
26 : #ifdef _MSC_VER
27 : #pragma warning(push)
28 : #pragma warning(disable: 4127) // conditional expression is constant
29 : #endif
30 :
31 : namespace boost {
32 : namespace urls {
33 : namespace grammar {
34 : namespace detail {
35 :
36 : template<class T, class = void>
37 : struct has_find_if : std::false_type {};
38 :
39 : template<class T>
40 : struct has_find_if<T, void_t<
41 : decltype(
42 : std::declval<char const*&>() =
43 : std::declval<T const&>().find_if(
44 : std::declval<char const*>(),
45 : std::declval<char const*>())
46 : )>> : std::true_type
47 : {
48 : };
49 :
50 : template<class T, class = void>
51 : struct has_find_if_not : std::false_type {};
52 :
53 : template<class T>
54 : struct has_find_if_not<T, void_t<
55 : decltype(
56 : std::declval<char const*&>() =
57 : std::declval<T const&>().find_if_not(
58 : std::declval<char const*>(),
59 : std::declval<char const*>())
60 : )>> : std::true_type
61 : {
62 : };
63 :
64 : template<class Pred>
65 : BOOST_URL_CXX14_CONSTEXPR
66 : char const*
67 1 : find_if(
68 : char const* first,
69 : char const* const last,
70 : Pred const& pred,
71 : std::false_type) noexcept
72 : {
73 9 : while(first != last)
74 : {
75 9 : if(pred(*first))
76 1 : break;
77 8 : ++first;
78 : }
79 1 : return first;
80 : }
81 :
82 : template<class Pred>
83 : BOOST_URL_CXX14_CONSTEXPR
84 : char const*
85 2883 : find_if(
86 : char const* first,
87 : char const* const last,
88 : Pred const& pred,
89 : std::true_type) noexcept
90 : {
91 : #if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
92 : if (__builtin_is_constant_evaluated())
93 : return find_if(first, last, pred,
94 : std::false_type{});
95 : #endif
96 2883 : return pred.find_if(
97 2883 : first, last);
98 : }
99 :
100 : template<class Pred>
101 : BOOST_URL_CXX14_CONSTEXPR
102 : char const*
103 1 : find_if_not(
104 : char const* first,
105 : char const* const last,
106 : Pred const& pred,
107 : std::false_type) noexcept
108 : {
109 4 : while(first != last)
110 : {
111 4 : if(! pred(*first))
112 1 : break;
113 3 : ++first;
114 : }
115 1 : return first;
116 : }
117 :
118 : template<class Pred>
119 : BOOST_URL_CXX14_CONSTEXPR
120 : char const*
121 19028 : find_if_not(
122 : char const* first,
123 : char const* const last,
124 : Pred const& pred,
125 : std::true_type) noexcept
126 : {
127 : #if (__cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
128 : if (__builtin_is_constant_evaluated())
129 : return find_if_not(first, last, pred,
130 : std::false_type{});
131 : #endif
132 19028 : return pred.find_if_not(
133 19028 : first, last);
134 : }
135 :
136 : #ifdef BOOST_URL_USE_SSE2
137 :
138 : // by Peter Dimov
139 : template<class Pred>
140 : char const*
141 2627 : find_if_pred(
142 : Pred const& pred,
143 : char const* first,
144 : char const* last ) noexcept
145 : {
146 2936 : while( last - first >= 16 )
147 : {
148 642 : unsigned char r[ 16 ] = {};
149 10914 : for( int i = 0; i < 16; ++i )
150 10272 : r[ i ] = pred( first[ i ] )? 0xFF: 0x00;
151 642 : __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
152 642 : unsigned r3 = _mm_movemask_epi8( r2 );
153 642 : if( r3 )
154 333 : return first + boost::core::countr_zero( r3 );
155 309 : first += 16;
156 : }
157 2294 : while(
158 8452 : first != last &&
159 3323 : ! pred(*first))
160 : {
161 2835 : ++first;
162 : }
163 2294 : return first;
164 : }
165 :
166 : // by Peter Dimov
167 : template<class Pred>
168 : char const*
169 16198 : find_if_not_pred(
170 : Pred const& pred,
171 : char const* first,
172 : char const* last ) noexcept
173 : {
174 16601 : while( last - first >= 16 )
175 : {
176 4367 : unsigned char r[ 16 ] = {};
177 74239 : for( int i = 0; i < 16; ++i )
178 69872 : r[ i ] = pred( first[ i ] )? 0x00: 0xFF;
179 4367 : __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
180 4367 : unsigned r3 = _mm_movemask_epi8( r2 );
181 4367 : if( r3 )
182 3964 : return first + boost::core::countr_zero( r3 );
183 403 : first += 16;
184 : }
185 12234 : while(
186 83583 : first != last &&
187 39991 : pred(*first))
188 : {
189 31358 : ++first;
190 : }
191 12234 : return first;
192 : }
193 :
194 : #endif
195 :
196 : } // detail
197 : } // grammar
198 : } // urls
199 : } // boost
200 :
201 : #ifdef _MSC_VER
202 : #pragma warning(pop)
203 : #endif
204 :
205 : #endif
|