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