url_impl.hpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. //
  2. // Copyright (c) 2022 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_URL_IMPL_HPP
  10. #define BOOST_URL_DETAIL_URL_IMPL_HPP
  11. #include <boost/url/host_type.hpp>
  12. #include <boost/url/pct_string_view.hpp>
  13. #include <boost/url/scheme.hpp>
  14. #include <boost/url/string_view.hpp>
  15. #include <boost/url/detail/parts_base.hpp>
  16. #include <boost/assert.hpp>
  17. #include <cstdint>
  18. namespace boost {
  19. namespace urls {
  20. class url_view;
  21. class authority_view;
  22. namespace detail {
  23. constexpr char const* const empty_c_str_ = "";
  24. // This is the private 'guts' of a
  25. // url_view, exposed so different parts
  26. // of the implementation can work on it.
  27. struct url_impl : parts_base
  28. {
  29. static
  30. constexpr
  31. std::size_t const zero_ = 0;
  32. // never nullptr
  33. char const* cs_ = empty_c_str_;
  34. std::size_t offset_[id_end + 1] = {};
  35. std::size_t decoded_[id_end] = {};
  36. std::size_t nseg_ = 0;
  37. std::size_t nparam_ = 0;
  38. unsigned char ip_addr_[16] = {};
  39. // VFALCO don't we need a bool?
  40. std::uint16_t port_number_ = 0;
  41. host_type host_type_ =
  42. urls::host_type::none;
  43. scheme scheme_ =
  44. urls::scheme::none;
  45. from from_ = from::string;
  46. url_impl(
  47. from b) noexcept
  48. : from_(b)
  49. {
  50. }
  51. // in url_view.ipp
  52. url_view construct() const noexcept;
  53. // in authority_view.ipp
  54. authority_view
  55. construct_authority() const noexcept;
  56. std::size_t len(int, int) const noexcept;
  57. std::size_t len(int) const noexcept;
  58. std::size_t offset(int) const noexcept;
  59. string_view get(int) const noexcept;
  60. string_view get(int, int) const noexcept;
  61. pct_string_view pct_get(int) const noexcept;
  62. pct_string_view pct_get(int, int) const noexcept;
  63. void set_size(int, std::size_t) noexcept;
  64. void split(int, std::size_t) noexcept;
  65. void adjust(int, int, std::size_t) noexcept;
  66. void collapse(int, int, std::size_t) noexcept;
  67. void apply_scheme(string_view) noexcept;
  68. void apply_userinfo(pct_string_view const&,
  69. pct_string_view const*) noexcept;
  70. void apply_host(host_type, pct_string_view,
  71. unsigned char const*) noexcept;
  72. void apply_port(string_view, unsigned short) noexcept;
  73. void apply_authority(authority_view const&) noexcept;
  74. void apply_path(pct_string_view, std::size_t) noexcept;
  75. void apply_query(pct_string_view, std::size_t) noexcept;
  76. void apply_frag(pct_string_view) noexcept;
  77. };
  78. //------------------------------------------------
  79. // this allows a path to come from a
  80. // url_impl or a separate string_view
  81. class path_ref
  82. : private parts_base
  83. {
  84. url_impl const* impl_ = nullptr;
  85. char const* data_ = nullptr;
  86. std::size_t size_ = 0;
  87. std::size_t nseg_ = 0;
  88. std::size_t dn_ = 0;
  89. public:
  90. path_ref() = default;
  91. path_ref(url_impl const& impl) noexcept;
  92. path_ref(string_view,
  93. std::size_t, std::size_t) noexcept;
  94. pct_string_view buffer() const noexcept;
  95. std::size_t size() const noexcept;
  96. char const* data() const noexcept;
  97. char const* end() const noexcept;
  98. std::size_t nseg() const noexcept;
  99. bool
  100. alias_of(
  101. url_impl const& impl) const noexcept
  102. {
  103. return impl_ == &impl;
  104. }
  105. bool
  106. alias_of(
  107. path_ref const& ref) const noexcept
  108. {
  109. if(impl_)
  110. return impl_ == ref.impl_;
  111. BOOST_ASSERT(data_ != ref.data_ || (
  112. size_ == ref.size_ &&
  113. nseg_ == ref.nseg_ &&
  114. dn_ == ref.dn_));
  115. return data_ == ref.data_;
  116. }
  117. };
  118. //------------------------------------------------
  119. // this allows a params to come from a
  120. // url_impl or a separate string_view
  121. class query_ref
  122. : private parts_base
  123. {
  124. url_impl const* impl_ = nullptr;
  125. char const* data_ = nullptr;
  126. std::size_t size_ = 0;
  127. std::size_t nparam_ = 0;
  128. std::size_t dn_ = 0;
  129. bool question_mark_ = false;
  130. public:
  131. query_ref(
  132. string_view s, // buffer, no '?'
  133. std::size_t dn, // decoded size
  134. std::size_t nparam
  135. ) noexcept;
  136. query_ref() = default;
  137. BOOST_URL_DECL
  138. query_ref(url_impl const& impl) noexcept;
  139. pct_string_view buffer() const noexcept;
  140. std::size_t size() const noexcept; // with '?'
  141. char const* begin() const noexcept; // no '?'
  142. char const* end() const noexcept;
  143. std::size_t nparam() const noexcept;
  144. bool
  145. alias_of(
  146. url_impl const& impl) const noexcept
  147. {
  148. return impl_ == &impl;
  149. }
  150. bool
  151. alias_of(
  152. query_ref const& ref) const noexcept
  153. {
  154. if(impl_)
  155. return impl_ == ref.impl_;
  156. BOOST_ASSERT(data_ != ref.data_ || (
  157. size_ == ref.size_ &&
  158. nparam_ == ref.nparam_ &&
  159. dn_ == ref.dn_));
  160. return data_ == ref.data_;
  161. }
  162. };
  163. //------------------------------------------------
  164. // return length of [first, last)
  165. inline
  166. auto
  167. url_impl::
  168. len(
  169. int first,
  170. int last) const noexcept ->
  171. std::size_t
  172. {
  173. BOOST_ASSERT(first <= last);
  174. BOOST_ASSERT(last <= id_end);
  175. return offset(last) - offset(first);
  176. }
  177. // return length of part
  178. inline
  179. auto
  180. url_impl::
  181. len(int id) const noexcept ->
  182. std::size_t
  183. {
  184. return id == id_end
  185. ? zero_
  186. : ( offset(id + 1) -
  187. offset(id) );
  188. }
  189. // return offset of id
  190. inline
  191. auto
  192. url_impl::
  193. offset(int id) const noexcept ->
  194. std::size_t
  195. {
  196. return
  197. id == id_scheme
  198. ? zero_
  199. : offset_[id];
  200. }
  201. // return id as string
  202. inline
  203. string_view
  204. url_impl::
  205. get(int id) const noexcept
  206. {
  207. return {
  208. cs_ + offset(id), len(id) };
  209. }
  210. // return [first, last) as string
  211. inline
  212. string_view
  213. url_impl::
  214. get(int first,
  215. int last) const noexcept
  216. {
  217. return { cs_ + offset(first),
  218. offset(last) - offset(first) };
  219. }
  220. // return id as pct-string
  221. inline
  222. pct_string_view
  223. url_impl::
  224. pct_get(
  225. int id) const noexcept
  226. {
  227. return make_pct_string_view_unsafe(
  228. cs_ + offset(id),
  229. len(id),
  230. decoded_[id]);
  231. }
  232. // return [first, last) as pct-string
  233. inline
  234. pct_string_view
  235. url_impl::
  236. pct_get(
  237. int first,
  238. int last) const noexcept
  239. {
  240. auto const pos = offset(first);
  241. std::size_t n = 0;
  242. for(auto i = first; i < last;)
  243. n += decoded_[i++];
  244. return make_pct_string_view_unsafe(
  245. cs_ + pos,
  246. offset(last) - pos,
  247. n);
  248. }
  249. //------------------------------------------------
  250. // change id to size n
  251. inline
  252. void
  253. url_impl::
  254. set_size(
  255. int id,
  256. std::size_t n) noexcept
  257. {
  258. auto d = n - len(id);
  259. for(auto i = id + 1;
  260. i <= id_end; ++i)
  261. offset_[i] += d;
  262. }
  263. // trim id to size n,
  264. // moving excess into id+1
  265. inline
  266. void
  267. url_impl::
  268. split(
  269. int id,
  270. std::size_t n) noexcept
  271. {
  272. BOOST_ASSERT(id < id_end - 1);
  273. //BOOST_ASSERT(n <= len(id));
  274. offset_[id + 1] = offset(id) + n;
  275. }
  276. // add n to [first, last]
  277. inline
  278. void
  279. url_impl::
  280. adjust(
  281. int first,
  282. int last,
  283. std::size_t n) noexcept
  284. {
  285. for(int i = first;
  286. i <= last; ++i)
  287. offset_[i] += n;
  288. }
  289. // set [first, last) offset
  290. inline
  291. void
  292. url_impl::
  293. collapse(
  294. int first,
  295. int last,
  296. std::size_t n) noexcept
  297. {
  298. for(int i = first + 1;
  299. i < last; ++i)
  300. offset_[i] = n;
  301. }
  302. } // detail
  303. } // urls
  304. } // boost
  305. #endif