param.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934
  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_PARAM_HPP
  11. #define BOOST_URL_PARAM_HPP
  12. #include <boost/url/detail/config.hpp>
  13. #include <boost/url/detail/optional_string.hpp>
  14. #include <boost/url/pct_string_view.hpp>
  15. #include <cstddef>
  16. #include <string>
  17. namespace boost {
  18. namespace urls {
  19. #ifndef BOOST_URL_DOCS
  20. struct param_pct_view;
  21. struct param_view;
  22. #endif
  23. /** The type of no_value
  24. */
  25. struct no_value_t
  26. {
  27. };
  28. /** Constant indicating no value in a param
  29. */
  30. constexpr no_value_t no_value{};
  31. //------------------------------------------------
  32. /** A query parameter
  33. Objects of this type represent a single key
  34. and value pair in a query string where a key
  35. is always present and may be empty, while the
  36. presence of a value is indicated by
  37. @ref has_value equal to true.
  38. An empty value is distinct from no value.
  39. Depending on where the object was obtained,
  40. the strings may or may not contain percent
  41. escapes.
  42. For most usages, key comparisons are
  43. case-sensitive and duplicate keys in
  44. a query are possible. However, it is
  45. the authority that has final control
  46. over how the query is interpreted.
  47. @par BNF
  48. @code
  49. query-params = query-param *( "&" query-param )
  50. query-param = key [ "=" value ]
  51. key = *qpchar
  52. value = *( qpchar / "=" )
  53. @endcode
  54. @par Specification
  55. @li <a href="https://en.wikipedia.org/wiki/Query_string"
  56. >Query string (Wikipedia)</a>
  57. @see
  58. @ref param_view,
  59. @ref param_pct_view.
  60. */
  61. struct param
  62. {
  63. /** The key
  64. For most usages, key comparisons are
  65. case-sensitive and duplicate keys in
  66. a query are possible. However, it is
  67. the authority that has final control
  68. over how the query is interpreted.
  69. */
  70. std::string key;
  71. /** The value
  72. The presence of a value is indicated by
  73. @ref has_value equal to true.
  74. An empty value is distinct from no value.
  75. */
  76. std::string value;
  77. /** True if a value is present
  78. The presence of a value is indicated by
  79. `has_value == true`.
  80. An empty value is distinct from no value.
  81. */
  82. bool has_value = false;
  83. /** Constructor
  84. Default constructed query parameters
  85. have an empty key and no value.
  86. @par Example
  87. @code
  88. param qp;
  89. @endcode
  90. @par Postconditions
  91. @code
  92. this->key == "" && this->value == "" && this->has_value == false
  93. @endcode
  94. @par Complexity
  95. Constant.
  96. @par Exception Safety
  97. Throws nothing.
  98. */
  99. param() = default;
  100. /** Constructor
  101. Upon construction, this acquires
  102. ownership of the members of other
  103. via move construction. The moved
  104. from object is as if default
  105. constructed.
  106. @par Complexity
  107. Constant.
  108. @par Exception Safety
  109. Throws nothing.
  110. @par other The object to construct from.
  111. */
  112. param(param&& other) noexcept
  113. : key(std::move(other.key))
  114. , value(std::move(other.value))
  115. , has_value(other.has_value)
  116. {
  117. #ifdef BOOST_URL_COW_STRINGS
  118. // for copy-on-write std::string
  119. other.key.clear();
  120. other.value.clear();
  121. #endif
  122. other.has_value = false;
  123. }
  124. /** Constructor
  125. Upon construction, this becomes a copy
  126. of `other`.
  127. @par Postconditions
  128. @code
  129. this->key == other.key && this->value == other.value && this->has_value == other.has_value
  130. @endcode
  131. @par Complexity
  132. Linear in `other.key.size() + other.value.size()`.
  133. @par Exception Safety
  134. Calls to allocate may throw.
  135. @par other The object to construct from.
  136. */
  137. param(param const& other) = default;
  138. /** Assignment
  139. Upon assignment, this acquires
  140. ownership of the members of other
  141. via move assignment. The moved
  142. from object is as if default
  143. constructed.
  144. @par Complexity
  145. Constant.
  146. @par Exception Safety
  147. Throws nothing.
  148. @par other The object to assign from.
  149. */
  150. param&
  151. operator=(param&& other) noexcept
  152. {
  153. key = std::move(other.key);
  154. value = std::move(other.value);
  155. has_value = other.has_value;
  156. #ifdef BOOST_URL_COW_STRINGS
  157. // for copy-on-write std::string
  158. other.key.clear();
  159. other.value.clear();
  160. #endif
  161. other.has_value = false;
  162. return *this;
  163. }
  164. /** Assignment
  165. Upon assignment, this becomes a copy
  166. of `other`.
  167. @par Postconditions
  168. @code
  169. this->key == other.key && this->value == other.value && this->has_value == other.has_value
  170. @endcode
  171. @par Complexity
  172. Linear in `other.key.size() + other.value.size()`.
  173. @par Exception Safety
  174. Calls to allocate may throw.
  175. @par other The object to assign from.
  176. */
  177. param& operator=(
  178. param const&) = default;
  179. //--------------------------------------------
  180. /** Constructor
  181. This constructs a parameter with a key
  182. and value.
  183. No validation is performed on the strings.
  184. Ownership of the key and value is acquired
  185. by making copies.
  186. @par Example
  187. @code
  188. param qp( "key", "value" );
  189. @endcode
  190. @code
  191. param qp( "key", optional<core::string_view>("value") );
  192. @endcode
  193. @code
  194. param qp( "key", boost::none );
  195. @endcode
  196. @code
  197. param qp( "key", nullptr );
  198. @endcode
  199. @code
  200. param qp( "key", no_value );
  201. @endcode
  202. @par Postconditions
  203. @code
  204. this->key == key && this->value == value && this->has_value == true
  205. @endcode
  206. @par Complexity
  207. Linear in `key.size() + value.size()`.
  208. @par Exception Safety
  209. Calls to allocate may throw.
  210. @tparam OptionalString An optional string
  211. type, such as `core::string_view`,
  212. `std::nullptr`, @ref no_value_t, or
  213. `optional<core::string_view>`.
  214. @param key, value The key and value to set.
  215. */
  216. template <class OptionalString>
  217. param(
  218. core::string_view key,
  219. OptionalString const& value)
  220. : param(key, detail::get_optional_string(value))
  221. {
  222. }
  223. /** Assignment
  224. The members of `other` are copied,
  225. re-using already existing string capacity.
  226. @par Postconditions
  227. @code
  228. this->key == other.key && this->value == other.value && this->has_value == other.has_value
  229. @endcode
  230. @par Complexity
  231. Linear in `other.key.size() + other.value.size()`.
  232. @par Exception Safety
  233. Calls to allocate may throw.
  234. @param other The parameter to copy.
  235. */
  236. param&
  237. operator=(param_view const& other);
  238. /** Assignment
  239. The members of `other` are copied,
  240. re-using already existing string capacity.
  241. @par Postconditions
  242. @code
  243. this->key == other.key && this->value == other.value && this->has_value == other.has_value
  244. @endcode
  245. @par Complexity
  246. Linear in `other.key.size() + other.value.size()`.
  247. @par Exception Safety
  248. Calls to allocate may throw.
  249. @param other The parameter to copy.
  250. */
  251. param&
  252. operator=(param_pct_view const& other);
  253. #ifndef BOOST_URL_DOCS
  254. // arrow support
  255. param const*
  256. operator->() const noexcept
  257. {
  258. return this;
  259. }
  260. // aggregate construction
  261. param(
  262. core::string_view key,
  263. core::string_view value,
  264. bool has_value) noexcept
  265. : key(key)
  266. , value(has_value
  267. ? value
  268. : core::string_view())
  269. , has_value(has_value)
  270. {
  271. }
  272. #endif
  273. private:
  274. param(
  275. core::string_view key,
  276. detail::optional_string const& value)
  277. : param(key, value.s, value.b)
  278. {
  279. }
  280. };
  281. //------------------------------------------------
  282. /** A query parameter
  283. Objects of this type represent a single key
  284. and value pair in a query string where a key
  285. is always present and may be empty, while the
  286. presence of a value is indicated by
  287. @ref has_value equal to true.
  288. An empty value is distinct from no value.
  289. Depending on where the object was obtained,
  290. the strings may or may not contain percent
  291. escapes.
  292. For most usages, key comparisons are
  293. case-sensitive and duplicate keys in
  294. a query are possible. However, it is
  295. the authority that has final control
  296. over how the query is interpreted.
  297. <br>
  298. Keys and values in this object reference
  299. external character buffers.
  300. Ownership of the buffers is not transferred;
  301. the caller is responsible for ensuring that
  302. the assigned buffers remain valid until
  303. they are no longer referenced.
  304. @par BNF
  305. @code
  306. query-params = query-param *( "&" query-param )
  307. query-param = key [ "=" value ]
  308. key = *qpchar
  309. value = *( qpchar / "=" )
  310. @endcode
  311. @par Specification
  312. @li <a href="https://en.wikipedia.org/wiki/Query_string"
  313. >Query string (Wikipedia)</a>
  314. @see
  315. @ref param,
  316. @ref param_pct_view.
  317. */
  318. struct param_view
  319. {
  320. /** The key
  321. For most usages, key comparisons are
  322. case-sensitive and duplicate keys in
  323. a query are possible. However, it is
  324. the authority that has final control
  325. over how the query is interpreted.
  326. */
  327. core::string_view key;
  328. /** The value
  329. The presence of a value is indicated by
  330. @ref has_value equal to true.
  331. An empty value is distinct from no value.
  332. */
  333. core::string_view value;
  334. /** True if a value is present
  335. The presence of a value is indicated by
  336. `has_value == true`.
  337. An empty value is distinct from no value.
  338. */
  339. bool has_value = false;
  340. //--------------------------------------------
  341. /** Constructor
  342. Default constructed query parameters
  343. have an empty key and no value.
  344. @par Example
  345. @code
  346. param_view qp;
  347. @endcode
  348. @par Postconditions
  349. @code
  350. this->key == "" && this->value == "" && this->has_value == false
  351. @endcode
  352. @par Complexity
  353. Constant.
  354. @par Exception Safety
  355. Throws nothing.
  356. */
  357. param_view() = default;
  358. /** Constructor
  359. This constructs a parameter with a key
  360. and value.
  361. No validation is performed on the strings.
  362. The new key and value reference
  363. the same corresponding underlying
  364. character buffers.
  365. Ownership of the buffers is not transferred;
  366. the caller is responsible for ensuring that
  367. the assigned buffers remain valid until
  368. they are no longer referenced.
  369. @par Example
  370. @code
  371. param_view qp( "key", "value" );
  372. @endcode
  373. @par Postconditions
  374. @code
  375. this->key.data() == key.data() && this->value.data() == value.data() && this->has_value == true
  376. @endcode
  377. @par Complexity
  378. Constant.
  379. @par Exception Safety
  380. Throws nothing.
  381. @tparam OptionalString An optional string
  382. type, such as `core::string_view`,
  383. `std::nullptr`, @ref no_value_t, or
  384. `optional<core::string_view>`.
  385. @param key, value The key and value to set.
  386. */
  387. template <class OptionalString>
  388. param_view(
  389. core::string_view key,
  390. OptionalString const& value) noexcept
  391. : param_view(key, detail::get_optional_string(value))
  392. {
  393. }
  394. /** Constructor
  395. This function constructs a param
  396. which references the character buffers
  397. representing the key and value in another
  398. container.
  399. Ownership of the buffers is not transferred;
  400. the caller is responsible for ensuring that
  401. the assigned buffers remain valid until
  402. they are no longer referenced.
  403. @par Example
  404. @code
  405. param qp( "key", "value" );
  406. param_view qpv( qp );
  407. @endcode
  408. @par Postconditions
  409. @code
  410. this->key == key && this->value == value && this->has_value == other.has_value
  411. @endcode
  412. @par Complexity
  413. Constant.
  414. @par Exception Safety
  415. Throws nothing.
  416. @param other The param to reference
  417. */
  418. param_view(
  419. param const& other) noexcept
  420. : param_view(
  421. other.key,
  422. other.value,
  423. other.has_value)
  424. {
  425. }
  426. /** Conversion
  427. This function performs a conversion from
  428. a reference-like query parameter to one
  429. retaining ownership of the strings by
  430. making a copy.
  431. No validation is performed on the strings.
  432. @par Complexity
  433. Linear in `this->key.size() + this->value.size()`.
  434. @par Exception Safety
  435. Calls to allocate may throw.
  436. */
  437. explicit
  438. operator
  439. param()
  440. {
  441. return { key, value, has_value };
  442. }
  443. #ifndef BOOST_URL_DOCS
  444. // arrow support
  445. param_view const*
  446. operator->() const noexcept
  447. {
  448. return this;
  449. }
  450. // aggregate construction
  451. param_view(
  452. core::string_view key_,
  453. core::string_view value_,
  454. bool has_value_) noexcept
  455. : key(key_)
  456. , value(has_value_
  457. ? value_
  458. : core::string_view())
  459. , has_value(has_value_)
  460. {
  461. }
  462. #endif
  463. private:
  464. param_view(
  465. core::string_view key,
  466. detail::optional_string const& value)
  467. : param_view(key, value.s, value.b)
  468. {
  469. }
  470. };
  471. //------------------------------------------------
  472. /** A query parameter
  473. Objects of this type represent a single key
  474. and value pair in a query string where a key
  475. is always present and may be empty, while the
  476. presence of a value is indicated by
  477. @ref has_value equal to true.
  478. An empty value is distinct from no value.
  479. The strings may have percent escapes, and
  480. offer an additional invariant: they never
  481. contain an invalid percent-encoding.
  482. For most usages, key comparisons are
  483. case-sensitive and duplicate keys in
  484. a query are possible. However, it is
  485. the authority that has final control
  486. over how the query is interpreted.
  487. <br>
  488. Keys and values in this object reference
  489. external character buffers.
  490. Ownership of the buffers is not transferred;
  491. the caller is responsible for ensuring that
  492. the assigned buffers remain valid until
  493. they are no longer referenced.
  494. @par BNF
  495. @code
  496. query-params = query-param *( "&" query-param )
  497. query-param = key [ "=" value ]
  498. key = *qpchar
  499. value = *( qpchar / "=" )
  500. @endcode
  501. @par Specification
  502. @li <a href="https://en.wikipedia.org/wiki/Query_string"
  503. >Query string (Wikipedia)</a>
  504. @see
  505. @ref param,
  506. @ref param_view.
  507. */
  508. struct param_pct_view
  509. {
  510. /** The key
  511. For most usages, key comparisons are
  512. case-sensitive and duplicate keys in
  513. a query are possible. However, it is
  514. the authority that has final control
  515. over how the query is interpreted.
  516. */
  517. pct_string_view key;
  518. /** The value
  519. The presence of a value is indicated by
  520. @ref has_value equal to true.
  521. An empty value is distinct from no value.
  522. */
  523. pct_string_view value;
  524. /** True if a value is present
  525. The presence of a value is indicated by
  526. `has_value == true`.
  527. An empty value is distinct from no value.
  528. */
  529. bool has_value = false;
  530. //--------------------------------------------
  531. /** Constructor
  532. Default constructed query parameters
  533. have an empty key and no value.
  534. @par Example
  535. @code
  536. param_pct_view qp;
  537. @endcode
  538. @par Postconditions
  539. @code
  540. this->key == "" && this->value == "" && this->has_value == false
  541. @endcode
  542. @par Complexity
  543. Constant.
  544. @par Exception Safety
  545. Throws nothing.
  546. */
  547. param_pct_view() = default;
  548. /** Constructor
  549. This constructs a parameter with a key
  550. and value, which may both contain percent
  551. escapes.
  552. The new key and value reference
  553. the same corresponding underlying
  554. character buffers.
  555. Ownership of the buffers is not transferred;
  556. the caller is responsible for ensuring that
  557. the assigned buffers remain valid until
  558. they are no longer referenced.
  559. @par Example
  560. @code
  561. param_pct_view qp( "key", "value" );
  562. @endcode
  563. @par Postconditions
  564. @code
  565. this->key.data() == key.data() && this->value.data() == value.data() && this->has_value == true
  566. @endcode
  567. @par Complexity
  568. Linear in `key.size() + value.size()`.
  569. @par Exception Safety
  570. Exceptions thrown on invalid input.
  571. @throw system_error
  572. `key` or `value` contains an invalid percent-encoding.
  573. @param key, value The key and value to set.
  574. */
  575. param_pct_view(
  576. pct_string_view key,
  577. pct_string_view value) noexcept
  578. : key(key)
  579. , value(value)
  580. , has_value(true)
  581. {
  582. }
  583. /** Constructor
  584. This constructs a parameter with a key
  585. and optional value, which may both
  586. contain percent escapes.
  587. The new key and value reference
  588. the same corresponding underlying
  589. character buffers.
  590. Ownership of the buffers is not transferred;
  591. the caller is responsible for ensuring that
  592. the assigned buffers remain valid until
  593. they are no longer referenced.
  594. @par Example
  595. @code
  596. param_pct_view qp( "key", optional<core::string_view>("value") );
  597. @endcode
  598. @par Postconditions
  599. @code
  600. this->key.data() == key.data() && this->value->data() == value->data() && this->has_value == true
  601. @endcode
  602. @par Complexity
  603. Linear in `key.size() + value->size()`.
  604. @par Exception Safety
  605. Exceptions thrown on invalid input.
  606. @throw system_error
  607. `key` or `value` contains an invalid percent-encoding.
  608. @tparam OptionalString An optional
  609. `core::string_view` type, such as
  610. `boost::optional<core::string_view>` or
  611. `std::optional<core::string_view>`.
  612. @param key, value The key and value to set.
  613. */
  614. template <class OptionalString>
  615. param_pct_view(
  616. pct_string_view key,
  617. OptionalString const& value)
  618. : param_pct_view(key, detail::get_optional_string(value))
  619. {
  620. }
  621. /** Construction
  622. This converts a param which may
  623. contain unvalidated percent-escapes into
  624. a param whose key and value are
  625. guaranteed to contain strings with no
  626. invalid percent-escapes, otherwise
  627. an exception is thrown.
  628. The new key and value reference
  629. the same corresponding underlying
  630. character buffers.
  631. Ownership of the buffers is not transferred;
  632. the caller is responsible for ensuring that
  633. the assigned buffers remain valid until
  634. they are no longer referenced.
  635. @par Example
  636. @code
  637. param_pct_view qp( param_view( "key", "value" ) );
  638. @endcode
  639. @par Complexity
  640. Linear in `key.size() + value.size()`.
  641. @par Exception Safety
  642. Exceptions thrown on invalid input.
  643. @throw system_error
  644. `key` or `value` contains an invalid percent escape.
  645. @param p The param to construct from.
  646. */
  647. explicit
  648. param_pct_view(
  649. param_view const& p)
  650. : key(p.key)
  651. , value(p.has_value
  652. ? pct_string_view(p.value)
  653. : pct_string_view())
  654. , has_value(p.has_value)
  655. {
  656. }
  657. /** Conversion
  658. This function performs a conversion from
  659. a reference-like query parameter to one
  660. retaining ownership of the strings by
  661. making a copy.
  662. @par Complexity
  663. Linear in `this->key.size() + this->value.size()`.
  664. @par Exception Safety
  665. Calls to allocate may throw.
  666. */
  667. explicit
  668. operator
  669. param() const
  670. {
  671. return param(
  672. static_cast<std::string>(key),
  673. static_cast<std::string>(value),
  674. has_value);
  675. }
  676. operator
  677. param_view() const noexcept
  678. {
  679. return param_view(
  680. key, value, has_value);
  681. }
  682. #ifndef BOOST_URL_DOCS
  683. // arrow support
  684. param_pct_view const*
  685. operator->() const noexcept
  686. {
  687. return this;
  688. }
  689. // aggregate construction
  690. param_pct_view(
  691. pct_string_view key,
  692. pct_string_view value,
  693. bool has_value) noexcept
  694. : key(key)
  695. , value(has_value
  696. ? value
  697. : pct_string_view())
  698. , has_value(has_value)
  699. {
  700. }
  701. #endif
  702. private:
  703. param_pct_view(
  704. pct_string_view key,
  705. detail::optional_string const& value)
  706. : param_pct_view(key, value.s, value.b)
  707. {
  708. }
  709. };
  710. //------------------------------------------------
  711. inline
  712. param&
  713. param::
  714. operator=(
  715. param_view const& other)
  716. {
  717. // VFALCO operator= assignment
  718. // causes a loss of original capacity:
  719. // https://godbolt.org/z/nYef8445K
  720. //
  721. // key = other.key;
  722. // value = other.value;
  723. // preserve capacity
  724. key.assign(
  725. other.key.data(),
  726. other.key.size());
  727. value.assign(
  728. other.value.data(),
  729. other.value.size());
  730. has_value = other.has_value;
  731. return *this;
  732. }
  733. inline
  734. param&
  735. param::
  736. operator=(
  737. param_pct_view const& other)
  738. {
  739. // preserve capacity
  740. key.assign(
  741. other.key.data(),
  742. other.key.size());
  743. value.assign(
  744. other.value.data(),
  745. other.value.size());
  746. has_value = other.has_value;
  747. return *this;
  748. }
  749. } // urls
  750. } // boost
  751. #endif