params_base.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. //
  2. // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.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. #ifndef BOOST_URL_PARAMS_BASE_HPP
  11. #define BOOST_URL_PARAMS_BASE_HPP
  12. #include <boost/url/detail/config.hpp>
  13. #include <boost/url/encoding_opts.hpp>
  14. #include <boost/url/ignore_case.hpp>
  15. #include <boost/url/param.hpp>
  16. #include <boost/url/detail/params_iter_impl.hpp>
  17. #include <boost/url/detail/url_impl.hpp>
  18. #include <iosfwd>
  19. namespace boost {
  20. namespace urls {
  21. /** Common functionality for containers
  22. This base class is used by the library
  23. to provide common member functions for
  24. containers. This cannot be instantiated
  25. directly; Instead, use one of the
  26. containers or functions:
  27. @par Containers
  28. @li @ref params_ref
  29. @li @ref params_view
  30. @li @ref params_encoded_ref
  31. @li @ref params_encoded_view
  32. */
  33. class params_base
  34. {
  35. friend class url_view_base;
  36. friend class params_ref;
  37. friend class params_view;
  38. detail::query_ref ref_;
  39. encoding_opts opt_;
  40. params_base() noexcept;
  41. BOOST_URL_DECL
  42. params_base(
  43. detail::query_ref const& ref,
  44. encoding_opts opt) noexcept;
  45. params_base(
  46. params_base const&) = default;
  47. params_base& operator=(
  48. params_base const&) = default;
  49. public:
  50. /** A Bidirectional iterator to a query parameter
  51. Objects of this type allow iteration
  52. through the parameters in the query.
  53. Any percent-escapes in returned strings
  54. are decoded first.
  55. The values returned are read-only;
  56. changes to parameters must be made
  57. through the container instead, if the
  58. container supports modification.
  59. <br>
  60. The strings produced when iterators are
  61. dereferenced belong to the iterator and
  62. become invalidated when that particular
  63. iterator is incremented, decremented,
  64. or destroyed.
  65. @note
  66. The implementation may use temporary,
  67. recycled storage to store decoded
  68. strings. These iterators are meant
  69. to be used ephemerally. That is, for
  70. short durations such as within a
  71. function scope. Do not store
  72. iterators with static storage
  73. duration or as long-lived objects.
  74. */
  75. #ifdef BOOST_URL_DOCS
  76. using iterator = __see_below__;
  77. #else
  78. class iterator;
  79. #endif
  80. /// @copydoc iterator
  81. using const_iterator = iterator;
  82. /** The value type
  83. Values of this type represent parameters
  84. whose strings retain unique ownership by
  85. making a copy.
  86. @par Example
  87. @code
  88. params_view::value_type qp( *url_view( "?first=John&last=Doe" ).params().find( "first" ) );
  89. @endcode
  90. @see
  91. @ref param.
  92. */
  93. using value_type = param;
  94. /** The reference type
  95. This is the type of value returned when
  96. iterators of the view are dereferenced.
  97. @see
  98. @ref param_view.
  99. */
  100. using reference = param;
  101. /// @copydoc reference
  102. using const_reference = param;
  103. /** An unsigned integer type to represent sizes.
  104. */
  105. using size_type = std::size_t;
  106. /** A signed integer type used to represent differences.
  107. */
  108. using difference_type = std::ptrdiff_t;
  109. //--------------------------------------------
  110. //
  111. // Observers
  112. //
  113. //--------------------------------------------
  114. /** Return the maximum number of characters possible
  115. This represents the largest number of
  116. characters that are possible in a path,
  117. not including any null terminator.
  118. @par Exception Safety
  119. Throws nothing.
  120. */
  121. static
  122. constexpr
  123. std::size_t
  124. max_size() noexcept
  125. {
  126. return BOOST_URL_MAX_SIZE;
  127. }
  128. /** Return the referenced character buffer.
  129. This function returns the character
  130. buffer referenced by the view.
  131. The returned string may contain
  132. percent escapes.
  133. @par Example
  134. @code
  135. assert( url_view( "?first=John&last=Doe" ).params().buffer() == "?first=John&last=Doe" );
  136. @endcode
  137. @par Complexity
  138. Constant.
  139. @par Exception Safety
  140. Throws nothing.
  141. */
  142. BOOST_URL_DECL
  143. pct_string_view
  144. buffer() const noexcept;
  145. /** Return true if there are no params
  146. @par Example
  147. @code
  148. assert( ! url_view( "?key=value" ).params().empty() );
  149. @endcode
  150. @par Complexity
  151. Constant.
  152. @par Exception Safety
  153. Throws nothing.
  154. */
  155. BOOST_URL_DECL
  156. bool
  157. empty() const noexcept;
  158. /** Return the number of params
  159. @par Example
  160. @code
  161. assert( url_view( "?key=value").params().size() == 1 );
  162. @endcode
  163. @par Complexity
  164. Constant.
  165. @par Exception Safety
  166. Throws nothing.
  167. */
  168. BOOST_URL_DECL
  169. std::size_t
  170. size() const noexcept;
  171. /** Return an iterator to the beginning
  172. @par Complexity
  173. Linear in the size of the first param.
  174. @par Exception Safety
  175. Throws nothing.
  176. */
  177. BOOST_URL_DECL
  178. iterator
  179. begin() const noexcept;
  180. /** Return an iterator to the end
  181. @par Complexity
  182. Constant.
  183. @par Exception Safety
  184. Throws nothing.
  185. */
  186. BOOST_URL_DECL
  187. iterator
  188. end() const noexcept;
  189. //--------------------------------------------
  190. /** Return true if a matching key exists
  191. This function examines the parameters
  192. in the container to find a match for
  193. the specified key.
  194. The comparison is performed as if all
  195. escaped characters were decoded first.
  196. @par Example
  197. @code
  198. assert( url_view( "?first=John&last=Doe" ).params().contains( "first" ) );
  199. @endcode
  200. @par Complexity
  201. Linear in `this->buffer().size()`.
  202. @par Exception Safety
  203. Throws nothing.
  204. @param key The key to match.
  205. By default, a case-sensitive
  206. comparison is used.
  207. @param ic An optional parameter. If
  208. the value @ref ignore_case is passed
  209. here, the comparison is
  210. case-insensitive.
  211. */
  212. bool
  213. contains(
  214. string_view key,
  215. ignore_case_param ic = {}) const noexcept;
  216. /** Return the number of matching keys
  217. This function examines the
  218. parameters in the container to
  219. find the number of matches for
  220. the specified key.
  221. The comparison is performed as if all
  222. escaped characters were decoded first.
  223. @par Example
  224. @code
  225. assert( url_view( "?first=John&last=Doe" ).params().count( "first" ) == 1 );
  226. @endcode
  227. @par Complexity
  228. Linear in `this->buffer().size()`.
  229. @par Exception Safety
  230. Throws nothing.
  231. @param key The key to match.
  232. By default, a case-sensitive
  233. comparison is used.
  234. @param ic An optional parameter. If
  235. the value @ref ignore_case is passed
  236. here, the comparison is
  237. case-insensitive.
  238. */
  239. BOOST_URL_DECL
  240. std::size_t
  241. count(
  242. string_view key,
  243. ignore_case_param ic = {}) const noexcept;
  244. /** Find a matching key
  245. This function examines the parameters
  246. in the container to find a match for
  247. the specified key.
  248. The comparison is performed as if all
  249. escaped characters were decoded first.
  250. <br>
  251. The search starts from the first param
  252. and proceeds forward until either the
  253. key is found or the end of the range is
  254. reached, in which case `end()` is
  255. returned.
  256. @par Example
  257. @code
  258. assert( (*url_view( "?first=John&last=Doe" ).params().find( "First", ignore_case )).value == "John" );
  259. @endcode
  260. @par Effects
  261. @code
  262. return this->find( this->begin(), key, ic );
  263. @endcode
  264. @par Complexity
  265. Linear in `this->buffer().size()`.
  266. @return an iterator to the param
  267. @param key The key to match.
  268. By default, a case-sensitive
  269. comparison is used.
  270. @param ic An optional parameter. If
  271. the value @ref ignore_case is passed
  272. here, the comparison is
  273. case-insensitive.
  274. */
  275. iterator
  276. find(
  277. string_view key,
  278. ignore_case_param ic = {}) const noexcept;
  279. /** Find a matching key
  280. This function examines the
  281. parameters in the container to
  282. find a match for the specified key.
  283. The comparison is performed as if all
  284. escaped characters were decoded first.
  285. <br>
  286. The search starts at `from`
  287. and proceeds forward until either the
  288. key is found or the end of the range is
  289. reached, in which case `end()` is
  290. returned.
  291. @par Example
  292. @code
  293. url_view u( "?First=John&Last=Doe" );
  294. assert( u.params().find( "first" ) != u.params().find( "first", ignore_case ) );
  295. @endcode
  296. @par Complexity
  297. Linear in `this->buffer().size()`.
  298. @return an iterator to the param
  299. @param from The position to begin the
  300. search from. This can be `end()`.
  301. @param key The key to match.
  302. By default, a case-sensitive
  303. comparison is used.
  304. @param ic An optional parameter. If
  305. the value @ref ignore_case is passed
  306. here, the comparison is
  307. case-insensitive.
  308. */
  309. iterator
  310. find(
  311. iterator from,
  312. string_view key,
  313. ignore_case_param ic = {}) const noexcept;
  314. /** Find a matching key
  315. This function examines the
  316. parameters in the container to
  317. find a match for the specified key.
  318. The comparison is performed as if all
  319. escaped characters were decoded first.
  320. <br>
  321. The search starts from the last param
  322. and proceeds backwards until either the
  323. key is found or the beginning of the
  324. range is reached, in which case `end()`
  325. is returned.
  326. @par Example
  327. @code
  328. assert( (*url_view( "?first=John&last=Doe" ).params().find_last( "last" )).value == "Doe" );
  329. @endcode
  330. @par Complexity
  331. Linear in `this->buffer().size()`.
  332. @return an iterator to the param
  333. @param key The key to match.
  334. By default, a case-sensitive
  335. comparison is used.
  336. @param ic An optional parameter. If
  337. the value @ref ignore_case is passed
  338. here, the comparison is
  339. case-insensitive.
  340. */
  341. iterator
  342. find_last(
  343. string_view key,
  344. ignore_case_param ic = {}) const noexcept;
  345. /** Find a matching key
  346. This function examines the
  347. parameters in the container to
  348. find a match for the specified key.
  349. The comparison is performed as if all
  350. escaped characters were decoded first.
  351. <br>
  352. The search starts prior to `before`
  353. and proceeds backwards until either the
  354. key is found or the beginning of the
  355. range is reached, in which case `end()`
  356. is returned.
  357. @par Example
  358. @code
  359. url_view u( "?First=John&Last=Doe" );
  360. assert( u.params().find_last( "last" ) != u.params().find_last( "last", ignore_case ) );
  361. @endcode
  362. @par Complexity
  363. Linear in `this->buffer().size()`.
  364. @return an iterator to the param
  365. @param before One past the position
  366. to begin the search from. This can
  367. be `end()`.
  368. @param key The key to match.
  369. By default, a case-sensitive
  370. comparison is used.
  371. @param ic An optional parameter. If
  372. the value @ref ignore_case is passed
  373. here, the comparison is
  374. case-insensitive.
  375. */
  376. iterator
  377. find_last(
  378. iterator before,
  379. string_view key,
  380. ignore_case_param ic = {}) const noexcept;
  381. private:
  382. BOOST_URL_DECL
  383. detail::params_iter_impl
  384. find_impl(
  385. detail::params_iter_impl,
  386. string_view,
  387. ignore_case_param) const noexcept;
  388. BOOST_URL_DECL
  389. detail::params_iter_impl
  390. find_last_impl(
  391. detail::params_iter_impl,
  392. string_view,
  393. ignore_case_param) const noexcept;
  394. };
  395. //------------------------------------------------
  396. /** Format to an output stream
  397. Any percent-escapes are emitted as-is;
  398. no decoding is performed.
  399. @par Complexity
  400. Linear in `ps.buffer().size()`.
  401. @par Effects
  402. @code
  403. return os << ps.buffer();
  404. @endcode
  405. */
  406. BOOST_URL_DECL
  407. std::ostream&
  408. operator<<(
  409. std::ostream& os,
  410. params_base const& qp);
  411. } // urls
  412. } // boost
  413. #include <boost/url/impl/params_base.hpp>
  414. #endif