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  
//
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  
#ifndef BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
10  
#ifndef BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
11  
#define BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
11  
#define BOOST_URL_GRAMMAR_DETAIL_CHARSET_HPP
12  

12  

13  
#include <boost/core/bit.hpp>
13  
#include <boost/core/bit.hpp>
14  
#include <type_traits>
14  
#include <type_traits>
15  

15  

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

23  

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

28  

29  
namespace boost {
29  
namespace boost {
30  
namespace urls {
30  
namespace urls {
31  
namespace grammar {
31  
namespace grammar {
32  
namespace detail {
32  
namespace detail {
33  

33  

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

36  

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

47  

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

50  

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

61  

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

78  

79  
template<class Pred>
79  
template<class Pred>
80  
char const*
80  
char const*
81  
find_if(
81  
find_if(
82  
    char const* first,
82  
    char const* first,
83  
    char const* const last,
83  
    char const* const last,
84  
    Pred const& pred,
84  
    Pred const& pred,
85  
    std::true_type) noexcept
85  
    std::true_type) noexcept
86  
{
86  
{
87  
    return pred.find_if(
87  
    return pred.find_if(
88  
        first, last);
88  
        first, last);
89  
}
89  
}
90  

90  

91  
template<class Pred>
91  
template<class Pred>
92  
char const*
92  
char const*
93  
find_if_not(
93  
find_if_not(
94  
    char const* first,
94  
    char const* first,
95  
    char const* const last,
95  
    char const* const last,
96  
    Pred const& pred,
96  
    Pred const& pred,
97  
    std::false_type) noexcept
97  
    std::false_type) noexcept
98  
{
98  
{
99  
    while(first != last)
99  
    while(first != last)
100  
    {
100  
    {
101  
        if(! pred(*first))
101  
        if(! pred(*first))
102  
            break;
102  
            break;
103  
        ++first;
103  
        ++first;
104  
    }
104  
    }
105  
    return first;
105  
    return first;
106  
}
106  
}
107  

107  

108  
template<class Pred>
108  
template<class Pred>
109  
char const*
109  
char const*
110  
find_if_not(
110  
find_if_not(
111  
    char const* first,
111  
    char const* first,
112  
    char const* const last,
112  
    char const* const last,
113  
    Pred const& pred,
113  
    Pred const& pred,
114  
    std::true_type) noexcept
114  
    std::true_type) noexcept
115  
{
115  
{
116  
    return pred.find_if_not(
116  
    return pred.find_if_not(
117  
        first, last);
117  
        first, last);
118  
}
118  
}
119  

119  

120  
#ifdef BOOST_URL_USE_SSE2
120  
#ifdef BOOST_URL_USE_SSE2
121  

121  

122  
// by Peter Dimov
122  
// by Peter Dimov
123  
template<class Pred>
123  
template<class Pred>
124  
char const*
124  
char const*
125  
find_if_pred(
125  
find_if_pred(
126  
    Pred const& pred,
126  
    Pred const& pred,
127  
    char const* first,
127  
    char const* first,
128  
    char const* last ) noexcept
128  
    char const* last ) noexcept
129  
{
129  
{
130  
    while( last - first >= 16 )
130  
    while( last - first >= 16 )
131  
    {
131  
    {
132  
        unsigned char r[ 16 ] = {};
132  
        unsigned char r[ 16 ] = {};
133  
        for( int i = 0; i < 16; ++i )
133  
        for( int i = 0; i < 16; ++i )
134  
            r[ i ] = pred( first[ i ] )? 0xFF: 0x00;
134  
            r[ i ] = pred( first[ i ] )? 0xFF: 0x00;
135  
        __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
135  
        __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
136  
        unsigned r3 = _mm_movemask_epi8( r2 );
136  
        unsigned r3 = _mm_movemask_epi8( r2 );
137  
        if( r3 )
137  
        if( r3 )
138  
            return first + boost::core::countr_zero( r3 );
138  
            return first + boost::core::countr_zero( r3 );
139  
        first += 16;
139  
        first += 16;
140  
    }
140  
    }
141  
    while(
141  
    while(
142  
        first != last &&
142  
        first != last &&
143  
        ! pred(*first))
143  
        ! pred(*first))
144  
    {
144  
    {
145  
        ++first;
145  
        ++first;
146  
    }
146  
    }
147  
    return first;
147  
    return first;
148  
}
148  
}
149  

149  

150  
// by Peter Dimov
150  
// by Peter Dimov
151  
template<class Pred>
151  
template<class Pred>
152  
char const*
152  
char const*
153  
find_if_not_pred(
153  
find_if_not_pred(
154  
    Pred const& pred,
154  
    Pred const& pred,
155  
    char const* first,
155  
    char const* first,
156  
    char const* last ) noexcept
156  
    char const* last ) noexcept
157  
{
157  
{
158  
    while( last - first >= 16 )
158  
    while( last - first >= 16 )
159  
    {
159  
    {
160  
        unsigned char r[ 16 ] = {};
160  
        unsigned char r[ 16 ] = {};
161  
        for( int i = 0; i < 16; ++i )
161  
        for( int i = 0; i < 16; ++i )
162  
            r[ i ] = pred( first[ i ] )? 0x00: 0xFF;
162  
            r[ i ] = pred( first[ i ] )? 0x00: 0xFF;
163  
        __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
163  
        __m128i r2 = _mm_loadu_si128( (__m128i const*)r );
164  
        unsigned r3 = _mm_movemask_epi8( r2 );
164  
        unsigned r3 = _mm_movemask_epi8( r2 );
165  
        if( r3 )
165  
        if( r3 )
166  
            return first + boost::core::countr_zero( r3 );
166  
            return first + boost::core::countr_zero( r3 );
167  
        first += 16;
167  
        first += 16;
168  
    }
168  
    }
169  
    while(
169  
    while(
170  
        first != last &&
170  
        first != last &&
171  
        pred(*first))
171  
        pred(*first))
172  
    {
172  
    {
173  
        ++first;
173  
        ++first;
174  
    }
174  
    }
175  
    return first;
175  
    return first;
176  
}
176  
}
177  

177  

178  
#endif
178  
#endif
179  

179  

180  
} // detail
180  
} // detail
181  
} // grammar
181  
} // grammar
182  
} // urls
182  
} // urls
183  
} // boost
183  
} // boost
184  

184  

185  
#ifdef _MSC_VER
185  
#ifdef _MSC_VER
186  
#pragma warning(pop)
186  
#pragma warning(pop)
187  
#endif
187  
#endif
188  

188  

189  
#endif
189  
#endif