params_ref.ipp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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_IMPL_PARAMS_REF_IPP
  11. #define BOOST_URL_IMPL_PARAMS_REF_IPP
  12. #include <boost/url/params_ref.hpp>
  13. #include <boost/url/params_view.hpp>
  14. #include <boost/url/url_base.hpp>
  15. #include <boost/url/grammar/ci_string.hpp>
  16. #include <boost/assert.hpp>
  17. #include <utility>
  18. namespace boost {
  19. namespace urls {
  20. //------------------------------------------------
  21. //
  22. // Special Members
  23. //
  24. //------------------------------------------------
  25. auto
  26. params_ref::
  27. operator=(params_ref const& other) ->
  28. params_ref&
  29. {
  30. if (!ref_.alias_of(other.ref_))
  31. assign(other.begin(), other.end());
  32. return *this;
  33. }
  34. params_ref::
  35. operator
  36. params_view() const noexcept
  37. {
  38. return { ref_, opt_ };
  39. }
  40. //------------------------------------------------
  41. //
  42. // Modifiers
  43. //
  44. //------------------------------------------------
  45. void
  46. params_ref::
  47. assign(
  48. std::initializer_list<
  49. param_view> init)
  50. {
  51. assign(init.begin(), init.end());
  52. }
  53. auto
  54. params_ref::
  55. insert(
  56. iterator before,
  57. param_view const& p) ->
  58. iterator
  59. {
  60. return iterator(
  61. u_->edit_params(
  62. before.it_,
  63. before.it_,
  64. detail::param_iter(p)),
  65. opt_);
  66. }
  67. auto
  68. params_ref::
  69. insert(
  70. iterator before,
  71. std::initializer_list<
  72. param_view> init) ->
  73. iterator
  74. {
  75. return insert(
  76. before,
  77. init.begin(),
  78. init.end());
  79. }
  80. std::size_t
  81. params_ref::
  82. erase(
  83. string_view key,
  84. ignore_case_param ic) noexcept
  85. {
  86. // end() can't be fully cached,
  87. // since erase invalidates it.
  88. iterator it;
  89. {
  90. auto const end_ = end();
  91. it = find_last(end_, key, ic);
  92. if(it == end_)
  93. return 0;
  94. }
  95. std::size_t n = 0;
  96. for(;;)
  97. {
  98. ++n;
  99. // Use it->key instead of key,
  100. // to handle self-intersection
  101. auto prev = find_last(it, (*it).key, ic);
  102. if(prev == end())
  103. break;
  104. erase(it);
  105. it = prev;
  106. }
  107. erase(it);
  108. return n;
  109. }
  110. auto
  111. params_ref::
  112. replace(
  113. iterator pos,
  114. param_view const& p) ->
  115. iterator
  116. {
  117. return iterator(
  118. u_->edit_params(
  119. pos.it_,
  120. std::next(pos).it_,
  121. detail::param_iter(p)),
  122. opt_);
  123. }
  124. auto
  125. params_ref::
  126. replace(
  127. iterator from,
  128. iterator to,
  129. std::initializer_list<
  130. param_view> init) ->
  131. iterator
  132. {
  133. return replace(
  134. from,
  135. to,
  136. init.begin(),
  137. init.end());
  138. }
  139. auto
  140. params_ref::
  141. unset(
  142. iterator pos) noexcept ->
  143. iterator
  144. {
  145. BOOST_ASSERT(pos.it_.nk > 0);
  146. string_view s;
  147. return iterator(
  148. u_->edit_params(
  149. pos.it_,
  150. pos.it_.next(),
  151. detail::param_value_iter(
  152. pos.it_.nk - 1, s, false)),
  153. opt_);
  154. }
  155. auto
  156. params_ref::
  157. set(
  158. iterator pos,
  159. string_view value) ->
  160. iterator
  161. {
  162. BOOST_ASSERT(pos.it_.nk > 0);
  163. return iterator(
  164. u_->edit_params(
  165. pos.it_,
  166. pos.it_.next(),
  167. detail::param_value_iter(
  168. pos.it_.nk - 1, value, true)),
  169. opt_);
  170. }
  171. auto
  172. params_ref::
  173. set(
  174. string_view key,
  175. string_view value,
  176. ignore_case_param ic) ->
  177. iterator
  178. {
  179. // VFALCO we can't cache end() here
  180. // because it is invalidated
  181. // every time we set or erase.
  182. auto it0 = find(key, ic);
  183. if(it0 == end())
  184. return append({key, value});
  185. it0 = set(it0, value);
  186. auto it = end();
  187. for(;;)
  188. {
  189. it = find_last(it, key, ic);
  190. if(it == it0)
  191. return it0;
  192. it = erase(it);
  193. }
  194. }
  195. //------------------------------------------------
  196. //
  197. // (implementation)
  198. //
  199. //------------------------------------------------
  200. detail::params_iter_impl
  201. params_ref::
  202. find_impl(
  203. detail::params_iter_impl it,
  204. string_view key,
  205. ignore_case_param ic) const noexcept
  206. {
  207. detail::params_iter_impl end_(u_->impl_, 0);
  208. if(! ic)
  209. {
  210. for(;;)
  211. {
  212. if(it.equal(end_))
  213. return it;
  214. if(*it.key() == key)
  215. return it;
  216. it.increment();
  217. }
  218. }
  219. for(;;)
  220. {
  221. if(it.equal(end_))
  222. return it;
  223. if( grammar::ci_is_equal(
  224. *it.key(), key))
  225. return it;
  226. it.increment();
  227. }
  228. }
  229. detail::params_iter_impl
  230. params_ref::
  231. find_last_impl(
  232. detail::params_iter_impl it,
  233. string_view key,
  234. ignore_case_param ic) const noexcept
  235. {
  236. detail::params_iter_impl begin_(u_->impl_);
  237. if(! ic)
  238. {
  239. for(;;)
  240. {
  241. if(it.equal(begin_))
  242. return { u_->impl_, 0 };
  243. it.decrement();
  244. if(*it.key() == key)
  245. return it;
  246. }
  247. }
  248. for(;;)
  249. {
  250. if(it.equal(begin_))
  251. return { u_->impl_, 0 };
  252. it.decrement();
  253. if(grammar::ci_is_equal(
  254. *it.key(), key))
  255. return it;
  256. }
  257. }
  258. } // urls
  259. } // boost
  260. #endif