100.00% Lines (25/25) 100.00% Functions (10/10)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.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_PCT_STRING_VIEW_HPP 11   #ifndef BOOST_URL_PCT_STRING_VIEW_HPP
12   #define BOOST_URL_PCT_STRING_VIEW_HPP 12   #define BOOST_URL_PCT_STRING_VIEW_HPP
13   13  
14   #include <boost/url/detail/config.hpp> 14   #include <boost/url/detail/config.hpp>
15   #include <boost/url/encoding_opts.hpp> 15   #include <boost/url/encoding_opts.hpp>
16   #include <boost/url/error_types.hpp> 16   #include <boost/url/error_types.hpp>
17   #include <boost/core/detail/string_view.hpp> 17   #include <boost/core/detail/string_view.hpp>
18   #include <boost/url/grammar/string_token.hpp> 18   #include <boost/url/grammar/string_token.hpp>
19   #include <boost/url/grammar/string_view_base.hpp> 19   #include <boost/url/grammar/string_view_base.hpp>
20   #include <cstddef> 20   #include <cstddef>
21   #include <iterator> 21   #include <iterator>
22   #include <string> 22   #include <string>
23   #include <type_traits> 23   #include <type_traits>
24   #include <utility> 24   #include <utility>
25   25  
26   namespace boost { 26   namespace boost {
27   namespace urls { 27   namespace urls {
28   28  
29   //------------------------------------------------ 29   //------------------------------------------------
30   30  
31   #ifndef BOOST_URL_DOCS 31   #ifndef BOOST_URL_DOCS
32   class decode_view; 32   class decode_view;
33   class pct_string_view; 33   class pct_string_view;
34   34  
35   BOOST_CXX14_CONSTEXPR 35   BOOST_CXX14_CONSTEXPR
36   pct_string_view 36   pct_string_view
37   make_pct_string_view_unsafe( 37   make_pct_string_view_unsafe(
38   char const*, std::size_t, 38   char const*, std::size_t,
39   std::size_t) noexcept; 39   std::size_t) noexcept;
40   40  
41   namespace detail { 41   namespace detail {
42   core::string_view& 42   core::string_view&
43   ref(pct_string_view& s) noexcept; 43   ref(pct_string_view& s) noexcept;
44   } // detail 44   } // detail
45   #endif 45   #endif
46   46  
47   //------------------------------------------------ 47   //------------------------------------------------
48   48  
49   /** A reference to a valid percent-encoded string 49   /** A reference to a valid percent-encoded string
50   50  
51   Objects of this type behave like a 51   Objects of this type behave like a
52   `core::string_view` and have the same interface, 52   `core::string_view` and have the same interface,
53   but offer an additional invariant: they can 53   but offer an additional invariant: they can
54   only be constructed from strings containing 54   only be constructed from strings containing
55   valid percent-escapes. 55   valid percent-escapes.
56   56  
57   Attempting construction from a string 57   Attempting construction from a string
58   containing invalid or malformed percent 58   containing invalid or malformed percent
59   escapes results in an exception. 59   escapes results in an exception.
60   */ 60   */
61   class pct_string_view final 61   class pct_string_view final
62   : public grammar::string_view_base 62   : public grammar::string_view_base
63   { 63   {
64   std::size_t dn_ = 0; 64   std::size_t dn_ = 0;
65   65  
66   #ifndef BOOST_URL_DOCS 66   #ifndef BOOST_URL_DOCS
67   friend 67   friend
68   BOOST_CXX14_CONSTEXPR 68   BOOST_CXX14_CONSTEXPR
69   pct_string_view 69   pct_string_view
70   make_pct_string_view_unsafe( 70   make_pct_string_view_unsafe(
71   char const*, std::size_t, 71   char const*, std::size_t,
72   std::size_t) noexcept; 72   std::size_t) noexcept;
73   73  
74   friend 74   friend
75   core::string_view& 75   core::string_view&
76   detail::ref(pct_string_view&) noexcept; 76   detail::ref(pct_string_view&) noexcept;
77   #endif 77   #endif
78   78  
79   // unsafe 79   // unsafe
80   BOOST_CXX14_CONSTEXPR 80   BOOST_CXX14_CONSTEXPR
HITCBC 81   137903 pct_string_view( 81   138519 pct_string_view(
82   char const* data, 82   char const* data,
83   std::size_t size, 83   std::size_t size,
84   std::size_t dn) noexcept 84   std::size_t dn) noexcept
HITCBC 85   137903 : string_view_base(data, size) 85   138519 : string_view_base(data, size)
HITCBC 86   137903 , dn_(dn) 86   138519 , dn_(dn)
87   { 87   {
HITCBC 88   137903 } 88   138519 }
89   89  
90   BOOST_URL_DECL 90   BOOST_URL_DECL
91   void 91   void
92   decode_impl( 92   decode_impl(
93   string_token::arg& dest, 93   string_token::arg& dest,
94   encoding_opts opt) const; 94   encoding_opts opt) const;
95   95  
96   public: 96   public:
97   /** Constructor 97   /** Constructor
98   98  
99   Default constructed string are empty. 99   Default constructed string are empty.
100   100  
101   @par Complexity 101   @par Complexity
102   Constant. 102   Constant.
103   103  
104   @par Exception Safety 104   @par Exception Safety
105   Throws nothing. 105   Throws nothing.
106   */ 106   */
HITCBC 107   89332 constexpr pct_string_view() = default; 107   89340 constexpr pct_string_view() = default;
108   108  
109   /** Constructor 109   /** Constructor
110   110  
111   The copy references the same 111   The copy references the same
112   underlying character buffer. 112   underlying character buffer.
113   Ownership is not transferred. 113   Ownership is not transferred.
114   114  
115   @par Postconditions 115   @par Postconditions
116   @code 116   @code
117   this->data() == other.data() 117   this->data() == other.data()
118   @endcode 118   @endcode
119   119  
120   @par Complexity 120   @par Complexity
121   Constant. 121   Constant.
122   122  
123   @par Exception Safety 123   @par Exception Safety
124   Throws nothing. 124   Throws nothing.
125   125  
126   @param other The string to copy. 126   @param other The string to copy.
127   127  
128   */ 128   */
129   constexpr 129   constexpr
130   pct_string_view( 130   pct_string_view(
131   pct_string_view const& other) = default; 131   pct_string_view const& other) = default;
132   132  
133   /** Constructor 133   /** Constructor
134   134  
135   The newly constructed string references 135   The newly constructed string references
136   the specified character buffer. 136   the specified character buffer.
137   Ownership is not transferred. 137   Ownership is not transferred.
138   138  
139   @par Postconditions 139   @par Postconditions
140   @code 140   @code
141   this->data() == core::string_view(s).data() 141   this->data() == core::string_view(s).data()
142   @endcode 142   @endcode
143   143  
144   @par Complexity 144   @par Complexity
145   Linear in `core::string_view(s).size()`. 145   Linear in `core::string_view(s).size()`.
146   146  
147   @par Exception Safety 147   @par Exception Safety
148   Exceptions thrown on invalid input. 148   Exceptions thrown on invalid input.
149   149  
150   @throw system_error 150   @throw system_error
151   The string contains an invalid percent encoding. 151   The string contains an invalid percent encoding.
152   152  
153   @tparam String A type convertible to `core::string_view` 153   @tparam String A type convertible to `core::string_view`
154   154  
155   @param s The string to construct from. 155   @param s The string to construct from.
156   */ 156   */
157   template< 157   template<
158   BOOST_URL_CONSTRAINT(std::convertible_to<core::string_view>) String 158   BOOST_URL_CONSTRAINT(std::convertible_to<core::string_view>) String
159   #ifndef BOOST_URL_DOCS 159   #ifndef BOOST_URL_DOCS
160   , class = typename std::enable_if< 160   , class = typename std::enable_if<
161   std::is_convertible< 161   std::is_convertible<
162   String, 162   String,
163   core::string_view 163   core::string_view
164   >::value>::type 164   >::value>::type
165   #endif 165   #endif
166   > 166   >
167   BOOST_CXX14_CONSTEXPR 167   BOOST_CXX14_CONSTEXPR
HITCBC 168   5386 pct_string_view( 168   5386 pct_string_view(
169   String const& s) 169   String const& s)
170   : pct_string_view( 170   : pct_string_view(
HITCBC 171   5386 detail::to_sv(s)) 171   5386 detail::to_sv(s))
172   { 172   {
HITCBC 173   5175 } 173   5175 }
174   174  
175   /** Constructor (deleted) 175   /** Constructor (deleted)
176   */ 176   */
177   pct_string_view( 177   pct_string_view(
178   std::nullptr_t) = delete; 178   std::nullptr_t) = delete;
179   179  
180   /** Constructor 180   /** Constructor
181   181  
182   The newly constructed string references 182   The newly constructed string references
183   the specified character buffer. Ownership 183   the specified character buffer. Ownership
184   is not transferred. 184   is not transferred.
185   185  
186   @par Postconditions 186   @par Postconditions
187   @code 187   @code
188   this->data() == s && this->size() == len 188   this->data() == s && this->size() == len
189   @endcode 189   @endcode
190   190  
191   @par Complexity 191   @par Complexity
192   Linear in `len`. 192   Linear in `len`.
193   193  
194   @par Exception Safety 194   @par Exception Safety
195   Exceptions thrown on invalid input. 195   Exceptions thrown on invalid input.
196   196  
197   @throw system_error 197   @throw system_error
198   The string contains an invalid percent encoding. 198   The string contains an invalid percent encoding.
199   199  
200   @param s The string to construct from. 200   @param s The string to construct from.
201   @param len The length of the string. 201   @param len The length of the string.
202   */ 202   */
HITCBC 203   221 pct_string_view( 203   221 pct_string_view(
204   char const* s, 204   char const* s,
205   std::size_t len) 205   std::size_t len)
HITCBC 206   221 : pct_string_view( 206   221 : pct_string_view(
HITCBC 207   221 core::string_view(s, len)) 207   221 core::string_view(s, len))
208   { 208   {
HITCBC 209   221 } 209   221 }
210   210  
211   /** Constructor 211   /** Constructor
212   212  
213   The newly constructed string references 213   The newly constructed string references
214   the specified character buffer. Ownership 214   the specified character buffer. Ownership
215   is not transferred. 215   is not transferred.
216   216  
217   @par Postconditions 217   @par Postconditions
218   @code 218   @code
219   this->data() == s.data() && this->size() == s.size() 219   this->data() == s.data() && this->size() == s.size()
220   @endcode 220   @endcode
221   221  
222   @par Complexity 222   @par Complexity
223   Linear in `s.size()`. 223   Linear in `s.size()`.
224   224  
225   @par Exception Safety 225   @par Exception Safety
226   Exceptions thrown on invalid input. 226   Exceptions thrown on invalid input.
227   227  
228   @throw system_error 228   @throw system_error
229   The string contains an invalid percent encoding. 229   The string contains an invalid percent encoding.
230   230  
231   @param s The string to construct from. 231   @param s The string to construct from.
232   */ 232   */
233   BOOST_URL_DECL 233   BOOST_URL_DECL
234   pct_string_view( 234   pct_string_view(
235   core::string_view s); 235   core::string_view s);
236   236  
237   /** Assignment 237   /** Assignment
238   238  
239   The copy references the same 239   The copy references the same
240   underlying character buffer. 240   underlying character buffer.
241   Ownership is not transferred. 241   Ownership is not transferred.
242   242  
243   @par Postconditions 243   @par Postconditions
244   @code 244   @code
245   this->data() == other.data() 245   this->data() == other.data()
246   @endcode 246   @endcode
247   247  
248   @par Complexity 248   @par Complexity
249   Constant. 249   Constant.
250   250  
251   @par Exception Safety 251   @par Exception Safety
252   Throws nothing. 252   Throws nothing.
253   253  
254   @param other The string to copy. 254   @param other The string to copy.
255   @return A reference to this object. 255   @return A reference to this object.
256   */ 256   */
257   pct_string_view& operator=( 257   pct_string_view& operator=(
258   pct_string_view const& other) = default; 258   pct_string_view const& other) = default;
259   259  
260   friend 260   friend
261   BOOST_URL_DECL 261   BOOST_URL_DECL
262   system::result<pct_string_view> 262   system::result<pct_string_view>
263   make_pct_string_view( 263   make_pct_string_view(
264   core::string_view s) noexcept; 264   core::string_view s) noexcept;
265   265  
266   //-------------------------------------------- 266   //--------------------------------------------
267   267  
268   /** Return the decoded size 268   /** Return the decoded size
269   269  
270   This function returns the number of 270   This function returns the number of
271   characters in the resulting string if 271   characters in the resulting string if
272   percent escapes were converted into 272   percent escapes were converted into
273   ordinary characters. 273   ordinary characters.
274   274  
275   @par Complexity 275   @par Complexity
276   Constant. 276   Constant.
277   277  
278   @par Exception Safety 278   @par Exception Safety
279   Throws nothing. 279   Throws nothing.
280   280  
281   @return The number of characters in the decoded string. 281   @return The number of characters in the decoded string.
282   */ 282   */
283   BOOST_CXX14_CONSTEXPR 283   BOOST_CXX14_CONSTEXPR
284   std::size_t 284   std::size_t
HITCBC 285   66411 decoded_size() const noexcept 285   66821 decoded_size() const noexcept
286   { 286   {
HITCBC 287   66411 return dn_; 287   66821 return dn_;
288   } 288   }
289   289  
290   /** Return the string as a range of decoded characters 290   /** Return the string as a range of decoded characters
291   291  
292   @par Complexity 292   @par Complexity
293   Constant. 293   Constant.
294   294  
295   @par Exception Safety 295   @par Exception Safety
296   Throws nothing. 296   Throws nothing.
297   297  
298   @see 298   @see
299   @ref decode_view. 299   @ref decode_view.
300   300  
301   @return A range of decoded characters. 301   @return A range of decoded characters.
302   */ 302   */
303   decode_view 303   decode_view
304   operator*() const noexcept; 304   operator*() const noexcept;
305   305  
306   /** Return the string with percent-decoding 306   /** Return the string with percent-decoding
307   307  
308   This function converts percent escapes 308   This function converts percent escapes
309   in the string into ordinary characters 309   in the string into ordinary characters
310   and returns the result. 310   and returns the result.
311   When called with no arguments, the 311   When called with no arguments, the
312   return type is `std::string`. 312   return type is `std::string`.
313   Otherwise, the return type and style 313   Otherwise, the return type and style
314   of output is determined by which string 314   of output is determined by which string
315   token is passed. 315   token is passed.
316   316  
317   @par Example 317   @par Example
318   @code 318   @code
319   assert( pct_string_view( "Program%20Files" ).decode() == "Program Files" ); 319   assert( pct_string_view( "Program%20Files" ).decode() == "Program Files" );
320   @endcode 320   @endcode
321   321  
322   @par Complexity 322   @par Complexity
323   Linear in `this->size()`. 323   Linear in `this->size()`.
324   324  
325   @par Exception Safety 325   @par Exception Safety
326   Calls to allocate may throw. 326   Calls to allocate may throw.
327   String tokens may throw exceptions. 327   String tokens may throw exceptions.
328   328  
329   @param opt The options for encoding. If 329   @param opt The options for encoding. If
330   this parameter is omitted, the default 330   this parameter is omitted, the default
331   options are used. 331   options are used.
332   332  
333   @param token An optional string token. 333   @param token An optional string token.
334   If this parameter is omitted, then 334   If this parameter is omitted, then
335   a new `std::string` is returned. 335   a new `std::string` is returned.
336   Otherwise, the function return type 336   Otherwise, the function return type
337   is the result type of the token. 337   is the result type of the token.
338   338  
339   @return The decoded string. 339   @return The decoded string.
340   340  
341   @see 341   @see
342   @ref encoding_opts, 342   @ref encoding_opts,
343   @ref string_token::return_string. 343   @ref string_token::return_string.
344   */ 344   */
345   template<BOOST_URL_STRTOK_TPARAM> 345   template<BOOST_URL_STRTOK_TPARAM>
346   BOOST_URL_STRTOK_RETURN 346   BOOST_URL_STRTOK_RETURN
HITCBC 347   21044 decode( 347   21044 decode(
348   encoding_opts opt = {}, 348   encoding_opts opt = {},
349   BOOST_URL_STRTOK_ARG(token)) const 349   BOOST_URL_STRTOK_ARG(token)) const
350   { 350   {
351   /* If you get a compile error here, it 351   /* If you get a compile error here, it
352   means that the token you passed does 352   means that the token you passed does
353   not meet the requirements stated 353   not meet the requirements stated
354   in the documentation. 354   in the documentation.
355   */ 355   */
356   static_assert( 356   static_assert(
357   string_token::is_token< 357   string_token::is_token<
358   StringToken>::value, 358   StringToken>::value,
359   "Type requirements not met"); 359   "Type requirements not met");
360   360  
HITCBC 361   21044 decode_impl(token, opt); 361   21044 decode_impl(token, opt);
HITCBC 362   21044 return token.result(); 362   21044 return token.result();
363   } 363   }
364   364  
365   #ifndef BOOST_URL_DOCS 365   #ifndef BOOST_URL_DOCS
366   /** Arrow support 366   /** Arrow support
367   367  
368   @return A pointer to this object. 368   @return A pointer to this object.
369   */ 369   */
370   pct_string_view const* 370   pct_string_view const*
HITCBC 371   123 operator->() const noexcept 371   123 operator->() const noexcept
372   { 372   {
HITCBC 373   123 return this; 373   123 return this;
374   } 374   }
375   #endif 375   #endif
376   376  
377   //-------------------------------------------- 377   //--------------------------------------------
378   378  
379   // VFALCO No idea why this fails in msvc 379   // VFALCO No idea why this fails in msvc
380   /** Swap 380   /** Swap
381   381  
382   @param s The object to swap with 382   @param s The object to swap with
383   */ 383   */
384   /*BOOST_CXX14_CONSTEXPR*/ void swap( 384   /*BOOST_CXX14_CONSTEXPR*/ void swap(
385   pct_string_view& s ) noexcept 385   pct_string_view& s ) noexcept
386   { 386   {
387   string_view_base::swap(s); 387   string_view_base::swap(s);
388   std::swap(dn_, s.dn_); 388   std::swap(dn_, s.dn_);
389   } 389   }
390   }; 390   };
391   391  
392   //------------------------------------------------ 392   //------------------------------------------------
393   393  
394   #ifndef BOOST_URL_DOCS 394   #ifndef BOOST_URL_DOCS
395   namespace detail { 395   namespace detail {
396   // obtain modifiable reference to 396   // obtain modifiable reference to
397   // underlying string, to handle 397   // underlying string, to handle
398   // self-intersection on modifiers. 398   // self-intersection on modifiers.
399   inline 399   inline
400   core::string_view& 400   core::string_view&
HITCBC 401   1219 ref(pct_string_view& s) noexcept 401   1219 ref(pct_string_view& s) noexcept
402   { 402   {
HITCBC 403   1219 return s.s_; 403   1219 return s.s_;
404   } 404   }
405   405  
406   } // detail 406   } // detail
407   #endif 407   #endif
408   408  
409   //------------------------------------------------ 409   //------------------------------------------------
410   410  
411   /** Return a valid percent-encoded string 411   /** Return a valid percent-encoded string
412   412  
413   If `s` is a valid percent-encoded string, 413   If `s` is a valid percent-encoded string,
414   the function returns the buffer as a valid 414   the function returns the buffer as a valid
415   view which may be used to perform decoding 415   view which may be used to perform decoding
416   or measurements. 416   or measurements.
417   Otherwise the result contains an error code. 417   Otherwise the result contains an error code.
418   Upon success, the returned view references 418   Upon success, the returned view references
419   the original character buffer; 419   the original character buffer;
420   Ownership is not transferred. 420   Ownership is not transferred.
421   421  
422   @par Complexity 422   @par Complexity
423   Linear in `s.size()`. 423   Linear in `s.size()`.
424   424  
425   @par Exception Safety 425   @par Exception Safety
426   Throws nothing. 426   Throws nothing.
427   427  
428   @param s The string to validate. 428   @param s The string to validate.
429   @return On success, the valid percent-encoded string. 429   @return On success, the valid percent-encoded string.
430   */ 430   */
431   BOOST_URL_DECL 431   BOOST_URL_DECL
432   system::result<pct_string_view> 432   system::result<pct_string_view>
433   make_pct_string_view( 433   make_pct_string_view(
434   core::string_view s) noexcept; 434   core::string_view s) noexcept;
435   435  
436   #ifndef BOOST_URL_DOCS 436   #ifndef BOOST_URL_DOCS
437   // VFALCO semi-private for now 437   // VFALCO semi-private for now
438   inline 438   inline
439   BOOST_CXX14_CONSTEXPR 439   BOOST_CXX14_CONSTEXPR
440   pct_string_view 440   pct_string_view
HITCBC 441   137903 make_pct_string_view_unsafe( 441   138519 make_pct_string_view_unsafe(
442   char const* data, 442   char const* data,
443   std::size_t size, 443   std::size_t size,
444   std::size_t decoded_size) noexcept 444   std::size_t decoded_size) noexcept
445   { 445   {
446   #if 0 446   #if 0
447   BOOST_ASSERT(! make_pct_string_view( 447   BOOST_ASSERT(! make_pct_string_view(
448   core::string_view(data, size)).has_error()); 448   core::string_view(data, size)).has_error());
449   #endif 449   #endif
450   return pct_string_view( 450   return pct_string_view(
HITCBC 451   137903 data, size, decoded_size); 451   138519 data, size, decoded_size);
452   } 452   }
453   #endif 453   #endif
454   454  
455   #ifndef BOOST_URL_DOCS 455   #ifndef BOOST_URL_DOCS
456   namespace detail { 456   namespace detail {
457   template <> 457   template <>
458   inline 458   inline
459   BOOST_CXX14_CONSTEXPR 459   BOOST_CXX14_CONSTEXPR
460   core::string_view 460   core::string_view
HITCBC 461   14429 to_sv(pct_string_view const& s) noexcept 461   14442 to_sv(pct_string_view const& s) noexcept
462   { 462   {
HITCBC 463   14429 return s.substr(); 463   14442 return s.substr();
464   } 464   }
465   } // detail 465   } // detail
466   #endif 466   #endif
467   467  
468   } // urls 468   } // urls
469   } // boost 469   } // boost
470   470  
471   // Ensure decode_view is complete for operator*() 471   // Ensure decode_view is complete for operator*()
472   #include <boost/url/decode_view.hpp> 472   #include <boost/url/decode_view.hpp>
473   473  
474   #ifdef BOOST_URL_HAS_CONCEPTS 474   #ifdef BOOST_URL_HAS_CONCEPTS
475   #include <ranges> 475   #include <ranges>
476   namespace std::ranges { 476   namespace std::ranges {
477   template<> 477   template<>
478   inline constexpr bool 478   inline constexpr bool
479   enable_borrowed_range< 479   enable_borrowed_range<
480   boost::urls::pct_string_view> = true; 480   boost::urls::pct_string_view> = true;
481   } // std::ranges 481   } // std::ranges
482   #endif 482   #endif
483   483  
484   #endif 484   #endif