any_params_iter.hpp 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  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/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. // element.
  58. // Returns false on end of range.
  59. // n is increased by encoded size.
  60. // Can throw on bad percent-escape
  61. virtual
  62. bool
  63. measure(std::size_t& n) = 0;
  64. // Copy and increment the current
  65. // element. encoding is performed
  66. // if needed.
  67. virtual
  68. void
  69. copy(
  70. char*& dest,
  71. char const* end) noexcept = 0;
  72. };
  73. //------------------------------------------------
  74. //
  75. // query_iter
  76. //
  77. //------------------------------------------------
  78. // A string of plain query params
  79. struct BOOST_SYMBOL_VISIBLE
  80. query_iter
  81. : any_params_iter
  82. {
  83. // ne = never empty
  84. BOOST_URL_DECL
  85. explicit
  86. query_iter(
  87. core::string_view s,
  88. bool ne = false) noexcept;
  89. private:
  90. core::string_view s_;
  91. std::size_t n_;
  92. char const* p_;
  93. bool at_end_;
  94. void rewind() noexcept override;
  95. bool measure(std::size_t&) noexcept override;
  96. void copy(char*&, char const*) noexcept override;
  97. void increment() noexcept;
  98. };
  99. //------------------------------------------------
  100. //
  101. // param_iter
  102. //
  103. //------------------------------------------------
  104. // A 1-param range allowing
  105. // self-intersection
  106. struct BOOST_SYMBOL_VISIBLE
  107. param_iter
  108. : any_params_iter
  109. {
  110. explicit
  111. param_iter(
  112. param_view const&) noexcept;
  113. private:
  114. bool has_value_;
  115. bool at_end_ = false;
  116. void rewind() noexcept override;
  117. bool measure(std::size_t&) noexcept override;
  118. void copy(char*&, char const*) noexcept override;
  119. };
  120. //------------------------------------------------
  121. //
  122. // params_iter_base
  123. //
  124. //------------------------------------------------
  125. struct params_iter_base
  126. {
  127. protected:
  128. // return encoded size
  129. BOOST_URL_DECL
  130. static
  131. void
  132. measure_impl(
  133. std::size_t& n,
  134. param_view const& p) noexcept;
  135. // encode to dest
  136. BOOST_URL_DECL
  137. static
  138. void
  139. copy_impl(
  140. char*& dest,
  141. char const* end,
  142. param_view const& v) noexcept;
  143. };
  144. //------------------------------------------------
  145. // A range of plain query params_ref
  146. template<class FwdIt>
  147. struct params_iter
  148. : any_params_iter
  149. , private params_iter_base
  150. {
  151. BOOST_STATIC_ASSERT(
  152. std::is_convertible<
  153. typename std::iterator_traits<
  154. FwdIt>::reference,
  155. param_view>::value);
  156. params_iter(
  157. FwdIt first,
  158. FwdIt last) noexcept
  159. : any_params_iter(
  160. first == last)
  161. , it0_(first)
  162. , it_(first)
  163. , end_(last)
  164. {
  165. }
  166. private:
  167. FwdIt it0_;
  168. FwdIt it_;
  169. FwdIt end_;
  170. void
  171. rewind() noexcept override
  172. {
  173. it_ = it0_;
  174. }
  175. bool
  176. measure(
  177. std::size_t& n) noexcept override
  178. {
  179. if(it_ == end_)
  180. return false;
  181. measure_impl(n,
  182. param_view(*it_++));
  183. return true;
  184. }
  185. void
  186. copy(
  187. char*& dest,
  188. char const* end) noexcept override
  189. {
  190. copy_impl(dest, end,
  191. param_view(*it_++));
  192. }
  193. };
  194. //------------------------------------------------
  195. //
  196. // param_encoded_iter
  197. //
  198. //------------------------------------------------
  199. // A 1-param encoded range
  200. // allowing self-intersection
  201. struct BOOST_SYMBOL_VISIBLE
  202. param_encoded_iter
  203. : any_params_iter
  204. {
  205. explicit
  206. param_encoded_iter(
  207. param_pct_view const&) noexcept;
  208. private:
  209. bool has_value_;
  210. bool at_end_ = false;
  211. void rewind() noexcept override;
  212. bool measure(std::size_t&) noexcept override;
  213. void copy(char*&, char const*) noexcept override;
  214. };
  215. //------------------------------------------------
  216. //
  217. // params_encoded_iter
  218. //
  219. //------------------------------------------------
  220. // Validating and copying from
  221. // a string of encoded params
  222. struct params_encoded_iter_base
  223. {
  224. protected:
  225. BOOST_URL_DECL
  226. static
  227. void
  228. measure_impl(
  229. std::size_t& n,
  230. param_view const& v) noexcept;
  231. BOOST_URL_DECL
  232. static
  233. void
  234. copy_impl(
  235. char*& dest,
  236. char const* end,
  237. param_view const& v) noexcept;
  238. };
  239. //------------------------------------------------
  240. // A range of encoded query params_ref
  241. template<class FwdIt>
  242. struct params_encoded_iter
  243. : any_params_iter
  244. , private params_encoded_iter_base
  245. {
  246. BOOST_STATIC_ASSERT(
  247. std::is_convertible<
  248. typename std::iterator_traits<
  249. FwdIt>::reference,
  250. param_view>::value);
  251. params_encoded_iter(
  252. FwdIt first,
  253. FwdIt last) noexcept
  254. : any_params_iter(
  255. first == last)
  256. , it0_(first)
  257. , it_(first)
  258. , end_(last)
  259. {
  260. }
  261. private:
  262. FwdIt it0_;
  263. FwdIt it_;
  264. FwdIt end_;
  265. void
  266. rewind() noexcept override
  267. {
  268. it_ = it0_;
  269. }
  270. bool
  271. measure(
  272. std::size_t& n) override
  273. {
  274. if(it_ == end_)
  275. return false;
  276. // throw on invalid input
  277. measure_impl(n,
  278. param_pct_view(
  279. param_view(*it_++)));
  280. return true;
  281. }
  282. void
  283. copy(
  284. char*& dest,
  285. char const* end
  286. ) noexcept override
  287. {
  288. copy_impl(dest, end,
  289. param_view(*it_++));
  290. }
  291. };
  292. //------------------------------------------------
  293. //
  294. // param_value_iter
  295. //
  296. //------------------------------------------------
  297. // An iterator which outputs
  298. // one value on an existing key
  299. struct param_value_iter
  300. : any_params_iter
  301. {
  302. param_value_iter(
  303. std::size_t nk,
  304. core::string_view const& value,
  305. bool has_value) noexcept
  306. : any_params_iter(
  307. false,
  308. value)
  309. , nk_(nk)
  310. , has_value_(has_value)
  311. {
  312. }
  313. private:
  314. std::size_t nk_ = 0;
  315. bool has_value_ = false;
  316. bool at_end_ = false;
  317. void rewind() noexcept override;
  318. bool measure(std::size_t&) noexcept override;
  319. void copy(char*&, char const*) noexcept override;
  320. };
  321. //------------------------------------------------
  322. //
  323. // param_encoded_value_iter
  324. //
  325. //------------------------------------------------
  326. // An iterator which outputs one
  327. // encoded value on an existing key
  328. struct param_encoded_value_iter
  329. : any_params_iter
  330. {
  331. param_encoded_value_iter(
  332. std::size_t nk,
  333. pct_string_view const& value,
  334. bool has_value) noexcept
  335. : any_params_iter(
  336. false,
  337. value)
  338. , nk_(nk)
  339. , has_value_(has_value)
  340. {
  341. }
  342. private:
  343. std::size_t nk_ = 0;
  344. bool has_value_ = false;
  345. bool at_end_ = false;
  346. void rewind() noexcept override;
  347. bool measure(std::size_t&) noexcept override;
  348. void copy(char*&, char const*) noexcept override;
  349. };
  350. //------------------------------------------------
  351. template<class FwdIt>
  352. params_iter<FwdIt>
  353. make_params_iter(
  354. FwdIt first, FwdIt last)
  355. {
  356. return params_iter<
  357. FwdIt>(first, last);
  358. }
  359. template<class FwdIt>
  360. params_encoded_iter<FwdIt>
  361. make_params_encoded_iter(
  362. FwdIt first, FwdIt last)
  363. {
  364. return params_encoded_iter<
  365. FwdIt>(first, last);
  366. }
  367. } // detail
  368. } // urls
  369. } // boost
  370. #endif