params_base.hpp 13 KB

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