any_params_iter.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. //
  2. // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // Official repository: https://github.com/boostorg/url
  8. //
  9. #ifndef BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
  10. #define BOOST_URL_DETAIL_ANY_PARAMS_ITER_HPP
  11. #include <boost/url/param.hpp>
  12. #include <boost/url/pct_string_view.hpp>
  13. #include <boost/core/detail/static_assert.hpp>
  14. #include <cstddef>
  15. #include <iterator>
  16. #include <type_traits>
  17. namespace boost {
  18. namespace urls {
  19. namespace detail {
  20. //------------------------------------------------
  21. //
  22. // any_params_iter
  23. //
  24. //------------------------------------------------
  25. /* An iterator to a type-erased,
  26. possibly encoded sequence of
  27. query params_ref.
  28. */
  29. struct BOOST_SYMBOL_VISIBLE
  30. any_params_iter
  31. {
  32. protected:
  33. any_params_iter(
  34. bool empty_,
  35. core::string_view s0_ = {},
  36. core::string_view s1_ = {}) noexcept
  37. : s0(s0_)
  38. , s1(s1_)
  39. , empty(empty_)
  40. {
  41. }
  42. public:
  43. // these are adjusted
  44. // when self-intersecting
  45. core::string_view s0;
  46. core::string_view s1;
  47. // True if the sequence is empty
  48. bool empty = false;
  49. BOOST_URL_DECL
  50. virtual
  51. ~any_params_iter() noexcept = 0;
  52. // Rewind the iterator to the beginning
  53. virtual
  54. void
  55. rewind() noexcept = 0;
  56. // Measure and increment current element.
  57. // Returns false on end of range.
  58. // n is increased by encoded size.
  59. // Can throw on bad percent-escape
  60. virtual
  61. bool
  62. measure(std::size_t& n) = 0;
  63. // Copy and increment the current
  64. // element. encoding is performed
  65. // if needed.
  66. virtual
  67. void
  68. copy(
  69. char*& dest,
  70. char const* end) noexcept = 0;
  71. };
  72. //------------------------------------------------
  73. //
  74. // query_string_iter
  75. //
  76. //------------------------------------------------
  77. // A string of plain query params
  78. struct BOOST_SYMBOL_VISIBLE
  79. query_string_iter
  80. : any_params_iter
  81. {
  82. // ne = never empty
  83. BOOST_URL_DECL
  84. explicit
  85. query_string_iter(
  86. core::string_view s,
  87. bool ne = false) noexcept;
  88. private:
  89. core::string_view s_;
  90. std::size_t n_;
  91. char const* p_;
  92. bool at_end_;
  93. void rewind() noexcept override;
  94. bool measure(std::size_t&) noexcept override;
  95. void copy(char*&, char const*) noexcept override;
  96. void increment() noexcept;
  97. };
  98. //------------------------------------------------
  99. //
  100. // param_iter
  101. //
  102. //------------------------------------------------
  103. // A 1-param range allowing
  104. // self-intersection
  105. struct BOOST_SYMBOL_VISIBLE
  106. single_param_iter
  107. : any_params_iter
  108. {
  109. explicit
  110. single_param_iter(
  111. param_view const&,
  112. bool space_as_plus) noexcept;
  113. private:
  114. bool has_value_;
  115. bool at_end_ = false;
  116. bool space_as_plus_ = false;
  117. void rewind() noexcept override;
  118. bool measure(std::size_t&) noexcept override;
  119. void copy(char*&, char const*) noexcept override;
  120. };
  121. //------------------------------------------------
  122. //
  123. // params_iter_base
  124. //
  125. //------------------------------------------------
  126. struct params_iter_base
  127. {
  128. bool space_as_plus_ = true;
  129. protected:
  130. explicit params_iter_base(
  131. bool space_as_plus) noexcept
  132. : space_as_plus_(space_as_plus)
  133. {}
  134. // return encoded size
  135. BOOST_URL_DECL
  136. void
  137. measure_impl(
  138. std::size_t& n,
  139. param_view const& p) noexcept;
  140. // encode to dest
  141. BOOST_URL_DECL
  142. void
  143. copy_impl(
  144. char*& dest,
  145. char const* end,
  146. param_view const& v) noexcept;
  147. };
  148. //------------------------------------------------
  149. // A range of plain query params_ref
  150. template<class FwdIt>
  151. struct params_iter
  152. : any_params_iter
  153. , private params_iter_base
  154. {
  155. BOOST_CORE_STATIC_ASSERT(
  156. std::is_convertible<
  157. typename std::iterator_traits<
  158. FwdIt>::reference,
  159. param_view>::value);
  160. params_iter(
  161. FwdIt first,
  162. FwdIt last,
  163. bool space_as_plus) noexcept
  164. : any_params_iter(
  165. first == last)
  166. , params_iter_base(space_as_plus)
  167. , it0_(first)
  168. , it_(first)
  169. , end_(last)
  170. {
  171. }
  172. private:
  173. FwdIt it0_;
  174. FwdIt it_;
  175. FwdIt end_;
  176. void
  177. rewind() noexcept override
  178. {
  179. it_ = it0_;
  180. }
  181. bool
  182. measure(
  183. std::size_t& n) noexcept override
  184. {
  185. if(it_ == end_)
  186. return false;
  187. measure_impl(n,
  188. param_view(*it_++));
  189. return true;
  190. }
  191. void
  192. copy(
  193. char*& dest,
  194. char const* end) noexcept override
  195. {
  196. copy_impl(dest, end,
  197. param_view(*it_++));
  198. }
  199. };
  200. //------------------------------------------------
  201. //
  202. // param_encoded_iter
  203. //
  204. //------------------------------------------------
  205. // A 1-param encoded range
  206. // allowing self-intersection
  207. struct BOOST_SYMBOL_VISIBLE
  208. param_encoded_iter
  209. : any_params_iter
  210. {
  211. explicit
  212. param_encoded_iter(
  213. param_pct_view const&) noexcept;
  214. private:
  215. bool has_value_;
  216. bool at_end_ = false;
  217. void rewind() noexcept override;
  218. bool measure(std::size_t&) noexcept override;
  219. void copy(char*&, char const*) noexcept override;
  220. };
  221. //------------------------------------------------
  222. //
  223. // params_encoded_iter
  224. //
  225. //------------------------------------------------
  226. // Validating and copying from
  227. // a string of encoded params
  228. struct params_encoded_iter_base
  229. {
  230. protected:
  231. BOOST_URL_DECL
  232. static
  233. void
  234. measure_impl(
  235. std::size_t& n,
  236. param_view const& v) noexcept;
  237. BOOST_URL_DECL
  238. static
  239. void
  240. copy_impl(
  241. char*& dest,
  242. char const* end,
  243. param_view const& v) noexcept;
  244. };
  245. //------------------------------------------------
  246. // A range of encoded query params_ref
  247. template<class FwdIt>
  248. struct params_encoded_iter
  249. : any_params_iter
  250. , private params_encoded_iter_base
  251. {
  252. BOOST_CORE_STATIC_ASSERT(
  253. std::is_convertible<
  254. typename std::iterator_traits<
  255. FwdIt>::reference,
  256. param_view>::value);
  257. params_encoded_iter(
  258. FwdIt first,
  259. FwdIt last) noexcept
  260. : any_params_iter(
  261. first == last)
  262. , it0_(first)
  263. , it_(first)
  264. , end_(last)
  265. {
  266. }
  267. private:
  268. FwdIt it0_;
  269. FwdIt it_;
  270. FwdIt end_;
  271. void
  272. rewind() noexcept override
  273. {
  274. it_ = it0_;
  275. }
  276. bool
  277. measure(
  278. std::size_t& n) override
  279. {
  280. if(it_ == end_)
  281. return false;
  282. // throw on invalid input
  283. measure_impl(n,
  284. param_pct_view(
  285. param_view(*it_++)));
  286. return true;
  287. }
  288. void
  289. copy(
  290. char*& dest,
  291. char const* end
  292. ) noexcept override
  293. {
  294. copy_impl(dest, end,
  295. param_view(*it_++));
  296. }
  297. };
  298. //------------------------------------------------
  299. //
  300. // param_value_iter
  301. //
  302. //------------------------------------------------
  303. // An iterator which outputs
  304. // one value on an existing key
  305. struct param_value_iter
  306. : any_params_iter
  307. {
  308. param_value_iter(
  309. std::size_t nk,
  310. core::string_view const& value,
  311. bool has_value) noexcept
  312. : any_params_iter(
  313. false,
  314. value)
  315. , nk_(nk)
  316. , has_value_(has_value)
  317. {
  318. }
  319. private:
  320. std::size_t nk_ = 0;
  321. bool has_value_ = false;
  322. bool at_end_ = false;
  323. void rewind() noexcept override;
  324. bool measure(std::size_t&) noexcept override;
  325. void copy(char*&, char const*) noexcept override;
  326. };
  327. //------------------------------------------------
  328. //
  329. // param_encoded_value_iter
  330. //
  331. //------------------------------------------------
  332. // An iterator which outputs one
  333. // encoded value on an existing key
  334. struct param_encoded_value_iter
  335. : any_params_iter
  336. {
  337. param_encoded_value_iter(
  338. std::size_t nk,
  339. pct_string_view const& value,
  340. bool has_value) noexcept
  341. : any_params_iter(
  342. false,
  343. value)
  344. , nk_(nk)
  345. , has_value_(has_value)
  346. {
  347. }
  348. private:
  349. std::size_t nk_ = 0;
  350. bool has_value_ = false;
  351. bool at_end_ = false;
  352. void rewind() noexcept override;
  353. bool measure(std::size_t&) noexcept override;
  354. void copy(char*&, char const*) noexcept override;
  355. };
  356. //------------------------------------------------
  357. template<class FwdIt>
  358. params_iter<FwdIt>
  359. make_params_iter(
  360. FwdIt first, FwdIt last, bool space_as_plus)
  361. {
  362. return params_iter<
  363. FwdIt>(first, last, space_as_plus);
  364. }
  365. template<class FwdIt>
  366. params_encoded_iter<FwdIt>
  367. make_params_encoded_iter(
  368. FwdIt first, FwdIt last)
  369. {
  370. return params_encoded_iter<
  371. FwdIt>(first, last);
  372. }
  373. } // detail
  374. } // urls
  375. } // boost
  376. #endif