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 : #ifdef BOOST_URL_HAS_CONCEPTS
21 : #include <concepts>
22 : #endif
23 :
24 : namespace boost {
25 : namespace urls {
26 : namespace grammar {
27 :
28 : namespace implementation_defined
29 : {
30 : template<class T, class = void>
31 : struct is_charset : std::false_type {};
32 :
33 : template<class T>
34 : struct is_charset<T, void_t<
35 : decltype(
36 : std::declval<bool&>() =
37 : std::declval<T const&>().operator()(
38 : std::declval<char>())
39 : ) > > : std::true_type
40 : {
41 : };
42 : }
43 :
44 : /** Alias for `std::true_type` if T satisfies @ref CharSet.
45 :
46 : This metafunction determines if the
47 : type `T` meets these requirements of
48 : <em>CharSet</em>:
49 :
50 : @li An instance of `T` is invocable
51 : with this equivalent function signature:
52 : @code
53 : bool T::operator()( char ) const noexcept;
54 : @endcode
55 :
56 : @par Example
57 : Use with `enable_if` on the return value:
58 : @code
59 : template< class CharSet >
60 : typename std::enable_if< is_charset<T>::value >::type
61 : func( CharSet const& cs );
62 : @endcode
63 :
64 : @tparam T the type to check.
65 : */
66 : template<class T>
67 : using is_charset = BOOST_URL_SEE_BELOW(implementation_defined::is_charset<T>);
68 :
69 : #ifdef BOOST_URL_HAS_CONCEPTS
70 : /** Concept for a CharSet
71 :
72 : A `CharSet` is a unary predicate which is invocable with
73 : this equivalent signature:
74 :
75 : @code
76 : bool( char ch ) const noexcept;
77 : @endcode
78 :
79 : The predicate returns `true` if `ch` is a member of the
80 : set, or `false` otherwise.
81 :
82 : @par Exemplar
83 :
84 : For best results, it is suggested that all constructors and
85 : member functions for character sets be marked `constexpr`.
86 :
87 : @code
88 : struct CharSet
89 : {
90 : bool operator()( char c ) const noexcept;
91 :
92 : // These are both optional. If either or both are left
93 : // unspecified, a default implementation will be used.
94 : //
95 : char const* find_if( char const* first, char const* last ) const noexcept;
96 : char const* find_if_not( char const* first, char const* last ) const noexcept;
97 : };
98 : @endcode
99 :
100 : @par Models
101 :
102 : @li @ref alnum_chars
103 : @li @ref alpha_chars
104 : @li @ref digit_chars
105 : @li @ref hexdig_chars
106 : @li @ref lut_chars
107 :
108 : @see
109 : @ref is_charset,
110 : @ref find_if,
111 : @ref find_if_not.
112 :
113 : */
114 : template <class T>
115 : concept CharSet =
116 : requires (T const t, char c)
117 : {
118 : { t(c) } -> std::convertible_to<bool>;
119 : };
120 : #endif
121 :
122 :
123 : //------------------------------------------------
124 :
125 : /** Find the first character in the string that is in the set.
126 :
127 : @par Exception Safety
128 : Throws nothing.
129 :
130 : @return A pointer to the found character,
131 : otherwise the value `last`.
132 :
133 : @param first A pointer to the first character
134 : in the string to search.
135 :
136 : @param last A pointer to one past the last
137 : character in the string to search.
138 :
139 : @param cs The character set to use.
140 :
141 : @see
142 : @ref find_if_not.
143 : */
144 : template<BOOST_URL_CONSTRAINT(CharSet) CS>
145 : char const*
146 2884 : find_if(
147 : char const* const first,
148 : char const* const last,
149 : CS const& cs) noexcept
150 : {
151 : // If you get a compile error here
152 : // it means your type does not meet
153 : // the requirements. Please check the
154 : // documentation.
155 : static_assert(
156 : is_charset<CS>::value,
157 : "CharSet requirements not met");
158 :
159 5768 : return detail::find_if(first, last, cs,
160 2884 : detail::has_find_if<CS>{});
161 : }
162 :
163 : /** Find the first character in the string that is not in CharSet
164 :
165 : @par Exception Safety
166 : Throws nothing.
167 :
168 : @return A pointer to the found character,
169 : otherwise the value `last`.
170 :
171 : @param first A pointer to the first character
172 : in the string to search.
173 :
174 : @param last A pointer to one past the last
175 : character in the string to search.
176 :
177 : @param cs The character set to use.
178 :
179 : @see
180 : @ref find_if_not.
181 : */
182 : template<BOOST_URL_CONSTRAINT(CharSet) CS>
183 : char const*
184 17738 : find_if_not(
185 : char const* const first,
186 : char const* const last,
187 : CS const& cs) noexcept
188 : {
189 : // If you get a compile error here
190 : // it means your type does not meet
191 : // the requirements. Please check the
192 : // documentation.
193 : static_assert(
194 : is_charset<CS>::value,
195 : "CharSet requirements not met");
196 :
197 35476 : return detail::find_if_not(first, last, cs,
198 17738 : detail::has_find_if_not<CS>{});
199 : }
200 :
201 : //------------------------------------------------
202 :
203 : namespace implementation_defined {
204 : template<class CharSet>
205 : struct charset_ref
206 : {
207 : CharSet const& cs_;
208 :
209 : constexpr
210 : bool
211 : operator()(char ch) const noexcept
212 : {
213 : return cs_(ch);
214 : }
215 :
216 : char const*
217 : find_if(
218 : char const* first,
219 : char const* last) const noexcept
220 : {
221 : return grammar::find_if(
222 : first, last, cs_);
223 : }
224 :
225 : char const*
226 2385 : find_if_not(
227 : char const* first,
228 : char const* last) const noexcept
229 : {
230 2385 : return grammar::find_if_not(
231 2385 : first, last, cs_ );
232 : }
233 : };
234 : } // implementation_defined
235 :
236 : /** Return a reference to a character set
237 :
238 : This function returns a character set which
239 : references the specified object. This is
240 : used to reduce the number of bytes of
241 : storage (`sizeof`) required by a combinator
242 : when it stores a copy of the object.
243 : <br>
244 : Ownership of the object is not transferred;
245 : the caller is responsible for ensuring the
246 : lifetime of the object is extended until it
247 : is no longer referenced. For best results,
248 : `ref` should only be used with compile-time
249 : constants.
250 : */
251 : template<BOOST_URL_CONSTRAINT(CharSet) CS>
252 : constexpr
253 : typename std::enable_if<
254 : is_charset<CS>::value &&
255 : ! std::is_same<CS,
256 : implementation_defined::charset_ref<CS> >::value,
257 : implementation_defined::charset_ref<CS> >::type
258 2235 : ref(CS const& cs) noexcept
259 : {
260 2235 : return implementation_defined::charset_ref<CS>{cs};
261 : }
262 :
263 : } // grammar
264 : } // urls
265 : } // boost
266 :
267 : #endif
|