Line data Source code
1 : // 2 : // Copyright (c) 2021 Vinnie Falco (vinnie dot falco at gmail dot com) 3 : // 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) 6 : // 7 : // Official repository: https://github.com/boostorg/url 8 : // 9 : 10 : #ifndef BOOST_URL_GRAMMAR_CHARSET_HPP 11 : #define BOOST_URL_GRAMMAR_CHARSET_HPP 12 : 13 : #include <boost/url/detail/config.hpp> 14 : #include <boost/url/grammar/detail/charset.hpp> 15 : #include <boost/static_assert.hpp> 16 : #include <cstdint> 17 : #include <type_traits> 18 : #include <utility> 19 : 20 : namespace boost { 21 : namespace urls { 22 : namespace grammar { 23 : 24 : /** Alias for `std::true_type` if T satisfies <em>CharSet</em>. 25 : 26 : This metafunction determines if the 27 : type `T` meets these requirements of 28 : <em>CharSet</em>: 29 : 30 : @li An instance of `T` is invocable 31 : with this equivalent function signature: 32 : @code 33 : bool T::operator()( char ) const noexcept; 34 : @endcode 35 : 36 : @par Example 37 : Use with `enable_if` on the return value: 38 : @code 39 : template< class CharSet > 40 : typename std::enable_if< is_charset<T>::value >::type 41 : func( CharSet const& cs ); 42 : @endcode 43 : 44 : @tparam T the type to check. 45 : */ 46 : #ifdef BOOST_URL_DOCS 47 : template<class T> 48 : using is_charset = __see_below__; 49 : #else 50 : template<class T, class = void> 51 : struct is_charset : std::false_type {}; 52 : 53 : template<class T> 54 : struct is_charset<T, void_t< 55 : decltype( 56 : std::declval<bool&>() = 57 : std::declval<T const&>().operator()( 58 : std::declval<char>()) 59 : ) > > : std::true_type 60 : { 61 : }; 62 : #endif 63 : 64 : //------------------------------------------------ 65 : 66 : /** Find the first character in the string that is in the set. 67 : 68 : @par Exception Safety 69 : Throws nothing. 70 : 71 : @return A pointer to the found character, 72 : otherwise the value `last`. 73 : 74 : @param first A pointer to the first character 75 : in the string to search. 76 : 77 : @param last A pointer to one past the last 78 : character in the string to search. 79 : 80 : @param cs The character set to use. 81 : 82 : @see 83 : @ref find_if_not. 84 : */ 85 : template<class CharSet> 86 : char const* 87 2884 : find_if( 88 : char const* const first, 89 : char const* const last, 90 : CharSet const& cs) noexcept 91 : { 92 : // If you get a compile error here 93 : // it means your type does not meet 94 : // the requirements. Please check the 95 : // documentation. 96 : static_assert( 97 : is_charset<CharSet>::value, 98 : "CharSet requirements not met"); 99 : 100 5768 : return detail::find_if(first, last, cs, 101 2884 : detail::has_find_if<CharSet>{}); 102 : } 103 : 104 : /** Find the first character in the string that is not in CharSet 105 : 106 : @par Exception Safety 107 : Throws nothing. 108 : 109 : @return A pointer to the found character, 110 : otherwise the value `last`. 111 : 112 : @param first A pointer to the first character 113 : in the string to search. 114 : 115 : @param last A pointer to one past the last 116 : character in the string to search. 117 : 118 : @param cs The character set to use. 119 : 120 : @see 121 : @ref find_if_not. 122 : */ 123 : template<class CharSet> 124 : char const* 125 17458 : find_if_not( 126 : char const* const first, 127 : char const* const last, 128 : CharSet const& cs) noexcept 129 : { 130 : // If you get a compile error here 131 : // it means your type does not meet 132 : // the requirements. Please check the 133 : // documentation. 134 : static_assert( 135 : is_charset<CharSet>::value, 136 : "CharSet requirements not met"); 137 : 138 34916 : return detail::find_if_not(first, last, cs, 139 17458 : detail::has_find_if_not<CharSet>{}); 140 : } 141 : 142 : //------------------------------------------------ 143 : 144 : #ifndef BOOST_URL_DOCS 145 : namespace detail { 146 : 147 : template<class CharSet> 148 : struct charset_ref 149 : { 150 : CharSet const& cs_; 151 : 152 : constexpr 153 : bool 154 : operator()(char ch) const noexcept 155 : { 156 : return cs_(ch); 157 : } 158 : 159 : char const* 160 : find_if( 161 : char const* first, 162 : char const* last) const noexcept 163 : { 164 : return grammar::find_if( 165 : first, last, cs_); 166 : } 167 : 168 : char const* 169 2334 : find_if_not( 170 : char const* first, 171 : char const* last) const noexcept 172 : { 173 2334 : return grammar::find_if_not( 174 2334 : first, last, cs_ ); 175 : } 176 : }; 177 : 178 : } // detail 179 : #endif 180 : 181 : /** Return a reference to a character set 182 : 183 : This function returns a character set which 184 : references the specified object. This is 185 : used to reduce the number of bytes of 186 : storage (`sizeof`) required by a combinator 187 : when it stores a copy of the object. 188 : <br> 189 : Ownership of the object is not transferred; 190 : the caller is responsible for ensuring the 191 : lifetime of the object is extended until it 192 : is no longer referenced. For best results, 193 : `ref` should only be used with compile-time 194 : constants. 195 : */ 196 : template<class CharSet> 197 : constexpr 198 : #ifdef BOOST_URL_DOCS 199 : __implementation_defined__ 200 : #else 201 : typename std::enable_if< 202 : is_charset<CharSet>::value && 203 : ! std::is_same<CharSet, 204 : detail::charset_ref<CharSet> >::value, 205 : detail::charset_ref<CharSet> >::type 206 : #endif 207 2184 : ref(CharSet const& cs) noexcept 208 : { 209 : return detail::charset_ref< 210 2184 : CharSet>{cs}; 211 : } 212 : 213 : } // grammar 214 : } // urls 215 : } // boost 216 : 217 : #endif