1  
//
1  
//
2  
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
2  
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
3  
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/url
8  
// Official repository: https://github.com/boostorg/url
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
11  
#ifndef BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
12  
#define BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
12  
#define BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
13  

13  

14  
#include <boost/url/detail/config.hpp>
14  
#include <boost/url/detail/config.hpp>
15  
#include <boost/core/bit.hpp>
15  
#include <boost/core/bit.hpp>
16  
#include <type_traits>
16  
#include <type_traits>
17  

17  

18  
#ifdef BOOST_URL_USE_SSE2
18  
#ifdef BOOST_URL_USE_SSE2
19  
# include <emmintrin.h>
19  
# include <emmintrin.h>
20  
# include <xmmintrin.h>
20  
# include <xmmintrin.h>
21  
# ifdef _MSC_VER
21  
# ifdef _MSC_VER
22  
#  include <intrin.h>
22  
#  include <intrin.h>
23  
# endif
23  
# endif
24  
#endif
24  
#endif
25  

25  

26  
#ifdef _MSC_VER
26  
#ifdef _MSC_VER
27  
#pragma warning(push)
27  
#pragma warning(push)
28  
#pragma warning(disable: 4127) // conditional expression is constant
28  
#pragma warning(disable: 4127) // conditional expression is constant
29  
#endif
29  
#endif
30  

30  

