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