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_CI_STRING_HPP
11  
#ifndef BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP
12  
#define BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP
12  
#define BOOST_URL_GRAMMAR_DETAIL_CI_STRING_HPP
13  

13  

14  
#include <boost/core/detail/string_view.hpp>
14  
#include <boost/core/detail/string_view.hpp>
15  
#include <boost/assert.hpp>
15  
#include <boost/assert.hpp>
16  
#include <cstdint>
16  
#include <cstdint>
17  
#include <iterator>
17  
#include <iterator>
18  
#include <type_traits>
18  
#include <type_traits>
19  

19  

20  
namespace boost {
20  
namespace boost {
21  
namespace urls {
21  
namespace urls {
22  
namespace grammar {
22  
namespace grammar {
23  
namespace detail {
23  
namespace detail {
24  

24  

25  
template<class T, class = void>
25  
template<class T, class = void>
26  
struct is_char_iter : std::false_type {};
26  
struct is_char_iter : std::false_type {};
27  

27  

28  
template<class T>
28  
template<class T>
29  
struct is_char_iter<T, void_t<
29  
struct is_char_iter<T, void_t<
30  
    decltype(std::declval<char&>() =
30  
    decltype(std::declval<char&>() =
31  
        *std::declval<T const&>()),
31  
        *std::declval<T const&>()),
32  
    decltype(std::declval<T&>() =
32  
    decltype(std::declval<T&>() =
33  
        ++std::declval<T&>()),
33  
        ++std::declval<T&>()),
34  
    decltype(std::declval<bool&>() =
34  
    decltype(std::declval<bool&>() =
35  
        std::declval<T const&>() ==
35  
        std::declval<T const&>() ==
36  
        std::declval<T const&>())
36  
        std::declval<T const&>())
37  
    > > : std::integral_constant<bool,
37  
    > > : std::integral_constant<bool,
38  
        std::is_copy_constructible<T>::value>
38  
        std::is_copy_constructible<T>::value>
39  
{
39  
{
40  
};
40  
};
41  

41  

42  
template<class T, class = void>
42  
template<class T, class = void>
43  
struct is_char_range : std::false_type {};
43  
struct is_char_range : std::false_type {};
44  

44  

45  
template<class T>
45  
template<class T>
46  
struct is_char_range<T, void_t<
46  
struct is_char_range<T, void_t<
47  
    decltype(std::declval<T const&>().begin()),
47  
    decltype(std::declval<T const&>().begin()),
48  
    decltype(std::declval<T const&>().end())
48  
    decltype(std::declval<T const&>().end())
49  
    > > : std::integral_constant<bool,
49  
    > > : std::integral_constant<bool,
50  
        is_char_iter<decltype(
50  
        is_char_iter<decltype(
51  
            std::declval<T const&>(
51  
            std::declval<T const&>(
52  
                ).begin())>::value &&
52  
                ).begin())>::value &&
53  
        is_char_iter<decltype(
53  
        is_char_iter<decltype(
54  
            std::declval<T const&>(
54  
            std::declval<T const&>(
55  
                ).end())>::value>
55  
                ).end())>::value>
56  
{
56  
{
57  
};
57  
};
58  

58  

59  
template<class T>
59  
template<class T>
60  
struct type_id_impl
60  
struct type_id_impl
61  
{
61  
{
62  
    static
62  
    static
63  
    constexpr
63  
    constexpr
64  
    char cid = 0;
64  
    char cid = 0;
65  
};
65  
};
66  

66  

67  
template<class T>
67  
template<class T>
68  
constexpr
68  
constexpr
69  
char
69  
char
70  
type_id_impl<T>::cid;
70  
type_id_impl<T>::cid;
71  

71  

72  
template<class T>
72  
template<class T>
73  
constexpr
73  
constexpr
74  
std::uintptr_t
74  
std::uintptr_t
75  
type_id() noexcept
75  
type_id() noexcept
76  
{
76  
{
77  
    return std::uintptr_t(
77  
    return std::uintptr_t(
78  
        &type_id_impl<T>::cid);
78  
        &type_id_impl<T>::cid);
79  
}
79  
}
80  

80  

81  
//------------------------------------------------
81  
//------------------------------------------------
82  

82  

83  
constexpr
83  
constexpr
84  
char
84  
char
85  
to_lower(char c) noexcept
85  
to_lower(char c) noexcept
86  
{
86  
{
87  
    return
87  
    return
88  
      (c >= 'A' &&
88  
      (c >= 'A' &&
89  
       c <= 'Z')
89  
       c <= 'Z')
90  
        ? c + 'a' - 'A'
90  
        ? c + 'a' - 'A'
91  
        : c;
91  
        : c;
92  
}
92  
}
93  

93  

94  
constexpr
94  
constexpr
95  
char
95  
char
96  
to_upper(char c) noexcept
96  
to_upper(char c) noexcept
97  
{
97  
{
98  
    return
98  
    return
99  
      (c >= 'a' &&
99  
      (c >= 'a' &&
100  
       c <= 'z')
100  
       c <= 'z')
101  
        ? c - ('a' - 'A')
101  
        ? c - ('a' - 'A')
102  
        : c;
102  
        : c;
103  
}
103  
}
104  

104  

105  
//------------------------------------------------
105  
//------------------------------------------------
106  

106  

107  
template<class S0, class S1>
107  
template<class S0, class S1>
108  
auto
108  
auto
109  
ci_is_equal(
109  
ci_is_equal(
110  
    S0 const& s0,
110  
    S0 const& s0,
111  
    S1 const& s1) ->
111  
    S1 const& s1) ->
112  
        typename std::enable_if<
112  
        typename std::enable_if<
113  
            ! std::is_convertible<
113  
            ! std::is_convertible<
114  
                S0, core::string_view>::value ||
114  
                S0, core::string_view>::value ||
115  
            ! std::is_convertible<
115  
            ! std::is_convertible<
116  
                S1, core::string_view>::value,
116  
                S1, core::string_view>::value,
117  
        bool>::type
117  
        bool>::type
118  
{
118  
{
119  
/*  If you get a compile error here, it
119  
/*  If you get a compile error here, it
120  
    means that a range you passed does
120  
    means that a range you passed does
121  
    not meet the requirements stated
121  
    not meet the requirements stated
122  
    in the documentation.
122  
    in the documentation.
123  
*/
123  
*/
124  
    static_assert(
124  
    static_assert(
125  
        is_char_range<S0>::value,
125  
        is_char_range<S0>::value,
126  
        "Type requirements not met");
126  
        "Type requirements not met");
127  
    static_assert(
127  
    static_assert(
128  
        is_char_range<S1>::value,
128  
        is_char_range<S1>::value,
129  
        "Type requirements not met");
129  
        "Type requirements not met");
130  

130  

131  
    // Arguments are sorted by type to
131  
    // Arguments are sorted by type to
132  
    // reduce the number of function
132  
    // reduce the number of function
133  
    // template instantiations. This
133  
    // template instantiations. This
134  
    // works because:
134  
    // works because:
135  
    //
135  
    //
136  
    // ci_is_equal(s0,s1) == ci_is_equal(s1,s0)
136  
    // ci_is_equal(s0,s1) == ci_is_equal(s1,s0)
137  
    //
137  
    //
138  
    BOOST_ASSERT(
138  
    BOOST_ASSERT(
139  
        detail::type_id<S0>() <=
139  
        detail::type_id<S0>() <=
140  
        detail::type_id<S1>());
140  
        detail::type_id<S1>());
141  

141  

142  
    auto it0 = s0.begin();
142  
    auto it0 = s0.begin();
143  
    auto it1 = s1.begin();
143  
    auto it1 = s1.begin();
144  
    auto const end0 = s0.end();
144  
    auto const end0 = s0.end();
145  
    auto const end1 = s1.end();
145  
    auto const end1 = s1.end();
146  
    for(;;)
146  
    for(;;)
147  
    {
147  
    {
148  
        if(it0 == end0)
148  
        if(it0 == end0)
149  
            return it1 == end1;
149  
            return it1 == end1;
150  
        if(it1 == end1)
150  
        if(it1 == end1)
151  
            return false;
151  
            return false;
152  
        if( to_lower(*it0) !=
152  
        if( to_lower(*it0) !=
153  
            to_lower(*it1))
153  
            to_lower(*it1))
154  
            return false;
154  
            return false;
155  
        ++it0;
155  
        ++it0;
156  
        ++it1;
156  
        ++it1;
157  
    }
157  
    }
158  
}
158  
}
159  

159  

160  
//------------------------------------------------
160  
//------------------------------------------------
161  

161  

162  
BOOST_URL_DECL
162  
BOOST_URL_DECL
163  
bool
163  
bool
164  
ci_is_equal(
164  
ci_is_equal(
165  
    core::string_view s0,
165  
    core::string_view s0,
166  
    core::string_view s1) noexcept;
166  
    core::string_view s1) noexcept;
167  

167  

168  
BOOST_URL_DECL
168  
BOOST_URL_DECL
169  
bool
169  
bool
170  
ci_is_less(
170  
ci_is_less(
171  
    core::string_view s0,
171  
    core::string_view s0,
172  
    core::string_view s1) noexcept;
172  
    core::string_view s1) noexcept;
173  

173  

174  
} // detail
174  
} // detail
175  
} // grammar
175  
} // grammar
176  
} // urls
176  
} // urls
177  
} // boost
177  
} // boost
178  

178  

179  
#endif
179  
#endif