31  
namespace boost {
31  
namespace boost {
32  
namespace urls {
32  
namespace urls {
33  
namespace grammar {
33  
namespace grammar {
34  
namespace detail {
34  
namespace detail {
35  

35  

36  
template<class T, class = void>
36  
template<class T, class = void>
37  
struct has_find_if : std::false_type {};
37  
struct has_find_if : std::false_type {};
38  

38  

39  
template<class T>
39  
template<class T>
40  
struct has_find_if<T, void_t<
40  
struct has_find_if<T, void_t<
41  
    decltype(
41  
    decltype(
42  
    std::declval<char const*&>() =
42  
    std::declval<char const*&>() =
43  
        std::declval<T const&>().find_if(
43  
        std::declval<T const&>().find_if(
44  
            std::declval<char const*>(),
44  
            std::declval<char const*>(),
45  
            std::declval<char const*>())
45  
            std::declval<char const*>())
46  
            )>> : std::true_type
46  
            )>> : std::true_type
47  
{
47  
{
48  
};
48  
};
49  

49  

50  
template<class T, class = void>
50  
template<class T, class = void>
51  
struct has_find_if_not : std::false_type {};
51  
struct has_find_if_not : std::false_type {};
52  

52  

53  
template<class T>
53  
template<class T>
54  
struct has_find_if_not<T, void_t<
54  
struct has_find_if_not<T, void_t<
55  
    decltype(
55  
    decltype(
56  
    std::declval<char const*&>() =
56  
    std::declval<char const*&>() =
57  
        std::declval<T const&>().find_if_not(
57  
        std::declval<T const&>().find_if_not(
58  
            std::declval<char const*>(),
58  
            std::declval<char const*>(),
59  
            std::declval<char const*>())
59  
            std::declval<char const*>())
60  
            )>> : std::true_type
60  
            )>> : std::true_type
61  
{
61  
{
62  
};
62  
};
63  

63  

64  
template<class Pred>
64  
template<class Pred>
65  
BOOST_URL_CXX14_CONSTEXPR
65  
BOOST_URL_CXX14_CONSTEXPR
66  
char const*
66  
char const*
67  
find_if(
67  
find_if(
68  
    char const* first,
68  
    char const* first,
69  
    char const* const last,
69  
    char const* const last,
70  
    Pred const& pred,
70  
    Pred const& pred,
71  
    std::false_type) noexcept
71  
    std::false_type) noexcept
72  
{
72  
{
73  
    while(first != last)
73  
    while(first != last)
74  
    {
74  
    {
75  
        if(pred(*first))
75  
        if(pred(*first))
76  
            break;
76  
            break;
77  
        ++first;
77  
        ++first;
78  
    }
78  
    }
79  
    return first;
79  
    return first;
80  
}
80  
}
81  

81  

82  
template<class Pred>
82  
template<class Pred>
83  
BOOST_URL_CXX14_CONSTEXPR
83  
BOOST_URL_CXX14_CONSTEXPR
84  
char const*
84  
char const*
85  
find_if(
85  
find_if(
86  
    char const* first,
86  
    char const* first,
87  
    char const* const last,
87  
    char const* const last,
88  
    Pred const& pred,
88  
    Pred const& pred,
89  
    std::true_type) noexcept
89  
    std::true_type) noexcept
90  
{
90  
{
91  
#if defined(BOOST_URL_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
91  
#if defined(BOOST_URL_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
92  
    if (__builtin_is_constant_evaluated())
92  
    if (__builtin_is_constant_evaluated())
93  
        return find_if(first, last, pred,
93  
        return find_if(first, last, pred,
94  
            std::false_type{});
94  
            std::false_type{});
95  
#endif
95  
#endif
96  
    return pred.find_if(
96  
    return pred.find_if(
97  
        first, last);
97  
        first, last);
98  
}
98  
}
99  

99  

100  
template<class Pred>
100  
template<class Pred>
101  
BOOST_URL_CXX14_CONSTEXPR
101  
BOOST_URL_CXX14_CONSTEXPR
102  
char const*
102  
char const*
103  
find_if_not(
103  
find_if_not(
104  
    char const* first,
104  
    char const* first,
105  
    char const* const last,
105  
    char const* const last,
106  
    Pred const& pred,
106  
    Pred const& pred,
107  
    std::false_type) noexcept
107  
    std::false_type) noexcept
108  
{
108  
{
109  
    while(first != last)
109  
    while(first != last)
110  
    {
110  
    {
111  
        if(! pred(*first))
111  
        if(! pred(*first))
112  
            break;
112  
            break;
113  
        ++first;
113  
        ++first;
114  
    }
114  
    }
115  
    return first;
115  
    return first;
116  
}
116  
}
117  

117  

118  
template<class Pred>
118  
template<class Pred>
119  
BOOST_URL_CXX14_CONSTEXPR
119  
BOOST_URL_CXX14_CONSTEXPR
120  
char const*
120  
char const*
121  
find_if_not(
121  
find_if_not(
122  
    char const* first,
122  
    char const* first,
123  
    char const* const last,
123  
    char const* const last,
124  
    Pred const& pred,
124  
    Pred const& pred,
125  
    std::true_type) noexcept
125  
    std::true_type) noexcept
126  
{
126  
{
127  
#if defined(BOOST_URL_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
127  
#if defined(BOOST_URL_HAS_BUILTIN_IS_CONSTANT_EVALUATED)
128  
    if (__builtin_is_constant_evaluated())
128  
    if (__builtin_is_constant_evaluated())
129  
        return find_if_not(first, last, pred,
129  
        return find_if_not(first, last, pred,
130  
            std::false_type{});
130  
            std::false_type{});
131  
#endif
131  
#endif
132  
    return pred.find_if_not(
132  
    return pred.find_if_not(
133  
        first, last);
133  
        first, last);
134  
}
134  
}
135  

135  

136  
#ifdef BOOST_URL_USE_SSE2
136  
#ifdef BOOST_URL_USE_SSE2
137  

137  

138  
// by Peter Dimov
138  
// by Peter Dimov
139  
template<class Pred>
139  
template<class Pred>
140  
char const*
140  
char const*
141  
find_if_pred(
141  
find_if_pred(
142  
    Pred const& pred,
142  
    Pred const& pred,
143  
    char const* first,
143  
    char const* first,
144  
    char const* last ) noexcept
144  
    char const* last ) noexcept
145  
{
145  
{
146  
    while( last - first >= 16 )
146  
    while( last - first >= 16 )
147  
    {
147  
    {
148  
        unsigned char r[ 16 ] = {};
148  
        unsigned char r[ 16 ] = {};
149  
        for( int i = 0; i < 16; ++i )
149  
        for( int i = 0; i < 16; ++i )
150  
            r[ i ] = pred( first[ i ] )? 0xFF: 0x00;
150  
            r[ i ] = pred( first[ i ] )? 0xFF: 0x00;
151  
        __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
151  
        __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
152  
        unsigned r3 = _mm_movemask_epi8( r2 );
152  
        unsigned r3 = _mm_movemask_epi8( r2 );
153  
        if( r3 )
153  
        if( r3 )
154  
            return first + boost::core::countr_zero( r3 );
154  
            return first + boost::core::countr_zero( r3 );
155  
        first += 16;
155  
        first += 16;
156  
    }
156  
    }
157  
    while(
157  
    while(
158  
        first != last &&
158  
        first != last &&
159  
        ! pred(*first))
159  
        ! pred(*first))
160  
    {
160  
    {
161  
        ++first;
161  
        ++first;
162  
    }
162  
    }
163  
    return first;
163  
    return first;
164  
}
164  
}
165  

165  

166  
// by Peter Dimov
166  
// by Peter Dimov
167  
template<class Pred>
167  
template<class Pred>
168  
char const*
168  
char const*
169  
find_if_not_pred(
169  
find_if_not_pred(
170  
    Pred const& pred,
170  
    Pred const& pred,
171  
    char const* first,
171  
    char const* first,
172  
    char const* last ) noexcept
172  
    char const* last ) noexcept
173  
{
173  
{
174  
    while( last - first >= 16 )
174  
    while( last - first >= 16 )
175  
    {
175  
    {
176  
        unsigned char r[ 16 ] = {};
176  
        unsigned char r[ 16 ] = {};
177  
        for( int i = 0; i < 16; ++i )
177  
        for( int i = 0; i < 16; ++i )
178  
            r[ i ] = pred( first[ i ] )? 0x00: 0xFF;
178  
            r[ i ] = pred( first[ i ] )? 0x00: 0xFF;
179  
        __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
179  
        __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
180  
        unsigned r3 = _mm_movemask_epi8( r2 );
180  
        unsigned r3 = _mm_movemask_epi8( r2 );
181  
        if( r3 )
181  
        if( r3 )
182  
            return first + boost::core::countr_zero( r3 );
182  
            return first + boost::core::countr_zero( r3 );
183  
        first += 16;
183  
        first += 16;
184  
    }
184  
    }
185  
    while(
185  
    while(
186  
        first != last &&
186  
        first != last &&
187  
        pred(*first))
187  
        pred(*first))
188  
    {
188  
    {
189  
        ++first;
189  
        ++first;
190  
    }
190  
    }
191  
    return first;
191  
    return first;
192  
}
192  
}
193  

193  

194  
#endif
194  
#endif
195  

195  

196  
} // detail
196  
} // detail
197  
} // grammar
197  
} // grammar
198  
} // urls
198  
} // urls
199  
} // boost
199  
} // boost
200  

200  

201  
#ifdef _MSC_VER
201  
#ifdef _MSC_VER
202  
#pragma warning(pop)
202  
#pragma warning(pop)
203  
#endif
203  
#endif
204  

204  

205  
#endif
205  
#endif