99.48% Lines (1519/1527)
100.00% Functions (80/80)
| TLA | Baseline | Branch | ||||||
|---|---|---|---|---|---|---|---|---|
| Line | Hits | Code | Line | Hits | Code | |||
| 1 | // | 1 | // | |||||
| 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | 2 | // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com) | |||||
| 3 | // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) | 3 | // Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com) | |||||
| 4 | // | 4 | // | |||||
| 5 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | 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) | 6 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |||||
| 7 | // | 7 | // | |||||
| 8 | // Official repository: https://github.com/boostorg/url | 8 | // Official repository: https://github.com/boostorg/url | |||||
| 9 | // | 9 | // | |||||
| 10 | 10 | |||||||
| 11 | #ifndef BOOST_URL_IMPL_URL_BASE_HPP | 11 | #ifndef BOOST_URL_IMPL_URL_BASE_HPP | |||||
| 12 | #define BOOST_URL_IMPL_URL_BASE_HPP | 12 | #define BOOST_URL_IMPL_URL_BASE_HPP | |||||
| 13 | 13 | |||||||
| 14 | #include <boost/url/encode.hpp> | 14 | #include <boost/url/encode.hpp> | |||||
| 15 | #include <boost/url/error.hpp> | 15 | #include <boost/url/error.hpp> | |||||
| 16 | #include <boost/url/host_type.hpp> | 16 | #include <boost/url/host_type.hpp> | |||||
| 17 | #include <boost/url/scheme.hpp> | 17 | #include <boost/url/scheme.hpp> | |||||
| 18 | #include <boost/url/url_view.hpp> | 18 | #include <boost/url/url_view.hpp> | |||||
| 19 | #include <boost/url/detail/any_params_iter.hpp> | 19 | #include <boost/url/detail/any_params_iter.hpp> | |||||
| 20 | #include <boost/url/detail/any_segments_iter.hpp> | 20 | #include <boost/url/detail/any_segments_iter.hpp> | |||||
| 21 | #include <boost/url/detail/decode.hpp> | 21 | #include <boost/url/detail/decode.hpp> | |||||
| 22 | #include <boost/url/detail/encode.hpp> | 22 | #include <boost/url/detail/encode.hpp> | |||||
| 23 | #include <boost/url/detail/except.hpp> | 23 | #include <boost/url/detail/except.hpp> | |||||
| 24 | #include <boost/url/detail/normalize.hpp> | 24 | #include <boost/url/detail/normalize.hpp> | |||||
| 25 | #include <boost/url/detail/path.hpp> | 25 | #include <boost/url/detail/path.hpp> | |||||
| 26 | #include <boost/url/detail/print.hpp> | 26 | #include <boost/url/detail/print.hpp> | |||||
| 27 | #include <boost/url/grammar/ci_string.hpp> | 27 | #include <boost/url/grammar/ci_string.hpp> | |||||
| 28 | #include <boost/url/rfc/authority_rule.hpp> | 28 | #include <boost/url/rfc/authority_rule.hpp> | |||||
| 29 | #include <boost/url/rfc/query_rule.hpp> | 29 | #include <boost/url/rfc/query_rule.hpp> | |||||
| 30 | #include <boost/url/rfc/ipv6_address_rule.hpp> | 30 | #include <boost/url/rfc/ipv6_address_rule.hpp> | |||||
| 31 | #include <boost/url/rfc/detail/charsets.hpp> | 31 | #include <boost/url/rfc/detail/charsets.hpp> | |||||
| 32 | #include <boost/url/rfc/detail/host_rule.hpp> | 32 | #include <boost/url/rfc/detail/host_rule.hpp> | |||||
| 33 | #include <boost/url/rfc/detail/ipvfuture_rule.hpp> | 33 | #include <boost/url/rfc/detail/ipvfuture_rule.hpp> | |||||
| 34 | #include <boost/url/rfc/detail/path_rules.hpp> | 34 | #include <boost/url/rfc/detail/path_rules.hpp> | |||||
| 35 | #include <boost/url/rfc/detail/port_rule.hpp> | 35 | #include <boost/url/rfc/detail/port_rule.hpp> | |||||
| 36 | #include <boost/url/rfc/detail/scheme_rule.hpp> | 36 | #include <boost/url/rfc/detail/scheme_rule.hpp> | |||||
| 37 | #include <boost/url/rfc/detail/userinfo_rule.hpp> | 37 | #include <boost/url/rfc/detail/userinfo_rule.hpp> | |||||
| 38 | #include <boost/url/grammar/parse.hpp> | 38 | #include <boost/url/grammar/parse.hpp> | |||||
| 39 | #include <boost/url/detail/move_chars.hpp> | 39 | #include <boost/url/detail/move_chars.hpp> | |||||
| 40 | #include <cstring> | 40 | #include <cstring> | |||||
| 41 | #include <iostream> | 41 | #include <iostream> | |||||
| 42 | #include <stdexcept> | 42 | #include <stdexcept> | |||||
| 43 | #include <utility> | 43 | #include <utility> | |||||
| 44 | 44 | |||||||
| 45 | namespace boost { | 45 | namespace boost { | |||||
| 46 | namespace urls { | 46 | namespace urls { | |||||
| 47 | 47 | |||||||
| 48 | //------------------------------------------------ | 48 | //------------------------------------------------ | |||||
| 49 | 49 | |||||||
| 50 | // these objects help handle the cases | 50 | // these objects help handle the cases | |||||
| 51 | // where the user passes in strings that | 51 | // where the user passes in strings that | |||||
| 52 | // come from inside the url buffer. | 52 | // come from inside the url buffer. | |||||
| 53 | 53 | |||||||
| 54 | inline | 54 | inline | |||||
| HITCBC | 55 | 18290 | url_base:: | 55 | 18300 | url_base:: | ||
| 56 | op_t:: | 56 | op_t:: | |||||
| 57 | ~op_t() | 57 | ~op_t() | |||||
| 58 | { | 58 | { | |||||
| HITCBC | 59 | 18290 | if(old) | 59 | 18300 | if(old) | ||
| HITCBC | 60 | 2561 | u.cleanup(*this); | 60 | 2564 | u.cleanup(*this); | ||
| HITCBC | 61 | 18290 | u.check_invariants(); | 61 | 18300 | u.check_invariants(); | ||
| HITCBC | 62 | 18290 | } | 62 | 18300 | } | ||
| 63 | 63 | |||||||
| 64 | inline | 64 | inline | |||||
| HITCBC | 65 | 18290 | url_base:: | 65 | 18300 | url_base:: | ||
| 66 | op_t:: | 66 | op_t:: | |||||
| 67 | op_t( | 67 | op_t( | |||||
| 68 | url_base& impl_, | 68 | url_base& impl_, | |||||
| 69 | core::string_view* s0_, | 69 | core::string_view* s0_, | |||||
| HITCBC | 70 | 18290 | core::string_view* s1_) noexcept | 70 | 18300 | core::string_view* s1_) noexcept | ||
| HITCBC | 71 | 18290 | : u(impl_) | 71 | 18300 | : u(impl_) | ||
| HITCBC | 72 | 18290 | , s0(s0_) | 72 | 18300 | , s0(s0_) | ||
| HITCBC | 73 | 18290 | , s1(s1_) | 73 | 18300 | , s1(s1_) | ||
| 74 | { | 74 | { | |||||
| HITCBC | 75 | 18290 | u.check_invariants(); | 75 | 18300 | u.check_invariants(); | ||
| HITCBC | 76 | 18290 | } | 76 | 18300 | } | ||
| 77 | 77 | |||||||
| 78 | inline | 78 | inline | |||||
| 79 | void | 79 | void | |||||
| HITCBC | 80 | 9366 | url_base:: | 80 | 9372 | url_base:: | ||
| 81 | op_t:: | 81 | op_t:: | |||||
| 82 | move( | 82 | move( | |||||
| 83 | char* dest, | 83 | char* dest, | |||||
| 84 | char const* src, | 84 | char const* src, | |||||
| 85 | std::size_t n) noexcept | 85 | std::size_t n) noexcept | |||||
| 86 | { | 86 | { | |||||
| HITCBC | 87 | 9366 | if(! n) | 87 | 9372 | if(! n) | ||
| HITCBC | 88 | 2519 | return; | 88 | 2523 | return; | ||
| HITCBC | 89 | 6847 | if(s0) | 89 | 6849 | if(s0) | ||
| 90 | { | 90 | { | |||||
| HITCBC | 91 | 4885 | if(s1) | 91 | 4887 | if(s1) | ||
| HITCBC | 92 | 654 | return detail::move_chars( | 92 | 656 | return detail::move_chars( | ||
| HITCBC | 93 | 654 | dest, src, n, *s0, *s1); | 93 | 656 | dest, src, n, *s0, *s1); | ||
| HITCBC | 94 | 4231 | return detail::move_chars( | 94 | 4231 | return detail::move_chars( | ||
| HITCBC | 95 | 4231 | dest, src, n, *s0); | 95 | 4231 | dest, src, n, *s0); | ||
| 96 | } | 96 | } | |||||
| HITCBC | 97 | 1962 | detail::move_chars( | 97 | 1962 | detail::move_chars( | ||
| 98 | dest, src, n); | 98 | dest, src, n); | |||||
| 99 | } | 99 | } | |||||
| 100 | 100 | |||||||
| 101 | //------------------------------------------------ | 101 | //------------------------------------------------ | |||||
| 102 | 102 | |||||||
| 103 | // construct reference | 103 | // construct reference | |||||
| 104 | inline | 104 | inline | |||||
| HITCBC | 105 | 1647 | url_base:: | 105 | 1647 | url_base:: | ||
| 106 | url_base( | 106 | url_base( | |||||
| HITCBC | 107 | 1647 | detail::url_impl const& impl) noexcept | 107 | 1647 | detail::url_impl const& impl) noexcept | ||
| HITCBC | 108 | 1647 | : url_view_base(impl) | 108 | 1647 | : url_view_base(impl) | ||
| 109 | { | 109 | { | |||||
| HITCBC | 110 | 1647 | } | 110 | 1647 | } | ||
| 111 | 111 | |||||||
| 112 | inline | 112 | inline | |||||
| 113 | void | 113 | void | |||||
| HITCBC | 114 | 305 | url_base:: | 114 | 305 | url_base:: | ||
| 115 | reserve_impl(std::size_t n) | 115 | reserve_impl(std::size_t n) | |||||
| 116 | { | 116 | { | |||||
| HITCBC | 117 | 305 | op_t op(*this); | 117 | 305 | op_t op(*this); | ||
| HITCBC | 118 | 305 | reserve_impl(n, op); | 118 | 305 | reserve_impl(n, op); | ||
| HITCBC | 119 | 304 | if(s_) | 119 | 304 | if(s_) | ||
| HITCBC | 120 | 302 | s_[size()] = '\0'; | 120 | 302 | s_[size()] = '\0'; | ||
| HITCBC | 121 | 305 | } | 121 | 305 | } | ||
| 122 | 122 | |||||||
| 123 | // make a copy of u | 123 | // make a copy of u | |||||
| 124 | inline | 124 | inline | |||||
| 125 | void | 125 | void | |||||
| HITCBC | 126 | 5227 | url_base:: | 126 | 5231 | url_base:: | ||
| 127 | copy(url_view_base const& u) | 127 | copy(url_view_base const& u) | |||||
| 128 | { | 128 | { | |||||
| HITCBC | 129 | 5227 | if (this == &u) | 129 | 5231 | if (this == &u) | ||
| HITCBC | 130 | 140 | return; | 130 | 140 | return; | ||
| HITCBC | 131 | 5213 | op_t op(*this); | 131 | 5217 | op_t op(*this); | ||
| HITCBC | 132 | 5213 | if(u.size() == 0) | 132 | 5217 | if(u.size() == 0) | ||
| 133 | { | 133 | { | |||||
| HITCBC | 134 | 126 | clear(); | 134 | 126 | clear(); | ||
| HITCBC | 135 | 126 | return; | 135 | 126 | return; | ||
| 136 | } | 136 | } | |||||
| HITCBC | 137 | 5087 | reserve_impl( | 137 | 5091 | reserve_impl( | ||
| 138 | u.size(), op); | 138 | u.size(), op); | |||||
| HITCBC | 139 | 5084 | impl_ = u.impl(); | 139 | 5088 | impl_ = u.impl(); | ||
| HITCBC | 140 | 5084 | impl_.cs_ = s_; | 140 | 5088 | impl_.cs_ = s_; | ||
| HITCBC | 141 | 5084 | impl_.from_ = {from::url}; | 141 | 5088 | impl_.from_ = {from::url}; | ||
| HITCBC | 142 | 5084 | std::memcpy(s_, | 142 | 5088 | std::memcpy(s_, | ||
| HITCBC | 143 | 5084 | u.data(), u.size()); | 143 | 5088 | u.data(), u.size()); | ||
| HITCBC | 144 | 5084 | s_[size()] = '\0'; | 144 | 5088 | s_[size()] = '\0'; | ||
| HITCBC | 145 | 5213 | } | 145 | 5217 | } | ||
| 146 | 146 | |||||||
| 147 | //------------------------------------------------ | 147 | //------------------------------------------------ | |||||
| 148 | // | 148 | // | |||||
| 149 | // Scheme | 149 | // Scheme | |||||
| 150 | // | 150 | // | |||||
| 151 | //------------------------------------------------ | 151 | //------------------------------------------------ | |||||
| 152 | 152 | |||||||
| 153 | inline | 153 | inline | |||||
| 154 | url_base& | 154 | url_base& | |||||
| HITCBC | 155 | 376 | url_base:: | 155 | 376 | url_base:: | ||
| 156 | set_scheme(core::string_view s) | 156 | set_scheme(core::string_view s) | |||||
| 157 | { | 157 | { | |||||
| HITCBC | 158 | 376 | set_scheme_impl( | 158 | 376 | set_scheme_impl( | ||
| 159 | s, string_to_scheme(s)); | 159 | s, string_to_scheme(s)); | |||||
| HITCBC | 160 | 359 | return *this; | 160 | 359 | return *this; | ||
| 161 | } | 161 | } | |||||
| 162 | 162 | |||||||
| 163 | inline | 163 | inline | |||||
| 164 | url_base& | 164 | url_base& | |||||
| HITCBC | 165 | 182 | url_base:: | 165 | 182 | url_base:: | ||
| 166 | set_scheme_id(urls::scheme id) | 166 | set_scheme_id(urls::scheme id) | |||||
| 167 | { | 167 | { | |||||
| HITCBC | 168 | 182 | if(id == urls::scheme::unknown) | 168 | 182 | if(id == urls::scheme::unknown) | ||
| HITCBC | 169 | 14 | detail::throw_invalid_argument(); | 169 | 14 | detail::throw_invalid_argument(); | ||
| HITCBC | 170 | 168 | if(id == urls::scheme::none) | 170 | 168 | if(id == urls::scheme::none) | ||
| HITCBC | 171 | 18 | return remove_scheme(); | 171 | 18 | return remove_scheme(); | ||
| HITCBC | 172 | 150 | set_scheme_impl(to_string(id), id); | 172 | 150 | set_scheme_impl(to_string(id), id); | ||
| HITCBC | 173 | 119 | return *this; | 173 | 119 | return *this; | ||
| 174 | } | 174 | } | |||||
| 175 | 175 | |||||||
| 176 | inline | 176 | inline | |||||
| 177 | url_base& | 177 | url_base& | |||||
| HITCBC | 178 | 53 | url_base:: | 178 | 53 | url_base:: | ||
| 179 | remove_scheme() | 179 | remove_scheme() | |||||
| 180 | { | 180 | { | |||||
| HITCBC | 181 | 53 | op_t op(*this); | 181 | 53 | op_t op(*this); | ||
| HITCBC | 182 | 53 | auto const sn = impl_.len(id_scheme); | 182 | 53 | auto const sn = impl_.len(id_scheme); | ||
| HITCBC | 183 | 53 | if(sn == 0) | 183 | 53 | if(sn == 0) | ||
| HITCBC | 184 | 15 | return *this; | 184 | 15 | return *this; | ||
| HITCBC | 185 | 38 | auto const po = impl_.offset(id_path); | 185 | 38 | auto const po = impl_.offset(id_path); | ||
| HITCBC | 186 | 38 | auto fseg = first_segment(); | 186 | 38 | auto fseg = first_segment(); | ||
| 187 | bool const encode_colon = | 187 | bool const encode_colon = | |||||
| HITCBC | 188 | 38 | !has_authority() && | 188 | 38 | !has_authority() && | ||
| HITCBC | 189 | 21 | impl_.nseg_ > 0 && | 189 | 21 | impl_.nseg_ > 0 && | ||
| HITCBC | 190 | 70 | s_[po] != '/' && | 190 | 70 | s_[po] != '/' && | ||
| HITCBC | 191 | 11 | fseg.contains(':'); | 191 | 11 | fseg.contains(':'); | ||
| HITCBC | 192 | 38 | if(!encode_colon) | 192 | 38 | if(!encode_colon) | ||
| 193 | { | 193 | { | |||||
| 194 | // just remove the scheme | 194 | // just remove the scheme | |||||
| HITCBC | 195 | 29 | resize_impl(id_scheme, 0, op); | 195 | 29 | resize_impl(id_scheme, 0, op); | ||
| HITCBC | 196 | 29 | impl_.scheme_ = urls::scheme::none; | 196 | 29 | impl_.scheme_ = urls::scheme::none; | ||
| HITCBC | 197 | 29 | check_invariants(); | 197 | 29 | check_invariants(); | ||
| HITCBC | 198 | 29 | return *this; | 198 | 29 | return *this; | ||
| 199 | } | 199 | } | |||||
| 200 | // encode any ":" in the first path segment | 200 | // encode any ":" in the first path segment | |||||
| HITCBC | 201 | 9 | BOOST_ASSERT(sn >= 2); | 201 | 9 | BOOST_ASSERT(sn >= 2); | ||
| HITCBC | 202 | 9 | auto pn = impl_.len(id_path); | 202 | 9 | auto pn = impl_.len(id_path); | ||
| HITCBC | 203 | 9 | std::size_t cn = 0; | 203 | 9 | std::size_t cn = 0; | ||
| HITCBC | 204 | 46 | for (char c: fseg) | 204 | 46 | for (char c: fseg) | ||
| HITCBC | 205 | 37 | cn += c == ':'; | 205 | 37 | cn += c == ':'; | ||
| 206 | std::size_t new_size = | 206 | std::size_t new_size = | |||||
| HITCBC | 207 | 9 | size() - sn + 2 * cn; | 207 | 9 | size() - sn + 2 * cn; | ||
| HITCBC | 208 | 9 | bool need_resize = new_size > size(); | 208 | 9 | bool need_resize = new_size > size(); | ||
| HITCBC | 209 | 9 | if (need_resize) | 209 | 9 | if (need_resize) | ||
| 210 | { | 210 | { | |||||
| HITCBC | 211 | 1 | resize_impl( | 211 | 1 | resize_impl( | ||
| HITCBC | 212 | 1 | id_path, pn + 2 * cn, op); | 212 | 1 | id_path, pn + 2 * cn, op); | ||
| 213 | } | 213 | } | |||||
| 214 | // move [id_scheme, id_path) left | 214 | // move [id_scheme, id_path) left | |||||
| HITCBC | 215 | 9 | op.move( | 215 | 9 | op.move( | ||
| 216 | s_, | 216 | s_, | |||||
| HITCBC | 217 | 9 | s_ + sn, | 217 | 9 | s_ + sn, | ||
| 218 | po - sn); | 218 | po - sn); | |||||
| 219 | // move [id_path, id_query) left | 219 | // move [id_path, id_query) left | |||||
| HITCBC | 220 | 9 | auto qo = impl_.offset(id_query); | 220 | 9 | auto qo = impl_.offset(id_query); | ||
| HITCBC | 221 | 9 | op.move( | 221 | 9 | op.move( | ||
| HITCBC | 222 | 9 | s_ + po - sn, | 222 | 9 | s_ + po - sn, | ||
| HITCBC | 223 | 9 | s_ + po, | 223 | 9 | s_ + po, | ||
| 224 | qo - po); | 224 | qo - po); | |||||
| 225 | // move [id_query, id_end) left | 225 | // move [id_query, id_end) left | |||||
| HITCBC | 226 | 9 | op.move( | 226 | 9 | op.move( | ||
| HITCBC | 227 | 9 | s_ + qo - sn + 2 * cn, | 227 | 9 | s_ + qo - sn + 2 * cn, | ||
| HITCBC | 228 | 9 | s_ + qo, | 228 | 9 | s_ + qo, | ||
| HITCBC | 229 | 9 | impl_.offset(id_end) - qo); | 229 | 9 | impl_.offset(id_end) - qo); | ||
| 230 | 230 | |||||||
| 231 | // adjust part offsets. | 231 | // adjust part offsets. | |||||
| 232 | // (po and qo are invalidated) | 232 | // (po and qo are invalidated) | |||||
| HITCBC | 233 | 9 | if (need_resize) | 233 | 9 | if (need_resize) | ||
| 234 | { | 234 | { | |||||
| HITCBC | 235 | 1 | impl_.adjust_left(id_user, id_end, sn); | 235 | 1 | impl_.adjust_left(id_user, id_end, sn); | ||
| 236 | } | 236 | } | |||||
| 237 | else | 237 | else | |||||
| 238 | { | 238 | { | |||||
| HITCBC | 239 | 8 | impl_.adjust_left(id_user, id_path, sn); | 239 | 8 | impl_.adjust_left(id_user, id_path, sn); | ||
| HITCBC | 240 | 8 | impl_.adjust_left(id_query, id_end, sn - 2 * cn); | 240 | 8 | impl_.adjust_left(id_query, id_end, sn - 2 * cn); | ||
| 241 | } | 241 | } | |||||
| HITCBC | 242 | 9 | if (encode_colon) | 242 | 9 | if (encode_colon) | ||
| 243 | { | 243 | { | |||||
| 244 | // move the 2nd, 3rd, ... segments | 244 | // move the 2nd, 3rd, ... segments | |||||
| HITCBC | 245 | 9 | auto begin = s_ + impl_.offset(id_path); | 245 | 9 | auto begin = s_ + impl_.offset(id_path); | ||
| HITCBC | 246 | 9 | auto it = begin; | 246 | 9 | auto it = begin; | ||
| HITCBC | 247 | 9 | auto end = begin + pn; | 247 | 9 | auto end = begin + pn; | ||
| HITCBC | 248 | 46 | while (it != end && | 248 | 46 | while (it != end && | ||
| HITCBC | 249 | 40 | *it != '/') | 249 | 40 | *it != '/') | ||
| HITCBC | 250 | 37 | ++it; | 250 | 37 | ++it; | ||
| 251 | // we don't need op here because this is | 251 | // we don't need op here because this is | |||||
| 252 | // an internal operation | 252 | // an internal operation | |||||
| HITCBC | 253 | 9 | std::memmove(it + (2 * cn), it, end - it); | 253 | 9 | std::memmove(it + (2 * cn), it, end - it); | ||
| 254 | 254 | |||||||
| 255 | // move 1st segment | 255 | // move 1st segment | |||||
| HITCBC | 256 | 9 | auto src = s_ + impl_.offset(id_path) + pn; | 256 | 9 | auto src = s_ + impl_.offset(id_path) + pn; | ||
| HITCBC | 257 | 9 | auto dest = s_ + impl_.offset(id_query); | 257 | 9 | auto dest = s_ + impl_.offset(id_query); | ||
| HITCBC | 258 | 9 | src -= end - it; | 258 | 9 | src -= end - it; | ||
| HITCBC | 259 | 9 | dest -= end - it; | 259 | 9 | dest -= end - it; | ||
| HITCBC | 260 | 9 | pn -= end - it; | 260 | 9 | pn -= end - it; | ||
| 261 | do { | 261 | do { | |||||
| HITCBC | 262 | 37 | --src; | 262 | 37 | --src; | ||
| HITCBC | 263 | 37 | --dest; | 263 | 37 | --dest; | ||
| HITCBC | 264 | 37 | if (*src != ':') | 264 | 37 | if (*src != ':') | ||
| 265 | { | 265 | { | |||||
| HITCBC | 266 | 25 | *dest = *src; | 266 | 25 | *dest = *src; | ||
| 267 | } | 267 | } | |||||
| 268 | else | 268 | else | |||||
| 269 | { | 269 | { | |||||
| 270 | // use uppercase as required by | 270 | // use uppercase as required by | |||||
| 271 | // syntax-based normalization | 271 | // syntax-based normalization | |||||
| HITCBC | 272 | 12 | *dest-- = 'A'; | 272 | 12 | *dest-- = 'A'; | ||
| HITCBC | 273 | 12 | *dest-- = '3'; | 273 | 12 | *dest-- = '3'; | ||
| HITCBC | 274 | 12 | *dest = '%'; | 274 | 12 | *dest = '%'; | ||
| 275 | } | 275 | } | |||||
| HITCBC | 276 | 37 | --pn; | 276 | 37 | --pn; | ||
| HITCBC | 277 | 37 | } while (pn); | 277 | 37 | } while (pn); | ||
| 278 | } | 278 | } | |||||
| HITCBC | 279 | 9 | s_[size()] = '\0'; | 279 | 9 | s_[size()] = '\0'; | ||
| HITCBC | 280 | 9 | impl_.scheme_ = urls::scheme::none; | 280 | 9 | impl_.scheme_ = urls::scheme::none; | ||
| HITCBC | 281 | 9 | return *this; | 281 | 9 | return *this; | ||
| HITCBC | 282 | 53 | } | 282 | 53 | } | ||
| 283 | 283 | |||||||
| 284 | //------------------------------------------------ | 284 | //------------------------------------------------ | |||||
| 285 | // | 285 | // | |||||
| 286 | // Authority | 286 | // Authority | |||||
| 287 | // | 287 | // | |||||
| 288 | //------------------------------------------------ | 288 | //------------------------------------------------ | |||||
| 289 | 289 | |||||||
| 290 | inline | 290 | inline | |||||
| 291 | url_base& | 291 | url_base& | |||||
| HITCBC | 292 | 120 | url_base:: | 292 | 120 | url_base:: | ||
| 293 | set_encoded_authority( | 293 | set_encoded_authority( | |||||
| 294 | pct_string_view s) | 294 | pct_string_view s) | |||||
| 295 | { | 295 | { | |||||
| HITCBC | 296 | 120 | op_t op(*this, &detail::ref(s)); | 296 | 120 | op_t op(*this, &detail::ref(s)); | ||
| HITCBC | 297 | 122 | authority_view a = grammar::parse( | 297 | 122 | authority_view a = grammar::parse( | ||
| 298 | s, authority_rule | 298 | s, authority_rule | |||||
| HITCBC | 299 | 120 | ).value(BOOST_URL_POS); | 299 | 120 | ).value(BOOST_URL_POS); | ||
| HITCBC | 300 | 119 | auto n = s.size() + 2; | 300 | 119 | auto n = s.size() + 2; | ||
| 301 | auto const need_slash = | 301 | auto const need_slash = | |||||
| HITCBC | 302 | 141 | ! is_path_absolute() && | 302 | 141 | ! is_path_absolute() && | ||
| HITCBC | 303 | 22 | impl_.len(id_path) > 0; | 303 | 22 | impl_.len(id_path) > 0; | ||
| HITCBC | 304 | 119 | if(need_slash) | 304 | 119 | if(need_slash) | ||
| HITCBC | 305 | 2 | ++n; | 305 | 2 | ++n; | ||
| HITCBC | 306 | 119 | auto dest = resize_impl( | 306 | 119 | auto dest = resize_impl( | ||
| 307 | id_user, id_path, n, op); | 307 | id_user, id_path, n, op); | |||||
| HITCBC | 308 | 119 | dest[0] = '/'; | 308 | 119 | dest[0] = '/'; | ||
| HITCBC | 309 | 119 | dest[1] = '/'; | 309 | 119 | dest[1] = '/'; | ||
| HITCBC | 310 | 119 | std::memcpy(dest + 2, | 310 | 119 | std::memcpy(dest + 2, | ||
| HITCBC | 311 | 119 | s.data(), s.size()); | 311 | 119 | s.data(), s.size()); | ||
| HITCBC | 312 | 119 | if(need_slash) | 312 | 119 | if(need_slash) | ||
| HITCBC | 313 | 2 | dest[n - 1] = '/'; | 313 | 2 | dest[n - 1] = '/'; | ||
| HITCBC | 314 | 119 | impl_.apply_authority(a.u_); | 314 | 119 | impl_.apply_authority(a.u_); | ||
| HITCBC | 315 | 119 | if(need_slash) | 315 | 119 | if(need_slash) | ||
| HITCBC | 316 | 2 | impl_.adjust_right( | 316 | 2 | impl_.adjust_right( | ||
| 317 | id_query, id_end, 1); | 317 | id_query, id_end, 1); | |||||
| HITCBC | 318 | 119 | return *this; | 318 | 119 | return *this; | ||
| HITCBC | 319 | 120 | } | 319 | 120 | } | ||
| 320 | 320 | |||||||
| 321 | inline | 321 | inline | |||||
| 322 | url_base& | 322 | url_base& | |||||
| HITCBC | 323 | 259 | url_base:: | 323 | 259 | url_base:: | ||
| 324 | remove_authority() | 324 | remove_authority() | |||||
| 325 | { | 325 | { | |||||
| HITCBC | 326 | 259 | if(! has_authority()) | 326 | 259 | if(! has_authority()) | ||
| HITCBC | 327 | 70 | return *this; | 327 | 70 | return *this; | ||
| 328 | 328 | |||||||
| HITCBC | 329 | 189 | op_t op(*this); | 329 | 189 | op_t op(*this); | ||
| HITCBC | 330 | 189 | auto path = impl_.get(id_path); | 330 | 189 | auto path = impl_.get(id_path); | ||
| HITCBC | 331 | 189 | bool const need_dot = path.starts_with("//"); | 331 | 189 | bool const need_dot = path.starts_with("//"); | ||
| HITCBC | 332 | 189 | if(need_dot) | 332 | 189 | if(need_dot) | ||
| 333 | { | 333 | { | |||||
| 334 | // prepend "/.", can't throw | 334 | // prepend "/.", can't throw | |||||
| HITCBC | 335 | 5 | auto p = resize_impl( | 335 | 5 | auto p = resize_impl( | ||
| 336 | id_user, id_path, 2, op); | 336 | id_user, id_path, 2, op); | |||||
| HITCBC | 337 | 5 | p[0] = '/'; | 337 | 5 | p[0] = '/'; | ||
| HITCBC | 338 | 5 | p[1] = '.'; | 338 | 5 | p[1] = '.'; | ||
| HITCBC | 339 | 5 | impl_.split(id_user, 0); | 339 | 5 | impl_.split(id_user, 0); | ||
| HITCBC | 340 | 5 | impl_.split(id_pass, 0); | 340 | 5 | impl_.split(id_pass, 0); | ||
| HITCBC | 341 | 5 | impl_.split(id_host, 0); | 341 | 5 | impl_.split(id_host, 0); | ||
| HITCBC | 342 | 5 | impl_.split(id_port, 0); | 342 | 5 | impl_.split(id_port, 0); | ||
| 343 | } | 343 | } | |||||
| 344 | else | 344 | else | |||||
| 345 | { | 345 | { | |||||
| HITCBC | 346 | 184 | resize_impl( | 346 | 184 | resize_impl( | ||
| 347 | id_user, id_path, 0, op); | 347 | id_user, id_path, 0, op); | |||||
| 348 | } | 348 | } | |||||
| HITCBC | 349 | 189 | impl_.host_type_ = | 349 | 189 | impl_.host_type_ = | ||
| 350 | urls::host_type::none; | 350 | urls::host_type::none; | |||||
| HITCBC | 351 | 189 | return *this; | 351 | 189 | return *this; | ||
| HITCBC | 352 | 189 | } | 352 | 189 | } | ||
| 353 | 353 | |||||||
| 354 | //------------------------------------------------ | 354 | //------------------------------------------------ | |||||
| 355 | // | 355 | // | |||||
| 356 | // Userinfo | 356 | // Userinfo | |||||
| 357 | // | 357 | // | |||||
| 358 | //------------------------------------------------ | 358 | //------------------------------------------------ | |||||
| 359 | 359 | |||||||
| 360 | inline | 360 | inline | |||||
| 361 | url_base& | 361 | url_base& | |||||
| HITCBC | 362 | 225 | url_base:: | 362 | 225 | url_base:: | ||
| 363 | set_userinfo( | 363 | set_userinfo( | |||||
| 364 | core::string_view s) | 364 | core::string_view s) | |||||
| 365 | { | 365 | { | |||||
| HITCBC | 366 | 225 | op_t op(*this, &s); | 366 | 225 | op_t op(*this, &s); | ||
| HITCBC | 367 | 225 | encoding_opts opt; | 367 | 225 | encoding_opts opt; | ||
| HITCBC | 368 | 225 | auto const n = encoded_size( | 368 | 225 | auto const n = encoded_size( | ||
| 369 | s, detail::userinfo_chars, opt); | 369 | s, detail::userinfo_chars, opt); | |||||
| HITCBC | 370 | 225 | auto dest = set_userinfo_impl(n, op); | 370 | 225 | auto dest = set_userinfo_impl(n, op); | ||
| HITCBC | 371 | 225 | encode( | 371 | 225 | encode( | ||
| 372 | dest, | 372 | dest, | |||||
| 373 | n, | 373 | n, | |||||
| 374 | s, | 374 | s, | |||||
| 375 | detail::userinfo_chars, | 375 | detail::userinfo_chars, | |||||
| 376 | opt); | 376 | opt); | |||||
| HITCBC | 377 | 225 | auto const pos = impl_.get( | 377 | 225 | auto const pos = impl_.get( | ||
| 378 | id_user, id_host | 378 | id_user, id_host | |||||
| HITCBC | 379 | 225 | ).find_first_of(':'); | 379 | 225 | ).find_first_of(':'); | ||
| HITCBC | 380 | 225 | if(pos != core::string_view::npos) | 380 | 225 | if(pos != core::string_view::npos) | ||
| 381 | { | 381 | { | |||||
| HITCBC | 382 | 22 | impl_.split(id_user, pos); | 382 | 22 | impl_.split(id_user, pos); | ||
| 383 | // find ':' in plain string | 383 | // find ':' in plain string | |||||
| 384 | auto const pos2 = | 384 | auto const pos2 = | |||||
| HITCBC | 385 | 22 | s.find_first_of(':'); | 385 | 22 | s.find_first_of(':'); | ||
| HITCBC | 386 | 22 | if(pos2 != core::string_view::npos) | 386 | 22 | if(pos2 != core::string_view::npos) | ||
| 387 | { | 387 | { | |||||
| 388 | // pos2 is the ':' index in plain input (user[:pass]) | 388 | // pos2 is the ':' index in plain input (user[:pass]) | |||||
| 389 | // decoded user is [0, pos2), decoded pass is (pos2, end]. | 389 | // decoded user is [0, pos2), decoded pass is (pos2, end]. | |||||
| HITCBC | 390 | 22 | impl_.decoded_[id_user] = | 390 | 22 | impl_.decoded_[id_user] = | ||
| HITCBC | 391 | 22 | detail::to_size_type(pos2); | 391 | 22 | detail::to_size_type(pos2); | ||
| HITCBC | 392 | 22 | impl_.decoded_[id_pass] = | 392 | 22 | impl_.decoded_[id_pass] = | ||
| HITCBC | 393 | 22 | detail::to_size_type(s.size() - pos2 - 1); | 393 | 22 | detail::to_size_type(s.size() - pos2 - 1); | ||
| 394 | } | 394 | } | |||||
| 395 | else | 395 | else | |||||
| 396 | { | 396 | { | |||||
| MISUBC | 397 | ✗ | impl_.decoded_[id_user] = | 397 | ✗ | impl_.decoded_[id_user] = | ||
| MISUBC | 398 | ✗ | detail::to_size_type(s.size()); | 398 | ✗ | detail::to_size_type(s.size()); | ||
| MISUBC | 399 | ✗ | impl_.decoded_[id_pass] = 0; | 399 | ✗ | impl_.decoded_[id_pass] = 0; | ||
| 400 | } | 400 | } | |||||
| 401 | } | 401 | } | |||||
| 402 | else | 402 | else | |||||
| 403 | { | 403 | { | |||||
| HITCBC | 404 | 203 | impl_.decoded_[id_user] = | 404 | 203 | impl_.decoded_[id_user] = | ||
| HITCBC | 405 | 203 | detail::to_size_type(s.size()); | 405 | 203 | detail::to_size_type(s.size()); | ||
| HITCBC | 406 | 203 | impl_.decoded_[id_pass] = 0; | 406 | 203 | impl_.decoded_[id_pass] = 0; | ||
| 407 | } | 407 | } | |||||
| HITCBC | 408 | 225 | return *this; | 408 | 225 | return *this; | ||
| HITCBC | 409 | 225 | } | 409 | 225 | } | ||
| 410 | 410 | |||||||
| 411 | inline | 411 | inline | |||||
| 412 | url_base& | 412 | url_base& | |||||
| HITCBC | 413 | 52 | url_base:: | 413 | 52 | url_base:: | ||
| 414 | set_encoded_userinfo( | 414 | set_encoded_userinfo( | |||||
| 415 | pct_string_view s) | 415 | pct_string_view s) | |||||
| 416 | { | 416 | { | |||||
| HITCBC | 417 | 52 | op_t op(*this, &detail::ref(s)); | 417 | 52 | op_t op(*this, &detail::ref(s)); | ||
| HITCBC | 418 | 52 | auto const pos = s.find_first_of(':'); | 418 | 52 | auto const pos = s.find_first_of(':'); | ||
| HITCBC | 419 | 52 | if(pos != core::string_view::npos) | 419 | 52 | if(pos != core::string_view::npos) | ||
| 420 | { | 420 | { | |||||
| 421 | // user:pass | 421 | // user:pass | |||||
| HITCBC | 422 | 7 | auto const s0 = s.substr(0, pos); | 422 | 7 | auto const s0 = s.substr(0, pos); | ||
| HITCBC | 423 | 7 | auto const s1 = s.substr(pos + 1); | 423 | 7 | auto const s1 = s.substr(pos + 1); | ||
| 424 | auto const n0 = | 424 | auto const n0 = | |||||
| HITCBC | 425 | 7 | detail::re_encoded_size_unsafe( | 425 | 7 | detail::re_encoded_size_unsafe( | ||
| 426 | s0, | 426 | s0, | |||||
| 427 | detail::user_chars); | 427 | detail::user_chars); | |||||
| 428 | auto const n1 = | 428 | auto const n1 = | |||||
| HITCBC | 429 | 7 | detail::re_encoded_size_unsafe(s1, | 429 | 7 | detail::re_encoded_size_unsafe(s1, | ||
| 430 | detail::password_chars); | 430 | detail::password_chars); | |||||
| 431 | auto dest = | 431 | auto dest = | |||||
| HITCBC | 432 | 7 | set_userinfo_impl(n0 + n1 + 1, op); | 432 | 7 | set_userinfo_impl(n0 + n1 + 1, op); | ||
| HITCBC | 433 | 7 | impl_.decoded_[id_user] = | 433 | 7 | impl_.decoded_[id_user] = | ||
| HITCBC | 434 | 7 | detail::to_size_type(detail::re_encode_unsafe( | 434 | 7 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 435 | dest, | 435 | dest, | |||||
| HITCBC | 436 | 7 | dest + n0, | 436 | 7 | dest + n0, | ||
| 437 | s0, | 437 | s0, | |||||
| 438 | detail::user_chars)); | 438 | detail::user_chars)); | |||||
| HITCBC | 439 | 7 | *dest++ = ':'; | 439 | 7 | *dest++ = ':'; | ||
| HITCBC | 440 | 7 | impl_.decoded_[id_pass] = | 440 | 7 | impl_.decoded_[id_pass] = | ||
| HITCBC | 441 | 7 | detail::to_size_type(detail::re_encode_unsafe( | 441 | 7 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 442 | dest, | 442 | dest, | |||||
| HITCBC | 443 | 7 | dest + n1, | 443 | 7 | dest + n1, | ||
| 444 | s1, | 444 | s1, | |||||
| 445 | detail::password_chars)); | 445 | detail::password_chars)); | |||||
| HITCBC | 446 | 7 | impl_.split(id_user, 2 + n0); | 446 | 7 | impl_.split(id_user, 2 + n0); | ||
| 447 | } | 447 | } | |||||
| 448 | else | 448 | else | |||||
| 449 | { | 449 | { | |||||
| 450 | // user | 450 | // user | |||||
| 451 | auto const n = | 451 | auto const n = | |||||
| HITCBC | 452 | 45 | detail::re_encoded_size_unsafe( | 452 | 45 | detail::re_encoded_size_unsafe( | ||
| 453 | s, detail::user_chars); | 453 | s, detail::user_chars); | |||||
| HITCBC | 454 | 45 | auto dest = set_userinfo_impl(n, op); | 454 | 45 | auto dest = set_userinfo_impl(n, op); | ||
| HITCBC | 455 | 45 | impl_.decoded_[id_user] = | 455 | 45 | impl_.decoded_[id_user] = | ||
| HITCBC | 456 | 90 | detail::to_size_type(detail::re_encode_unsafe( | 456 | 90 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 457 | dest, | 457 | dest, | |||||
| HITCBC | 458 | 45 | dest + n, | 458 | 45 | dest + n, | ||
| 459 | s, | 459 | s, | |||||
| 460 | detail::user_chars)); | 460 | detail::user_chars)); | |||||
| HITCBC | 461 | 45 | impl_.split(id_user, 2 + n); | 461 | 45 | impl_.split(id_user, 2 + n); | ||
| HITCBC | 462 | 45 | impl_.decoded_[id_pass] = 0; | 462 | 45 | impl_.decoded_[id_pass] = 0; | ||
| 463 | } | 463 | } | |||||
| HITCBC | 464 | 52 | return *this; | 464 | 52 | return *this; | ||
| HITCBC | 465 | 52 | } | 465 | 52 | } | ||
| 466 | 466 | |||||||
| 467 | inline | 467 | inline | |||||
| 468 | url_base& | 468 | url_base& | |||||
| HITCBC | 469 | 214 | url_base:: | 469 | 214 | url_base:: | ||
| 470 | remove_userinfo() noexcept | 470 | remove_userinfo() noexcept | |||||
| 471 | { | 471 | { | |||||
| HITCBC | 472 | 214 | if(impl_.len(id_pass) == 0) | 472 | 214 | if(impl_.len(id_pass) == 0) | ||
| HITCBC | 473 | 138 | return *this; // no userinfo | 473 | 138 | return *this; // no userinfo | ||
| 474 | 474 | |||||||
| HITCBC | 475 | 76 | op_t op(*this); | 475 | 76 | op_t op(*this); | ||
| 476 | // keep authority '//' | 476 | // keep authority '//' | |||||
| HITCBC | 477 | 76 | resize_impl( | 477 | 76 | resize_impl( | ||
| 478 | id_user, id_host, 2, op); | 478 | id_user, id_host, 2, op); | |||||
| HITCBC | 479 | 76 | impl_.decoded_[id_user] = 0; | 479 | 76 | impl_.decoded_[id_user] = 0; | ||
| HITCBC | 480 | 76 | impl_.decoded_[id_pass] = 0; | 480 | 76 | impl_.decoded_[id_pass] = 0; | ||
| HITCBC | 481 | 76 | return *this; | 481 | 76 | return *this; | ||
| HITCBC | 482 | 76 | } | 482 | 76 | } | ||
| 483 | 483 | |||||||
| 484 | //------------------------------------------------ | 484 | //------------------------------------------------ | |||||
| 485 | 485 | |||||||
| 486 | inline | 486 | inline | |||||
| 487 | url_base& | 487 | url_base& | |||||
| HITCBC | 488 | 241 | url_base:: | 488 | 241 | url_base:: | ||
| 489 | set_user(core::string_view s) | 489 | set_user(core::string_view s) | |||||
| 490 | { | 490 | { | |||||
| HITCBC | 491 | 241 | op_t op(*this, &s); | 491 | 241 | op_t op(*this, &s); | ||
| HITCBC | 492 | 241 | encoding_opts opt; | 492 | 241 | encoding_opts opt; | ||
| HITCBC | 493 | 241 | auto const n = encoded_size( | 493 | 241 | auto const n = encoded_size( | ||
| 494 | s, detail::user_chars, opt); | 494 | s, detail::user_chars, opt); | |||||
| HITCBC | 495 | 241 | auto dest = set_user_impl(n, op); | 495 | 241 | auto dest = set_user_impl(n, op); | ||
| HITCBC | 496 | 241 | encode_unsafe( | 496 | 241 | encode_unsafe( | ||
| 497 | dest, | 497 | dest, | |||||
| 498 | n, | 498 | n, | |||||
| 499 | s, | 499 | s, | |||||
| 500 | detail::user_chars, | 500 | detail::user_chars, | |||||
| 501 | opt); | 501 | opt); | |||||
| HITCBC | 502 | 241 | impl_.decoded_[id_user] = | 502 | 241 | impl_.decoded_[id_user] = | ||
| HITCBC | 503 | 241 | detail::to_size_type(s.size()); | 503 | 241 | detail::to_size_type(s.size()); | ||
| HITCBC | 504 | 241 | return *this; | 504 | 241 | return *this; | ||
| HITCBC | 505 | 241 | } | 505 | 241 | } | ||
| 506 | 506 | |||||||
| 507 | inline | 507 | inline | |||||
| 508 | url_base& | 508 | url_base& | |||||
| HITCBC | 509 | 147 | url_base:: | 509 | 147 | url_base:: | ||
| 510 | set_encoded_user( | 510 | set_encoded_user( | |||||
| 511 | pct_string_view s) | 511 | pct_string_view s) | |||||
| 512 | { | 512 | { | |||||
| HITCBC | 513 | 147 | op_t op(*this, &detail::ref(s)); | 513 | 147 | op_t op(*this, &detail::ref(s)); | ||
| 514 | auto const n = | 514 | auto const n = | |||||
| HITCBC | 515 | 147 | detail::re_encoded_size_unsafe( | 515 | 147 | detail::re_encoded_size_unsafe( | ||
| 516 | s, detail::user_chars); | 516 | s, detail::user_chars); | |||||
| HITCBC | 517 | 147 | auto dest = set_user_impl(n, op); | 517 | 147 | auto dest = set_user_impl(n, op); | ||
| HITCBC | 518 | 147 | impl_.decoded_[id_user] = | 518 | 147 | impl_.decoded_[id_user] = | ||
| HITCBC | 519 | 294 | detail::to_size_type(detail::re_encode_unsafe( | 519 | 294 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 520 | dest, | 520 | dest, | |||||
| HITCBC | 521 | 147 | dest + n, | 521 | 147 | dest + n, | ||
| 522 | s, | 522 | s, | |||||
| 523 | detail::user_chars)); | 523 | detail::user_chars)); | |||||
| HITCBC | 524 | 147 | BOOST_ASSERT( | 524 | 147 | BOOST_ASSERT( | ||
| 525 | impl_.decoded_[id_user] == | 525 | impl_.decoded_[id_user] == | |||||
| 526 | s.decoded_size()); | 526 | s.decoded_size()); | |||||
| HITCBC | 527 | 147 | return *this; | 527 | 147 | return *this; | ||
| HITCBC | 528 | 147 | } | 528 | 147 | } | ||
| 529 | 529 | |||||||
| 530 | //------------------------------------------------ | 530 | //------------------------------------------------ | |||||
| 531 | 531 | |||||||
| 532 | inline | 532 | inline | |||||
| 533 | url_base& | 533 | url_base& | |||||
| HITCBC | 534 | 231 | url_base:: | 534 | 231 | url_base:: | ||
| 535 | set_password(core::string_view s) | 535 | set_password(core::string_view s) | |||||
| 536 | { | 536 | { | |||||
| HITCBC | 537 | 231 | op_t op(*this, &s); | 537 | 231 | op_t op(*this, &s); | ||
| HITCBC | 538 | 231 | encoding_opts opt; | 538 | 231 | encoding_opts opt; | ||
| HITCBC | 539 | 231 | auto const n = encoded_size( | 539 | 231 | auto const n = encoded_size( | ||
| 540 | s, detail::password_chars, opt); | 540 | s, detail::password_chars, opt); | |||||
| HITCBC | 541 | 231 | auto dest = set_password_impl(n, op); | 541 | 231 | auto dest = set_password_impl(n, op); | ||
| HITCBC | 542 | 231 | encode_unsafe( | 542 | 231 | encode_unsafe( | ||
| 543 | dest, | 543 | dest, | |||||
| 544 | n, | 544 | n, | |||||
| 545 | s, | 545 | s, | |||||
| 546 | detail::password_chars, | 546 | detail::password_chars, | |||||
| 547 | opt); | 547 | opt); | |||||
| HITCBC | 548 | 231 | impl_.decoded_[id_pass] = | 548 | 231 | impl_.decoded_[id_pass] = | ||
| HITCBC | 549 | 231 | detail::to_size_type(s.size()); | 549 | 231 | detail::to_size_type(s.size()); | ||
| HITCBC | 550 | 231 | return *this; | 550 | 231 | return *this; | ||
| HITCBC | 551 | 231 | } | 551 | 231 | } | ||
| 552 | 552 | |||||||
| 553 | inline | 553 | inline | |||||
| 554 | url_base& | 554 | url_base& | |||||
| HITCBC | 555 | 140 | url_base:: | 555 | 140 | url_base:: | ||
| 556 | set_encoded_password( | 556 | set_encoded_password( | |||||
| 557 | pct_string_view s) | 557 | pct_string_view s) | |||||
| 558 | { | 558 | { | |||||
| HITCBC | 559 | 140 | op_t op(*this, &detail::ref(s)); | 559 | 140 | op_t op(*this, &detail::ref(s)); | ||
| 560 | auto const n = | 560 | auto const n = | |||||
| HITCBC | 561 | 140 | detail::re_encoded_size_unsafe( | 561 | 140 | detail::re_encoded_size_unsafe( | ||
| 562 | s, | 562 | s, | |||||
| 563 | detail::password_chars); | 563 | detail::password_chars); | |||||
| HITCBC | 564 | 140 | auto dest = set_password_impl(n, op); | 564 | 140 | auto dest = set_password_impl(n, op); | ||
| HITCBC | 565 | 140 | impl_.decoded_[id_pass] = | 565 | 140 | impl_.decoded_[id_pass] = | ||
| HITCBC | 566 | 280 | detail::to_size_type(detail::re_encode_unsafe( | 566 | 280 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 567 | dest, | 567 | dest, | |||||
| HITCBC | 568 | 140 | dest + n, | 568 | 140 | dest + n, | ||
| 569 | s, | 569 | s, | |||||
| 570 | detail::password_chars)); | 570 | detail::password_chars)); | |||||
| HITCBC | 571 | 140 | BOOST_ASSERT( | 571 | 140 | BOOST_ASSERT( | ||
| 572 | impl_.decoded_[id_pass] == | 572 | impl_.decoded_[id_pass] == | |||||
| 573 | s.decoded_size()); | 573 | s.decoded_size()); | |||||
| HITCBC | 574 | 140 | return *this; | 574 | 140 | return *this; | ||
| HITCBC | 575 | 140 | } | 575 | 140 | } | ||
| 576 | 576 | |||||||
| 577 | inline | 577 | inline | |||||
| 578 | url_base& | 578 | url_base& | |||||
| HITCBC | 579 | 19 | url_base:: | 579 | 19 | url_base:: | ||
| 580 | remove_password() noexcept | 580 | remove_password() noexcept | |||||
| 581 | { | 581 | { | |||||
| HITCBC | 582 | 19 | auto const n = impl_.len(id_pass); | 582 | 19 | auto const n = impl_.len(id_pass); | ||
| HITCBC | 583 | 19 | if(n < 2) | 583 | 19 | if(n < 2) | ||
| HITCBC | 584 | 12 | return *this; // no password | 584 | 12 | return *this; // no password | ||
| 585 | 585 | |||||||
| HITCBC | 586 | 7 | op_t op(*this); | 586 | 7 | op_t op(*this); | ||
| 587 | // clear password, retain '@' | 587 | // clear password, retain '@' | |||||
| 588 | auto dest = | 588 | auto dest = | |||||
| HITCBC | 589 | 7 | resize_impl(id_pass, 1, op); | 589 | 7 | resize_impl(id_pass, 1, op); | ||
| HITCBC | 590 | 7 | dest[0] = '@'; | 590 | 7 | dest[0] = '@'; | ||
| HITCBC | 591 | 7 | impl_.decoded_[id_pass] = 0; | 591 | 7 | impl_.decoded_[id_pass] = 0; | ||
| HITCBC | 592 | 7 | return *this; | 592 | 7 | return *this; | ||
| HITCBC | 593 | 7 | } | 593 | 7 | } | ||
| 594 | 594 | |||||||
| 595 | //------------------------------------------------ | 595 | //------------------------------------------------ | |||||
| 596 | // | 596 | // | |||||
| 597 | // Host | 597 | // Host | |||||
| 598 | // | 598 | // | |||||
| 599 | //------------------------------------------------ | 599 | //------------------------------------------------ | |||||
| 600 | /* | 600 | /* | |||||
| 601 | host_type host_type() // ipv4, ipv6, ipvfuture, name | 601 | host_type host_type() // ipv4, ipv6, ipvfuture, name | |||||
| 602 | 602 | |||||||
| 603 | std::string host() // return encoded_host().decode() | 603 | std::string host() // return encoded_host().decode() | |||||
| 604 | pct_string_view encoded_host() // return host part, as-is | 604 | pct_string_view encoded_host() // return host part, as-is | |||||
| 605 | std::string host_address() // return encoded_host_address().decode() | 605 | std::string host_address() // return encoded_host_address().decode() | |||||
| 606 | pct_string_view encoded_host_address() // ipv4, ipv6, ipvfut, or encoded name, no brackets | 606 | pct_string_view encoded_host_address() // ipv4, ipv6, ipvfut, or encoded name, no brackets | |||||
| 607 | 607 | |||||||
| 608 | ipv4_address host_ipv4_address() // return ipv4_address or {} | 608 | ipv4_address host_ipv4_address() // return ipv4_address or {} | |||||
| 609 | ipv6_address host_ipv6_address() // return ipv6_address or {} | 609 | ipv6_address host_ipv6_address() // return ipv6_address or {} | |||||
| 610 | core::string_view host_ipvfuture() // return ipvfuture or {} | 610 | core::string_view host_ipvfuture() // return ipvfuture or {} | |||||
| 611 | std::string host_name() // return decoded name or "" | 611 | std::string host_name() // return decoded name or "" | |||||
| 612 | pct_string_view encoded_host_name() // return encoded host name or "" | 612 | pct_string_view encoded_host_name() // return encoded host name or "" | |||||
| 613 | 613 | |||||||
| 614 | -------------------------------------------------- | 614 | -------------------------------------------------- | |||||
| 615 | 615 | |||||||
| 616 | set_host( core::string_view ) // set host part from plain text | 616 | set_host( core::string_view ) // set host part from plain text | |||||
| 617 | set_encoded_host( pct_string_view ) // set host part from encoded text | 617 | set_encoded_host( pct_string_view ) // set host part from encoded text | |||||
| 618 | set_host_address( core::string_view ) // set host from ipv4, ipv6, ipvfut, or plain reg-name string | 618 | set_host_address( core::string_view ) // set host from ipv4, ipv6, ipvfut, or plain reg-name string | |||||
| 619 | set_encoded_host_address( pct_string_view ) // set host from ipv4, ipv6, ipvfut, or encoded reg-name string | 619 | set_encoded_host_address( pct_string_view ) // set host from ipv4, ipv6, ipvfut, or encoded reg-name string | |||||
| 620 | 620 | |||||||
| 621 | set_host_ipv4( ipv4_address ) // set ipv4 | 621 | set_host_ipv4( ipv4_address ) // set ipv4 | |||||
| 622 | set_host_ipv6( ipv6_address ) // set ipv6 | 622 | set_host_ipv6( ipv6_address ) // set ipv6 | |||||
| 623 | set_host_ipvfuture( core::string_view ) // set ipvfuture | 623 | set_host_ipvfuture( core::string_view ) // set ipvfuture | |||||
| 624 | set_host_name( core::string_view ) // set name from plain | 624 | set_host_name( core::string_view ) // set name from plain | |||||
| 625 | set_encoded_host_name( pct_string_view ) // set name from encoded | 625 | set_encoded_host_name( pct_string_view ) // set name from encoded | |||||
| 626 | */ | 626 | */ | |||||
| 627 | 627 | |||||||
| 628 | // set host part from plain text | 628 | // set host part from plain text | |||||
| 629 | inline | 629 | inline | |||||
| 630 | url_base& | 630 | url_base& | |||||
| HITCBC | 631 | 401 | url_base:: | 631 | 401 | url_base:: | ||
| 632 | set_host( | 632 | set_host( | |||||
| 633 | core::string_view s) | 633 | core::string_view s) | |||||
| 634 | { | 634 | { | |||||
| HITCBC | 635 | 401 | if( s.size() > 2 && | 635 | 401 | if( s.size() > 2 && | ||
| HITCBC | 636 | 450 | s.front() == '[' && | 636 | 450 | s.front() == '[' && | ||
| HITCBC | 637 | 49 | s.back() == ']') | 637 | 49 | s.back() == ']') | ||
| 638 | { | 638 | { | |||||
| 639 | // IP-literal | 639 | // IP-literal | |||||
| HITCBC | 640 | 49 | if (s[1] != 'v') | 640 | 49 | if (s[1] != 'v') | ||
| 641 | { | 641 | { | |||||
| 642 | // IPv6-address | 642 | // IPv6-address | |||||
| HITCBC | 643 | 48 | auto innersv = s.substr(1, s.size() - 2); | 643 | 48 | auto innersv = s.substr(1, s.size() - 2); | ||
| HITCBC | 644 | 48 | auto innerit = innersv.begin(); | 644 | 48 | auto innerit = innersv.begin(); | ||
| HITCBC | 645 | 48 | auto endit = innersv.end(); | 645 | 48 | auto endit = innersv.end(); | ||
| HITCBC | 646 | 48 | auto rv = grammar::parse( | 646 | 48 | auto rv = grammar::parse( | ||
| 647 | innerit, | 647 | innerit, | |||||
| 648 | endit, | 648 | endit, | |||||
| 649 | ipv6_address_rule); | 649 | ipv6_address_rule); | |||||
| HITCBC | 650 | 48 | if(rv) | 650 | 48 | if(rv) | ||
| 651 | { | 651 | { | |||||
| HITCBC | 652 | 48 | if (innerit == endit) | 652 | 48 | if (innerit == endit) | ||
| 653 | { | 653 | { | |||||
| HITCBC | 654 | 47 | set_host_ipv6_and_encoded_zone_id(*rv, {}); | 654 | 47 | set_host_ipv6_and_encoded_zone_id(*rv, {}); | ||
| HITCBC | 655 | 48 | return *this; | 655 | 48 | return *this; | ||
| 656 | } | 656 | } | |||||
| 657 | // IPv6addrz: https://datatracker.ietf.org/doc/html/rfc6874 | 657 | // IPv6addrz: https://datatracker.ietf.org/doc/html/rfc6874 | |||||
| HITCBC | 658 | 1 | auto chars_left = endit - innerit; | 658 | 1 | auto chars_left = endit - innerit; | ||
| HITCBC | 659 | 2 | if (chars_left >= 2 && | 659 | 2 | if (chars_left >= 2 && | ||
| HITCBC | 660 | 1 | *innerit++ == '%') | 660 | 1 | *innerit++ == '%') | ||
| 661 | { | 661 | { | |||||
| HITCBC | 662 | 1 | core::string_view zone_id_str = {&*innerit, std::size_t(chars_left - 1)}; | 662 | 1 | core::string_view zone_id_str = {&*innerit, std::size_t(chars_left - 1)}; | ||
| HITCBC | 663 | 1 | set_host_ipv6_and_zone_id(*rv, zone_id_str); | 663 | 1 | set_host_ipv6_and_zone_id(*rv, zone_id_str); | ||
| HITCBC | 664 | 1 | return *this; | 664 | 1 | return *this; | ||
| 665 | } | 665 | } | |||||
| 666 | } | 666 | } | |||||
| 667 | } | 667 | } | |||||
| 668 | else | 668 | else | |||||
| 669 | { | 669 | { | |||||
| 670 | // IPvFuture | 670 | // IPvFuture | |||||
| HITCBC | 671 | 1 | auto rv = grammar::parse( | 671 | 1 | auto rv = grammar::parse( | ||
| HITCBC | 672 | 1 | s.substr(1, s.size() - 2), | 672 | 1 | s.substr(1, s.size() - 2), | ||
| 673 | detail::ipvfuture_rule); | 673 | detail::ipvfuture_rule); | |||||
| HITCBC | 674 | 1 | if(rv) | 674 | 1 | if(rv) | ||
| HITCBC | 675 | 1 | return set_host_ipvfuture(rv->str); | 675 | 1 | return set_host_ipvfuture(rv->str); | ||
| 676 | } | 676 | } | |||||
| 677 | } | 677 | } | |||||
| HITCBC | 678 | 352 | else if(s.size() >= 7) // "0.0.0.0" | 678 | 352 | else if(s.size() >= 7) // "0.0.0.0" | ||
| 679 | { | 679 | { | |||||
| 680 | // IPv4-address | 680 | // IPv4-address | |||||
| HITCBC | 681 | 348 | auto rv = parse_ipv4_address(s); | 681 | 348 | auto rv = parse_ipv4_address(s); | ||
| HITCBC | 682 | 348 | if(rv) | 682 | 348 | if(rv) | ||
| HITCBC | 683 | 189 | return set_host_ipv4(*rv); | 683 | 189 | return set_host_ipv4(*rv); | ||
| 684 | } | 684 | } | |||||
| 685 | 685 | |||||||
| 686 | // reg-name | 686 | // reg-name | |||||
| HITCBC | 687 | 163 | op_t op(*this, &s); | 687 | 163 | op_t op(*this, &s); | ||
| HITCBC | 688 | 163 | encoding_opts opt; | 688 | 163 | encoding_opts opt; | ||
| HITCBC | 689 | 163 | auto const n = encoded_size( | 689 | 163 | auto const n = encoded_size( | ||
| 690 | s, detail::host_chars, opt); | 690 | s, detail::host_chars, opt); | |||||
| HITCBC | 691 | 163 | auto dest = set_host_impl(n, op); | 691 | 163 | auto dest = set_host_impl(n, op); | ||
| HITCBC | 692 | 163 | encode( | 692 | 163 | encode( | ||
| 693 | dest, | 693 | dest, | |||||
| HITCBC | 694 | 163 | impl_.get(id_path).data() - dest, | 694 | 163 | impl_.get(id_path).data() - dest, | ||
| 695 | s, | 695 | s, | |||||
| 696 | detail::host_chars, | 696 | detail::host_chars, | |||||
| 697 | opt); | 697 | opt); | |||||
| HITCBC | 698 | 163 | impl_.decoded_[id_host] = | 698 | 163 | impl_.decoded_[id_host] = | ||
| HITCBC | 699 | 163 | detail::to_size_type(s.size()); | 699 | 163 | detail::to_size_type(s.size()); | ||
| HITCBC | 700 | 163 | impl_.host_type_ = | 700 | 163 | impl_.host_type_ = | ||
| 701 | urls::host_type::name; | 701 | urls::host_type::name; | |||||
| HITCBC | 702 | 163 | return *this; | 702 | 163 | return *this; | ||
| HITCBC | 703 | 163 | } | 703 | 163 | } | ||
| 704 | 704 | |||||||
| 705 | // set host part from encoded text | 705 | // set host part from encoded text | |||||
| 706 | inline | 706 | inline | |||||
| 707 | url_base& | 707 | url_base& | |||||
| HITCBC | 708 | 218 | url_base:: | 708 | 218 | url_base:: | ||
| 709 | set_encoded_host( | 709 | set_encoded_host( | |||||
| 710 | pct_string_view s) | 710 | pct_string_view s) | |||||
| 711 | { | 711 | { | |||||
| HITCBC | 712 | 218 | if( s.size() > 2 && | 712 | 218 | if( s.size() > 2 && | ||
| HITCBC | 713 | 235 | s.front() == '[' && | 713 | 235 | s.front() == '[' && | ||
| HITCBC | 714 | 17 | s.back() == ']') | 714 | 17 | s.back() == ']') | ||
| 715 | { | 715 | { | |||||
| 716 | // IP-literal | 716 | // IP-literal | |||||
| HITCBC | 717 | 17 | if (s[1] != 'v') | 717 | 17 | if (s[1] != 'v') | ||
| 718 | { | 718 | { | |||||
| 719 | // IPv6-address | 719 | // IPv6-address | |||||
| HITCBC | 720 | 16 | auto innersv = s.substr(1, s.size() - 2); | 720 | 16 | auto innersv = s.substr(1, s.size() - 2); | ||
| HITCBC | 721 | 16 | auto innerit = innersv.begin(); | 721 | 16 | auto innerit = innersv.begin(); | ||
| HITCBC | 722 | 16 | auto endit = innersv.end(); | 722 | 16 | auto endit = innersv.end(); | ||
| HITCBC | 723 | 16 | auto rv = grammar::parse( | 723 | 16 | auto rv = grammar::parse( | ||
| 724 | innerit, | 724 | innerit, | |||||
| 725 | endit, | 725 | endit, | |||||
| 726 | ipv6_address_rule); | 726 | ipv6_address_rule); | |||||
| HITCBC | 727 | 16 | if(rv) | 727 | 16 | if(rv) | ||
| 728 | { | 728 | { | |||||
| HITCBC | 729 | 8 | if (innerit == endit) | 729 | 8 | if (innerit == endit) | ||
| 730 | { | 730 | { | |||||
| HITCBC | 731 | 5 | set_host_ipv6_and_encoded_zone_id(*rv, {}); | 731 | 5 | set_host_ipv6_and_encoded_zone_id(*rv, {}); | ||
| HITCBC | 732 | 6 | return *this; | 732 | 6 | return *this; | ||
| 733 | } | 733 | } | |||||
| 734 | // IPv6addrz: https://datatracker.ietf.org/doc/html/rfc6874 | 734 | // IPv6addrz: https://datatracker.ietf.org/doc/html/rfc6874 | |||||
| HITCBC | 735 | 3 | auto chars_left = endit - innerit; | 735 | 3 | auto chars_left = endit - innerit; | ||
| HITCBC | 736 | 4 | if (chars_left >= 3 && | 736 | 4 | if (chars_left >= 3 && | ||
| HITCBC | 737 | 1 | *innerit++ == '%' && | 737 | 1 | *innerit++ == '%' && | ||
| HITCBC | 738 | 5 | *innerit++ == '2' && | 738 | 5 | *innerit++ == '2' && | ||
| HITCBC | 739 | 1 | *innerit++ == '5') | 739 | 1 | *innerit++ == '5') | ||
| 740 | { | 740 | { | |||||
| HITCBC | 741 | 1 | auto const nz = std::size_t(chars_left - 3); | 741 | 1 | auto const nz = std::size_t(chars_left - 3); | ||
| HITCBC | 742 | 1 | core::string_view zone_id_str = {&*innerit, std::size_t(chars_left - 3)}; | 742 | 1 | core::string_view zone_id_str = {&*innerit, std::size_t(chars_left - 3)}; | ||
| HITCBC | 743 | 1 | std::size_t dnz = detail::decode_bytes_unsafe(zone_id_str); | 743 | 1 | std::size_t dnz = detail::decode_bytes_unsafe(zone_id_str); | ||
| HITCBC | 744 | 1 | pct_string_view zone_id_pct = make_pct_string_view_unsafe(innerit, nz, dnz); | 744 | 1 | pct_string_view zone_id_pct = make_pct_string_view_unsafe(innerit, nz, dnz); | ||
| HITCBC | 745 | 1 | set_host_ipv6_and_encoded_zone_id(*rv, zone_id_pct); | 745 | 1 | set_host_ipv6_and_encoded_zone_id(*rv, zone_id_pct); | ||
| HITCBC | 746 | 1 | return *this; | 746 | 1 | return *this; | ||
| 747 | } | 747 | } | |||||
| 748 | } | 748 | } | |||||
| 749 | } | 749 | } | |||||
| 750 | else | 750 | else | |||||
| 751 | { | 751 | { | |||||
| 752 | // IPvFuture | 752 | // IPvFuture | |||||
| HITCBC | 753 | 1 | auto rv = grammar::parse( | 753 | 1 | auto rv = grammar::parse( | ||
| HITCBC | 754 | 1 | s.substr(1, s.size() - 2), | 754 | 1 | s.substr(1, s.size() - 2), | ||
| 755 | detail::ipvfuture_rule); | 755 | detail::ipvfuture_rule); | |||||
| HITCBC | 756 | 1 | if(rv) | 756 | 1 | if(rv) | ||
| HITCBC | 757 | 1 | return set_host_ipvfuture(rv->str); | 757 | 1 | return set_host_ipvfuture(rv->str); | ||
| 758 | } | 758 | } | |||||
| 759 | } | 759 | } | |||||
| HITCBC | 760 | 201 | else if(s.size() >= 7) // "0.0.0.0" | 760 | 201 | else if(s.size() >= 7) // "0.0.0.0" | ||
| 761 | { | 761 | { | |||||
| 762 | // IPv4-address | 762 | // IPv4-address | |||||
| HITCBC | 763 | 74 | auto rv = parse_ipv4_address(s); | 763 | 74 | auto rv = parse_ipv4_address(s); | ||
| HITCBC | 764 | 74 | if(rv) | 764 | 74 | if(rv) | ||
| HITCBC | 765 | 5 | return set_host_ipv4(*rv); | 765 | 5 | return set_host_ipv4(*rv); | ||
| 766 | } | 766 | } | |||||
| 767 | 767 | |||||||
| 768 | // reg-name | 768 | // reg-name | |||||
| HITCBC | 769 | 206 | op_t op(*this, &detail::ref(s)); | 769 | 206 | op_t op(*this, &detail::ref(s)); | ||
| HITCBC | 770 | 206 | auto const n = detail::re_encoded_size_unsafe( | 770 | 206 | auto const n = detail::re_encoded_size_unsafe( | ||
| 771 | s, detail::host_chars); | 771 | s, detail::host_chars); | |||||
| HITCBC | 772 | 206 | auto dest = set_host_impl(n, op); | 772 | 206 | auto dest = set_host_impl(n, op); | ||
| HITCBC | 773 | 206 | impl_.decoded_[id_host] = | 773 | 206 | impl_.decoded_[id_host] = | ||
| HITCBC | 774 | 412 | detail::to_size_type(detail::re_encode_unsafe( | 774 | 412 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 775 | dest, | 775 | dest, | |||||
| HITCBC | 776 | 206 | impl_.get(id_path).data(), | 776 | 206 | impl_.get(id_path).data(), | ||
| 777 | s, | 777 | s, | |||||
| 778 | detail::host_chars)); | 778 | detail::host_chars)); | |||||
| HITCBC | 779 | 206 | BOOST_ASSERT(impl_.decoded_[id_host] == | 779 | 206 | BOOST_ASSERT(impl_.decoded_[id_host] == | ||
| 780 | s.decoded_size()); | 780 | s.decoded_size()); | |||||
| HITCBC | 781 | 206 | impl_.host_type_ = | 781 | 206 | impl_.host_type_ = | ||
| 782 | urls::host_type::name; | 782 | urls::host_type::name; | |||||
| HITCBC | 783 | 206 | return *this; | 783 | 206 | return *this; | ||
| HITCBC | 784 | 206 | } | 784 | 206 | } | ||
| 785 | 785 | |||||||
| 786 | inline | 786 | inline | |||||
| 787 | url_base& | 787 | url_base& | |||||
| HITCBC | 788 | 10 | url_base:: | 788 | 10 | url_base:: | ||
| 789 | set_host_address( | 789 | set_host_address( | |||||
| 790 | core::string_view s) | 790 | core::string_view s) | |||||
| 791 | { | 791 | { | |||||
| HITCBC | 792 | 10 | if (!s.empty()) | 792 | 10 | if (!s.empty()) | ||
| 793 | { | 793 | { | |||||
| 794 | // IP-literal | 794 | // IP-literal | |||||
| HITCBC | 795 | 9 | if (s[0] != 'v') | 795 | 9 | if (s[0] != 'v') | ||
| 796 | { | 796 | { | |||||
| 797 | // IPv6-address | 797 | // IPv6-address | |||||
| HITCBC | 798 | 8 | auto innerit = s.begin(); | 798 | 8 | auto innerit = s.begin(); | ||
| HITCBC | 799 | 8 | auto endit = s.end(); | 799 | 8 | auto endit = s.end(); | ||
| HITCBC | 800 | 8 | auto rv = grammar::parse( | 800 | 8 | auto rv = grammar::parse( | ||
| 801 | innerit, | 801 | innerit, | |||||
| 802 | endit, | 802 | endit, | |||||
| 803 | ipv6_address_rule); | 803 | ipv6_address_rule); | |||||
| HITCBC | 804 | 8 | if(rv) | 804 | 8 | if(rv) | ||
| 805 | { | 805 | { | |||||
| HITCBC | 806 | 2 | if (innerit == endit) | 806 | 2 | if (innerit == endit) | ||
| 807 | { | 807 | { | |||||
| HITCBC | 808 | 1 | set_host_ipv6_and_encoded_zone_id(*rv, {}); | 808 | 1 | set_host_ipv6_and_encoded_zone_id(*rv, {}); | ||
| HITCBC | 809 | 2 | return *this; | 809 | 2 | return *this; | ||
| 810 | } | 810 | } | |||||
| 811 | // IPv6addrz: https://datatracker.ietf.org/doc/html/rfc6874 | 811 | // IPv6addrz: https://datatracker.ietf.org/doc/html/rfc6874 | |||||
| HITCBC | 812 | 1 | auto chars_left = endit - innerit; | 812 | 1 | auto chars_left = endit - innerit; | ||
| HITCBC | 813 | 2 | if (chars_left >= 2 && | 813 | 2 | if (chars_left >= 2 && | ||
| HITCBC | 814 | 1 | *innerit++ == '%') | 814 | 1 | *innerit++ == '%') | ||
| 815 | { | 815 | { | |||||
| HITCBC | 816 | 1 | core::string_view zone_id_str = {&*innerit, std::size_t(chars_left - 1)}; | 816 | 1 | core::string_view zone_id_str = {&*innerit, std::size_t(chars_left - 1)}; | ||
| HITCBC | 817 | 1 | set_host_ipv6_and_zone_id(*rv, zone_id_str); | 817 | 1 | set_host_ipv6_and_zone_id(*rv, zone_id_str); | ||
| HITCBC | 818 | 1 | return *this; | 818 | 1 | return *this; | ||
| 819 | } | 819 | } | |||||
| 820 | } | 820 | } | |||||
| 821 | } | 821 | } | |||||
| 822 | 822 | |||||||
| 823 | // IPvFuture | 823 | // IPvFuture | |||||
| HITCBC | 824 | 7 | auto rv = grammar::parse(s, detail::ipvfuture_rule); | 824 | 7 | auto rv = grammar::parse(s, detail::ipvfuture_rule); | ||
| HITCBC | 825 | 7 | if(rv) | 825 | 7 | if(rv) | ||
| HITCBC | 826 | 1 | return set_host_ipvfuture(rv->str); | 826 | 1 | return set_host_ipvfuture(rv->str); | ||
| 827 | 827 | |||||||
| HITCBC | 828 | 6 | if(s.size() >= 7) // "0.0.0.0" | 828 | 6 | if(s.size() >= 7) // "0.0.0.0" | ||
| 829 | { | 829 | { | |||||
| 830 | // IPv4-address | 830 | // IPv4-address | |||||
| HITCBC | 831 | 5 | auto rv2 = parse_ipv4_address(s); | 831 | 5 | auto rv2 = parse_ipv4_address(s); | ||
| HITCBC | 832 | 5 | if(rv2) | 832 | 5 | if(rv2) | ||
| HITCBC | 833 | 2 | return set_host_ipv4(*rv2); | 833 | 2 | return set_host_ipv4(*rv2); | ||
| 834 | } | 834 | } | |||||
| 835 | } | 835 | } | |||||
| 836 | 836 | |||||||
| 837 | // reg-name | 837 | // reg-name | |||||
| HITCBC | 838 | 5 | op_t op(*this, &s); | 838 | 5 | op_t op(*this, &s); | ||
| HITCBC | 839 | 5 | encoding_opts opt; | 839 | 5 | encoding_opts opt; | ||
| HITCBC | 840 | 5 | auto const n = encoded_size( | 840 | 5 | auto const n = encoded_size( | ||
| 841 | s, detail::host_chars, opt); | 841 | s, detail::host_chars, opt); | |||||
| HITCBC | 842 | 5 | auto dest = set_host_impl(n, op); | 842 | 5 | auto dest = set_host_impl(n, op); | ||
| HITCBC | 843 | 5 | encode( | 843 | 5 | encode( | ||
| 844 | dest, | 844 | dest, | |||||
| HITCBC | 845 | 5 | impl_.get(id_path).data() - dest, | 845 | 5 | impl_.get(id_path).data() - dest, | ||
| 846 | s, | 846 | s, | |||||
| 847 | detail::host_chars, | 847 | detail::host_chars, | |||||
| 848 | opt); | 848 | opt); | |||||
| HITCBC | 849 | 5 | impl_.decoded_[id_host] = | 849 | 5 | impl_.decoded_[id_host] = | ||
| HITCBC | 850 | 5 | detail::to_size_type(s.size()); | 850 | 5 | detail::to_size_type(s.size()); | ||
| HITCBC | 851 | 5 | impl_.host_type_ = | 851 | 5 | impl_.host_type_ = | ||
| 852 | urls::host_type::name; | 852 | urls::host_type::name; | |||||
| HITCBC | 853 | 5 | return *this; | 853 | 5 | return *this; | ||
| HITCBC | 854 | 5 | } | 854 | 5 | } | ||
| 855 | 855 | |||||||
| 856 | inline | 856 | inline | |||||
| 857 | url_base& | 857 | url_base& | |||||
| HITCBC | 858 | 8 | url_base:: | 858 | 8 | url_base:: | ||
| 859 | set_encoded_host_address( | 859 | set_encoded_host_address( | |||||
| 860 | pct_string_view s) | 860 | pct_string_view s) | |||||
| 861 | { | 861 | { | |||||
| HITCBC | 862 | 8 | if( !s.empty() ) | 862 | 8 | if( !s.empty() ) | ||
| 863 | { | 863 | { | |||||
| 864 | // IP-literal | 864 | // IP-literal | |||||
| HITCBC | 865 | 7 | if (s[0] != 'v') | 865 | 7 | if (s[0] != 'v') | ||
| 866 | { | 866 | { | |||||
| 867 | // IPv6-address | 867 | // IPv6-address | |||||
| HITCBC | 868 | 6 | auto innerit = s.begin(); | 868 | 6 | auto innerit = s.begin(); | ||
| HITCBC | 869 | 6 | auto endit = s.end(); | 869 | 6 | auto endit = s.end(); | ||
| HITCBC | 870 | 6 | auto rv = grammar::parse( | 870 | 6 | auto rv = grammar::parse( | ||
| 871 | innerit, | 871 | innerit, | |||||
| 872 | endit, | 872 | endit, | |||||
| 873 | ipv6_address_rule); | 873 | ipv6_address_rule); | |||||
| HITCBC | 874 | 6 | if(rv) | 874 | 6 | if(rv) | ||
| 875 | { | 875 | { | |||||
| HITCBC | 876 | 2 | if (innerit == endit) | 876 | 2 | if (innerit == endit) | ||
| 877 | { | 877 | { | |||||
| HITCBC | 878 | 1 | set_host_ipv6_and_encoded_zone_id(*rv, {}); | 878 | 1 | set_host_ipv6_and_encoded_zone_id(*rv, {}); | ||
| HITCBC | 879 | 3 | return *this; | 879 | 3 | return *this; | ||
| 880 | } | 880 | } | |||||
| 881 | // IPv6addrz: https://datatracker.ietf.org/doc/html/rfc6874 | 881 | // IPv6addrz: https://datatracker.ietf.org/doc/html/rfc6874 | |||||
| HITCBC | 882 | 1 | auto chars_left = endit - innerit; | 882 | 1 | auto chars_left = endit - innerit; | ||
| HITCBC | 883 | 2 | if (chars_left >= 3 && | 883 | 2 | if (chars_left >= 3 && | ||
| HITCBC | 884 | 1 | *innerit++ == '%' && | 884 | 1 | *innerit++ == '%' && | ||
| HITCBC | 885 | 3 | *innerit++ == '2' && | 885 | 3 | *innerit++ == '2' && | ||
| HITCBC | 886 | 1 | *innerit++ == '5') | 886 | 1 | *innerit++ == '5') | ||
| 887 | { | 887 | { | |||||
| HITCBC | 888 | 1 | auto const nz = std::size_t(chars_left - 3); | 888 | 1 | auto const nz = std::size_t(chars_left - 3); | ||
| HITCBC | 889 | 1 | core::string_view zone_id_str = {&*innerit, std::size_t(chars_left - 3)}; | 889 | 1 | core::string_view zone_id_str = {&*innerit, std::size_t(chars_left - 3)}; | ||
| HITCBC | 890 | 1 | std::size_t dnz = detail::decode_bytes_unsafe(zone_id_str); | 890 | 1 | std::size_t dnz = detail::decode_bytes_unsafe(zone_id_str); | ||
| HITCBC | 891 | 1 | pct_string_view zone_id_pct = make_pct_string_view_unsafe(innerit, nz, dnz); | 891 | 1 | pct_string_view zone_id_pct = make_pct_string_view_unsafe(innerit, nz, dnz); | ||
| HITCBC | 892 | 1 | set_host_ipv6_and_encoded_zone_id(*rv, zone_id_pct); | 892 | 1 | set_host_ipv6_and_encoded_zone_id(*rv, zone_id_pct); | ||
| HITCBC | 893 | 1 | return *this; | 893 | 1 | return *this; | ||
| 894 | } | 894 | } | |||||
| 895 | } | 895 | } | |||||
| 896 | 896 | |||||||
| HITCBC | 897 | 4 | if(s.size() >= 7) // "0.0.0.0" | 897 | 4 | if(s.size() >= 7) // "0.0.0.0" | ||
| 898 | { | 898 | { | |||||
| 899 | // IPv4-address | 899 | // IPv4-address | |||||
| HITCBC | 900 | 3 | auto rv2 = parse_ipv4_address(s); | 900 | 3 | auto rv2 = parse_ipv4_address(s); | ||
| HITCBC | 901 | 3 | if(rv2) | 901 | 3 | if(rv2) | ||
| HITCBC | 902 | 1 | return set_host_ipv4(*rv2); | 902 | 1 | return set_host_ipv4(*rv2); | ||
| 903 | } | 903 | } | |||||
| 904 | } | 904 | } | |||||
| 905 | else | 905 | else | |||||
| 906 | { | 906 | { | |||||
| 907 | // IPvFuture | 907 | // IPvFuture | |||||
| HITCBC | 908 | 1 | auto rv = grammar::parse( | 908 | 1 | auto rv = grammar::parse( | ||
| 909 | s, detail::ipvfuture_rule); | 909 | s, detail::ipvfuture_rule); | |||||
| HITCBC | 910 | 1 | if(rv) | 910 | 1 | if(rv) | ||
| HITCBC | 911 | 1 | return set_host_ipvfuture(rv->str); | 911 | 1 | return set_host_ipvfuture(rv->str); | ||
| 912 | } | 912 | } | |||||
| 913 | } | 913 | } | |||||
| 914 | 914 | |||||||
| 915 | // reg-name | 915 | // reg-name | |||||
| HITCBC | 916 | 4 | op_t op(*this, &detail::ref(s)); | 916 | 4 | op_t op(*this, &detail::ref(s)); | ||
| HITCBC | 917 | 4 | auto const n = detail::re_encoded_size_unsafe( | 917 | 4 | auto const n = detail::re_encoded_size_unsafe( | ||
| 918 | s, detail::host_chars); | 918 | s, detail::host_chars); | |||||
| HITCBC | 919 | 4 | auto dest = set_host_impl(n, op); | 919 | 4 | auto dest = set_host_impl(n, op); | ||
| HITCBC | 920 | 4 | impl_.decoded_[id_host] = | 920 | 4 | impl_.decoded_[id_host] = | ||
| HITCBC | 921 | 8 | detail::to_size_type(detail::re_encode_unsafe( | 921 | 8 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 922 | dest, | 922 | dest, | |||||
| HITCBC | 923 | 4 | impl_.get(id_path).data(), | 923 | 4 | impl_.get(id_path).data(), | ||
| 924 | s, | 924 | s, | |||||
| 925 | detail::host_chars)); | 925 | detail::host_chars)); | |||||
| HITCBC | 926 | 4 | BOOST_ASSERT(impl_.decoded_[id_host] == | 926 | 4 | BOOST_ASSERT(impl_.decoded_[id_host] == | ||
| 927 | s.decoded_size()); | 927 | s.decoded_size()); | |||||
| HITCBC | 928 | 4 | impl_.host_type_ = | 928 | 4 | impl_.host_type_ = | ||
| 929 | urls::host_type::name; | 929 | urls::host_type::name; | |||||
| HITCBC | 930 | 4 | return *this; | 930 | 4 | return *this; | ||
| HITCBC | 931 | 4 | } | 931 | 4 | } | ||
| 932 | 932 | |||||||
| 933 | inline | 933 | inline | |||||
| 934 | url_base& | 934 | url_base& | |||||
| HITCBC | 935 | 203 | url_base:: | 935 | 203 | url_base:: | ||
| 936 | set_host_ipv4( | 936 | set_host_ipv4( | |||||
| 937 | ipv4_address const& addr) | 937 | ipv4_address const& addr) | |||||
| 938 | { | 938 | { | |||||
| HITCBC | 939 | 203 | op_t op(*this); | 939 | 203 | op_t op(*this); | ||
| 940 | char buf[urls::ipv4_address::max_str_len]; | 940 | char buf[urls::ipv4_address::max_str_len]; | |||||
| HITCBC | 941 | 203 | auto s = addr.to_buffer(buf, sizeof(buf)); | 941 | 203 | auto s = addr.to_buffer(buf, sizeof(buf)); | ||
| HITCBC | 942 | 203 | auto dest = set_host_impl(s.size(), op); | 942 | 203 | auto dest = set_host_impl(s.size(), op); | ||
| HITCBC | 943 | 203 | std::memcpy(dest, s.data(), s.size()); | 943 | 203 | std::memcpy(dest, s.data(), s.size()); | ||
| HITCBC | 944 | 203 | impl_.decoded_[id_host] = | 944 | 203 | impl_.decoded_[id_host] = | ||
| HITCBC | 945 | 203 | detail::to_size_type(impl_.len(id_host)); | 945 | 203 | detail::to_size_type(impl_.len(id_host)); | ||
| HITCBC | 946 | 203 | impl_.host_type_ = urls::host_type::ipv4; | 946 | 203 | impl_.host_type_ = urls::host_type::ipv4; | ||
| HITCBC | 947 | 203 | auto bytes = addr.to_bytes(); | 947 | 203 | auto bytes = addr.to_bytes(); | ||
| HITCBC | 948 | 203 | std::memcpy( | 948 | 203 | std::memcpy( | ||
| HITCBC | 949 | 203 | impl_.ip_addr_, | 949 | 203 | impl_.ip_addr_, | ||
| HITCBC | 950 | 203 | bytes.data(), | 950 | 203 | bytes.data(), | ||
| 951 | bytes.size()); | 951 | bytes.size()); | |||||
| HITCBC | 952 | 203 | return *this; | 952 | 203 | return *this; | ||
| HITCBC | 953 | 203 | } | 953 | 203 | } | ||
| 954 | 954 | |||||||
| 955 | inline | 955 | inline | |||||
| 956 | url_base& | 956 | url_base& | |||||
| HITCBC | 957 | 5 | url_base:: | 957 | 5 | url_base:: | ||
| 958 | set_host_ipv6( | 958 | set_host_ipv6( | |||||
| 959 | ipv6_address const& addr) | 959 | ipv6_address const& addr) | |||||
| 960 | { | 960 | { | |||||
| HITCBC | 961 | 5 | set_host_ipv6_and_encoded_zone_id(addr, encoded_zone_id()); | 961 | 5 | set_host_ipv6_and_encoded_zone_id(addr, encoded_zone_id()); | ||
| HITCBC | 962 | 5 | return *this; | 962 | 5 | return *this; | ||
| 963 | } | 963 | } | |||||
| 964 | 964 | |||||||
| 965 | inline | 965 | inline | |||||
| 966 | url_base& | 966 | url_base& | |||||
| HITCBC | 967 | 3 | url_base:: | 967 | 3 | url_base:: | ||
| 968 | set_zone_id(core::string_view s) | 968 | set_zone_id(core::string_view s) | |||||
| 969 | { | 969 | { | |||||
| HITCBC | 970 | 3 | set_host_ipv6_and_zone_id(host_ipv6_address(), s); | 970 | 3 | set_host_ipv6_and_zone_id(host_ipv6_address(), s); | ||
| HITCBC | 971 | 3 | return *this; | 971 | 3 | return *this; | ||
| 972 | } | 972 | } | |||||
| 973 | 973 | |||||||
| 974 | inline | 974 | inline | |||||
| 975 | url_base& | 975 | url_base& | |||||
| HITCBC | 976 | 3 | url_base:: | 976 | 3 | url_base:: | ||
| 977 | set_encoded_zone_id(pct_string_view s) | 977 | set_encoded_zone_id(pct_string_view s) | |||||
| 978 | { | 978 | { | |||||
| HITCBC | 979 | 3 | set_host_ipv6_and_encoded_zone_id(host_ipv6_address(), s); | 979 | 3 | set_host_ipv6_and_encoded_zone_id(host_ipv6_address(), s); | ||
| HITCBC | 980 | 3 | return *this; | 980 | 3 | return *this; | ||
| 981 | } | 981 | } | |||||
| 982 | 982 | |||||||
| 983 | inline | 983 | inline | |||||
| 984 | void | 984 | void | |||||
| HITCBC | 985 | 5 | url_base:: | 985 | 5 | url_base:: | ||
| 986 | set_host_ipv6_and_zone_id( | 986 | set_host_ipv6_and_zone_id( | |||||
| 987 | ipv6_address const& addr, | 987 | ipv6_address const& addr, | |||||
| 988 | core::string_view zone_id) | 988 | core::string_view zone_id) | |||||
| 989 | { | 989 | { | |||||
| HITCBC | 990 | 5 | op_t op(*this, &zone_id); | 990 | 5 | op_t op(*this, &zone_id); | ||
| 991 | char ipv6_str_buf[urls::ipv6_address::max_str_len]; | 991 | char ipv6_str_buf[urls::ipv6_address::max_str_len]; | |||||
| HITCBC | 992 | 5 | auto ipv6_str = addr.to_buffer(ipv6_str_buf, sizeof(ipv6_str_buf)); | 992 | 5 | auto ipv6_str = addr.to_buffer(ipv6_str_buf, sizeof(ipv6_str_buf)); | ||
| HITCBC | 993 | 5 | bool const has_zone_id = !zone_id.empty(); | 993 | 5 | bool const has_zone_id = !zone_id.empty(); | ||
| HITCBC | 994 | 5 | encoding_opts opt; | 994 | 5 | encoding_opts opt; | ||
| HITCBC | 995 | 5 | auto const ipn = ipv6_str.size(); | 995 | 5 | auto const ipn = ipv6_str.size(); | ||
| HITCBC | 996 | 5 | auto const zn = encoded_size(zone_id, unreserved_chars, opt); | 996 | 5 | auto const zn = encoded_size(zone_id, unreserved_chars, opt); | ||
| HITCBC | 997 | 5 | auto const n = ipn + 2 + has_zone_id * (3 + zn); | 997 | 5 | auto const n = ipn + 2 + has_zone_id * (3 + zn); | ||
| HITCBC | 998 | 5 | auto dest = set_host_impl(n, op); | 998 | 5 | auto dest = set_host_impl(n, op); | ||
| HITCBC | 999 | 5 | *dest++ = '['; | 999 | 5 | *dest++ = '['; | ||
| HITCBC | 1000 | 5 | std::memcpy(dest, ipv6_str.data(), ipn); | 1000 | 5 | std::memcpy(dest, ipv6_str.data(), ipn); | ||
| HITCBC | 1001 | 5 | dest += ipn; | 1001 | 5 | dest += ipn; | ||
| HITCBC | 1002 | 5 | if (has_zone_id) | 1002 | 5 | if (has_zone_id) | ||
| 1003 | { | 1003 | { | |||||
| HITCBC | 1004 | 5 | *dest++ = '%'; | 1004 | 5 | *dest++ = '%'; | ||
| HITCBC | 1005 | 5 | *dest++ = '2'; | 1005 | 5 | *dest++ = '2'; | ||
| HITCBC | 1006 | 5 | *dest++ = '5'; | 1006 | 5 | *dest++ = '5'; | ||
| HITCBC | 1007 | 5 | encode(dest, zn, zone_id, unreserved_chars, opt); | 1007 | 5 | encode(dest, zn, zone_id, unreserved_chars, opt); | ||
| HITCBC | 1008 | 5 | dest += zn; | 1008 | 5 | dest += zn; | ||
| 1009 | } | 1009 | } | |||||
| HITCBC | 1010 | 5 | *dest++ = ']'; | 1010 | 5 | *dest++ = ']'; | ||
| 1011 | // ipn + |"["| + |"]"| + (has_zone_id ? |"%"| + zn : 0) | 1011 | // ipn + |"["| + |"]"| + (has_zone_id ? |"%"| + zn : 0) | |||||
| HITCBC | 1012 | 10 | impl_.decoded_[id_host] = detail::to_size_type( | 1012 | 10 | impl_.decoded_[id_host] = detail::to_size_type( | ||
| HITCBC | 1013 | 5 | ipn + 2 + has_zone_id * (1 + zone_id.size())); | 1013 | 5 | ipn + 2 + has_zone_id * (1 + zone_id.size())); | ||
| HITCBC | 1014 | 5 | impl_.host_type_ = urls::host_type::ipv6; | 1014 | 5 | impl_.host_type_ = urls::host_type::ipv6; | ||
| HITCBC | 1015 | 5 | auto bytes = addr.to_bytes(); | 1015 | 5 | auto bytes = addr.to_bytes(); | ||
| HITCBC | 1016 | 5 | std::memcpy( | 1016 | 5 | std::memcpy( | ||
| HITCBC | 1017 | 5 | impl_.ip_addr_, | 1017 | 5 | impl_.ip_addr_, | ||
| HITCBC | 1018 | 5 | bytes.data(), | 1018 | 5 | bytes.data(), | ||
| 1019 | bytes.size()); | 1019 | bytes.size()); | |||||
| HITCBC | 1020 | 5 | } | 1020 | 5 | } | ||
| 1021 | 1021 | |||||||
| 1022 | inline | 1022 | inline | |||||
| 1023 | void | 1023 | void | |||||
| HITCBC | 1024 | 64 | url_base:: | 1024 | 64 | url_base:: | ||
| 1025 | set_host_ipv6_and_encoded_zone_id( | 1025 | set_host_ipv6_and_encoded_zone_id( | |||||
| 1026 | ipv6_address const& addr, | 1026 | ipv6_address const& addr, | |||||
| 1027 | pct_string_view zone_id) | 1027 | pct_string_view zone_id) | |||||
| 1028 | { | 1028 | { | |||||
| HITCBC | 1029 | 64 | op_t op(*this, &detail::ref(zone_id)); | 1029 | 64 | op_t op(*this, &detail::ref(zone_id)); | ||
| 1030 | char ipv6_str_buf[urls::ipv6_address::max_str_len]; | 1030 | char ipv6_str_buf[urls::ipv6_address::max_str_len]; | |||||
| HITCBC | 1031 | 64 | auto ipv6_str = addr.to_buffer(ipv6_str_buf, sizeof(ipv6_str_buf)); | 1031 | 64 | auto ipv6_str = addr.to_buffer(ipv6_str_buf, sizeof(ipv6_str_buf)); | ||
| HITCBC | 1032 | 64 | bool const has_zone_id = !zone_id.empty(); | 1032 | 64 | bool const has_zone_id = !zone_id.empty(); | ||
| HITCBC | 1033 | 64 | auto const ipn = ipv6_str.size(); | 1033 | 64 | auto const ipn = ipv6_str.size(); | ||
| HITCBC | 1034 | 64 | auto const zn = detail::re_encoded_size_unsafe(zone_id, unreserved_chars); | 1034 | 64 | auto const zn = detail::re_encoded_size_unsafe(zone_id, unreserved_chars); | ||
| HITCBC | 1035 | 64 | auto const n = ipn + 2 + has_zone_id * (3 + zn); | 1035 | 64 | auto const n = ipn + 2 + has_zone_id * (3 + zn); | ||
| HITCBC | 1036 | 64 | auto dest = set_host_impl(n, op); | 1036 | 64 | auto dest = set_host_impl(n, op); | ||
| HITCBC | 1037 | 64 | *dest++ = '['; | 1037 | 64 | *dest++ = '['; | ||
| HITCBC | 1038 | 64 | std::memcpy(dest, ipv6_str.data(), ipn); | 1038 | 64 | std::memcpy(dest, ipv6_str.data(), ipn); | ||
| HITCBC | 1039 | 64 | dest += ipn; | 1039 | 64 | dest += ipn; | ||
| HITCBC | 1040 | 64 | std::size_t dzn = 0; | 1040 | 64 | std::size_t dzn = 0; | ||
| HITCBC | 1041 | 64 | if (has_zone_id) | 1041 | 64 | if (has_zone_id) | ||
| 1042 | { | 1042 | { | |||||
| HITCBC | 1043 | 6 | *dest++ = '%'; | 1043 | 6 | *dest++ = '%'; | ||
| HITCBC | 1044 | 6 | *dest++ = '2'; | 1044 | 6 | *dest++ = '2'; | ||
| HITCBC | 1045 | 6 | *dest++ = '5'; | 1045 | 6 | *dest++ = '5'; | ||
| HITCBC | 1046 | 6 | dzn = detail::re_encode_unsafe(dest, dest + zn, zone_id, unreserved_chars); | 1046 | 6 | dzn = detail::re_encode_unsafe(dest, dest + zn, zone_id, unreserved_chars); | ||
| 1047 | } | 1047 | } | |||||
| HITCBC | 1048 | 64 | *dest++ = ']'; | 1048 | 64 | *dest++ = ']'; | ||
| 1049 | // ipn + |"["| + |"]"| + (has_zone_id ? |"%"| + zn : 0) | 1049 | // ipn + |"["| + |"]"| + (has_zone_id ? |"%"| + zn : 0) | |||||
| HITCBC | 1050 | 128 | impl_.decoded_[id_host] = detail::to_size_type( | 1050 | 128 | impl_.decoded_[id_host] = detail::to_size_type( | ||
| HITCBC | 1051 | 64 | ipn + 2 + has_zone_id * (1 + dzn)); | 1051 | 64 | ipn + 2 + has_zone_id * (1 + dzn)); | ||
| HITCBC | 1052 | 64 | impl_.host_type_ = urls::host_type::ipv6; | 1052 | 64 | impl_.host_type_ = urls::host_type::ipv6; | ||
| HITCBC | 1053 | 64 | auto bytes = addr.to_bytes(); | 1053 | 64 | auto bytes = addr.to_bytes(); | ||
| HITCBC | 1054 | 64 | std::memcpy( | 1054 | 64 | std::memcpy( | ||
| HITCBC | 1055 | 64 | impl_.ip_addr_, | 1055 | 64 | impl_.ip_addr_, | ||
| HITCBC | 1056 | 64 | bytes.data(), | 1056 | 64 | bytes.data(), | ||
| 1057 | bytes.size()); | 1057 | bytes.size()); | |||||
| HITCBC | 1058 | 64 | } | 1058 | 64 | } | ||
| 1059 | 1059 | |||||||
| 1060 | inline | 1060 | inline | |||||
| 1061 | url_base& | 1061 | url_base& | |||||
| HITCBC | 1062 | 7 | url_base:: | 1062 | 7 | url_base:: | ||
| 1063 | set_host_ipvfuture( | 1063 | set_host_ipvfuture( | |||||
| 1064 | core::string_view s) | 1064 | core::string_view s) | |||||
| 1065 | { | 1065 | { | |||||
| HITCBC | 1066 | 7 | op_t op(*this, &s); | 1066 | 7 | op_t op(*this, &s); | ||
| 1067 | // validate | 1067 | // validate | |||||
| HITCBC | 1068 | 8 | grammar::parse(s, | 1068 | 8 | grammar::parse(s, | ||
| 1069 | detail::ipvfuture_rule | 1069 | detail::ipvfuture_rule | |||||
| HITCBC | 1070 | 8 | ).value(BOOST_URL_POS); | 1070 | 8 | ).value(BOOST_URL_POS); | ||
| HITCBC | 1071 | 6 | auto dest = set_host_impl( | 1071 | 6 | auto dest = set_host_impl( | ||
| HITCBC | 1072 | 6 | s.size() + 2, op); | 1072 | 6 | s.size() + 2, op); | ||
| HITCBC | 1073 | 6 | *dest++ = '['; | 1073 | 6 | *dest++ = '['; | ||
| HITCBC | 1074 | 6 | dest += s.copy(dest, s.size()); | 1074 | 6 | dest += s.copy(dest, s.size()); | ||
| HITCBC | 1075 | 6 | *dest = ']'; | 1075 | 6 | *dest = ']'; | ||
| HITCBC | 1076 | 6 | impl_.host_type_ = | 1076 | 6 | impl_.host_type_ = | ||
| 1077 | urls::host_type::ipvfuture; | 1077 | urls::host_type::ipvfuture; | |||||
| HITCBC | 1078 | 6 | impl_.decoded_[id_host] = | 1078 | 6 | impl_.decoded_[id_host] = | ||
| HITCBC | 1079 | 6 | detail::to_size_type(s.size() + 2); | 1079 | 6 | detail::to_size_type(s.size() + 2); | ||
| HITCBC | 1080 | 6 | return *this; | 1080 | 6 | return *this; | ||
| HITCBC | 1081 | 7 | } | 1081 | 7 | } | ||
| 1082 | 1082 | |||||||
| 1083 | inline | 1083 | inline | |||||
| 1084 | url_base& | 1084 | url_base& | |||||
| HITCBC | 1085 | 4 | url_base:: | 1085 | 4 | url_base:: | ||
| 1086 | set_host_name( | 1086 | set_host_name( | |||||
| 1087 | core::string_view s) | 1087 | core::string_view s) | |||||
| 1088 | { | 1088 | { | |||||
| HITCBC | 1089 | 4 | bool is_ipv4 = false; | 1089 | 4 | bool is_ipv4 = false; | ||
| HITCBC | 1090 | 4 | if(s.size() >= 7) // "0.0.0.0" | 1090 | 4 | if(s.size() >= 7) // "0.0.0.0" | ||
| 1091 | { | 1091 | { | |||||
| 1092 | // IPv4-address | 1092 | // IPv4-address | |||||
| HITCBC | 1093 | 3 | if(parse_ipv4_address(s).has_value()) | 1093 | 3 | if(parse_ipv4_address(s).has_value()) | ||
| HITCBC | 1094 | 1 | is_ipv4 = true; | 1094 | 1 | is_ipv4 = true; | ||
| 1095 | } | 1095 | } | |||||
| HITCBC | 1096 | 4 | auto allowed = detail::host_chars; | 1096 | 4 | auto allowed = detail::host_chars; | ||
| HITCBC | 1097 | 4 | if(is_ipv4) | 1097 | 4 | if(is_ipv4) | ||
| HITCBC | 1098 | 1 | allowed = allowed - '.'; | 1098 | 1 | allowed = allowed - '.'; | ||
| 1099 | 1099 | |||||||
| HITCBC | 1100 | 4 | op_t op(*this, &s); | 1100 | 4 | op_t op(*this, &s); | ||
| HITCBC | 1101 | 4 | encoding_opts opt; | 1101 | 4 | encoding_opts opt; | ||
| HITCBC | 1102 | 4 | auto const n = encoded_size( | 1102 | 4 | auto const n = encoded_size( | ||
| 1103 | s, allowed, opt); | 1103 | s, allowed, opt); | |||||
| HITCBC | 1104 | 4 | auto dest = set_host_impl(n, op); | 1104 | 4 | auto dest = set_host_impl(n, op); | ||
| HITCBC | 1105 | 4 | encode_unsafe( | 1105 | 4 | encode_unsafe( | ||
| 1106 | dest, | 1106 | dest, | |||||
| 1107 | n, | 1107 | n, | |||||
| 1108 | s, | 1108 | s, | |||||
| 1109 | allowed, | 1109 | allowed, | |||||
| 1110 | opt); | 1110 | opt); | |||||
| HITCBC | 1111 | 4 | impl_.host_type_ = | 1111 | 4 | impl_.host_type_ = | ||
| 1112 | urls::host_type::name; | 1112 | urls::host_type::name; | |||||
| HITCBC | 1113 | 4 | impl_.decoded_[id_host] = | 1113 | 4 | impl_.decoded_[id_host] = | ||
| HITCBC | 1114 | 4 | detail::to_size_type(s.size()); | 1114 | 4 | detail::to_size_type(s.size()); | ||
| HITCBC | 1115 | 4 | return *this; | 1115 | 4 | return *this; | ||
| HITCBC | 1116 | 4 | } | 1116 | 4 | } | ||
| 1117 | 1117 | |||||||
| 1118 | inline | 1118 | inline | |||||
| 1119 | url_base& | 1119 | url_base& | |||||
| HITCBC | 1120 | 4 | url_base:: | 1120 | 4 | url_base:: | ||
| 1121 | set_encoded_host_name( | 1121 | set_encoded_host_name( | |||||
| 1122 | pct_string_view s) | 1122 | pct_string_view s) | |||||
| 1123 | { | 1123 | { | |||||
| HITCBC | 1124 | 4 | bool is_ipv4 = false; | 1124 | 4 | bool is_ipv4 = false; | ||
| HITCBC | 1125 | 4 | if(s.size() >= 7) // "0.0.0.0" | 1125 | 4 | if(s.size() >= 7) // "0.0.0.0" | ||
| 1126 | { | 1126 | { | |||||
| 1127 | // IPv4-address | 1127 | // IPv4-address | |||||
| HITCBC | 1128 | 3 | if(parse_ipv4_address(s).has_value()) | 1128 | 3 | if(parse_ipv4_address(s).has_value()) | ||
| HITCBC | 1129 | 1 | is_ipv4 = true; | 1129 | 1 | is_ipv4 = true; | ||
| 1130 | } | 1130 | } | |||||
| HITCBC | 1131 | 4 | auto allowed = detail::host_chars; | 1131 | 4 | auto allowed = detail::host_chars; | ||
| HITCBC | 1132 | 4 | if(is_ipv4) | 1132 | 4 | if(is_ipv4) | ||
| HITCBC | 1133 | 1 | allowed = allowed - '.'; | 1133 | 1 | allowed = allowed - '.'; | ||
| 1134 | 1134 | |||||||
| HITCBC | 1135 | 4 | op_t op(*this, &detail::ref(s)); | 1135 | 4 | op_t op(*this, &detail::ref(s)); | ||
| HITCBC | 1136 | 4 | auto const n = detail::re_encoded_size_unsafe( | 1136 | 4 | auto const n = detail::re_encoded_size_unsafe( | ||
| 1137 | s, allowed); | 1137 | s, allowed); | |||||
| HITCBC | 1138 | 4 | auto dest = set_host_impl(n, op); | 1138 | 4 | auto dest = set_host_impl(n, op); | ||
| HITCBC | 1139 | 4 | impl_.decoded_[id_host] = | 1139 | 4 | impl_.decoded_[id_host] = | ||
| HITCBC | 1140 | 8 | detail::to_size_type(detail::re_encode_unsafe( | 1140 | 8 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 1141 | dest, | 1141 | dest, | |||||
| HITCBC | 1142 | 4 | dest + n, | 1142 | 4 | dest + n, | ||
| 1143 | s, | 1143 | s, | |||||
| 1144 | allowed)); | 1144 | allowed)); | |||||
| HITCBC | 1145 | 4 | BOOST_ASSERT( | 1145 | 4 | BOOST_ASSERT( | ||
| 1146 | impl_.decoded_[id_host] == | 1146 | impl_.decoded_[id_host] == | |||||
| 1147 | s.decoded_size()); | 1147 | s.decoded_size()); | |||||
| HITCBC | 1148 | 4 | impl_.host_type_ = | 1148 | 4 | impl_.host_type_ = | ||
| 1149 | urls::host_type::name; | 1149 | urls::host_type::name; | |||||
| HITCBC | 1150 | 4 | return *this; | 1150 | 4 | return *this; | ||
| HITCBC | 1151 | 4 | } | 1151 | 4 | } | ||
| 1152 | 1152 | |||||||
| 1153 | //------------------------------------------------ | 1153 | //------------------------------------------------ | |||||
| 1154 | 1154 | |||||||
| 1155 | inline | 1155 | inline | |||||
| 1156 | url_base& | 1156 | url_base& | |||||
| HITCBC | 1157 | 215 | url_base:: | 1157 | 215 | url_base:: | ||
| 1158 | set_port_number( | 1158 | set_port_number( | |||||
| 1159 | std::uint16_t n) | 1159 | std::uint16_t n) | |||||
| 1160 | { | 1160 | { | |||||
| HITCBC | 1161 | 215 | op_t op(*this); | 1161 | 215 | op_t op(*this); | ||
| 1162 | auto s = | 1162 | auto s = | |||||
| HITCBC | 1163 | 215 | detail::make_printed(n); | 1163 | 215 | detail::make_printed(n); | ||
| HITCBC | 1164 | 215 | auto dest = set_port_impl( | 1164 | 215 | auto dest = set_port_impl( | ||
| HITCBC | 1165 | 215 | s.string().size(), op); | 1165 | 215 | s.string().size(), op); | ||
| HITCBC | 1166 | 215 | std::memcpy( | 1166 | 215 | std::memcpy( | ||
| HITCBC | 1167 | 215 | dest, s.string().data(), | 1167 | 215 | dest, s.string().data(), | ||
| HITCBC | 1168 | 215 | s.string().size()); | 1168 | 215 | s.string().size()); | ||
| HITCBC | 1169 | 215 | impl_.port_number_ = n; | 1169 | 215 | impl_.port_number_ = n; | ||
| HITCBC | 1170 | 215 | return *this; | 1170 | 215 | return *this; | ||
| HITCBC | 1171 | 215 | } | 1171 | 215 | } | ||
| 1172 | 1172 | |||||||
| 1173 | inline | 1173 | inline | |||||
| 1174 | url_base& | 1174 | url_base& | |||||
| HITCBC | 1175 | 389 | url_base:: | 1175 | 389 | url_base:: | ||
| 1176 | set_port( | 1176 | set_port( | |||||
| 1177 | core::string_view s) | 1177 | core::string_view s) | |||||
| 1178 | { | 1178 | { | |||||
| HITCBC | 1179 | 389 | op_t op(*this, &s); | 1179 | 389 | op_t op(*this, &s); | ||
| HITCBC | 1180 | 410 | auto t = grammar::parse(s, | 1180 | 410 | auto t = grammar::parse(s, | ||
| HITCBC | 1181 | 21 | detail::port_rule{} | 1181 | 21 | detail::port_rule{} | ||
| HITCBC | 1182 | 389 | ).value(BOOST_URL_POS); | 1182 | 389 | ).value(BOOST_URL_POS); | ||
| 1183 | auto dest = | 1183 | auto dest = | |||||
| HITCBC | 1184 | 368 | set_port_impl(t.str.size(), op); | 1184 | 368 | set_port_impl(t.str.size(), op); | ||
| HITCBC | 1185 | 368 | std::memcpy(dest, | 1185 | 368 | std::memcpy(dest, | ||
| HITCBC | 1186 | 368 | t.str.data(), t.str.size()); | 1186 | 368 | t.str.data(), t.str.size()); | ||
| HITCBC | 1187 | 368 | if(t.has_number) | 1187 | 368 | if(t.has_number) | ||
| HITCBC | 1188 | 208 | impl_.port_number_ = t.number; | 1188 | 208 | impl_.port_number_ = t.number; | ||
| 1189 | else | 1189 | else | |||||
| HITCBC | 1190 | 160 | impl_.port_number_ = 0; | 1190 | 160 | impl_.port_number_ = 0; | ||
| HITCBC | 1191 | 368 | return *this; | 1191 | 368 | return *this; | ||
| HITCBC | 1192 | 389 | } | 1192 | 389 | } | ||
| 1193 | 1193 | |||||||
| 1194 | inline | 1194 | inline | |||||
| 1195 | url_base& | 1195 | url_base& | |||||
| HITCBC | 1196 | 206 | url_base:: | 1196 | 206 | url_base:: | ||
| 1197 | remove_port() noexcept | 1197 | remove_port() noexcept | |||||
| 1198 | { | 1198 | { | |||||
| HITCBC | 1199 | 206 | op_t op(*this); | 1199 | 206 | op_t op(*this); | ||
| HITCBC | 1200 | 206 | resize_impl(id_port, 0, op); | 1200 | 206 | resize_impl(id_port, 0, op); | ||
| HITCBC | 1201 | 206 | impl_.port_number_ = 0; | 1201 | 206 | impl_.port_number_ = 0; | ||
| HITCBC | 1202 | 412 | return *this; | 1202 | 412 | return *this; | ||
| HITCBC | 1203 | 206 | } | 1203 | 206 | } | ||
| 1204 | 1204 | |||||||
| 1205 | //------------------------------------------------ | 1205 | //------------------------------------------------ | |||||
| 1206 | // | 1206 | // | |||||
| 1207 | // Compound Fields | 1207 | // Compound Fields | |||||
| 1208 | // | 1208 | // | |||||
| 1209 | //------------------------------------------------ | 1209 | //------------------------------------------------ | |||||
| 1210 | 1210 | |||||||
| 1211 | inline | 1211 | inline | |||||
| 1212 | url_base& | 1212 | url_base& | |||||
| HITCBC | 1213 | 14 | url_base:: | 1213 | 14 | url_base:: | ||
| 1214 | remove_origin() | 1214 | remove_origin() | |||||
| 1215 | { | 1215 | { | |||||
| 1216 | // these two calls perform 2 memmoves instead of 1 | 1216 | // these two calls perform 2 memmoves instead of 1 | |||||
| HITCBC | 1217 | 14 | remove_authority(); | 1217 | 14 | remove_authority(); | ||
| HITCBC | 1218 | 14 | remove_scheme(); | 1218 | 14 | remove_scheme(); | ||
| HITCBC | 1219 | 14 | return *this; | 1219 | 14 | return *this; | ||
| 1220 | } | 1220 | } | |||||
| 1221 | 1221 | |||||||
| 1222 | //------------------------------------------------ | 1222 | //------------------------------------------------ | |||||
| 1223 | // | 1223 | // | |||||
| 1224 | // Path | 1224 | // Path | |||||
| 1225 | // | 1225 | // | |||||
| 1226 | //------------------------------------------------ | 1226 | //------------------------------------------------ | |||||
| 1227 | 1227 | |||||||
| 1228 | inline | 1228 | inline | |||||
| 1229 | bool | 1229 | bool | |||||
| HITCBC | 1230 | 52 | url_base:: | 1230 | 52 | url_base:: | ||
| 1231 | set_path_absolute( | 1231 | set_path_absolute( | |||||
| 1232 | bool absolute) | 1232 | bool absolute) | |||||
| 1233 | { | 1233 | { | |||||
| HITCBC | 1234 | 52 | op_t op(*this); | 1234 | 52 | op_t op(*this); | ||
| 1235 | 1235 | |||||||
| 1236 | // check if path empty | 1236 | // check if path empty | |||||
| HITCBC | 1237 | 52 | if(impl_.len(id_path) == 0) | 1237 | 52 | if(impl_.len(id_path) == 0) | ||
| 1238 | { | 1238 | { | |||||
| HITCBC | 1239 | 40 | if(! absolute) | 1239 | 40 | if(! absolute) | ||
| 1240 | { | 1240 | { | |||||
| 1241 | // already not absolute | 1241 | // already not absolute | |||||
| HITCBC | 1242 | 34 | return true; | 1242 | 34 | return true; | ||
| 1243 | } | 1243 | } | |||||
| 1244 | 1244 | |||||||
| 1245 | // add '/' | 1245 | // add '/' | |||||
| HITCBC | 1246 | 6 | auto dest = resize_impl( | 1246 | 6 | auto dest = resize_impl( | ||
| 1247 | id_path, 1, op); | 1247 | id_path, 1, op); | |||||
| HITCBC | 1248 | 6 | *dest = '/'; | 1248 | 6 | *dest = '/'; | ||
| HITCBC | 1249 | 6 | ++impl_.decoded_[id_path]; | 1249 | 6 | ++impl_.decoded_[id_path]; | ||
| HITCBC | 1250 | 6 | return true; | 1250 | 6 | return true; | ||
| 1251 | } | 1251 | } | |||||
| 1252 | 1252 | |||||||
| 1253 | // check if path absolute | 1253 | // check if path absolute | |||||
| HITCBC | 1254 | 12 | if(s_[impl_.offset(id_path)] == '/') | 1254 | 12 | if(s_[impl_.offset(id_path)] == '/') | ||
| 1255 | { | 1255 | { | |||||
| HITCBC | 1256 | 9 | if(absolute) | 1256 | 9 | if(absolute) | ||
| 1257 | { | 1257 | { | |||||
| 1258 | // already absolute | 1258 | // already absolute | |||||
| HITCBC | 1259 | 2 | return true; | 1259 | 2 | return true; | ||
| 1260 | } | 1260 | } | |||||
| 1261 | 1261 | |||||||
| HITCBC | 1262 | 11 | if( has_authority() && | 1262 | 11 | if( has_authority() && | ||
| HITCBC | 1263 | 4 | impl_.len(id_path) > 1) | 1263 | 4 | impl_.len(id_path) > 1) | ||
| 1264 | { | 1264 | { | |||||
| 1265 | // can't do it, paths are always | 1265 | // can't do it, paths are always | |||||
| 1266 | // absolute when authority present! | 1266 | // absolute when authority present! | |||||
| HITCBC | 1267 | 2 | return false; | 1267 | 2 | return false; | ||
| 1268 | } | 1268 | } | |||||
| 1269 | 1269 | |||||||
| HITCBC | 1270 | 5 | auto p = encoded_path(); | 1270 | 5 | auto p = encoded_path(); | ||
| HITCBC | 1271 | 5 | auto pos = p.find_first_of(":/", 1); | 1271 | 5 | auto pos = p.find_first_of(":/", 1); | ||
| HITCBC | 1272 | 6 | if (pos != core::string_view::npos && | 1272 | 6 | if (pos != core::string_view::npos && | ||
| HITCBC | 1273 | 1 | p[pos] == ':') | 1273 | 1 | p[pos] == ':') | ||
| 1274 | { | 1274 | { | |||||
| 1275 | // prepend with . | 1275 | // prepend with . | |||||
| HITCBC | 1276 | 1 | auto n = impl_.len(id_path); | 1276 | 1 | auto n = impl_.len(id_path); | ||
| HITCBC | 1277 | 1 | resize_impl(id_path, n + 1, op); | 1277 | 1 | resize_impl(id_path, n + 1, op); | ||
| HITCBC | 1278 | 1 | std::memmove( | 1278 | 1 | std::memmove( | ||
| HITCBC | 1279 | 2 | s_ + impl_.offset(id_path) + 1, | 1279 | 2 | s_ + impl_.offset(id_path) + 1, | ||
| HITCBC | 1280 | 1 | s_ + impl_.offset(id_path), n); | 1280 | 1 | s_ + impl_.offset(id_path), n); | ||
| HITCBC | 1281 | 1 | *(s_ + impl_.offset(id_path)) = '.'; | 1281 | 1 | *(s_ + impl_.offset(id_path)) = '.'; | ||
| HITCBC | 1282 | 1 | ++impl_.decoded_[id_path]; | 1282 | 1 | ++impl_.decoded_[id_path]; | ||
| HITCBC | 1283 | 1 | return true; | 1283 | 1 | return true; | ||
| 1284 | } | 1284 | } | |||||
| 1285 | 1285 | |||||||
| 1286 | // remove '/' | 1286 | // remove '/' | |||||
| HITCBC | 1287 | 4 | auto n = impl_.len(id_port); | 1287 | 4 | auto n = impl_.len(id_port); | ||
| HITCBC | 1288 | 4 | impl_.split(id_port, n + 1); | 1288 | 4 | impl_.split(id_port, n + 1); | ||
| HITCBC | 1289 | 4 | resize_impl(id_port, n, op); | 1289 | 4 | resize_impl(id_port, n, op); | ||
| HITCBC | 1290 | 4 | --impl_.decoded_[id_path]; | 1290 | 4 | --impl_.decoded_[id_path]; | ||
| HITCBC | 1291 | 4 | return true; | 1291 | 4 | return true; | ||
| 1292 | } | 1292 | } | |||||
| 1293 | 1293 | |||||||
| HITCBC | 1294 | 3 | if(! absolute) | 1294 | 3 | if(! absolute) | ||
| 1295 | { | 1295 | { | |||||
| 1296 | // already not absolute | 1296 | // already not absolute | |||||
| HITCBC | 1297 | 1 | return true; | 1297 | 1 | return true; | ||
| 1298 | } | 1298 | } | |||||
| 1299 | 1299 | |||||||
| 1300 | // add '/' | 1300 | // add '/' | |||||
| HITCBC | 1301 | 2 | auto n = impl_.len(id_port); | 1301 | 2 | auto n = impl_.len(id_port); | ||
| HITCBC | 1302 | 2 | auto dest = resize_impl( | 1302 | 2 | auto dest = resize_impl( | ||
| HITCBC | 1303 | 2 | id_port, n + 1, op) + n; | 1303 | 2 | id_port, n + 1, op) + n; | ||
| HITCBC | 1304 | 2 | impl_.split(id_port, n); | 1304 | 2 | impl_.split(id_port, n); | ||
| HITCBC | 1305 | 2 | *dest = '/'; | 1305 | 2 | *dest = '/'; | ||
| HITCBC | 1306 | 2 | ++impl_.decoded_[id_path]; | 1306 | 2 | ++impl_.decoded_[id_path]; | ||
| HITCBC | 1307 | 2 | return true; | 1307 | 2 | return true; | ||
| HITCBC | 1308 | 52 | } | 1308 | 52 | } | ||
| 1309 | 1309 | |||||||
| 1310 | inline | 1310 | inline | |||||
| 1311 | url_base& | 1311 | url_base& | |||||
| HITCBC | 1312 | 298 | url_base:: | 1312 | 298 | url_base:: | ||
| 1313 | set_path( | 1313 | set_path( | |||||
| 1314 | core::string_view s) | 1314 | core::string_view s) | |||||
| 1315 | { | 1315 | { | |||||
| HITCBC | 1316 | 298 | op_t op(*this, &s); | 1316 | 298 | op_t op(*this, &s); | ||
| HITCBC | 1317 | 298 | encoding_opts opt; | 1317 | 298 | encoding_opts opt; | ||
| 1318 | 1318 | |||||||
| 1319 | //------------------------------------------------ | 1319 | //------------------------------------------------ | |||||
| 1320 | // | 1320 | // | |||||
| 1321 | // Calculate encoded size | 1321 | // Calculate encoded size | |||||
| 1322 | // | 1322 | // | |||||
| 1323 | // - "/"s are not encoded | 1323 | // - "/"s are not encoded | |||||
| 1324 | // - "%2F"s are not encoded | 1324 | // - "%2F"s are not encoded | |||||
| 1325 | // | 1325 | // | |||||
| 1326 | // - reserved path chars are re-encoded | 1326 | // - reserved path chars are re-encoded | |||||
| 1327 | // - colons in first segment might need to be re-encoded | 1327 | // - colons in first segment might need to be re-encoded | |||||
| 1328 | // - the path might need to receive a prefix | 1328 | // - the path might need to receive a prefix | |||||
| HITCBC | 1329 | 298 | auto const n = encoded_size( | 1329 | 298 | auto const n = encoded_size( | ||
| 1330 | s, detail::path_chars, opt); | 1330 | s, detail::path_chars, opt); | |||||
| HITCBC | 1331 | 298 | std::size_t n_reencode_colons = 0; | 1331 | 298 | std::size_t n_reencode_colons = 0; | ||
| HITCBC | 1332 | 298 | core::string_view first_seg; | 1332 | 298 | core::string_view first_seg; | ||
| HITCBC | 1333 | 298 | if (!has_scheme() && | 1333 | 298 | if (!has_scheme() && | ||
| HITCBC | 1334 | 337 | !has_authority() && | 1334 | 337 | !has_authority() && | ||
| HITCBC | 1335 | 39 | !s.starts_with('/')) | 1335 | 39 | !s.starts_with('/')) | ||
| 1336 | { | 1336 | { | |||||
| 1337 | // the first segment with unencoded colons would look | 1337 | // the first segment with unencoded colons would look | |||||
| 1338 | // like the scheme | 1338 | // like the scheme | |||||
| HITCBC | 1339 | 6 | first_seg = detail::to_sv(s); | 1339 | 6 | first_seg = detail::to_sv(s); | ||
| HITCBC | 1340 | 6 | std::size_t p = s.find('/'); | 1340 | 6 | std::size_t p = s.find('/'); | ||
| HITCBC | 1341 | 6 | if (p != core::string_view::npos) | 1341 | 6 | if (p != core::string_view::npos) | ||
| HITCBC | 1342 | 2 | first_seg = s.substr(0, p); | 1342 | 2 | first_seg = s.substr(0, p); | ||
| HITCBC | 1343 | 6 | n_reencode_colons = std::count( | 1343 | 6 | n_reencode_colons = std::count( | ||
| HITCBC | 1344 | 12 | first_seg.begin(), first_seg.end(), ':'); | 1344 | 12 | first_seg.begin(), first_seg.end(), ':'); | ||
| 1345 | } | 1345 | } | |||||
| 1346 | // the authority can only be followed by an empty or relative path | 1346 | // the authority can only be followed by an empty or relative path | |||||
| 1347 | // if we have an authority and the path is a non-empty relative path, we | 1347 | // if we have an authority and the path is a non-empty relative path, we | |||||
| 1348 | // add the "/" prefix to make it valid. | 1348 | // add the "/" prefix to make it valid. | |||||
| 1349 | bool make_absolute = | 1349 | bool make_absolute = | |||||
| HITCBC | 1350 | 298 | has_authority() && | 1350 | 298 | has_authority() && | ||
| HITCBC | 1351 | 305 | !s.starts_with('/') && | 1351 | 305 | !s.starts_with('/') && | ||
| HITCBC | 1352 | 7 | !s.empty(); | 1352 | 7 | !s.empty(); | ||
| 1353 | // a path starting with "//" might look like the authority. | 1353 | // a path starting with "//" might look like the authority. | |||||
| 1354 | // we add a "/." prefix to prevent that | 1354 | // we add a "/." prefix to prevent that | |||||
| 1355 | bool add_dot_segment = | 1355 | bool add_dot_segment = | |||||
| HITCBC | 1356 | 592 | !make_absolute && | 1356 | 592 | !make_absolute && | ||
| HITCBC | 1357 | 294 | s.starts_with("//"); | 1357 | 294 | s.starts_with("//"); | ||
| 1358 | 1358 | |||||||
| 1359 | //------------------------------------------------ | 1359 | //------------------------------------------------ | |||||
| 1360 | // | 1360 | // | |||||
| 1361 | // Re-encode data | 1361 | // Re-encode data | |||||
| 1362 | // | 1362 | // | |||||
| HITCBC | 1363 | 596 | auto dest = set_path_impl( | 1363 | 596 | auto dest = set_path_impl( | ||
| HITCBC | 1364 | 298 | n + make_absolute + 2 * n_reencode_colons + 2 * add_dot_segment, op); | 1364 | 298 | n + make_absolute + 2 * n_reencode_colons + 2 * add_dot_segment, op); | ||
| HITCBC | 1365 | 298 | impl_.decoded_[id_path] = 0; | 1365 | 298 | impl_.decoded_[id_path] = 0; | ||
| HITCBC | 1366 | 298 | if (!dest) | 1366 | 298 | if (!dest) | ||
| 1367 | { | 1367 | { | |||||
| HITCBC | 1368 | 3 | impl_.nseg_ = 0; | 1368 | 3 | impl_.nseg_ = 0; | ||
| HITCBC | 1369 | 3 | return *this; | 1369 | 3 | return *this; | ||
| 1370 | } | 1370 | } | |||||
| HITCBC | 1371 | 295 | if (make_absolute) | 1371 | 295 | if (make_absolute) | ||
| 1372 | { | 1372 | { | |||||
| HITCBC | 1373 | 4 | *dest++ = '/'; | 1373 | 4 | *dest++ = '/'; | ||
| HITCBC | 1374 | 4 | impl_.decoded_[id_path] += 1; | 1374 | 4 | impl_.decoded_[id_path] += 1; | ||
| 1375 | } | 1375 | } | |||||
| HITCBC | 1376 | 291 | else if (add_dot_segment) | 1376 | 291 | else if (add_dot_segment) | ||
| 1377 | { | 1377 | { | |||||
| HITCBC | 1378 | 12 | *dest++ = '/'; | 1378 | 12 | *dest++ = '/'; | ||
| HITCBC | 1379 | 12 | *dest++ = '.'; | 1379 | 12 | *dest++ = '.'; | ||
| HITCBC | 1380 | 12 | impl_.decoded_[id_path] += 2; | 1380 | 12 | impl_.decoded_[id_path] += 2; | ||
| 1381 | } | 1381 | } | |||||
| HITCBC | 1382 | 590 | dest += encode_unsafe( | 1382 | 590 | dest += encode_unsafe( | ||
| 1383 | dest, | 1383 | dest, | |||||
| HITCBC | 1384 | 295 | impl_.get(id_query).data() - dest, | 1384 | 295 | impl_.get(id_query).data() - dest, | ||
| 1385 | first_seg, | 1385 | first_seg, | |||||
| HITCBC | 1386 | 295 | detail::segment_chars - ':', | 1386 | 295 | detail::segment_chars - ':', | ||
| 1387 | opt); | 1387 | opt); | |||||
| HITCBC | 1388 | 295 | dest += encode_unsafe( | 1388 | 295 | dest += encode_unsafe( | ||
| 1389 | dest, | 1389 | dest, | |||||
| HITCBC | 1390 | 295 | impl_.get(id_query).data() - dest, | 1390 | 295 | impl_.get(id_query).data() - dest, | ||
| 1391 | s.substr(first_seg.size()), | 1391 | s.substr(first_seg.size()), | |||||
| 1392 | detail::path_chars, | 1392 | detail::path_chars, | |||||
| 1393 | opt); | 1393 | opt); | |||||
| HITCBC | 1394 | 295 | impl_.decoded_[id_path] += | 1394 | 295 | impl_.decoded_[id_path] += | ||
| HITCBC | 1395 | 295 | detail::to_size_type(s.size()); | 1395 | 295 | detail::to_size_type(s.size()); | ||
| HITCBC | 1396 | 295 | BOOST_ASSERT(!dest || dest == impl_.get(id_query).data()); | 1396 | 295 | BOOST_ASSERT(!dest || dest == impl_.get(id_query).data()); | ||
| HITCBC | 1397 | 295 | BOOST_ASSERT( | 1397 | 295 | BOOST_ASSERT( | ||
| 1398 | impl_.decoded_[id_path] == | 1398 | impl_.decoded_[id_path] == | |||||
| 1399 | s.size() + make_absolute + 2 * add_dot_segment); | 1399 | s.size() + make_absolute + 2 * add_dot_segment); | |||||
| 1400 | 1400 | |||||||
| 1401 | //------------------------------------------------ | 1401 | //------------------------------------------------ | |||||
| 1402 | // | 1402 | // | |||||
| 1403 | // Update path parameters | 1403 | // Update path parameters | |||||
| 1404 | // | 1404 | // | |||||
| 1405 | // get the encoded_path with the replacements we applied | 1405 | // get the encoded_path with the replacements we applied | |||||
| HITCBC | 1406 | 295 | if (s == "/") | 1406 | 295 | if (s == "/") | ||
| 1407 | { | 1407 | { | |||||
| 1408 | // "/" maps to sequence {} | 1408 | // "/" maps to sequence {} | |||||
| HITCBC | 1409 | 144 | impl_.nseg_ = 0; | 1409 | 144 | impl_.nseg_ = 0; | ||
| 1410 | } | 1410 | } | |||||
| HITCBC | 1411 | 151 | else if (!s.empty()) | 1411 | 151 | else if (!s.empty()) | ||
| 1412 | { | 1412 | { | |||||
| HITCBC | 1413 | 146 | if (s.starts_with("/./")) | 1413 | 146 | if (s.starts_with("/./")) | ||
| HITCBC | 1414 | 1 | s = s.substr(2); | 1414 | 1 | s = s.substr(2); | ||
| 1415 | // count segments as number of '/'s + 1 | 1415 | // count segments as number of '/'s + 1 | |||||
| HITCBC | 1416 | 292 | impl_.nseg_ = detail::to_size_type( | 1416 | 292 | impl_.nseg_ = detail::to_size_type( | ||
| HITCBC | 1417 | 146 | std::count( | 1417 | 146 | std::count( | ||
| HITCBC | 1418 | 292 | s.begin() + 1, s.end(), '/') + 1); | 1418 | 292 | s.begin() + 1, s.end(), '/') + 1); | ||
| 1419 | } | 1419 | } | |||||
| 1420 | else | 1420 | else | |||||
| 1421 | { | 1421 | { | |||||
| 1422 | // an empty relative path maps to sequence {} | 1422 | // an empty relative path maps to sequence {} | |||||
| HITCBC | 1423 | 5 | impl_.nseg_ = 0; | 1423 | 5 | impl_.nseg_ = 0; | ||
| 1424 | } | 1424 | } | |||||
| 1425 | 1425 | |||||||
| HITCBC | 1426 | 295 | check_invariants(); | 1426 | 295 | check_invariants(); | ||
| HITCBC | 1427 | 295 | return *this; | 1427 | 295 | return *this; | ||
| HITCBC | 1428 | 298 | } | 1428 | 298 | } | ||
| 1429 | 1429 | |||||||
| 1430 | inline | 1430 | inline | |||||
| 1431 | url_base& | 1431 | url_base& | |||||
| HITCBC | 1432 | 299 | url_base:: | 1432 | 299 | url_base:: | ||
| 1433 | set_encoded_path( | 1433 | set_encoded_path( | |||||
| 1434 | pct_string_view s) | 1434 | pct_string_view s) | |||||
| 1435 | { | 1435 | { | |||||
| HITCBC | 1436 | 299 | op_t op(*this, &detail::ref(s)); | 1436 | 299 | op_t op(*this, &detail::ref(s)); | ||
| 1437 | 1437 | |||||||
| 1438 | //------------------------------------------------ | 1438 | //------------------------------------------------ | |||||
| 1439 | // | 1439 | // | |||||
| 1440 | // Calculate re-encoded output size | 1440 | // Calculate re-encoded output size | |||||
| 1441 | // | 1441 | // | |||||
| 1442 | // - reserved path chars are re-encoded | 1442 | // - reserved path chars are re-encoded | |||||
| 1443 | // - colons in first segment might need to be re-encoded | 1443 | // - colons in first segment might need to be re-encoded | |||||
| 1444 | // - the path might need to receive a prefix | 1444 | // - the path might need to receive a prefix | |||||
| HITCBC | 1445 | 299 | auto const n = detail::re_encoded_size_unsafe( | 1445 | 299 | auto const n = detail::re_encoded_size_unsafe( | ||
| 1446 | s, detail::path_chars); | 1446 | s, detail::path_chars); | |||||
| HITCBC | 1447 | 299 | std::size_t n_reencode_colons = 0; | 1447 | 299 | std::size_t n_reencode_colons = 0; | ||
| HITCBC | 1448 | 299 | core::string_view first_seg; | 1448 | 299 | core::string_view first_seg; | ||
| HITCBC | 1449 | 299 | if (!has_scheme() && | 1449 | 299 | if (!has_scheme() && | ||
| HITCBC | 1450 | 332 | !has_authority() && | 1450 | 332 | !has_authority() && | ||
| HITCBC | 1451 | 33 | !s.starts_with('/')) | 1451 | 33 | !s.starts_with('/')) | ||
| 1452 | { | 1452 | { | |||||
| 1453 | // the first segment with unencoded colons would look | 1453 | // the first segment with unencoded colons would look | |||||
| 1454 | // like the scheme | 1454 | // like the scheme | |||||
| HITCBC | 1455 | 26 | first_seg = detail::to_sv(s); | 1455 | 26 | first_seg = detail::to_sv(s); | ||
| HITCBC | 1456 | 26 | std::size_t p = s.find('/'); | 1456 | 26 | std::size_t p = s.find('/'); | ||
| HITCBC | 1457 | 26 | if (p != core::string_view::npos) | 1457 | 26 | if (p != core::string_view::npos) | ||
| HITCBC | 1458 | 9 | first_seg = s.substr(0, p); | 1458 | 9 | first_seg = s.substr(0, p); | ||
| HITCBC | 1459 | 26 | n_reencode_colons = std::count( | 1459 | 26 | n_reencode_colons = std::count( | ||
| HITCBC | 1460 | 52 | first_seg.begin(), first_seg.end(), ':'); | 1460 | 52 | first_seg.begin(), first_seg.end(), ':'); | ||
| 1461 | } | 1461 | } | |||||
| 1462 | // the authority can only be followed by an empty or relative path | 1462 | // the authority can only be followed by an empty or relative path | |||||
| 1463 | // if we have an authority and the path is a non-empty relative path, we | 1463 | // if we have an authority and the path is a non-empty relative path, we | |||||
| 1464 | // add the "/" prefix to make it valid. | 1464 | // add the "/" prefix to make it valid. | |||||
| 1465 | bool make_absolute = | 1465 | bool make_absolute = | |||||
| HITCBC | 1466 | 299 | has_authority() && | 1466 | 299 | has_authority() && | ||
| HITCBC | 1467 | 443 | !s.starts_with('/') && | 1467 | 443 | !s.starts_with('/') && | ||
| HITCBC | 1468 | 144 | !s.empty(); | 1468 | 144 | !s.empty(); | ||
| 1469 | // a path starting with "//" might look like the authority | 1469 | // a path starting with "//" might look like the authority | |||||
| 1470 | // we add a "/." prefix to prevent that | 1470 | // we add a "/." prefix to prevent that | |||||
| 1471 | bool add_dot_segment = | 1471 | bool add_dot_segment = | |||||
| HITCBC | 1472 | 502 | !make_absolute && | 1472 | 502 | !make_absolute && | ||
| HITCBC | 1473 | 362 | !has_authority() && | 1473 | 362 | !has_authority() && | ||
| HITCBC | 1474 | 63 | s.starts_with("//"); | 1474 | 63 | s.starts_with("//"); | ||
| 1475 | 1475 | |||||||
| 1476 | //------------------------------------------------ | 1476 | //------------------------------------------------ | |||||
| 1477 | // | 1477 | // | |||||
| 1478 | // Re-encode data | 1478 | // Re-encode data | |||||
| 1479 | // | 1479 | // | |||||
| HITCBC | 1480 | 598 | auto dest = set_path_impl( | 1480 | 598 | auto dest = set_path_impl( | ||
| HITCBC | 1481 | 299 | n + make_absolute + 2 * n_reencode_colons + 2 * add_dot_segment, op); | 1481 | 299 | n + make_absolute + 2 * n_reencode_colons + 2 * add_dot_segment, op); | ||
| HITCBC | 1482 | 299 | impl_.decoded_[id_path] = 0; | 1482 | 299 | impl_.decoded_[id_path] = 0; | ||
| HITCBC | 1483 | 299 | if (!dest) | 1483 | 299 | if (!dest) | ||
| 1484 | { | 1484 | { | |||||
| HITCBC | 1485 | 2 | impl_.nseg_ = 0; | 1485 | 2 | impl_.nseg_ = 0; | ||
| HITCBC | 1486 | 2 | return *this; | 1486 | 2 | return *this; | ||
| 1487 | } | 1487 | } | |||||
| HITCBC | 1488 | 297 | if (make_absolute) | 1488 | 297 | if (make_absolute) | ||
| 1489 | { | 1489 | { | |||||
| HITCBC | 1490 | 96 | *dest++ = '/'; | 1490 | 96 | *dest++ = '/'; | ||
| HITCBC | 1491 | 96 | impl_.decoded_[id_path] += 1; | 1491 | 96 | impl_.decoded_[id_path] += 1; | ||
| 1492 | } | 1492 | } | |||||
| HITCBC | 1493 | 201 | else if (add_dot_segment) | 1493 | 201 | else if (add_dot_segment) | ||
| 1494 | { | 1494 | { | |||||
| HITCBC | 1495 | 5 | *dest++ = '/'; | 1495 | 5 | *dest++ = '/'; | ||
| HITCBC | 1496 | 5 | *dest++ = '.'; | 1496 | 5 | *dest++ = '.'; | ||
| HITCBC | 1497 | 5 | impl_.decoded_[id_path] += 2; | 1497 | 5 | impl_.decoded_[id_path] += 2; | ||
| 1498 | } | 1498 | } | |||||
| HITCBC | 1499 | 297 | impl_.decoded_[id_path] += | 1499 | 297 | impl_.decoded_[id_path] += | ||
| HITCBC | 1500 | 297 | detail::to_size_type(detail::re_encode_unsafe( | 1500 | 297 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 1501 | dest, | 1501 | dest, | |||||
| HITCBC | 1502 | 297 | impl_.get(id_query).data(), | 1502 | 297 | impl_.get(id_query).data(), | ||
| 1503 | first_seg, | 1503 | first_seg, | |||||
| HITCBC | 1504 | 297 | detail::segment_chars - ':')); | 1504 | 297 | detail::segment_chars - ':')); | ||
| HITCBC | 1505 | 297 | impl_.decoded_[id_path] += | 1505 | 297 | impl_.decoded_[id_path] += | ||
| HITCBC | 1506 | 594 | detail::to_size_type(detail::re_encode_unsafe( | 1506 | 594 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 1507 | dest, | 1507 | dest, | |||||
| HITCBC | 1508 | 297 | impl_.get(id_query).data(), | 1508 | 297 | impl_.get(id_query).data(), | ||
| 1509 | s.substr(first_seg.size()), | 1509 | s.substr(first_seg.size()), | |||||
| 1510 | detail::path_chars)); | 1510 | detail::path_chars)); | |||||
| HITCBC | 1511 | 297 | BOOST_ASSERT(dest == impl_.get(id_query).data()); | 1511 | 297 | BOOST_ASSERT(dest == impl_.get(id_query).data()); | ||
| HITCBC | 1512 | 297 | BOOST_ASSERT( | 1512 | 297 | BOOST_ASSERT( | ||
| 1513 | impl_.decoded_[id_path] == | 1513 | impl_.decoded_[id_path] == | |||||
| 1514 | s.decoded_size() + make_absolute + 2 * add_dot_segment); | 1514 | s.decoded_size() + make_absolute + 2 * add_dot_segment); | |||||
| 1515 | 1515 | |||||||
| 1516 | //------------------------------------------------ | 1516 | //------------------------------------------------ | |||||
| 1517 | // | 1517 | // | |||||
| 1518 | // Update path parameters | 1518 | // Update path parameters | |||||
| 1519 | // | 1519 | // | |||||
| 1520 | // get the encoded_path with the replacements we applied | 1520 | // get the encoded_path with the replacements we applied | |||||
| HITCBC | 1521 | 297 | if (s == "/") | 1521 | 297 | if (s == "/") | ||
| 1522 | { | 1522 | { | |||||
| 1523 | // "/" maps to sequence {} | 1523 | // "/" maps to sequence {} | |||||
| HITCBC | 1524 | 19 | impl_.nseg_ = 0; | 1524 | 19 | impl_.nseg_ = 0; | ||
| 1525 | } | 1525 | } | |||||
| HITCBC | 1526 | 278 | else if (!s.empty()) | 1526 | 278 | else if (!s.empty()) | ||
| 1527 | { | 1527 | { | |||||
| HITCBC | 1528 | 227 | if (s.starts_with("/./")) | 1528 | 227 | if (s.starts_with("/./")) | ||
| HITCBC | 1529 | 7 | s = s.substr(2); | 1529 | 7 | s = s.substr(2); | ||
| 1530 | // count segments as number of '/'s + 1 | 1530 | // count segments as number of '/'s + 1 | |||||
| HITCBC | 1531 | 454 | impl_.nseg_ = detail::to_size_type( | 1531 | 454 | impl_.nseg_ = detail::to_size_type( | ||
| HITCBC | 1532 | 227 | std::count( | 1532 | 227 | std::count( | ||
| HITCBC | 1533 | 454 | s.begin() + 1, s.end(), '/') + 1); | 1533 | 454 | s.begin() + 1, s.end(), '/') + 1); | ||
| 1534 | } | 1534 | } | |||||
| 1535 | else | 1535 | else | |||||
| 1536 | { | 1536 | { | |||||
| 1537 | // an empty relative path maps to sequence {} | 1537 | // an empty relative path maps to sequence {} | |||||
| HITCBC | 1538 | 51 | impl_.nseg_ = 0; | 1538 | 51 | impl_.nseg_ = 0; | ||
| 1539 | } | 1539 | } | |||||
| 1540 | 1540 | |||||||
| HITCBC | 1541 | 297 | check_invariants(); | 1541 | 297 | check_invariants(); | ||
| HITCBC | 1542 | 297 | return *this; | 1542 | 297 | return *this; | ||
| HITCBC | 1543 | 299 | } | 1543 | 299 | } | ||
| 1544 | 1544 | |||||||
| 1545 | inline | 1545 | inline | |||||
| 1546 | segments_ref | 1546 | segments_ref | |||||
| HITCBC | 1547 | 1146 | url_base:: | 1547 | 1146 | url_base:: | ||
| 1548 | segments() noexcept | 1548 | segments() noexcept | |||||
| 1549 | { | 1549 | { | |||||
| HITCBC | 1550 | 1146 | return {*this}; | 1550 | 1146 | return {*this}; | ||
| 1551 | } | 1551 | } | |||||
| 1552 | 1552 | |||||||
| 1553 | inline | 1553 | inline | |||||
| 1554 | segments_encoded_ref | 1554 | segments_encoded_ref | |||||
| HITCBC | 1555 | 497 | url_base:: | 1555 | 497 | url_base:: | ||
| 1556 | encoded_segments() noexcept | 1556 | encoded_segments() noexcept | |||||
| 1557 | { | 1557 | { | |||||
| HITCBC | 1558 | 497 | return {*this}; | 1558 | 497 | return {*this}; | ||
| 1559 | } | 1559 | } | |||||
| 1560 | 1560 | |||||||
| 1561 | //------------------------------------------------ | 1561 | //------------------------------------------------ | |||||
| 1562 | // | 1562 | // | |||||
| 1563 | // Query | 1563 | // Query | |||||
| 1564 | // | 1564 | // | |||||
| 1565 | //------------------------------------------------ | 1565 | //------------------------------------------------ | |||||
| 1566 | 1566 | |||||||
| 1567 | inline | 1567 | inline | |||||
| 1568 | url_base& | 1568 | url_base& | |||||
| HITCBC | 1569 | 169 | url_base:: | 1569 | 169 | url_base:: | ||
| 1570 | set_query( | 1570 | set_query( | |||||
| 1571 | core::string_view s) | 1571 | core::string_view s) | |||||
| 1572 | { | 1572 | { | |||||
| HITCBC | 1573 | 169 | edit_params( | 1573 | 169 | edit_params( | ||
| HITCBC | 1574 | 169 | detail::params_iter_impl(impl_), | 1574 | 169 | detail::params_iter_impl(impl_), | ||
| HITCBC | 1575 | 169 | detail::params_iter_impl(impl_, 0), | 1575 | 169 | detail::params_iter_impl(impl_, 0), | ||
| HITCBC | 1576 | 338 | detail::query_string_iter(s, true)); | 1576 | 338 | detail::query_string_iter(s, true)); | ||
| HITCBC | 1577 | 169 | return *this; | 1577 | 169 | return *this; | ||
| 1578 | } | 1578 | } | |||||
| 1579 | 1579 | |||||||
| 1580 | inline | 1580 | inline | |||||
| 1581 | url_base& | 1581 | url_base& | |||||
| HITCBC | 1582 | 179 | url_base:: | 1582 | 179 | url_base:: | ||
| 1583 | set_encoded_query( | 1583 | set_encoded_query( | |||||
| 1584 | pct_string_view s) | 1584 | pct_string_view s) | |||||
| 1585 | { | 1585 | { | |||||
| HITCBC | 1586 | 179 | op_t op(*this); | 1586 | 179 | op_t op(*this); | ||
| HITCBC | 1587 | 179 | std::size_t n = 0; // encoded size | 1587 | 179 | std::size_t n = 0; // encoded size | ||
| HITCBC | 1588 | 179 | std::size_t nparam = 1; // param count | 1588 | 179 | std::size_t nparam = 1; // param count | ||
| HITCBC | 1589 | 179 | auto const end = s.end(); | 1589 | 179 | auto const end = s.end(); | ||
| HITCBC | 1590 | 179 | auto p = s.begin(); | 1590 | 179 | auto p = s.begin(); | ||
| 1591 | 1591 | |||||||
| 1592 | // measure | 1592 | // measure | |||||
| HITCBC | 1593 | 742 | while(p != end) | 1593 | 742 | while(p != end) | ||
| 1594 | { | 1594 | { | |||||
| HITCBC | 1595 | 563 | if(*p == '&') | 1595 | 563 | if(*p == '&') | ||
| 1596 | { | 1596 | { | |||||
| HITCBC | 1597 | 4 | ++p; | 1597 | 4 | ++p; | ||
| HITCBC | 1598 | 4 | ++n; | 1598 | 4 | ++n; | ||
| HITCBC | 1599 | 4 | ++nparam; | 1599 | 4 | ++nparam; | ||
| 1600 | } | 1600 | } | |||||
| HITCBC | 1601 | 559 | else if(*p != '%') | 1601 | 559 | else if(*p != '%') | ||
| 1602 | { | 1602 | { | |||||
| HITCBC | 1603 | 533 | if(detail::query_chars(*p)) | 1603 | 533 | if(detail::query_chars(*p)) | ||
| HITCBC | 1604 | 518 | n += 1; // allowed | 1604 | 518 | n += 1; // allowed | ||
| 1605 | else | 1605 | else | |||||
| HITCBC | 1606 | 15 | n += 3; // escaped | 1606 | 15 | n += 3; // escaped | ||
| HITCBC | 1607 | 533 | ++p; | 1607 | 533 | ++p; | ||
| 1608 | } | 1608 | } | |||||
| 1609 | else | 1609 | else | |||||
| 1610 | { | 1610 | { | |||||
| 1611 | // escape | 1611 | // escape | |||||
| HITCBC | 1612 | 26 | n += 3; | 1612 | 26 | n += 3; | ||
| HITCBC | 1613 | 26 | p += 3; | 1613 | 26 | p += 3; | ||
| 1614 | } | 1614 | } | |||||
| 1615 | } | 1615 | } | |||||
| 1616 | 1616 | |||||||
| 1617 | // resize | 1617 | // resize | |||||
| HITCBC | 1618 | 179 | auto dest = resize_impl( | 1618 | 179 | auto dest = resize_impl( | ||
| HITCBC | 1619 | 179 | id_query, n + 1, op); | 1619 | 179 | id_query, n + 1, op); | ||
| HITCBC | 1620 | 179 | *dest++ = '?'; | 1620 | 179 | *dest++ = '?'; | ||
| 1621 | 1621 | |||||||
| 1622 | // encode | 1622 | // encode | |||||
| HITCBC | 1623 | 179 | impl_.decoded_[id_query] = | 1623 | 179 | impl_.decoded_[id_query] = | ||
| HITCBC | 1624 | 358 | detail::to_size_type(detail::re_encode_unsafe( | 1624 | 358 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 1625 | dest, | 1625 | dest, | |||||
| HITCBC | 1626 | 179 | dest + n, | 1626 | 179 | dest + n, | ||
| 1627 | s, | 1627 | s, | |||||
| 1628 | detail::query_chars)); | 1628 | detail::query_chars)); | |||||
| HITCBC | 1629 | 179 | BOOST_ASSERT( | 1629 | 179 | BOOST_ASSERT( | ||
| 1630 | impl_.decoded_[id_query] == | 1630 | impl_.decoded_[id_query] == | |||||
| 1631 | s.decoded_size()); | 1631 | s.decoded_size()); | |||||
| HITCBC | 1632 | 179 | impl_.nparam_ = | 1632 | 179 | impl_.nparam_ = | ||
| HITCBC | 1633 | 179 | detail::to_size_type(nparam); | 1633 | 179 | detail::to_size_type(nparam); | ||
| HITCBC | 1634 | 179 | return *this; | 1634 | 179 | return *this; | ||
| HITCBC | 1635 | 179 | } | 1635 | 179 | } | ||
| 1636 | 1636 | |||||||
| 1637 | inline | 1637 | inline | |||||
| 1638 | params_ref | 1638 | params_ref | |||||
| HITCBC | 1639 | 977 | url_base:: | 1639 | 986 | url_base:: | ||
| 1640 | params() noexcept | 1640 | params() noexcept | |||||
| 1641 | { | 1641 | { | |||||
| 1642 | return params_ref( | 1642 | return params_ref( | |||||
| 1643 | *this, | 1643 | *this, | |||||
| 1644 | encoding_opts{ | 1644 | encoding_opts{ | |||||
| HITCBC | 1645 | 977 | true, false, false}); | 1645 | 986 | true, false, false}); | ||
| 1646 | } | 1646 | } | |||||
| 1647 | 1647 | |||||||
| 1648 | inline | 1648 | inline | |||||
| 1649 | params_ref | 1649 | params_ref | |||||
| HITCBC | 1650 | 4 | url_base:: | 1650 | 4 | url_base:: | ||
| 1651 | params(encoding_opts opt) noexcept | 1651 | params(encoding_opts opt) noexcept | |||||
| 1652 | { | 1652 | { | |||||
| HITCBC | 1653 | 4 | return {*this, opt}; | 1653 | 4 | return {*this, opt}; | ||
| 1654 | } | 1654 | } | |||||
| 1655 | 1655 | |||||||
| 1656 | inline | 1656 | inline | |||||
| 1657 | params_encoded_ref | 1657 | params_encoded_ref | |||||
| HITCBC | 1658 | 77 | url_base:: | 1658 | 77 | url_base:: | ||
| 1659 | encoded_params() noexcept | 1659 | encoded_params() noexcept | |||||
| 1660 | { | 1660 | { | |||||
| HITCBC | 1661 | 77 | return {*this}; | 1661 | 77 | return {*this}; | ||
| 1662 | } | 1662 | } | |||||
| 1663 | 1663 | |||||||
| 1664 | inline | 1664 | inline | |||||
| 1665 | url_base& | 1665 | url_base& | |||||
| HITCBC | 1666 | 1 | url_base:: | 1666 | 1 | url_base:: | ||
| 1667 | set_params( | 1667 | set_params( | |||||
| 1668 | std::initializer_list<param_view> ps, | 1668 | std::initializer_list<param_view> ps, | |||||
| 1669 | encoding_opts opts) noexcept | 1669 | encoding_opts opts) noexcept | |||||
| 1670 | { | 1670 | { | |||||
| HITCBC | 1671 | 1 | params(opts).assign(ps); | 1671 | 1 | params(opts).assign(ps); | ||
| HITCBC | 1672 | 1 | return *this; | 1672 | 1 | return *this; | ||
| 1673 | } | 1673 | } | |||||
| 1674 | 1674 | |||||||
| 1675 | inline | 1675 | inline | |||||
| 1676 | url_base& | 1676 | url_base& | |||||
| HITCBC | 1677 | 1 | url_base:: | 1677 | 1 | url_base:: | ||
| 1678 | set_encoded_params( std::initializer_list< param_pct_view > ps ) noexcept | 1678 | set_encoded_params( std::initializer_list< param_pct_view > ps ) noexcept | |||||
| 1679 | { | 1679 | { | |||||
| HITCBC | 1680 | 1 | encoded_params().assign(ps); | 1680 | 1 | encoded_params().assign(ps); | ||
| HITCBC | 1681 | 1 | return *this; | 1681 | 1 | return *this; | ||
| 1682 | } | 1682 | } | |||||
| 1683 | 1683 | |||||||
| 1684 | inline | 1684 | inline | |||||
| 1685 | url_base& | 1685 | url_base& | |||||
| HITCBC | 1686 | 990 | url_base:: | 1686 | 990 | url_base:: | ||
| 1687 | remove_query() noexcept | 1687 | remove_query() noexcept | |||||
| 1688 | { | 1688 | { | |||||
| HITCBC | 1689 | 990 | op_t op(*this); | 1689 | 990 | op_t op(*this); | ||
| HITCBC | 1690 | 990 | resize_impl(id_query, 0, op); | 1690 | 990 | resize_impl(id_query, 0, op); | ||
| HITCBC | 1691 | 990 | impl_.nparam_ = 0; | 1691 | 990 | impl_.nparam_ = 0; | ||
| HITCBC | 1692 | 990 | impl_.decoded_[id_query] = 0; | 1692 | 990 | impl_.decoded_[id_query] = 0; | ||
| HITCBC | 1693 | 1980 | return *this; | 1693 | 1980 | return *this; | ||
| HITCBC | 1694 | 990 | } | 1694 | 990 | } | ||
| 1695 | 1695 | |||||||
| 1696 | //------------------------------------------------ | 1696 | //------------------------------------------------ | |||||
| 1697 | // | 1697 | // | |||||
| 1698 | // Fragment | 1698 | // Fragment | |||||
| 1699 | // | 1699 | // | |||||
| 1700 | //------------------------------------------------ | 1700 | //------------------------------------------------ | |||||
| 1701 | 1701 | |||||||
| 1702 | inline | 1702 | inline | |||||
| 1703 | url_base& | 1703 | url_base& | |||||
| HITCBC | 1704 | 407 | url_base:: | 1704 | 407 | url_base:: | ||
| 1705 | remove_fragment() noexcept | 1705 | remove_fragment() noexcept | |||||
| 1706 | { | 1706 | { | |||||
| HITCBC | 1707 | 407 | op_t op(*this); | 1707 | 407 | op_t op(*this); | ||
| HITCBC | 1708 | 407 | resize_impl(id_frag, 0, op); | 1708 | 407 | resize_impl(id_frag, 0, op); | ||
| HITCBC | 1709 | 407 | impl_.decoded_[id_frag] = 0; | 1709 | 407 | impl_.decoded_[id_frag] = 0; | ||
| HITCBC | 1710 | 814 | return *this; | 1710 | 814 | return *this; | ||
| HITCBC | 1711 | 407 | } | 1711 | 407 | } | ||
| 1712 | 1712 | |||||||
| 1713 | inline | 1713 | inline | |||||
| 1714 | url_base& | 1714 | url_base& | |||||
| HITCBC | 1715 | 151 | url_base:: | 1715 | 151 | url_base:: | ||
| 1716 | set_fragment(core::string_view s) | 1716 | set_fragment(core::string_view s) | |||||
| 1717 | { | 1717 | { | |||||
| HITCBC | 1718 | 151 | op_t op(*this, &s); | 1718 | 151 | op_t op(*this, &s); | ||
| HITCBC | 1719 | 151 | encoding_opts opt; | 1719 | 151 | encoding_opts opt; | ||
| HITCBC | 1720 | 151 | auto const n = encoded_size( | 1720 | 151 | auto const n = encoded_size( | ||
| 1721 | s, | 1721 | s, | |||||
| 1722 | detail::fragment_chars, | 1722 | detail::fragment_chars, | |||||
| 1723 | opt); | 1723 | opt); | |||||
| HITCBC | 1724 | 151 | auto dest = resize_impl( | 1724 | 151 | auto dest = resize_impl( | ||
| 1725 | id_frag, n + 1, op); | 1725 | id_frag, n + 1, op); | |||||
| HITCBC | 1726 | 151 | *dest++ = '#'; | 1726 | 151 | *dest++ = '#'; | ||
| HITCBC | 1727 | 151 | encode_unsafe( | 1727 | 151 | encode_unsafe( | ||
| 1728 | dest, | 1728 | dest, | |||||
| 1729 | n, | 1729 | n, | |||||
| 1730 | s, | 1730 | s, | |||||
| 1731 | detail::fragment_chars, | 1731 | detail::fragment_chars, | |||||
| 1732 | opt); | 1732 | opt); | |||||
| HITCBC | 1733 | 151 | impl_.decoded_[id_frag] = | 1733 | 151 | impl_.decoded_[id_frag] = | ||
| HITCBC | 1734 | 151 | detail::to_size_type(s.size()); | 1734 | 151 | detail::to_size_type(s.size()); | ||
| HITCBC | 1735 | 151 | return *this; | 1735 | 151 | return *this; | ||
| HITCBC | 1736 | 151 | } | 1736 | 151 | } | ||
| 1737 | 1737 | |||||||
| 1738 | inline | 1738 | inline | |||||
| 1739 | url_base& | 1739 | url_base& | |||||
| HITCBC | 1740 | 183 | url_base:: | 1740 | 183 | url_base:: | ||
| 1741 | set_encoded_fragment( | 1741 | set_encoded_fragment( | |||||
| 1742 | pct_string_view s) | 1742 | pct_string_view s) | |||||
| 1743 | { | 1743 | { | |||||
| HITCBC | 1744 | 183 | op_t op(*this, &detail::ref(s)); | 1744 | 183 | op_t op(*this, &detail::ref(s)); | ||
| 1745 | auto const n = | 1745 | auto const n = | |||||
| HITCBC | 1746 | 183 | detail::re_encoded_size_unsafe( | 1746 | 183 | detail::re_encoded_size_unsafe( | ||
| 1747 | s, | 1747 | s, | |||||
| 1748 | detail::fragment_chars); | 1748 | detail::fragment_chars); | |||||
| HITCBC | 1749 | 183 | auto dest = resize_impl( | 1749 | 183 | auto dest = resize_impl( | ||
| HITCBC | 1750 | 183 | id_frag, n + 1, op); | 1750 | 183 | id_frag, n + 1, op); | ||
| HITCBC | 1751 | 183 | *dest++ = '#'; | 1751 | 183 | *dest++ = '#'; | ||
| HITCBC | 1752 | 183 | impl_.decoded_[id_frag] = | 1752 | 183 | impl_.decoded_[id_frag] = | ||
| HITCBC | 1753 | 366 | detail::to_size_type(detail::re_encode_unsafe( | 1753 | 366 | detail::to_size_type(detail::re_encode_unsafe( | ||
| 1754 | dest, | 1754 | dest, | |||||
| HITCBC | 1755 | 183 | dest + n, | 1755 | 183 | dest + n, | ||
| 1756 | s, | 1756 | s, | |||||
| 1757 | detail::fragment_chars)); | 1757 | detail::fragment_chars)); | |||||
| HITCBC | 1758 | 183 | BOOST_ASSERT( | 1758 | 183 | BOOST_ASSERT( | ||
| 1759 | impl_.decoded_[id_frag] == | 1759 | impl_.decoded_[id_frag] == | |||||
| 1760 | s.decoded_size()); | 1760 | s.decoded_size()); | |||||
| HITCBC | 1761 | 183 | return *this; | 1761 | 183 | return *this; | ||
| HITCBC | 1762 | 183 | } | 1762 | 183 | } | ||
| 1763 | 1763 | |||||||
| 1764 | //------------------------------------------------ | 1764 | //------------------------------------------------ | |||||
| 1765 | // | 1765 | // | |||||
| 1766 | // Resolution | 1766 | // Resolution | |||||
| 1767 | // | 1767 | // | |||||
| 1768 | //------------------------------------------------ | 1768 | //------------------------------------------------ | |||||
| 1769 | 1769 | |||||||
| 1770 | inline | 1770 | inline | |||||
| 1771 | system::result<void> | 1771 | system::result<void> | |||||
| HITCBC | 1772 | 516 | url_base:: | 1772 | 516 | url_base:: | ||
| 1773 | resolve( | 1773 | resolve( | |||||
| 1774 | url_view_base const& ref) | 1774 | url_view_base const& ref) | |||||
| 1775 | { | 1775 | { | |||||
| HITCBC | 1776 | 516 | if(! has_scheme()) | 1776 | 516 | if(! has_scheme()) | ||
| 1777 | { | 1777 | { | |||||
| HITCBC | 1778 | 2 | BOOST_URL_RETURN_EC(error::not_a_base); | 1778 | 2 | BOOST_URL_RETURN_EC(error::not_a_base); | ||
| 1779 | } | 1779 | } | |||||
| 1780 | 1780 | |||||||
| HITCBC | 1781 | 514 | if (this == &ref) | 1781 | 514 | if (this == &ref) | ||
| 1782 | { | 1782 | { | |||||
| HITCBC | 1783 | 2 | normalize_path(); | 1783 | 2 | normalize_path(); | ||
| HITCBC | 1784 | 2 | return {}; | 1784 | 2 | return {}; | ||
| 1785 | } | 1785 | } | |||||
| 1786 | 1786 | |||||||
| HITCBC | 1787 | 512 | op_t op(*this); | 1787 | 512 | op_t op(*this); | ||
| 1788 | 1788 | |||||||
| 1789 | // | 1789 | // | |||||
| 1790 | // 5.2.2. Transform References | 1790 | // 5.2.2. Transform References | |||||
| 1791 | // https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.2 | 1791 | // https://datatracker.ietf.org/doc/html/rfc3986#section-5.2.2 | |||||
| 1792 | // | 1792 | // | |||||
| 1793 | 1793 | |||||||
| HITCBC | 1794 | 782 | if( ref.has_scheme() && | 1794 | 782 | if( ref.has_scheme() && | ||
| HITCBC | 1795 | 270 | ref.scheme() != scheme()) | 1795 | 270 | ref.scheme() != scheme()) | ||
| 1796 | { | 1796 | { | |||||
| HITCBC | 1797 | 202 | reserve_impl(ref.size(), op); | 1797 | 202 | reserve_impl(ref.size(), op); | ||
| HITCBC | 1798 | 202 | copy(ref); | 1798 | 202 | copy(ref); | ||
| HITCBC | 1799 | 202 | normalize_path(); | 1799 | 202 | normalize_path(); | ||
| HITCBC | 1800 | 202 | return {}; | 1800 | 202 | return {}; | ||
| 1801 | } | 1801 | } | |||||
| HITCBC | 1802 | 310 | if(ref.has_authority()) | 1802 | 310 | if(ref.has_authority()) | ||
| 1803 | { | 1803 | { | |||||
| HITCBC | 1804 | 78 | reserve_impl( | 1804 | 78 | reserve_impl( | ||
| HITCBC | 1805 | 78 | impl_.offset(id_user) + ref.size(), op); | 1805 | 78 | impl_.offset(id_user) + ref.size(), op); | ||
| HITCBC | 1806 | 78 | set_encoded_authority( | 1806 | 78 | set_encoded_authority( | ||
| 1807 | ref.encoded_authority()); | 1807 | ref.encoded_authority()); | |||||
| HITCBC | 1808 | 78 | set_encoded_path( | 1808 | 78 | set_encoded_path( | ||
| 1809 | ref.encoded_path()); | 1809 | ref.encoded_path()); | |||||
| HITCBC | 1810 | 78 | if (ref.encoded_path().empty()) | 1810 | 78 | if (ref.encoded_path().empty()) | ||
| HITCBC | 1811 | 33 | set_path_absolute(false); | 1811 | 33 | set_path_absolute(false); | ||
| 1812 | else | 1812 | else | |||||
| HITCBC | 1813 | 45 | normalize_path(); | 1813 | 45 | normalize_path(); | ||
| HITCBC | 1814 | 78 | if(ref.has_query()) | 1814 | 78 | if(ref.has_query()) | ||
| HITCBC | 1815 | 8 | set_encoded_query( | 1815 | 8 | set_encoded_query( | ||
| 1816 | ref.encoded_query()); | 1816 | ref.encoded_query()); | |||||
| 1817 | else | 1817 | else | |||||
| HITCBC | 1818 | 70 | remove_query(); | 1818 | 70 | remove_query(); | ||
| HITCBC | 1819 | 78 | if(ref.has_fragment()) | 1819 | 78 | if(ref.has_fragment()) | ||
| HITCBC | 1820 | 7 | set_encoded_fragment( | 1820 | 7 | set_encoded_fragment( | ||
| 1821 | ref.encoded_fragment()); | 1821 | ref.encoded_fragment()); | |||||
| 1822 | else | 1822 | else | |||||
| HITCBC | 1823 | 71 | remove_fragment(); | 1823 | 71 | remove_fragment(); | ||
| HITCBC | 1824 | 78 | return {}; | 1824 | 78 | return {}; | ||
| 1825 | } | 1825 | } | |||||
| HITCBC | 1826 | 232 | if(ref.encoded_path().empty()) | 1826 | 232 | if(ref.encoded_path().empty()) | ||
| 1827 | { | 1827 | { | |||||
| HITCBC | 1828 | 43 | reserve_impl( | 1828 | 43 | reserve_impl( | ||
| HITCBC | 1829 | 43 | impl_.offset(id_query) + | 1829 | 43 | impl_.offset(id_query) + | ||
| HITCBC | 1830 | 43 | ref.size(), op); | 1830 | 43 | ref.size(), op); | ||
| HITCBC | 1831 | 43 | normalize_path(); | 1831 | 43 | normalize_path(); | ||
| HITCBC | 1832 | 43 | if(ref.has_query()) | 1832 | 43 | if(ref.has_query()) | ||
| 1833 | { | 1833 | { | |||||
| HITCBC | 1834 | 12 | set_encoded_query( | 1834 | 12 | set_encoded_query( | ||
| 1835 | ref.encoded_query()); | 1835 | ref.encoded_query()); | |||||
| 1836 | } | 1836 | } | |||||
| HITCBC | 1837 | 43 | if(ref.has_fragment()) | 1837 | 43 | if(ref.has_fragment()) | ||
| HITCBC | 1838 | 20 | set_encoded_fragment( | 1838 | 20 | set_encoded_fragment( | ||
| 1839 | ref.encoded_fragment()); | 1839 | ref.encoded_fragment()); | |||||
| 1840 | else | 1840 | else | |||||
| HITCBC | 1841 | 23 | remove_fragment(); | 1841 | 23 | remove_fragment(); | ||
| HITCBC | 1842 | 43 | return {}; | 1842 | 43 | return {}; | ||
| 1843 | } | 1843 | } | |||||
| HITCBC | 1844 | 189 | if(ref.is_path_absolute()) | 1844 | 189 | if(ref.is_path_absolute()) | ||
| 1845 | { | 1845 | { | |||||
| HITCBC | 1846 | 41 | reserve_impl( | 1846 | 41 | reserve_impl( | ||
| HITCBC | 1847 | 41 | impl_.offset(id_path) + | 1847 | 41 | impl_.offset(id_path) + | ||
| HITCBC | 1848 | 41 | ref.size(), op); | 1848 | 41 | ref.size(), op); | ||
| HITCBC | 1849 | 41 | set_encoded_path( | 1849 | 41 | set_encoded_path( | ||
| 1850 | ref.encoded_path()); | 1850 | ref.encoded_path()); | |||||
| HITCBC | 1851 | 41 | normalize_path(); | 1851 | 41 | normalize_path(); | ||
| HITCBC | 1852 | 41 | if(ref.has_query()) | 1852 | 41 | if(ref.has_query()) | ||
| HITCBC | 1853 | 4 | set_encoded_query( | 1853 | 4 | set_encoded_query( | ||
| 1854 | ref.encoded_query()); | 1854 | ref.encoded_query()); | |||||
| 1855 | else | 1855 | else | |||||
| HITCBC | 1856 | 37 | remove_query(); | 1856 | 37 | remove_query(); | ||
| HITCBC | 1857 | 41 | if(ref.has_fragment()) | 1857 | 41 | if(ref.has_fragment()) | ||
| HITCBC | 1858 | 2 | set_encoded_fragment( | 1858 | 2 | set_encoded_fragment( | ||
| 1859 | ref.encoded_fragment()); | 1859 | ref.encoded_fragment()); | |||||
| 1860 | else | 1860 | else | |||||
| HITCBC | 1861 | 39 | remove_fragment(); | 1861 | 39 | remove_fragment(); | ||
| HITCBC | 1862 | 41 | return {}; | 1862 | 41 | return {}; | ||
| 1863 | } | 1863 | } | |||||
| 1864 | // General case: ref is relative path | 1864 | // General case: ref is relative path | |||||
| HITCBC | 1865 | 148 | reserve_impl( | 1865 | 148 | reserve_impl( | ||
| HITCBC | 1866 | 148 | impl_.offset(id_query) + | 1866 | 148 | impl_.offset(id_query) + | ||
| HITCBC | 1867 | 148 | ref.size(), op); | 1867 | 148 | ref.size(), op); | ||
| 1868 | // 5.2.3. Merge Paths | 1868 | // 5.2.3. Merge Paths | |||||
| HITCBC | 1869 | 148 | auto es = encoded_segments(); | 1869 | 148 | auto es = encoded_segments(); | ||
| HITCBC | 1870 | 148 | if(es.size() > 0) | 1870 | 148 | if(es.size() > 0) | ||
| 1871 | { | 1871 | { | |||||
| HITCBC | 1872 | 141 | es.pop_back(); | 1872 | 141 | es.pop_back(); | ||
| 1873 | } | 1873 | } | |||||
| HITCBC | 1874 | 296 | es.insert(es.end(), | 1874 | 296 | es.insert(es.end(), | ||
| HITCBC | 1875 | 148 | ref.encoded_segments().begin(), | 1875 | 148 | ref.encoded_segments().begin(), | ||
| HITCBC | 1876 | 148 | ref.encoded_segments().end()); | 1876 | 148 | ref.encoded_segments().end()); | ||
| HITCBC | 1877 | 148 | normalize_path(); | 1877 | 148 | normalize_path(); | ||
| HITCBC | 1878 | 148 | if(ref.has_query()) | 1878 | 148 | if(ref.has_query()) | ||
| HITCBC | 1879 | 10 | set_encoded_query( | 1879 | 10 | set_encoded_query( | ||
| 1880 | ref.encoded_query()); | 1880 | ref.encoded_query()); | |||||
| 1881 | else | 1881 | else | |||||
| HITCBC | 1882 | 138 | remove_query(); | 1882 | 138 | remove_query(); | ||
| HITCBC | 1883 | 148 | if(ref.has_fragment()) | 1883 | 148 | if(ref.has_fragment()) | ||
| HITCBC | 1884 | 13 | set_encoded_fragment( | 1884 | 13 | set_encoded_fragment( | ||
| 1885 | ref.encoded_fragment()); | 1885 | ref.encoded_fragment()); | |||||
| 1886 | else | 1886 | else | |||||
| HITCBC | 1887 | 135 | remove_fragment(); | 1887 | 135 | remove_fragment(); | ||
| HITCBC | 1888 | 148 | return {}; | 1888 | 148 | return {}; | ||
| HITCBC | 1889 | 512 | } | 1889 | 512 | } | ||
| 1890 | 1890 | |||||||
| 1891 | //------------------------------------------------ | 1891 | //------------------------------------------------ | |||||
| 1892 | // | 1892 | // | |||||
| 1893 | // Normalization | 1893 | // Normalization | |||||
| 1894 | // | 1894 | // | |||||
| 1895 | //------------------------------------------------ | 1895 | //------------------------------------------------ | |||||
| 1896 | 1896 | |||||||
| 1897 | template < | 1897 | template < | |||||
| 1898 | class AllowedCharset, | 1898 | class AllowedCharset, | |||||
| 1899 | class IgnoredCharset> | 1899 | class IgnoredCharset> | |||||
| 1900 | void | 1900 | void | |||||
| HITCBC | 1901 | 2975 | url_base:: | 1901 | 2975 | url_base:: | ||
| 1902 | normalize_octets_impl( | 1902 | normalize_octets_impl( | |||||
| 1903 | int id, | 1903 | int id, | |||||
| 1904 | AllowedCharset const& allowed, | 1904 | AllowedCharset const& allowed, | |||||
| 1905 | IgnoredCharset const& ignored, | 1905 | IgnoredCharset const& ignored, | |||||
| 1906 | op_t& op) noexcept | 1906 | op_t& op) noexcept | |||||
| 1907 | { | 1907 | { | |||||
| HITCBC | 1908 | 2975 | char* it = s_ + impl_.offset(id); | 1908 | 2975 | char* it = s_ + impl_.offset(id); | ||
| HITCBC | 1909 | 2975 | char* end = s_ + impl_.offset(id + 1); | 1909 | 2975 | char* end = s_ + impl_.offset(id + 1); | ||
| HITCBC | 1910 | 2975 | char d = 0; | 1910 | 2975 | char d = 0; | ||
| HITCBC | 1911 | 2975 | char* dest = it; | 1911 | 2975 | char* dest = it; | ||
| HITCBC | 1912 | 16442 | while (it < end) | 1912 | 16442 | while (it < end) | ||
| 1913 | { | 1913 | { | |||||
| HITCBC | 1914 | 13467 | if (*it != '%') | 1914 | 13467 | if (*it != '%') | ||
| 1915 | { | 1915 | { | |||||
| HITCBC | 1916 | 13249 | *dest = *it; | 1916 | 13249 | *dest = *it; | ||
| HITCBC | 1917 | 13249 | ++it; | 1917 | 13249 | ++it; | ||
| HITCBC | 1918 | 13249 | ++dest; | 1918 | 13249 | ++dest; | ||
| HITCBC | 1919 | 13249 | continue; | 1919 | 13249 | continue; | ||
| 1920 | } | 1920 | } | |||||
| HITCBC | 1921 | 218 | BOOST_ASSERT(end - it >= 3); | 1921 | 218 | BOOST_ASSERT(end - it >= 3); | ||
| 1922 | 1922 | |||||||
| 1923 | // decode unreserved octets | 1923 | // decode unreserved octets | |||||
| HITCBC | 1924 | 218 | d = detail::decode_one(it + 1); | 1924 | 218 | d = detail::decode_one(it + 1); | ||
| HITCBC | 1925 | 314 | if (allowed(d) && | 1925 | 314 | if (allowed(d) && | ||
| HITCBC | 1926 | 96 | !ignored(d)) | 1926 | 96 | !ignored(d)) | ||
| 1927 | { | 1927 | { | |||||
| HITCBC | 1928 | 87 | *dest = d; | 1928 | 87 | *dest = d; | ||
| HITCBC | 1929 | 87 | it += 3; | 1929 | 87 | it += 3; | ||
| HITCBC | 1930 | 87 | ++dest; | 1930 | 87 | ++dest; | ||
| HITCBC | 1931 | 87 | continue; | 1931 | 87 | continue; | ||
| 1932 | } | 1932 | } | |||||
| 1933 | 1933 | |||||||
| 1934 | // uppercase percent-encoding triplets | 1934 | // uppercase percent-encoding triplets | |||||
| HITCBC | 1935 | 131 | *dest++ = '%'; | 1935 | 131 | *dest++ = '%'; | ||
| HITCBC | 1936 | 131 | ++it; | 1936 | 131 | ++it; | ||
| HITCBC | 1937 | 131 | *dest++ = grammar::to_upper(*it++); | 1937 | 131 | *dest++ = grammar::to_upper(*it++); | ||
| HITCBC | 1938 | 131 | *dest++ = grammar::to_upper(*it++); | 1938 | 131 | *dest++ = grammar::to_upper(*it++); | ||
| 1939 | } | 1939 | } | |||||
| HITCBC | 1940 | 2975 | if (it != dest) | 1940 | 2975 | if (it != dest) | ||
| 1941 | { | 1941 | { | |||||
| HITCBC | 1942 | 35 | auto diff = it - dest; | 1942 | 35 | auto diff = it - dest; | ||
| HITCBC | 1943 | 35 | auto n = impl_.len(id) - diff; | 1943 | 35 | auto n = impl_.len(id) - diff; | ||
| HITCBC | 1944 | 35 | shrink_impl(id, n, op); | 1944 | 35 | shrink_impl(id, n, op); | ||
| HITCBC | 1945 | 35 | s_[size()] = '\0'; | 1945 | 35 | s_[size()] = '\0'; | ||
| 1946 | } | 1946 | } | |||||
| HITCBC | 1947 | 2975 | } | 1947 | 2975 | } | ||
| 1948 | 1948 | |||||||
| 1949 | template<class CharSet> | 1949 | template<class CharSet> | |||||
| 1950 | void | 1950 | void | |||||
| HITCBC | 1951 | 2757 | url_base:: | 1951 | 2757 | url_base:: | ||
| 1952 | normalize_octets_impl( | 1952 | normalize_octets_impl( | |||||
| 1953 | int idx, | 1953 | int idx, | |||||
| 1954 | CharSet const& allowed, | 1954 | CharSet const& allowed, | |||||
| 1955 | op_t& op) noexcept | 1955 | op_t& op) noexcept | |||||
| 1956 | { | 1956 | { | |||||
| HITCBC | 1957 | 2757 | return normalize_octets_impl( | 1957 | 2757 | return normalize_octets_impl( | ||
| HITCBC | 1958 | 2757 | idx, allowed, detail::empty_chars, op); | 1958 | 2757 | idx, allowed, detail::empty_chars, op); | ||
| 1959 | } | 1959 | } | |||||
| 1960 | 1960 | |||||||
| 1961 | inline | 1961 | inline | |||||
| 1962 | url_base& | 1962 | url_base& | |||||
| HITCBC | 1963 | 217 | url_base:: | 1963 | 217 | url_base:: | ||
| 1964 | normalize_scheme() | 1964 | normalize_scheme() | |||||
| 1965 | { | 1965 | { | |||||
| HITCBC | 1966 | 217 | to_lower_impl(id_scheme); | 1966 | 217 | to_lower_impl(id_scheme); | ||
| HITCBC | 1967 | 217 | return *this; | 1967 | 217 | return *this; | ||
| 1968 | } | 1968 | } | |||||
| 1969 | 1969 | |||||||
| 1970 | inline | 1970 | inline | |||||
| 1971 | url_base& | 1971 | url_base& | |||||
| HITCBC | 1972 | 563 | url_base:: | 1972 | 563 | url_base:: | ||
| 1973 | normalize_authority() | 1973 | normalize_authority() | |||||
| 1974 | { | 1974 | { | |||||
| HITCBC | 1975 | 563 | op_t op(*this); | 1975 | 563 | op_t op(*this); | ||
| 1976 | 1976 | |||||||
| 1977 | // normalize host | 1977 | // normalize host | |||||
| HITCBC | 1978 | 563 | if (host_type() == urls::host_type::name) | 1978 | 563 | if (host_type() == urls::host_type::name) | ||
| 1979 | { | 1979 | { | |||||
| HITCBC | 1980 | 351 | normalize_octets_impl( | 1980 | 351 | normalize_octets_impl( | ||
| 1981 | id_host, | 1981 | id_host, | |||||
| 1982 | detail::reg_name_chars, op); | 1982 | detail::reg_name_chars, op); | |||||
| 1983 | } | 1983 | } | |||||
| HITCBC | 1984 | 563 | decoded_to_lower_impl(id_host); | 1984 | 563 | decoded_to_lower_impl(id_host); | ||
| 1985 | 1985 | |||||||
| 1986 | // normalize password | 1986 | // normalize password | |||||
| HITCBC | 1987 | 563 | normalize_octets_impl(id_pass, detail::password_chars, op); | 1987 | 563 | normalize_octets_impl(id_pass, detail::password_chars, op); | ||
| 1988 | 1988 | |||||||
| 1989 | // normalize user | 1989 | // normalize user | |||||
| HITCBC | 1990 | 563 | normalize_octets_impl(id_user, detail::user_chars, op); | 1990 | 563 | normalize_octets_impl(id_user, detail::user_chars, op); | ||
| HITCBC | 1991 | 1126 | return *this; | 1991 | 1126 | return *this; | ||
| HITCBC | 1992 | 563 | } | 1992 | 563 | } | ||
| 1993 | 1993 | |||||||
| 1994 | inline | 1994 | inline | |||||
| 1995 | url_base& | 1995 | url_base& | |||||
| HITCBC | 1996 | 1065 | url_base:: | 1996 | 1065 | url_base:: | ||
| 1997 | normalize_path() | 1997 | normalize_path() | |||||
| 1998 | { | 1998 | { | |||||
| HITCBC | 1999 | 1065 | op_t op(*this); | 1999 | 1065 | op_t op(*this); | ||
| 2000 | 2000 | |||||||
| 2001 | // | 2001 | // | |||||
| 2002 | // Step 1: Percent-encoding normalization | 2002 | // Step 1: Percent-encoding normalization | |||||
| 2003 | // | 2003 | // | |||||
| 2004 | // Decode percent-encoded characters that are | 2004 | // Decode percent-encoded characters that are | |||||
| 2005 | // valid unencoded in path segments (pchar), | 2005 | // valid unencoded in path segments (pchar), | |||||
| 2006 | // and uppercase remaining hex digits. | 2006 | // and uppercase remaining hex digits. | |||||
| 2007 | // | 2007 | // | |||||
| 2008 | // This can introduce: | 2008 | // This can introduce: | |||||
| 2009 | // - New '.' from %2E (dot is unreserved) | 2009 | // - New '.' from %2E (dot is unreserved) | |||||
| 2010 | // - New ':' from %3A (colon is a pchar) | 2010 | // - New ':' from %3A (colon is a pchar) | |||||
| 2011 | // This cannot introduce: | 2011 | // This cannot introduce: | |||||
| 2012 | // - New '/' (%2F stays encoded, '/' is not | 2012 | // - New '/' (%2F stays encoded, '/' is not | |||||
| 2013 | // a segment character) | 2013 | // a segment character) | |||||
| 2014 | // | 2014 | // | |||||
| 2015 | // These new '.' and ':' characters can create | 2015 | // These new '.' and ':' characters can create | |||||
| 2016 | // ambiguities that Steps 2 and 3 must handle. | 2016 | // ambiguities that Steps 2 and 3 must handle. | |||||
| 2017 | // | 2017 | // | |||||
| HITCBC | 2018 | 1065 | normalize_octets_impl(id_path, detail::segment_chars, op); | 2018 | 1065 | normalize_octets_impl(id_path, detail::segment_chars, op); | ||
| HITCBC | 2019 | 1065 | core::string_view p = impl_.get(id_path); | 2019 | 1065 | core::string_view p = impl_.get(id_path); | ||
| HITCBC | 2020 | 1065 | char* p_dest = s_ + impl_.offset(id_path); | 2020 | 1065 | char* p_dest = s_ + impl_.offset(id_path); | ||
| HITCBC | 2021 | 1065 | char* p_end = s_ + impl_.offset(id_path + 1); | 2021 | 1065 | char* p_end = s_ + impl_.offset(id_path + 1); | ||
| HITCBC | 2022 | 1065 | auto pn = p.size(); | 2022 | 1065 | auto pn = p.size(); | ||
| 2023 | 2023 | |||||||
| 2024 | // | 2024 | // | |||||
| 2025 | // Step 2: Preserve existing path shields | 2025 | // Step 2: Preserve existing path shields | |||||
| 2026 | // | 2026 | // | |||||
| 2027 | // If the URL has no authority, a path starting | 2027 | // If the URL has no authority, a path starting | |||||
| 2028 | // with "//" would be misinterpreted as an | 2028 | // with "//" would be misinterpreted as an | |||||
| 2029 | // authority when serialized and re-parsed. | 2029 | // authority when serialized and re-parsed. | |||||
| 2030 | // Some paths already have a dot prefix ("/." | 2030 | // Some paths already have a dot prefix ("/." | |||||
| 2031 | // or "./") that shields against this. We | 2031 | // or "./") that shields against this. We | |||||
| 2032 | // preserve them so remove_dot_segments (Step 3) | 2032 | // preserve them so remove_dot_segments (Step 3) | |||||
| 2033 | // does not strip them. Step 1 can also reveal | 2033 | // does not strip them. Step 1 can also reveal | |||||
| 2034 | // new shields by decoding %2E to '.'. | 2034 | // new shields by decoding %2E to '.'. | |||||
| 2035 | // | 2035 | // | |||||
| 2036 | // This is an optimization. Step 4 would create | 2036 | // This is an optimization. Step 4 would create | |||||
| 2037 | // a new shield anyway if remove_dot_segments | 2037 | // a new shield anyway if remove_dot_segments | |||||
| 2038 | // produces a problematic output, but preserving | 2038 | // produces a problematic output, but preserving | |||||
| 2039 | // an existing shield avoids the memmove in | 2039 | // an existing shield avoids the memmove in | |||||
| 2040 | // Step 4. | 2040 | // Step 4. | |||||
| 2041 | // | 2041 | // | |||||
| 2042 | // path_shield_len: number of leading bytes | 2042 | // path_shield_len: number of leading bytes | |||||
| 2043 | // to skip during remove_dot_segments. | 2043 | // to skip during remove_dot_segments. | |||||
| 2044 | // Always 0 (no shield) or 2 ("/." or "./"). | 2044 | // Always 0 (no shield) or 2 ("/." or "./"). | |||||
| 2045 | // | 2045 | // | |||||
| HITCBC | 2046 | 1065 | auto path_shield_len = 0; | 2046 | 1065 | auto path_shield_len = 0; | ||
| HITCBC | 2047 | 1065 | if (!has_authority()) | 2047 | 1065 | if (!has_authority()) | ||
| 2048 | { | 2048 | { | |||||
| HITCBC | 2049 | 313 | if (p.starts_with("/./")) | 2049 | 313 | if (p.starts_with("/./")) | ||
| 2050 | { | 2050 | { | |||||
| 2051 | // (a) Absolute path with "/." prefix. | 2051 | // (a) Absolute path with "/." prefix. | |||||
| 2052 | // | 2052 | // | |||||
| 2053 | // Check if "/." shields a "//" | 2053 | // Check if "/." shields a "//" | |||||
| 2054 | // underneath (possibly through | 2054 | // underneath (possibly through | |||||
| 2055 | // multiple "/./" layers like "/././/"). | 2055 | // multiple "/./" layers like "/././/"). | |||||
| 2056 | // If so, preserve the first 2 chars. | 2056 | // If so, preserve the first 2 chars. | |||||
| 2057 | // | 2057 | // | |||||
| 2058 | // /.//evil -> /.//evil (preserved) | 2058 | // /.//evil -> /.//evil (preserved) | |||||
| 2059 | // Without it: //evil (ambiguous). | 2059 | // Without it: //evil (ambiguous). | |||||
| 2060 | // /././/evil -> /.//evil (same idea) | 2060 | // /././/evil -> /.//evil (same idea) | |||||
| 2061 | // | 2061 | // | |||||
| 2062 | // Requires no authority (with authority, | 2062 | // Requires no authority (with authority, | |||||
| 2063 | // "//" in the path is unambiguous): | 2063 | // "//" in the path is unambiguous): | |||||
| 2064 | // http://h/.//x -> http://h//x (OK) | 2064 | // http://h/.//x -> http://h//x (OK) | |||||
| 2065 | // Scheme is irrelevant (absolute paths | 2065 | // Scheme is irrelevant (absolute paths | |||||
| 2066 | // can't be confused with a scheme): | 2066 | // can't be confused with a scheme): | |||||
| 2067 | // scheme:/.//x and /.//x both need it. | 2067 | // scheme:/.//x and /.//x both need it. | |||||
| 2068 | // | 2068 | // | |||||
| HITCBC | 2069 | 18 | path_shield_len = 2; | 2069 | 18 | path_shield_len = 2; | ||
| HITCBC | 2070 | 19 | while (p.substr(path_shield_len, 3).starts_with("/./")) | 2070 | 19 | while (p.substr(path_shield_len, 3).starts_with("/./")) | ||
| 2071 | { | 2071 | { | |||||
| HITCBC | 2072 | 1 | path_shield_len += 2; | 2072 | 1 | path_shield_len += 2; | ||
| 2073 | } | 2073 | } | |||||
| HITCBC | 2074 | 18 | if (p.substr(path_shield_len).starts_with("//")) | 2074 | 18 | if (p.substr(path_shield_len).starts_with("//")) | ||
| 2075 | { | 2075 | { | |||||
| HITCBC | 2076 | 15 | path_shield_len = 2; | 2076 | 15 | path_shield_len = 2; | ||
| 2077 | } | 2077 | } | |||||
| 2078 | else | 2078 | else | |||||
| 2079 | { | 2079 | { | |||||
| HITCBC | 2080 | 3 | path_shield_len = 0; | 2080 | 3 | path_shield_len = 0; | ||
| 2081 | } | 2081 | } | |||||
| 2082 | } | 2082 | } | |||||
| HITCBC | 2083 | 295 | else if ( | 2083 | 295 | else if ( | ||
| HITCBC | 2084 | 349 | !has_scheme() && | 2084 | 349 | !has_scheme() && | ||
| HITCBC | 2085 | 54 | p.starts_with("./")) | 2085 | 54 | p.starts_with("./")) | ||
| 2086 | { | 2086 | { | |||||
| 2087 | // (b) Relative path with "./" prefix, | 2087 | // (b) Relative path with "./" prefix, | |||||
| 2088 | // no scheme. | 2088 | // no scheme. | |||||
| 2089 | // | 2089 | // | |||||
| 2090 | // Check if "./" shields a "//" | 2090 | // Check if "./" shields a "//" | |||||
| 2091 | // underneath. If so, preserve it. | 2091 | // underneath. If so, preserve it. | |||||
| 2092 | // | 2092 | // | |||||
| 2093 | // .//evil -> .//evil (preserved) | 2093 | // .//evil -> .//evil (preserved) | |||||
| 2094 | // Without it: //evil (ambiguous). | 2094 | // Without it: //evil (ambiguous). | |||||
| 2095 | // ././/evil -> .//evil (same idea) | 2095 | // ././/evil -> .//evil (same idea) | |||||
| 2096 | // | 2096 | // | |||||
| 2097 | // Requires no authority (with authority, | 2097 | // Requires no authority (with authority, | |||||
| 2098 | // "//" in the path is unambiguous): | 2098 | // "//" in the path is unambiguous): | |||||
| 2099 | // //h/.//x -> //h//x (OK) | 2099 | // //h/.//x -> //h//x (OK) | |||||
| 2100 | // Requires no scheme: with a scheme, | 2100 | // Requires no scheme: with a scheme, | |||||
| 2101 | // remove_dot_segments would strip "./" | 2101 | // remove_dot_segments would strip "./" | |||||
| 2102 | // and Step 4 handles any resulting "//". | 2102 | // and Step 4 handles any resulting "//". | |||||
| 2103 | // | 2103 | // | |||||
| HITCBC | 2104 | 12 | path_shield_len = 1; | 2104 | 12 | path_shield_len = 1; | ||
| HITCBC | 2105 | 16 | while (p.substr(path_shield_len, 3).starts_with("/./")) | 2105 | 16 | while (p.substr(path_shield_len, 3).starts_with("/./")) | ||
| 2106 | { | 2106 | { | |||||
| HITCBC | 2107 | 4 | path_shield_len += 2; | 2107 | 4 | path_shield_len += 2; | ||
| 2108 | } | 2108 | } | |||||
| HITCBC | 2109 | 12 | if (p.substr(path_shield_len).starts_with("//")) | 2109 | 12 | if (p.substr(path_shield_len).starts_with("//")) | ||
| 2110 | { | 2110 | { | |||||
| HITCBC | 2111 | 4 | path_shield_len = 2; | 2111 | 4 | path_shield_len = 2; | ||
| 2112 | } | 2112 | } | |||||
| 2113 | else | 2113 | else | |||||
| 2114 | { | 2114 | { | |||||
| HITCBC | 2115 | 8 | path_shield_len = 0; | 2115 | 8 | path_shield_len = 0; | ||
| 2116 | } | 2116 | } | |||||
| 2117 | } | 2117 | } | |||||
| 2118 | } | 2118 | } | |||||
| 2119 | 2119 | |||||||
| 2120 | // | 2120 | // | |||||
| 2121 | // Step 3: Remove "." and ".." segments | 2121 | // Step 3: Remove "." and ".." segments | |||||
| 2122 | // | 2122 | // | |||||
| 2123 | // RFC 3986 Section 5.2.4. | 2123 | // RFC 3986 Section 5.2.4. | |||||
| 2124 | // | 2124 | // | |||||
| 2125 | // If path_shield_len > 0, the first | 2125 | // If path_shield_len > 0, the first | |||||
| 2126 | // path_shield_len characters are an existing | 2126 | // path_shield_len characters are an existing | |||||
| 2127 | // path shield ("/." or "./") that must | 2127 | // path shield ("/." or "./") that must | |||||
| 2128 | // be preserved (see Step 2), we tell | 2128 | // be preserved (see Step 2), we tell | |||||
| 2129 | // remove_dot_segments to start after that | 2129 | // remove_dot_segments to start after that | |||||
| 2130 | // prefix. | 2130 | // prefix. | |||||
| 2131 | // | 2131 | // | |||||
| 2132 | // Note: remove_dot_segments only recognizes | 2132 | // Note: remove_dot_segments only recognizes | |||||
| 2133 | // literal '.' and '..', not encoded forms like | 2133 | // literal '.' and '..', not encoded forms like | |||||
| 2134 | // '%2E'. This is correct here because Step 1 | 2134 | // '%2E'. This is correct here because Step 1 | |||||
| 2135 | // already decoded %2E to '.'. If this function | 2135 | // already decoded %2E to '.'. If this function | |||||
| 2136 | // were called without Step 1, encoded dots | 2136 | // were called without Step 1, encoded dots | |||||
| 2137 | // would be missed. | 2137 | // would be missed. | |||||
| 2138 | // | 2138 | // | |||||
| HITCBC | 2139 | 1065 | bool was_absolute = is_path_absolute(); | 2139 | 1065 | bool was_absolute = is_path_absolute(); | ||
| HITCBC | 2140 | 1065 | p.remove_prefix(path_shield_len); | 2140 | 1065 | p.remove_prefix(path_shield_len); | ||
| HITCBC | 2141 | 1065 | p_dest += path_shield_len; | 2141 | 1065 | p_dest += path_shield_len; | ||
| HITCBC | 2142 | 1065 | auto n = detail::remove_dot_segments( | 2142 | 1065 | auto n = detail::remove_dot_segments( | ||
| HITCBC | 2143 | 1065 | p_dest, p_end, p); | 2143 | 1065 | p_dest, p_end, p); | ||
| 2144 | 2144 | |||||||
| 2145 | // | 2145 | // | |||||
| 2146 | // Step 4: Create path shield if needed, | 2146 | // Step 4: Create path shield if needed, | |||||
| 2147 | // then shrink path to final size | 2147 | // then shrink path to final size | |||||
| 2148 | // | 2148 | // | |||||
| 2149 | // remove_dot_segments can produce output that | 2149 | // remove_dot_segments can produce output that | |||||
| 2150 | // needs a 2-byte shield prefix, as explained | 2150 | // needs a 2-byte shield prefix, as explained | |||||
| 2151 | // in step 2. The memmove below writes within | 2151 | // in step 2. The memmove below writes within | |||||
| 2152 | // the original path region (before shrink_impl) | 2152 | // the original path region (before shrink_impl) | |||||
| 2153 | // and always has room because ".." cancellation | 2153 | // and always has room because ".." cancellation | |||||
| 2154 | // consumes >= 5 bytes but we only need 2 for the | 2154 | // consumes >= 5 bytes but we only need 2 for the | |||||
| 2155 | // shield. | 2155 | // shield. | |||||
| 2156 | // | 2156 | // | |||||
| HITCBC | 2157 | 3195 | bool needs_shield = [&]() | 2157 | 3195 | bool needs_shield = [&]() | ||
| 2158 | { | 2158 | { | |||||
| HITCBC | 2159 | 1065 | if (path_shield_len) | 2159 | 1065 | if (path_shield_len) | ||
| 2160 | { | 2160 | { | |||||
| 2161 | // Step 2 already preserved a shield. | 2161 | // Step 2 already preserved a shield. | |||||
| HITCBC | 2162 | 19 | return false; | 2162 | 19 | return false; | ||
| 2163 | } | 2163 | } | |||||
| HITCBC | 2164 | 1046 | if (has_authority()) | 2164 | 1046 | if (has_authority()) | ||
| 2165 | { | 2165 | { | |||||
| 2166 | // With an authority, "//" in the path | 2166 | // With an authority, "//" in the path | |||||
| 2167 | // is unambiguous and the path is always | 2167 | // is unambiguous and the path is always | |||||
| 2168 | // absolute (path-abempty). | 2168 | // absolute (path-abempty). | |||||
| HITCBC | 2169 | 752 | return false; | 2169 | 752 | return false; | ||
| 2170 | } | 2170 | } | |||||
| HITCBC | 2171 | 294 | if (n == 0) | 2171 | 294 | if (n == 0) | ||
| 2172 | { | 2172 | { | |||||
| 2173 | // Empty output. Nothing to shield. | 2173 | // Empty output. Nothing to shield. | |||||
| HITCBC | 2174 | 28 | return false; | 2174 | 28 | return false; | ||
| 2175 | } | 2175 | } | |||||
| HITCBC | 2176 | 266 | if (p_dest[0] != '/') | 2176 | 266 | if (p_dest[0] != '/') | ||
| 2177 | { | 2177 | { | |||||
| 2178 | // Output doesn't start with '/'. | 2178 | // Output doesn't start with '/'. | |||||
| 2179 | // No authority ambiguity, and if it | 2179 | // No authority ambiguity, and if it | |||||
| 2180 | // was relative, it stayed relative. | 2180 | // was relative, it stayed relative. | |||||
| HITCBC | 2181 | 129 | return false; | 2181 | 129 | return false; | ||
| 2182 | } | 2182 | } | |||||
| HITCBC | 2183 | 137 | if (n >= 2 && p_dest[1] == '/') | 2183 | 137 | if (n >= 2 && p_dest[1] == '/') | ||
| 2184 | { | 2184 | { | |||||
| 2185 | // Output starts with "//": would be | 2185 | // Output starts with "//": would be | |||||
| 2186 | // misinterpreted as authority. | 2186 | // misinterpreted as authority. | |||||
| 2187 | // /a/..//evil -> //evil | 2187 | // /a/..//evil -> //evil | |||||
| 2188 | // so we need a shield | 2188 | // so we need a shield | |||||
| 2189 | // /a/..//evil -> /.//evil | 2189 | // /a/..//evil -> /.//evil | |||||
| HITCBC | 2190 | 7 | return true; | 2190 | 7 | return true; | ||
| 2191 | } | 2191 | } | |||||
| HITCBC | 2192 | 130 | if (!was_absolute) | 2192 | 130 | if (!was_absolute) | ||
| 2193 | { | 2193 | { | |||||
| 2194 | // Relative path became absolute: ".." | 2194 | // Relative path became absolute: ".." | |||||
| 2195 | // canceled all leading segments and | 2195 | // canceled all leading segments and | |||||
| 2196 | // the remaining input started with "/" | 2196 | // the remaining input started with "/" | |||||
| 2197 | // because of how remove_dot_segments is | 2197 | // because of how remove_dot_segments is | |||||
| 2198 | // defined. | 2198 | // defined. | |||||
| 2199 | // a/..//evil -> /evil -> .//evil | 2199 | // a/..//evil -> /evil -> .//evil | |||||
| 2200 | // a/b/../..//evil -> /evil -> .//evil | 2200 | // a/b/../..//evil -> /evil -> .//evil | |||||
| HITCBC | 2201 | 5 | return true; | 2201 | 5 | return true; | ||
| 2202 | } | 2202 | } | |||||
| HITCBC | 2203 | 125 | return false; | 2203 | 125 | return false; | ||
| HITCBC | 2204 | 1065 | }(); | 2204 | 1065 | }(); | ||
| HITCBC | 2205 | 1065 | if (needs_shield) | 2205 | 1065 | if (needs_shield) | ||
| 2206 | { | 2206 | { | |||||
| HITCBC | 2207 | 12 | BOOST_ASSERT(n + 2 <= pn); | 2207 | 12 | BOOST_ASSERT(n + 2 <= pn); | ||
| HITCBC | 2208 | 12 | std::memmove(p_dest + 2, p_dest, n); | 2208 | 12 | std::memmove(p_dest + 2, p_dest, n); | ||
| HITCBC | 2209 | 12 | if (was_absolute) | 2209 | 12 | if (was_absolute) | ||
| 2210 | { | 2210 | { | |||||
| 2211 | // "/." keeps the path absolute. | 2211 | // "/." keeps the path absolute. | |||||
| HITCBC | 2212 | 7 | p_dest[0] = '/'; | 2212 | 7 | p_dest[0] = '/'; | ||
| HITCBC | 2213 | 7 | p_dest[1] = '.'; | 2213 | 7 | p_dest[1] = '.'; | ||
| 2214 | } | 2214 | } | |||||
| 2215 | else | 2215 | else | |||||
| 2216 | { | 2216 | { | |||||
| 2217 | // "./" keeps the path relative. | 2217 | // "./" keeps the path relative. | |||||
| HITCBC | 2218 | 5 | p_dest[0] = '.'; | 2218 | 5 | p_dest[0] = '.'; | ||
| HITCBC | 2219 | 5 | p_dest[1] = '/'; | 2219 | 5 | p_dest[1] = '/'; | ||
| 2220 | } | 2220 | } | |||||
| HITCBC | 2221 | 12 | path_shield_len = 2; | 2221 | 12 | path_shield_len = 2; | ||
| 2222 | } | 2222 | } | |||||
| HITCBC | 2223 | 1065 | if (n != pn) | 2223 | 1065 | if (n != pn) | ||
| 2224 | { | 2224 | { | |||||
| HITCBC | 2225 | 163 | BOOST_ASSERT(n < pn); | 2225 | 163 | BOOST_ASSERT(n < pn); | ||
| HITCBC | 2226 | 163 | shrink_impl(id_path, n + path_shield_len, op); | 2226 | 163 | shrink_impl(id_path, n + path_shield_len, op); | ||
| 2227 | } | 2227 | } | |||||
| 2228 | 2228 | |||||||
| 2229 | // | 2229 | // | |||||
| 2230 | // Step 5: Encode colons in first segment | 2230 | // Step 5: Encode colons in first segment | |||||
| 2231 | // | 2231 | // | |||||
| 2232 | // If the URL has no scheme and no authority, | 2232 | // If the URL has no scheme and no authority, | |||||
| 2233 | // a colon in the first path segment would be | 2233 | // a colon in the first path segment would be | |||||
| 2234 | // misinterpreted as a scheme delimiter when | 2234 | // misinterpreted as a scheme delimiter when | |||||
| 2235 | // serialized and re-parsed. | 2235 | // serialized and re-parsed. | |||||
| 2236 | // | 2236 | // | |||||
| 2237 | // Colons can appear in the first segment either | 2237 | // Colons can appear in the first segment either | |||||
| 2238 | // because they were already there (decoded from | 2238 | // because they were already there (decoded from | |||||
| 2239 | // %3A in Step 1), or because remove_dot_segments | 2239 | // %3A in Step 1), or because remove_dot_segments | |||||
| 2240 | // (Step 3) canceled preceding segments via ".." | 2240 | // (Step 3) canceled preceding segments via ".." | |||||
| 2241 | // and exposed a colon that was deeper in the path. | 2241 | // and exposed a colon that was deeper in the path. | |||||
| 2242 | // | 2242 | // | |||||
| 2243 | // Example (pre-existing): | 2243 | // Example (pre-existing): | |||||
| 2244 | // my%3Asharona -> Step 1: my:sharona | 2244 | // my%3Asharona -> Step 1: my:sharona | |||||
| 2245 | // -> Step 5: my%3Asharona | 2245 | // -> Step 5: my%3Asharona | |||||
| 2246 | // Example (exposed by dot removal): | 2246 | // Example (exposed by dot removal): | |||||
| 2247 | // a/../b:c -> Step 3: b:c | 2247 | // a/../b:c -> Step 3: b:c | |||||
| 2248 | // -> Step 5: b%3Ac | 2248 | // -> Step 5: b%3Ac | |||||
| 2249 | // | 2249 | // | |||||
| 2250 | // ALL colons in the first segment must be | 2250 | // ALL colons in the first segment must be | |||||
| 2251 | // encoded, not just the first one. In a | 2251 | // encoded, not just the first one. In a | |||||
| 2252 | // schemeless relative-reference, the first | 2252 | // schemeless relative-reference, the first | |||||
| 2253 | // segment must be segment-nz-nc (RFC 3986 | 2253 | // segment must be segment-nz-nc (RFC 3986 | |||||
| 2254 | // Section 4.2), which does not allow ':': | 2254 | // Section 4.2), which does not allow ':': | |||||
| 2255 | // path-noscheme = segment-nz-nc *( "/" segment ) | 2255 | // path-noscheme = segment-nz-nc *( "/" segment ) | |||||
| 2256 | // segment-nz-nc = 1*( unreserved / pct-encoded | 2256 | // segment-nz-nc = 1*( unreserved / pct-encoded | |||||
| 2257 | // / sub-delims / "@" ) | 2257 | // / sub-delims / "@" ) | |||||
| 2258 | // So "b%3Ac:d" would fail to re-parse. | 2258 | // So "b%3Ac:d" would fail to re-parse. | |||||
| 2259 | // All colons must go: "b%3Ac%3Ad". | 2259 | // All colons must go: "b%3Ac%3Ad". | |||||
| 2260 | // | 2260 | // | |||||
| 2261 | // Requires no scheme (with a scheme, colons | 2261 | // Requires no scheme (with a scheme, colons | |||||
| 2262 | // in the path are unambiguous): | 2262 | // in the path are unambiguous): | |||||
| 2263 | // scheme:a:b -> scheme:a:b (OK) | 2263 | // scheme:a:b -> scheme:a:b (OK) | |||||
| 2264 | // Requires no authority (with authority, | 2264 | // Requires no authority (with authority, | |||||
| 2265 | // path starts with "/" so the first segment | 2265 | // path starts with "/" so the first segment | |||||
| 2266 | // is empty, no colon issue). | 2266 | // is empty, no colon issue). | |||||
| 2267 | // | 2267 | // | |||||
| HITCBC | 2268 | 1142 | if (!has_scheme() && | 2268 | 1142 | if (!has_scheme() && | ||
| HITCBC | 2269 | 77 | !has_authority()) | 2269 | 77 | !has_authority()) | ||
| 2270 | { | 2270 | { | |||||
| HITCBC | 2271 | 58 | p = impl_.get(id_path); | 2271 | 58 | p = impl_.get(id_path); | ||
| HITCBC | 2272 | 58 | core::string_view first_seg = p; | 2272 | 58 | core::string_view first_seg = p; | ||
| HITCBC | 2273 | 58 | auto i = first_seg.find('/'); | 2273 | 58 | auto i = first_seg.find('/'); | ||
| HITCBC | 2274 | 58 | if (i != core::string_view::npos) | 2274 | 58 | if (i != core::string_view::npos) | ||
| 2275 | { | 2275 | { | |||||
| HITCBC | 2276 | 28 | first_seg = p.substr(0, i); | 2276 | 28 | first_seg = p.substr(0, i); | ||
| 2277 | } | 2277 | } | |||||
| HITCBC | 2278 | 58 | if (first_seg.contains(':')) | 2278 | 58 | if (first_seg.contains(':')) | ||
| 2279 | { | 2279 | { | |||||
| HITCBC | 2280 | 13 | pn = p.size(); | 2280 | 13 | pn = p.size(); | ||
| 2281 | auto cn = | 2281 | auto cn = | |||||
| HITCBC | 2282 | 13 | std::count( | 2282 | 13 | std::count( | ||
| 2283 | first_seg.begin(), | 2283 | first_seg.begin(), | |||||
| 2284 | first_seg.end(), | 2284 | first_seg.end(), | |||||
| HITCBC | 2285 | 13 | ':'); | 2285 | 13 | ':'); | ||
| HITCBC | 2286 | 13 | resize_impl( | 2286 | 13 | resize_impl( | ||
| HITCBC | 2287 | 13 | id_path, pn + (2 * cn), op); | 2287 | 13 | id_path, pn + (2 * cn), op); | ||
| HITCBC | 2288 | 13 | auto begin = s_ + impl_.offset(id_path); | 2288 | 13 | auto begin = s_ + impl_.offset(id_path); | ||
| HITCBC | 2289 | 13 | auto it = begin; | 2289 | 13 | auto it = begin; | ||
| HITCBC | 2290 | 13 | auto end = begin + pn; | 2290 | 13 | auto end = begin + pn; | ||
| HITCBC | 2291 | 103 | while (it != end && | 2291 | 103 | while (it != end && | ||
| HITCBC | 2292 | 91 | *it != '/') | 2292 | 91 | *it != '/') | ||
| 2293 | { | 2293 | { | |||||
| HITCBC | 2294 | 90 | ++it; | 2294 | 90 | ++it; | ||
| 2295 | } | 2295 | } | |||||
| HITCBC | 2296 | 13 | std::memmove(it + (2 * cn), it, end - it); | 2296 | 13 | std::memmove(it + (2 * cn), it, end - it); | ||
| HITCBC | 2297 | 13 | auto src = s_ + impl_.offset(id_path) + pn; | 2297 | 13 | auto src = s_ + impl_.offset(id_path) + pn; | ||
| HITCBC | 2298 | 13 | auto dest = s_ + impl_.offset(id_query); | 2298 | 13 | auto dest = s_ + impl_.offset(id_query); | ||
| HITCBC | 2299 | 13 | src -= end - it; | 2299 | 13 | src -= end - it; | ||
| HITCBC | 2300 | 13 | dest -= end - it; | 2300 | 13 | dest -= end - it; | ||
| HITCBC | 2301 | 13 | pn -= end - it; | 2301 | 13 | pn -= end - it; | ||
| 2302 | do { | 2302 | do { | |||||
| HITCBC | 2303 | 90 | --src; | 2303 | 90 | --src; | ||
| HITCBC | 2304 | 90 | --dest; | 2304 | 90 | --dest; | ||
| HITCBC | 2305 | 90 | if (*src != ':') | 2305 | 90 | if (*src != ':') | ||
| 2306 | { | 2306 | { | |||||
| HITCBC | 2307 | 65 | *dest = *src; | 2307 | 65 | *dest = *src; | ||
| 2308 | } | 2308 | } | |||||
| 2309 | else | 2309 | else | |||||
| 2310 | { | 2310 | { | |||||
| HITCBC | 2311 | 25 | *dest-- = 'A'; | 2311 | 25 | *dest-- = 'A'; | ||
| HITCBC | 2312 | 25 | *dest-- = '3'; | 2312 | 25 | *dest-- = '3'; | ||
| HITCBC | 2313 | 25 | *dest = '%'; | 2313 | 25 | *dest = '%'; | ||
| 2314 | } | 2314 | } | |||||
| HITCBC | 2315 | 90 | --pn; | 2315 | 90 | --pn; | ||
| HITCBC | 2316 | 90 | } while (pn); | 2316 | 90 | } while (pn); | ||
| 2317 | } | 2317 | } | |||||
| 2318 | } | 2318 | } | |||||
| 2319 | 2319 | |||||||
| 2320 | // | 2320 | // | |||||
| 2321 | // Step 6: Update path parameters | 2321 | // Step 6: Update path parameters | |||||
| 2322 | // | 2322 | // | |||||
| 2323 | { | 2323 | { | |||||
| HITCBC | 2324 | 1065 | p = encoded_path(); | 2324 | 1065 | p = encoded_path(); | ||
| HITCBC | 2325 | 1065 | if (p == "/") | 2325 | 1065 | if (p == "/") | ||
| 2326 | { | 2326 | { | |||||
| HITCBC | 2327 | 126 | impl_.nseg_ = 0; | 2327 | 126 | impl_.nseg_ = 0; | ||
| 2328 | } | 2328 | } | |||||
| HITCBC | 2329 | 939 | else if (!p.empty()) | 2329 | 939 | else if (!p.empty()) | ||
| 2330 | { | 2330 | { | |||||
| HITCBC | 2331 | 1622 | impl_.nseg_ = detail::to_size_type( | 2331 | 1622 | impl_.nseg_ = detail::to_size_type( | ||
| HITCBC | 2332 | 811 | std::count( | 2332 | 811 | std::count( | ||
| HITCBC | 2333 | 1622 | p.begin() + 1, p.end(), '/') + 1); | 2333 | 1622 | p.begin() + 1, p.end(), '/') + 1); | ||
| 2334 | } | 2334 | } | |||||
| 2335 | else | 2335 | else | |||||
| 2336 | { | 2336 | { | |||||
| HITCBC | 2337 | 128 | impl_.nseg_ = 0; | 2337 | 128 | impl_.nseg_ = 0; | ||
| 2338 | } | 2338 | } | |||||
| HITCBC | 2339 | 1065 | impl_.decoded_[id_path] = | 2339 | 1065 | impl_.decoded_[id_path] = | ||
| HITCBC | 2340 | 1065 | detail::to_size_type(detail::decode_bytes_unsafe( | 2340 | 1065 | detail::to_size_type(detail::decode_bytes_unsafe( | ||
| 2341 | impl_.get(id_path))); | 2341 | impl_.get(id_path))); | |||||
| 2342 | } | 2342 | } | |||||
| HITCBC | 2343 | 1065 | return *this; | 2343 | 1065 | return *this; | ||
| HITCBC | 2344 | 1065 | } | 2344 | 1065 | } | ||
| 2345 | 2345 | |||||||
| 2346 | inline | 2346 | inline | |||||
| 2347 | url_base& | 2347 | url_base& | |||||
| HITCBC | 2348 | 218 | url_base:: | 2348 | 218 | url_base:: | ||
| 2349 | normalize_query() | 2349 | normalize_query() | |||||
| 2350 | { | 2350 | { | |||||
| HITCBC | 2351 | 218 | op_t op(*this); | 2351 | 218 | op_t op(*this); | ||
| HITCBC | 2352 | 218 | normalize_octets_impl( | 2352 | 218 | normalize_octets_impl( | ||
| 2353 | id_query, | 2353 | id_query, | |||||
| 2354 | detail::query_chars, | 2354 | detail::query_chars, | |||||
| 2355 | detail::query_ignore_chars, | 2355 | detail::query_ignore_chars, | |||||
| 2356 | op); | 2356 | op); | |||||
| HITCBC | 2357 | 436 | return *this; | 2357 | 436 | return *this; | ||
| HITCBC | 2358 | 218 | } | 2358 | 218 | } | ||
| 2359 | 2359 | |||||||
| 2360 | inline | 2360 | inline | |||||
| 2361 | url_base& | 2361 | url_base& | |||||
| HITCBC | 2362 | 215 | url_base:: | 2362 | 215 | url_base:: | ||
| 2363 | normalize_fragment() | 2363 | normalize_fragment() | |||||
| 2364 | { | 2364 | { | |||||
| HITCBC | 2365 | 215 | op_t op(*this); | 2365 | 215 | op_t op(*this); | ||
| HITCBC | 2366 | 215 | normalize_octets_impl( | 2366 | 215 | normalize_octets_impl( | ||
| 2367 | id_frag, detail::fragment_chars, op); | 2367 | id_frag, detail::fragment_chars, op); | |||||
| HITCBC | 2368 | 430 | return *this; | 2368 | 430 | return *this; | ||
| HITCBC | 2369 | 215 | } | 2369 | 215 | } | ||
| 2370 | 2370 | |||||||
| 2371 | inline | 2371 | inline | |||||
| 2372 | url_base& | 2372 | url_base& | |||||
| HITCBC | 2373 | 214 | url_base:: | 2373 | 214 | url_base:: | ||
| 2374 | normalize() | 2374 | normalize() | |||||
| 2375 | { | 2375 | { | |||||
| HITCBC | 2376 | 214 | normalize_fragment(); | 2376 | 214 | normalize_fragment(); | ||
| HITCBC | 2377 | 214 | normalize_query(); | 2377 | 214 | normalize_query(); | ||
| HITCBC | 2378 | 214 | normalize_path(); | 2378 | 214 | normalize_path(); | ||
| HITCBC | 2379 | 214 | normalize_authority(); | 2379 | 214 | normalize_authority(); | ||
| HITCBC | 2380 | 214 | normalize_scheme(); | 2380 | 214 | normalize_scheme(); | ||
| HITCBC | 2381 | 214 | return *this; | 2381 | 214 | return *this; | ||
| 2382 | } | 2382 | } | |||||
| 2383 | 2383 | |||||||
| 2384 | //------------------------------------------------ | 2384 | //------------------------------------------------ | |||||
| 2385 | // | 2385 | // | |||||
| 2386 | // Implementation | 2386 | // Implementation | |||||
| 2387 | // | 2387 | // | |||||
| 2388 | //------------------------------------------------ | 2388 | //------------------------------------------------ | |||||
| 2389 | 2389 | |||||||
| 2390 | inline | 2390 | inline | |||||
| 2391 | void | 2391 | void | |||||
| HITCBC | 2392 | 43552 | url_base:: | 2392 | 43572 | url_base:: | ||
| 2393 | check_invariants() const noexcept | 2393 | check_invariants() const noexcept | |||||
| 2394 | { | 2394 | { | |||||
| HITCBC | 2395 | 43552 | BOOST_ASSERT( | 2395 | 43572 | BOOST_ASSERT( | ||
| 2396 | impl_.len(id_scheme) == 0 || | 2396 | impl_.len(id_scheme) == 0 || | |||||
| 2397 | impl_.get(id_scheme).ends_with(':')); | 2397 | impl_.get(id_scheme).ends_with(':')); | |||||
| HITCBC | 2398 | 43552 | BOOST_ASSERT( | 2398 | 43572 | BOOST_ASSERT( | ||
| 2399 | impl_.len(id_user) == 0 || | 2399 | impl_.len(id_user) == 0 || | |||||
| 2400 | impl_.get(id_user).starts_with("//")); | 2400 | impl_.get(id_user).starts_with("//")); | |||||
| HITCBC | 2401 | 43552 | BOOST_ASSERT( | 2401 | 43572 | BOOST_ASSERT( | ||
| 2402 | impl_.len(id_pass) == 0 || | 2402 | impl_.len(id_pass) == 0 || | |||||
| 2403 | impl_.get(id_user).starts_with("//")); | 2403 | impl_.get(id_user).starts_with("//")); | |||||
| HITCBC | 2404 | 43552 | BOOST_ASSERT( | 2404 | 43572 | BOOST_ASSERT( | ||
| 2405 | impl_.len(id_pass) == 0 || | 2405 | impl_.len(id_pass) == 0 || | |||||
| 2406 | (impl_.len(id_pass) == 1 && | 2406 | (impl_.len(id_pass) == 1 && | |||||
| 2407 | impl_.get(id_pass) == "@") || | 2407 | impl_.get(id_pass) == "@") || | |||||
| 2408 | (impl_.len(id_pass) > 1 && | 2408 | (impl_.len(id_pass) > 1 && | |||||
| 2409 | impl_.get(id_pass).starts_with(':') && | 2409 | impl_.get(id_pass).starts_with(':') && | |||||
| 2410 | impl_.get(id_pass).ends_with('@'))); | 2410 | impl_.get(id_pass).ends_with('@'))); | |||||
| HITCBC | 2411 | 43552 | BOOST_ASSERT( | 2411 | 43572 | BOOST_ASSERT( | ||
| 2412 | impl_.len(id_user, id_path) == 0 || | 2412 | impl_.len(id_user, id_path) == 0 || | |||||
| 2413 | impl_.get(id_user).starts_with("//")); | 2413 | impl_.get(id_user).starts_with("//")); | |||||
| HITCBC | 2414 | 43552 | BOOST_ASSERT(impl_.decoded_[id_path] >= | 2414 | 43572 | BOOST_ASSERT(impl_.decoded_[id_path] >= | ||
| 2415 | ((impl_.len(id_path) + 2) / 3)); | 2415 | ((impl_.len(id_path) + 2) / 3)); | |||||
| HITCBC | 2416 | 43552 | BOOST_ASSERT( | 2416 | 43572 | BOOST_ASSERT( | ||
| 2417 | impl_.len(id_port) == 0 || | 2417 | impl_.len(id_port) == 0 || | |||||
| 2418 | impl_.get(id_port).starts_with(':')); | 2418 | impl_.get(id_port).starts_with(':')); | |||||
| HITCBC | 2419 | 43552 | BOOST_ASSERT( | 2419 | 43572 | BOOST_ASSERT( | ||
| 2420 | impl_.len(id_query) == 0 || | 2420 | impl_.len(id_query) == 0 || | |||||
| 2421 | impl_.get(id_query).starts_with('?')); | 2421 | impl_.get(id_query).starts_with('?')); | |||||
| HITCBC | 2422 | 43552 | BOOST_ASSERT( | 2422 | 43572 | BOOST_ASSERT( | ||
| 2423 | (impl_.len(id_query) == 0 && impl_.nparam_ == 0) || | 2423 | (impl_.len(id_query) == 0 && impl_.nparam_ == 0) || | |||||
| 2424 | (impl_.len(id_query) > 0 && impl_.nparam_ > 0)); | 2424 | (impl_.len(id_query) > 0 && impl_.nparam_ > 0)); | |||||
| HITCBC | 2425 | 43552 | BOOST_ASSERT( | 2425 | 43572 | BOOST_ASSERT( | ||
| 2426 | impl_.len(id_frag) == 0 || | 2426 | impl_.len(id_frag) == 0 || | |||||
| 2427 | impl_.get(id_frag).starts_with('#')); | 2427 | impl_.get(id_frag).starts_with('#')); | |||||
| HITCBC | 2428 | 43552 | BOOST_ASSERT(c_str()[size()] == '\0'); | 2428 | 43572 | BOOST_ASSERT(c_str()[size()] == '\0'); | ||
| HITCBC | 2429 | 43552 | } | 2429 | 43572 | } | ||
| 2430 | 2430 | |||||||
| 2431 | inline | 2431 | inline | |||||
| 2432 | char* | 2432 | char* | |||||
| HITCBC | 2433 | 5500 | url_base:: | 2433 | 5500 | url_base:: | ||
| 2434 | resize_impl( | 2434 | resize_impl( | |||||
| 2435 | int id, | 2435 | int id, | |||||
| 2436 | std::size_t new_size, | 2436 | std::size_t new_size, | |||||
| 2437 | op_t& op) | 2437 | op_t& op) | |||||
| 2438 | { | 2438 | { | |||||
| HITCBC | 2439 | 5500 | return resize_impl( | 2439 | 5500 | return resize_impl( | ||
| HITCBC | 2440 | 5500 | id, id + 1, new_size, op); | 2440 | 5500 | id, id + 1, new_size, op); | ||
| 2441 | } | 2441 | } | |||||
| 2442 | 2442 | |||||||
| 2443 | inline | 2443 | inline | |||||
| 2444 | char* | 2444 | char* | |||||
| HITCBC | 2445 | 6225 | url_base:: | 2445 | 6225 | url_base:: | ||
| 2446 | resize_impl( | 2446 | resize_impl( | |||||
| 2447 | int first, | 2447 | int first, | |||||
| 2448 | int last, | 2448 | int last, | |||||
| 2449 | std::size_t new_len, | 2449 | std::size_t new_len, | |||||
| 2450 | op_t& op) | 2450 | op_t& op) | |||||
| 2451 | { | 2451 | { | |||||
| HITCBC | 2452 | 6225 | auto const n0 = impl_.len(first, last); | 2452 | 6225 | auto const n0 = impl_.len(first, last); | ||
| HITCBC | 2453 | 6225 | if(new_len == 0 && n0 == 0) | 2453 | 6225 | if(new_len == 0 && n0 == 0) | ||
| HITCBC | 2454 | 1090 | return s_ + impl_.offset(first); | 2454 | 1090 | return s_ + impl_.offset(first); | ||
| HITCBC | 2455 | 5135 | if(new_len <= n0) | 2455 | 5135 | if(new_len <= n0) | ||
| HITCBC | 2456 | 2193 | return shrink_impl( | 2456 | 2193 | return shrink_impl( | ||
| HITCBC | 2457 | 2193 | first, last, new_len, op); | 2457 | 2193 | first, last, new_len, op); | ||
| 2458 | 2458 | |||||||
| 2459 | // growing | 2459 | // growing | |||||
| HITCBC | 2460 | 2942 | std::size_t n = new_len - n0; | 2460 | 2942 | std::size_t n = new_len - n0; | ||
| HITCBC | 2461 | 2942 | reserve_impl(size() + n, op); | 2461 | 2942 | reserve_impl(size() + n, op); | ||
| 2462 | auto const pos = | 2462 | auto const pos = | |||||
| HITCBC | 2463 | 2942 | impl_.offset(last); | 2463 | 2942 | impl_.offset(last); | ||
| 2464 | // adjust chars | 2464 | // adjust chars | |||||
| HITCBC | 2465 | 2942 | op.move( | 2465 | 2942 | op.move( | ||
| HITCBC | 2466 | 2942 | s_ + pos + n, | 2466 | 2942 | s_ + pos + n, | ||
| HITCBC | 2467 | 2942 | s_ + pos, | 2467 | 2942 | s_ + pos, | ||
| HITCBC | 2468 | 2942 | impl_.offset(id_end) - | 2468 | 2942 | impl_.offset(id_end) - | ||
| 2469 | pos + 1); | 2469 | pos + 1); | |||||
| 2470 | // collapse (first, last) | 2470 | // collapse (first, last) | |||||
| HITCBC | 2471 | 2942 | impl_.collapse(first, last, | 2471 | 2942 | impl_.collapse(first, last, | ||
| HITCBC | 2472 | 2942 | impl_.offset(last) + n); | 2472 | 2942 | impl_.offset(last) + n); | ||
| 2473 | // shift (last, end) right | 2473 | // shift (last, end) right | |||||
| HITCBC | 2474 | 2942 | impl_.adjust_right(last, id_end, n); | 2474 | 2942 | impl_.adjust_right(last, id_end, n); | ||
| HITCBC | 2475 | 2942 | s_[size()] = '\0'; | 2475 | 2942 | s_[size()] = '\0'; | ||
| HITCBC | 2476 | 2942 | return s_ + impl_.offset(first); | 2476 | 2942 | return s_ + impl_.offset(first); | ||
| 2477 | } | 2477 | } | |||||
| 2478 | 2478 | |||||||
| 2479 | inline | 2479 | inline | |||||
| 2480 | char* | 2480 | char* | |||||
| HITCBC | 2481 | 198 | url_base:: | 2481 | 198 | url_base:: | ||
| 2482 | shrink_impl( | 2482 | shrink_impl( | |||||
| 2483 | int id, | 2483 | int id, | |||||
| 2484 | std::size_t new_size, | 2484 | std::size_t new_size, | |||||
| 2485 | op_t& op) | 2485 | op_t& op) | |||||
| 2486 | { | 2486 | { | |||||
| HITCBC | 2487 | 198 | return shrink_impl( | 2487 | 198 | return shrink_impl( | ||
| HITCBC | 2488 | 198 | id, id + 1, new_size, op); | 2488 | 198 | id, id + 1, new_size, op); | ||
| 2489 | } | 2489 | } | |||||
| 2490 | 2490 | |||||||
| 2491 | inline | 2491 | inline | |||||
| 2492 | char* | 2492 | char* | |||||
| HITCBC | 2493 | 2391 | url_base:: | 2493 | 2391 | url_base:: | ||
| 2494 | shrink_impl( | 2494 | shrink_impl( | |||||
| 2495 | int first, | 2495 | int first, | |||||
| 2496 | int last, | 2496 | int last, | |||||
| 2497 | std::size_t new_len, | 2497 | std::size_t new_len, | |||||
| 2498 | op_t& op) | 2498 | op_t& op) | |||||
| 2499 | { | 2499 | { | |||||
| 2500 | // shrinking | 2500 | // shrinking | |||||
| HITCBC | 2501 | 2391 | auto const n0 = impl_.len(first, last); | 2501 | 2391 | auto const n0 = impl_.len(first, last); | ||
| HITCBC | 2502 | 2391 | BOOST_ASSERT(new_len <= n0); | 2502 | 2391 | BOOST_ASSERT(new_len <= n0); | ||
| HITCBC | 2503 | 2391 | std::size_t n = n0 - new_len; | 2503 | 2391 | std::size_t n = n0 - new_len; | ||
| 2504 | auto const pos = | 2504 | auto const pos = | |||||
| HITCBC | 2505 | 2391 | impl_.offset(last); | 2505 | 2391 | impl_.offset(last); | ||
| 2506 | // adjust chars | 2506 | // adjust chars | |||||
| HITCBC | 2507 | 2391 | op.move( | 2507 | 2391 | op.move( | ||
| HITCBC | 2508 | 2391 | s_ + pos - n, | 2508 | 2391 | s_ + pos - n, | ||
| HITCBC | 2509 | 2391 | s_ + pos, | 2509 | 2391 | s_ + pos, | ||
| HITCBC | 2510 | 2391 | impl_.offset( | 2510 | 2391 | impl_.offset( | ||
| HITCBC | 2511 | 2391 | id_end) - pos + 1); | 2511 | 2391 | id_end) - pos + 1); | ||
| 2512 | // collapse (first, last) | 2512 | // collapse (first, last) | |||||
| HITCBC | 2513 | 2391 | impl_.collapse(first, last, | 2513 | 2391 | impl_.collapse(first, last, | ||
| HITCBC | 2514 | 2391 | impl_.offset(last) - n); | 2514 | 2391 | impl_.offset(last) - n); | ||
| 2515 | // shift (last, end) left | 2515 | // shift (last, end) left | |||||
| HITCBC | 2516 | 2391 | impl_.adjust_left(last, id_end, n); | 2516 | 2391 | impl_.adjust_left(last, id_end, n); | ||
| HITCBC | 2517 | 2391 | s_[size()] = '\0'; | 2517 | 2391 | s_[size()] = '\0'; | ||
| HITCBC | 2518 | 2391 | return s_ + impl_.offset(first); | 2518 | 2391 | return s_ + impl_.offset(first); | ||
| 2519 | } | 2519 | } | |||||
| 2520 | 2520 | |||||||
| 2521 | //------------------------------------------------ | 2521 | //------------------------------------------------ | |||||
| 2522 | 2522 | |||||||
| 2523 | inline | 2523 | inline | |||||
| 2524 | void | 2524 | void | |||||
| HITCBC | 2525 | 526 | url_base:: | 2525 | 526 | url_base:: | ||
| 2526 | set_scheme_impl( | 2526 | set_scheme_impl( | |||||
| 2527 | core::string_view s, | 2527 | core::string_view s, | |||||
| 2528 | urls::scheme id) | 2528 | urls::scheme id) | |||||
| 2529 | { | 2529 | { | |||||
| HITCBC | 2530 | 526 | op_t op(*this, &s); | 2530 | 526 | op_t op(*this, &s); | ||
| HITCBC | 2531 | 526 | check_invariants(); | 2531 | 526 | check_invariants(); | ||
| HITCBC | 2532 | 574 | grammar::parse( | 2532 | 574 | grammar::parse( | ||
| HITCBC | 2533 | 48 | s, detail::scheme_rule() | 2533 | 48 | s, detail::scheme_rule() | ||
| HITCBC | 2534 | 574 | ).value(BOOST_URL_POS); | 2534 | 574 | ).value(BOOST_URL_POS); | ||
| HITCBC | 2535 | 478 | auto const n = s.size(); | 2535 | 478 | auto const n = s.size(); | ||
| HITCBC | 2536 | 478 | auto const p = impl_.offset(id_path); | 2536 | 478 | auto const p = impl_.offset(id_path); | ||
| 2537 | 2537 | |||||||
| 2538 | // check for "./" prefix | 2538 | // check for "./" prefix | |||||
| 2539 | bool const has_dot = | 2539 | bool const has_dot = | |||||
| HITCBC | 2540 | 1434 | [this, p] | 2540 | 1434 | [this, p] | ||
| 2541 | { | 2541 | { | |||||
| HITCBC | 2542 | 478 | if(impl_.nseg_ == 0) | 2542 | 478 | if(impl_.nseg_ == 0) | ||
| HITCBC | 2543 | 213 | return false; | 2543 | 213 | return false; | ||
| HITCBC | 2544 | 265 | if(first_segment().size() < 2) | 2544 | 265 | if(first_segment().size() < 2) | ||
| HITCBC | 2545 | 42 | return false; | 2545 | 42 | return false; | ||
| HITCBC | 2546 | 223 | auto const src = s_ + p; | 2546 | 223 | auto const src = s_ + p; | ||
| HITCBC | 2547 | 223 | if(src[0] != '.') | 2547 | 223 | if(src[0] != '.') | ||
| HITCBC | 2548 | 220 | return false; | 2548 | 220 | return false; | ||
| HITCBC | 2549 | 3 | if(src[1] != '/') | 2549 | 3 | if(src[1] != '/') | ||
| MISUBC | 2550 | ✗ | return false; | 2550 | ✗ | return false; | ||
| HITCBC | 2551 | 3 | return true; | 2551 | 3 | return true; | ||
| HITCBC | 2552 | 478 | }(); | 2552 | 478 | }(); | ||
| 2553 | 2553 | |||||||
| 2554 | // Remove "./" | 2554 | // Remove "./" | |||||
| HITCBC | 2555 | 478 | if(has_dot) | 2555 | 478 | if(has_dot) | ||
| 2556 | { | 2556 | { | |||||
| 2557 | // do this first, for | 2557 | // do this first, for | |||||
| 2558 | // strong exception safety | 2558 | // strong exception safety | |||||
| HITCBC | 2559 | 6 | reserve_impl( | 2559 | 6 | reserve_impl( | ||
| HITCBC | 2560 | 3 | size() + n + 1 - 2, op); | 2560 | 3 | size() + n + 1 - 2, op); | ||
| HITCBC | 2561 | 3 | op.move( | 2561 | 3 | op.move( | ||
| HITCBC | 2562 | 3 | s_ + p, | 2562 | 3 | s_ + p, | ||
| HITCBC | 2563 | 3 | s_ + p + 2, | 2563 | 3 | s_ + p + 2, | ||
| HITCBC | 2564 | 3 | size() + 1 - | 2564 | 3 | size() + 1 - | ||
| 2565 | (p + 2)); | 2565 | (p + 2)); | |||||
| HITCBC | 2566 | 3 | impl_.set_size( | 2566 | 3 | impl_.set_size( | ||
| 2567 | id_path, | 2567 | id_path, | |||||
| HITCBC | 2568 | 3 | impl_.len(id_path) - 2); | 2568 | 3 | impl_.len(id_path) - 2); | ||
| HITCBC | 2569 | 3 | s_[size()] = '\0'; | 2569 | 3 | s_[size()] = '\0'; | ||
| 2570 | } | 2570 | } | |||||
| 2571 | 2571 | |||||||
| HITCBC | 2572 | 478 | auto dest = resize_impl( | 2572 | 478 | auto dest = resize_impl( | ||
| 2573 | id_scheme, n + 1, op); | 2573 | id_scheme, n + 1, op); | |||||
| HITCBC | 2574 | 478 | s.copy(dest, n); | 2574 | 478 | s.copy(dest, n); | ||
| HITCBC | 2575 | 478 | dest[n] = ':'; | 2575 | 478 | dest[n] = ':'; | ||
| HITCBC | 2576 | 478 | impl_.scheme_ = id; | 2576 | 478 | impl_.scheme_ = id; | ||
| HITCBC | 2577 | 478 | check_invariants(); | 2577 | 478 | check_invariants(); | ||
| HITCBC | 2578 | 526 | } | 2578 | 526 | } | ||
| 2579 | 2579 | |||||||
| 2580 | inline | 2580 | inline | |||||
| 2581 | char* | 2581 | char* | |||||
| HITCBC | 2582 | 396 | url_base:: | 2582 | 396 | url_base:: | ||
| 2583 | set_user_impl( | 2583 | set_user_impl( | |||||
| 2584 | std::size_t n, | 2584 | std::size_t n, | |||||
| 2585 | op_t& op) | 2585 | op_t& op) | |||||
| 2586 | { | 2586 | { | |||||
| HITCBC | 2587 | 396 | check_invariants(); | 2587 | 396 | check_invariants(); | ||
| HITCBC | 2588 | 396 | if(impl_.len(id_pass) != 0) | 2588 | 396 | if(impl_.len(id_pass) != 0) | ||
| 2589 | { | 2589 | { | |||||
| 2590 | // keep "//" | 2590 | // keep "//" | |||||
| HITCBC | 2591 | 147 | auto dest = resize_impl( | 2591 | 147 | auto dest = resize_impl( | ||
| 2592 | id_user, 2 + n, op); | 2592 | id_user, 2 + n, op); | |||||
| HITCBC | 2593 | 147 | check_invariants(); | 2593 | 147 | check_invariants(); | ||
| HITCBC | 2594 | 147 | return dest + 2; | 2594 | 147 | return dest + 2; | ||
| 2595 | } | 2595 | } | |||||
| 2596 | // add authority | 2596 | // add authority | |||||
| 2597 | bool const make_absolute = | 2597 | bool const make_absolute = | |||||
| HITCBC | 2598 | 333 | !is_path_absolute() && | 2598 | 333 | !is_path_absolute() && | ||
| HITCBC | 2599 | 84 | !impl_.get(id_path).empty(); | 2599 | 84 | !impl_.get(id_path).empty(); | ||
| HITCBC | 2600 | 498 | auto dest = resize_impl( | 2600 | 498 | auto dest = resize_impl( | ||
| HITCBC | 2601 | 249 | id_user, 2 + n + 1 + make_absolute, op); | 2601 | 249 | id_user, 2 + n + 1 + make_absolute, op); | ||
| HITCBC | 2602 | 249 | impl_.split(id_user, 2 + n); | 2602 | 249 | impl_.split(id_user, 2 + n); | ||
| HITCBC | 2603 | 249 | dest[0] = '/'; | 2603 | 249 | dest[0] = '/'; | ||
| HITCBC | 2604 | 249 | dest[1] = '/'; | 2604 | 249 | dest[1] = '/'; | ||
| HITCBC | 2605 | 249 | dest[2 + n] = '@'; | 2605 | 249 | dest[2 + n] = '@'; | ||
| HITCBC | 2606 | 249 | if (make_absolute) | 2606 | 249 | if (make_absolute) | ||
| 2607 | { | 2607 | { | |||||
| HITCBC | 2608 | 6 | impl_.split(id_pass, 1); | 2608 | 6 | impl_.split(id_pass, 1); | ||
| HITCBC | 2609 | 6 | impl_.split(id_host, 0); | 2609 | 6 | impl_.split(id_host, 0); | ||
| HITCBC | 2610 | 6 | impl_.split(id_port, 0); | 2610 | 6 | impl_.split(id_port, 0); | ||
| HITCBC | 2611 | 6 | dest[3 + n] = '/'; | 2611 | 6 | dest[3 + n] = '/'; | ||
| 2612 | } | 2612 | } | |||||
| HITCBC | 2613 | 249 | check_invariants(); | 2613 | 249 | check_invariants(); | ||
| HITCBC | 2614 | 249 | return dest + 2; | 2614 | 249 | return dest + 2; | ||
| 2615 | } | 2615 | } | |||||
| 2616 | 2616 | |||||||
| 2617 | inline | 2617 | inline | |||||
| 2618 | char* | 2618 | char* | |||||
| HITCBC | 2619 | 377 | url_base:: | 2619 | 377 | url_base:: | ||
| 2620 | set_password_impl( | 2620 | set_password_impl( | |||||
| 2621 | std::size_t n, | 2621 | std::size_t n, | |||||
| 2622 | op_t& op) | 2622 | op_t& op) | |||||
| 2623 | { | 2623 | { | |||||
| HITCBC | 2624 | 377 | check_invariants(); | 2624 | 377 | check_invariants(); | ||
| HITCBC | 2625 | 377 | if(impl_.len(id_user) != 0) | 2625 | 377 | if(impl_.len(id_user) != 0) | ||
| 2626 | { | 2626 | { | |||||
| 2627 | // already have authority | 2627 | // already have authority | |||||
| HITCBC | 2628 | 313 | auto const dest = resize_impl( | 2628 | 313 | auto const dest = resize_impl( | ||
| 2629 | id_pass, 1 + n + 1, op); | 2629 | id_pass, 1 + n + 1, op); | |||||
| HITCBC | 2630 | 313 | dest[0] = ':'; | 2630 | 313 | dest[0] = ':'; | ||
| HITCBC | 2631 | 313 | dest[n + 1] = '@'; | 2631 | 313 | dest[n + 1] = '@'; | ||
| HITCBC | 2632 | 313 | check_invariants(); | 2632 | 313 | check_invariants(); | ||
| HITCBC | 2633 | 313 | return dest + 1; | 2633 | 313 | return dest + 1; | ||
| 2634 | } | 2634 | } | |||||
| 2635 | // add authority | 2635 | // add authority | |||||
| 2636 | bool const make_absolute = | 2636 | bool const make_absolute = | |||||
| HITCBC | 2637 | 104 | !is_path_absolute() && | 2637 | 104 | !is_path_absolute() && | ||
| HITCBC | 2638 | 40 | !impl_.get(id_path).empty(); | 2638 | 40 | !impl_.get(id_path).empty(); | ||
| 2639 | auto const dest = | 2639 | auto const dest = | |||||
| HITCBC | 2640 | 128 | resize_impl( | 2640 | 128 | resize_impl( | ||
| 2641 | id_user, id_host, | 2641 | id_user, id_host, | |||||
| HITCBC | 2642 | 64 | 2 + 1 + n + 1 + make_absolute, op); | 2642 | 64 | 2 + 1 + n + 1 + make_absolute, op); | ||
| HITCBC | 2643 | 64 | impl_.split(id_user, 2); | 2643 | 64 | impl_.split(id_user, 2); | ||
| HITCBC | 2644 | 64 | dest[0] = '/'; | 2644 | 64 | dest[0] = '/'; | ||
| HITCBC | 2645 | 64 | dest[1] = '/'; | 2645 | 64 | dest[1] = '/'; | ||
| HITCBC | 2646 | 64 | dest[2] = ':'; | 2646 | 64 | dest[2] = ':'; | ||
| HITCBC | 2647 | 64 | dest[2 + n + 1] = '@'; | 2647 | 64 | dest[2 + n + 1] = '@'; | ||
| HITCBC | 2648 | 64 | if (make_absolute) | 2648 | 64 | if (make_absolute) | ||
| 2649 | { | 2649 | { | |||||
| HITCBC | 2650 | 7 | impl_.split(id_pass, 2 + n); | 2650 | 7 | impl_.split(id_pass, 2 + n); | ||
| HITCBC | 2651 | 7 | impl_.split(id_host, 0); | 2651 | 7 | impl_.split(id_host, 0); | ||
| HITCBC | 2652 | 7 | impl_.split(id_port, 0); | 2652 | 7 | impl_.split(id_port, 0); | ||
| HITCBC | 2653 | 7 | dest[4 + n] = '/'; | 2653 | 7 | dest[4 + n] = '/'; | ||
| 2654 | } | 2654 | } | |||||
| HITCBC | 2655 | 64 | check_invariants(); | 2655 | 64 | check_invariants(); | ||
| HITCBC | 2656 | 64 | return dest + 3; | 2656 | 64 | return dest + 3; | ||
| 2657 | } | 2657 | } | |||||
| 2658 | 2658 | |||||||
| 2659 | inline | 2659 | inline | |||||
| 2660 | char* | 2660 | char* | |||||
| HITCBC | 2661 | 277 | url_base:: | 2661 | 277 | url_base:: | ||
| 2662 | set_userinfo_impl( | 2662 | set_userinfo_impl( | |||||
| 2663 | std::size_t n, | 2663 | std::size_t n, | |||||
| 2664 | op_t& op) | 2664 | op_t& op) | |||||
| 2665 | { | 2665 | { | |||||
| 2666 | // "//" {dest} "@" | 2666 | // "//" {dest} "@" | |||||
| HITCBC | 2667 | 277 | check_invariants(); | 2667 | 277 | check_invariants(); | ||
| 2668 | bool const make_absolute = | 2668 | bool const make_absolute = | |||||
| HITCBC | 2669 | 406 | !is_path_absolute() && | 2669 | 406 | !is_path_absolute() && | ||
| HITCBC | 2670 | 129 | !impl_.get(id_path).empty(); | 2670 | 129 | !impl_.get(id_path).empty(); | ||
| HITCBC | 2671 | 554 | auto dest = resize_impl( | 2671 | 554 | auto dest = resize_impl( | ||
| HITCBC | 2672 | 277 | id_user, id_host, n + 3 + make_absolute, op); | 2672 | 277 | id_user, id_host, n + 3 + make_absolute, op); | ||
| HITCBC | 2673 | 277 | impl_.split(id_user, n + 2); | 2673 | 277 | impl_.split(id_user, n + 2); | ||
| HITCBC | 2674 | 277 | dest[0] = '/'; | 2674 | 277 | dest[0] = '/'; | ||
| HITCBC | 2675 | 277 | dest[1] = '/'; | 2675 | 277 | dest[1] = '/'; | ||
| HITCBC | 2676 | 277 | dest[n + 2] = '@'; | 2676 | 277 | dest[n + 2] = '@'; | ||
| HITCBC | 2677 | 277 | if (make_absolute) | 2677 | 277 | if (make_absolute) | ||
| 2678 | { | 2678 | { | |||||
| HITCBC | 2679 | 3 | impl_.split(id_pass, 1); | 2679 | 3 | impl_.split(id_pass, 1); | ||
| HITCBC | 2680 | 3 | impl_.split(id_host, 0); | 2680 | 3 | impl_.split(id_host, 0); | ||
| HITCBC | 2681 | 3 | impl_.split(id_port, 0); | 2681 | 3 | impl_.split(id_port, 0); | ||
| HITCBC | 2682 | 3 | dest[3 + n] = '/'; | 2682 | 3 | dest[3 + n] = '/'; | ||
| 2683 | } | 2683 | } | |||||
| HITCBC | 2684 | 277 | check_invariants(); | 2684 | 277 | check_invariants(); | ||
| HITCBC | 2685 | 277 | return dest + 2; | 2685 | 277 | return dest + 2; | ||
| 2686 | } | 2686 | } | |||||
| 2687 | 2687 | |||||||
| 2688 | inline | 2688 | inline | |||||
| 2689 | char* | 2689 | char* | |||||
| HITCBC | 2690 | 721 | url_base:: | 2690 | 721 | url_base:: | ||
| 2691 | set_host_impl( | 2691 | set_host_impl( | |||||
| 2692 | std::size_t n, | 2692 | std::size_t n, | |||||
| 2693 | op_t& op) | 2693 | op_t& op) | |||||
| 2694 | { | 2694 | { | |||||
| HITCBC | 2695 | 721 | check_invariants(); | 2695 | 721 | check_invariants(); | ||
| HITCBC | 2696 | 721 | if(impl_.len(id_user) == 0) | 2696 | 721 | if(impl_.len(id_user) == 0) | ||
| 2697 | { | 2697 | { | |||||
| 2698 | // add authority | 2698 | // add authority | |||||
| 2699 | bool make_absolute = | 2699 | bool make_absolute = | |||||
| HITCBC | 2700 | 320 | !is_path_absolute() && | 2700 | 320 | !is_path_absolute() && | ||
| HITCBC | 2701 | 147 | impl_.len(id_path) != 0; | 2701 | 147 | impl_.len(id_path) != 0; | ||
| HITCBC | 2702 | 173 | auto pn = impl_.len(id_path); | 2702 | 173 | auto pn = impl_.len(id_path); | ||
| HITCBC | 2703 | 346 | auto dest = resize_impl( | 2703 | 346 | auto dest = resize_impl( | ||
| HITCBC | 2704 | 173 | id_user, n + 2 + make_absolute, op); | 2704 | 173 | id_user, n + 2 + make_absolute, op); | ||
| HITCBC | 2705 | 173 | impl_.split(id_user, 2); | 2705 | 173 | impl_.split(id_user, 2); | ||
| HITCBC | 2706 | 173 | impl_.split(id_pass, 0); | 2706 | 173 | impl_.split(id_pass, 0); | ||
| HITCBC | 2707 | 173 | impl_.split(id_host, n); | 2707 | 173 | impl_.split(id_host, n); | ||
| HITCBC | 2708 | 173 | impl_.split(id_port, 0); | 2708 | 173 | impl_.split(id_port, 0); | ||
| HITCBC | 2709 | 173 | impl_.split(id_path, pn + make_absolute); | 2709 | 173 | impl_.split(id_path, pn + make_absolute); | ||
| HITCBC | 2710 | 173 | if (make_absolute) | 2710 | 173 | if (make_absolute) | ||
| 2711 | { | 2711 | { | |||||
| HITCBC | 2712 | 9 | dest[n + 2] = '/'; | 2712 | 9 | dest[n + 2] = '/'; | ||
| HITCBC | 2713 | 9 | ++impl_.decoded_[id_path]; | 2713 | 9 | ++impl_.decoded_[id_path]; | ||
| 2714 | } | 2714 | } | |||||
| HITCBC | 2715 | 173 | dest[0] = '/'; | 2715 | 173 | dest[0] = '/'; | ||
| HITCBC | 2716 | 173 | dest[1] = '/'; | 2716 | 173 | dest[1] = '/'; | ||
| HITCBC | 2717 | 173 | check_invariants(); | 2717 | 173 | check_invariants(); | ||
| HITCBC | 2718 | 173 | return dest + 2; | 2718 | 173 | return dest + 2; | ||
| 2719 | } | 2719 | } | |||||
| 2720 | // already have authority | 2720 | // already have authority | |||||
| HITCBC | 2721 | 548 | auto const dest = resize_impl( | 2721 | 548 | auto const dest = resize_impl( | ||
| 2722 | id_host, n, op); | 2722 | id_host, n, op); | |||||
| HITCBC | 2723 | 548 | check_invariants(); | 2723 | 548 | check_invariants(); | ||
| HITCBC | 2724 | 548 | return dest; | 2724 | 548 | return dest; | ||
| 2725 | } | 2725 | } | |||||
| 2726 | 2726 | |||||||
| 2727 | inline | 2727 | inline | |||||
| 2728 | char* | 2728 | char* | |||||
| HITCBC | 2729 | 604 | url_base:: | 2729 | 604 | url_base:: | ||
| 2730 | set_port_impl( | 2730 | set_port_impl( | |||||
| 2731 | std::size_t n, | 2731 | std::size_t n, | |||||
| 2732 | op_t& op) | 2732 | op_t& op) | |||||
| 2733 | { | 2733 | { | |||||
| HITCBC | 2734 | 604 | check_invariants(); | 2734 | 604 | check_invariants(); | ||
| HITCBC | 2735 | 604 | if(impl_.len(id_user) != 0) | 2735 | 604 | if(impl_.len(id_user) != 0) | ||
| 2736 | { | 2736 | { | |||||
| 2737 | // authority exists | 2737 | // authority exists | |||||
| HITCBC | 2738 | 503 | auto dest = resize_impl( | 2738 | 503 | auto dest = resize_impl( | ||
| 2739 | id_port, n + 1, op); | 2739 | id_port, n + 1, op); | |||||
| HITCBC | 2740 | 503 | dest[0] = ':'; | 2740 | 503 | dest[0] = ':'; | ||
| HITCBC | 2741 | 503 | check_invariants(); | 2741 | 503 | check_invariants(); | ||
| HITCBC | 2742 | 503 | return dest + 1; | 2742 | 503 | return dest + 1; | ||
| 2743 | } | 2743 | } | |||||
| 2744 | bool make_absolute = | 2744 | bool make_absolute = | |||||
| HITCBC | 2745 | 174 | !is_path_absolute() && | 2745 | 174 | !is_path_absolute() && | ||
| HITCBC | 2746 | 73 | impl_.len(id_path) != 0; | 2746 | 73 | impl_.len(id_path) != 0; | ||
| HITCBC | 2747 | 202 | auto dest = resize_impl( | 2747 | 202 | auto dest = resize_impl( | ||
| HITCBC | 2748 | 101 | id_user, 3 + n + make_absolute, op); | 2748 | 101 | id_user, 3 + n + make_absolute, op); | ||
| HITCBC | 2749 | 101 | impl_.split(id_user, 2); | 2749 | 101 | impl_.split(id_user, 2); | ||
| HITCBC | 2750 | 101 | impl_.split(id_pass, 0); | 2750 | 101 | impl_.split(id_pass, 0); | ||
| HITCBC | 2751 | 101 | impl_.split(id_host, 0); | 2751 | 101 | impl_.split(id_host, 0); | ||
| HITCBC | 2752 | 101 | dest[0] = '/'; | 2752 | 101 | dest[0] = '/'; | ||
| HITCBC | 2753 | 101 | dest[1] = '/'; | 2753 | 101 | dest[1] = '/'; | ||
| HITCBC | 2754 | 101 | dest[2] = ':'; | 2754 | 101 | dest[2] = ':'; | ||
| HITCBC | 2755 | 101 | if (make_absolute) | 2755 | 101 | if (make_absolute) | ||
| 2756 | { | 2756 | { | |||||
| HITCBC | 2757 | 8 | impl_.split(id_port, n + 1); | 2757 | 8 | impl_.split(id_port, n + 1); | ||
| HITCBC | 2758 | 8 | dest[n + 3] = '/'; | 2758 | 8 | dest[n + 3] = '/'; | ||
| HITCBC | 2759 | 8 | ++impl_.decoded_[id_path]; | 2759 | 8 | ++impl_.decoded_[id_path]; | ||
| 2760 | } | 2760 | } | |||||
| HITCBC | 2761 | 101 | check_invariants(); | 2761 | 101 | check_invariants(); | ||
| HITCBC | 2762 | 101 | return dest + 3; | 2762 | 101 | return dest + 3; | ||
| 2763 | } | 2763 | } | |||||
| 2764 | 2764 | |||||||
| 2765 | inline | 2765 | inline | |||||
| 2766 | char* | 2766 | char* | |||||
| HITCBC | 2767 | 597 | url_base:: | 2767 | 597 | url_base:: | ||
| 2768 | set_path_impl( | 2768 | set_path_impl( | |||||
| 2769 | std::size_t n, | 2769 | std::size_t n, | |||||
| 2770 | op_t& op) | 2770 | op_t& op) | |||||
| 2771 | { | 2771 | { | |||||
| HITCBC | 2772 | 597 | check_invariants(); | 2772 | 597 | check_invariants(); | ||
| HITCBC | 2773 | 597 | auto const dest = resize_impl( | 2773 | 597 | auto const dest = resize_impl( | ||
| 2774 | id_path, n, op); | 2774 | id_path, n, op); | |||||
| HITCBC | 2775 | 597 | return dest; | 2775 | 597 | return dest; | ||
| 2776 | } | 2776 | } | |||||
| 2777 | 2777 | |||||||
| 2778 | 2778 | |||||||
| 2779 | //------------------------------------------------ | 2779 | //------------------------------------------------ | |||||
| 2780 | 2780 | |||||||
| 2781 | // return the first segment of the path. | 2781 | // return the first segment of the path. | |||||
| 2782 | // this is needed for some algorithms. | 2782 | // this is needed for some algorithms. | |||||
| 2783 | inline | 2783 | inline | |||||
| 2784 | core::string_view | 2784 | core::string_view | |||||
| HITCBC | 2785 | 303 | url_base:: | 2785 | 303 | url_base:: | ||
| 2786 | first_segment() const noexcept | 2786 | first_segment() const noexcept | |||||
| 2787 | { | 2787 | { | |||||
| HITCBC | 2788 | 303 | if(impl_.nseg_ == 0) | 2788 | 303 | if(impl_.nseg_ == 0) | ||
| HITCBC | 2789 | 9 | return {}; | 2789 | 9 | return {}; | ||
| HITCBC | 2790 | 294 | auto const p0 = impl_.cs_ + | 2790 | 294 | auto const p0 = impl_.cs_ + | ||
| HITCBC | 2791 | 294 | impl_.offset(id_path) + | 2791 | 294 | impl_.offset(id_path) + | ||
| HITCBC | 2792 | 294 | detail::path_prefix( | 2792 | 294 | detail::path_prefix( | ||
| HITCBC | 2793 | 294 | impl_.get(id_path)); | 2793 | 294 | impl_.get(id_path)); | ||
| HITCBC | 2794 | 294 | auto const end = impl_.cs_ + | 2794 | 294 | auto const end = impl_.cs_ + | ||
| HITCBC | 2795 | 294 | impl_.offset(id_query); | 2795 | 294 | impl_.offset(id_query); | ||
| HITCBC | 2796 | 294 | if(impl_.nseg_ == 1) | 2796 | 294 | if(impl_.nseg_ == 1) | ||
| HITCBC | 2797 | 182 | return core::string_view( | 2797 | 182 | return core::string_view( | ||
| HITCBC | 2798 | 91 | p0, end - p0); | 2798 | 91 | p0, end - p0); | ||
| HITCBC | 2799 | 203 | auto p = p0; | 2799 | 203 | auto p = p0; | ||
| HITCBC | 2800 | 910 | while(*p != '/') | 2800 | 910 | while(*p != '/') | ||
| 2801 | { | 2801 | { | |||||
| HITCBC | 2802 | 707 | BOOST_ASSERT(p < end); | 2802 | 707 | BOOST_ASSERT(p < end); | ||
| HITCBC | 2803 | 707 | ++p; | 2803 | 707 | ++p; | ||
| 2804 | } | 2804 | } | |||||
| HITCBC | 2805 | 203 | return core::string_view(p0, p - p0); | 2805 | 203 | return core::string_view(p0, p - p0); | ||
| 2806 | } | 2806 | } | |||||
| 2807 | 2807 | |||||||
| 2808 | inline | 2808 | inline | |||||
| 2809 | detail::segments_iter_impl | 2809 | detail::segments_iter_impl | |||||
| HITCBC | 2810 | 2315 | url_base:: | 2810 | 2315 | url_base:: | ||
| 2811 | edit_segments( | 2811 | edit_segments( | |||||
| 2812 | detail::segments_iter_impl const& it0, | 2812 | detail::segments_iter_impl const& it0, | |||||
| 2813 | detail::segments_iter_impl const& it1, | 2813 | detail::segments_iter_impl const& it1, | |||||
| 2814 | detail::any_segments_iter&& src, | 2814 | detail::any_segments_iter&& src, | |||||
| 2815 | // -1 = preserve | 2815 | // -1 = preserve | |||||
| 2816 | // 0 = make relative (can fail) | 2816 | // 0 = make relative (can fail) | |||||
| 2817 | // 1 = make absolute | 2817 | // 1 = make absolute | |||||
| 2818 | int absolute) | 2818 | int absolute) | |||||
| 2819 | { | 2819 | { | |||||
| 2820 | // Iterator doesn't belong to this url | 2820 | // Iterator doesn't belong to this url | |||||
| HITCBC | 2821 | 2315 | BOOST_ASSERT(it0.ref.alias_of(impl_)); | 2821 | 2315 | BOOST_ASSERT(it0.ref.alias_of(impl_)); | ||
| 2822 | 2822 | |||||||
| 2823 | // Iterator doesn't belong to this url | 2823 | // Iterator doesn't belong to this url | |||||
| HITCBC | 2824 | 2315 | BOOST_ASSERT(it1.ref.alias_of(impl_)); | 2824 | 2315 | BOOST_ASSERT(it1.ref.alias_of(impl_)); | ||
| 2825 | 2825 | |||||||
| 2826 | // Iterator is in the wrong order | 2826 | // Iterator is in the wrong order | |||||
| HITCBC | 2827 | 2315 | BOOST_ASSERT(it0.index <= it1.index); | 2827 | 2315 | BOOST_ASSERT(it0.index <= it1.index); | ||
| 2828 | 2828 | |||||||
| 2829 | // Iterator is out of range | 2829 | // Iterator is out of range | |||||
| HITCBC | 2830 | 2315 | BOOST_ASSERT(it0.index <= impl_.nseg_); | 2830 | 2315 | BOOST_ASSERT(it0.index <= impl_.nseg_); | ||
| HITCBC | 2831 | 2315 | BOOST_ASSERT(it0.pos <= impl_.len(id_path)); | 2831 | 2315 | BOOST_ASSERT(it0.pos <= impl_.len(id_path)); | ||
| 2832 | 2832 | |||||||
| 2833 | // Iterator is out of range | 2833 | // Iterator is out of range | |||||
| HITCBC | 2834 | 2315 | BOOST_ASSERT(it1.index <= impl_.nseg_); | 2834 | 2315 | BOOST_ASSERT(it1.index <= impl_.nseg_); | ||
| HITCBC | 2835 | 2315 | BOOST_ASSERT(it1.pos <= impl_.len(id_path)); | 2835 | 2315 | BOOST_ASSERT(it1.pos <= impl_.len(id_path)); | ||
| 2836 | 2836 | |||||||
| 2837 | //------------------------------------------------ | 2837 | //------------------------------------------------ | |||||
| 2838 | // | 2838 | // | |||||
| 2839 | // Calculate output prefix | 2839 | // Calculate output prefix | |||||
| 2840 | // | 2840 | // | |||||
| 2841 | // 0 = "" | 2841 | // 0 = "" | |||||
| 2842 | // 1 = "/" | 2842 | // 1 = "/" | |||||
| 2843 | // 2 = "./" | 2843 | // 2 = "./" | |||||
| 2844 | // 3 = "/./" | 2844 | // 3 = "/./" | |||||
| 2845 | // | 2845 | // | |||||
| HITCBC | 2846 | 2315 | bool const is_abs = is_path_absolute(); | 2846 | 2315 | bool const is_abs = is_path_absolute(); | ||
| HITCBC | 2847 | 2315 | if(has_authority()) | 2847 | 2315 | if(has_authority()) | ||
| 2848 | { | 2848 | { | |||||
| 2849 | // Check if the new | 2849 | // Check if the new | |||||
| 2850 | // path would be empty | 2850 | // path would be empty | |||||
| HITCBC | 2851 | 1855 | if( src.fast_nseg == 0 && | 2851 | 1855 | if( src.fast_nseg == 0 && | ||
| HITCBC | 2852 | 911 | it0.index == 0 && | 2852 | 911 | it0.index == 0 && | ||
| HITCBC | 2853 | 655 | it1.index == impl_.nseg_) | 2853 | 655 | it1.index == impl_.nseg_) | ||
| 2854 | { | 2854 | { | |||||
| 2855 | // VFALCO we don't have | 2855 | // VFALCO we don't have | |||||
| 2856 | // access to nchar this early | 2856 | // access to nchar this early | |||||
| 2857 | // | 2857 | // | |||||
| 2858 | //BOOST_ASSERT(nchar == 0); | 2858 | //BOOST_ASSERT(nchar == 0); | |||||
| HITCBC | 2859 | 627 | absolute = 0; | 2859 | 627 | absolute = 0; | ||
| 2860 | } | 2860 | } | |||||
| 2861 | else | 2861 | else | |||||
| 2862 | { | 2862 | { | |||||
| 2863 | // prefix "/" required | 2863 | // prefix "/" required | |||||
| HITCBC | 2864 | 1228 | absolute = 1; | 2864 | 1228 | absolute = 1; | ||
| 2865 | } | 2865 | } | |||||
| 2866 | } | 2866 | } | |||||
| HITCBC | 2867 | 460 | else if(absolute < 0) | 2867 | 460 | else if(absolute < 0) | ||
| 2868 | { | 2868 | { | |||||
| HITCBC | 2869 | 460 | absolute = is_abs; // preserve | 2869 | 460 | absolute = is_abs; // preserve | ||
| 2870 | } | 2870 | } | |||||
| HITCBC | 2871 | 2315 | auto const path_pos = impl_.offset(id_path); | 2871 | 2315 | auto const path_pos = impl_.offset(id_path); | ||
| 2872 | 2872 | |||||||
| HITCBC | 2873 | 2315 | std::size_t nchar = 0; | 2873 | 2315 | std::size_t nchar = 0; | ||
| HITCBC | 2874 | 2315 | std::size_t prefix = 0; | 2874 | 2315 | std::size_t prefix = 0; | ||
| HITCBC | 2875 | 2315 | bool encode_colons = false; | 2875 | 2315 | bool encode_colons = false; | ||
| HITCBC | 2876 | 2315 | bool cp_src_prefix = false; | 2876 | 2315 | bool cp_src_prefix = false; | ||
| HITCBC | 2877 | 2315 | if(it0.index > 0) | 2877 | 2315 | if(it0.index > 0) | ||
| 2878 | { | 2878 | { | |||||
| 2879 | // first segment unchanged | 2879 | // first segment unchanged | |||||
| HITCBC | 2880 | 870 | prefix = src.fast_nseg > 0; | 2880 | 870 | prefix = src.fast_nseg > 0; | ||
| 2881 | } | 2881 | } | |||||
| HITCBC | 2882 | 1445 | else if(src.fast_nseg > 0) | 2882 | 1445 | else if(src.fast_nseg > 0) | ||
| 2883 | { | 2883 | { | |||||
| 2884 | // first segment from src | 2884 | // first segment from src | |||||
| HITCBC | 2885 | 718 | if(! src.front.empty()) | 2885 | 718 | if(! src.front.empty()) | ||
| 2886 | { | 2886 | { | |||||
| HITCBC | 2887 | 640 | if( src.front == "." && | 2887 | 640 | if( src.front == "." && | ||
| HITCBC | 2888 | 7 | src.fast_nseg > 1) | 2888 | 7 | src.fast_nseg > 1) | ||
| HITCBC | 2889 | 4 | if (src.s.empty()) | 2889 | 4 | if (src.s.empty()) | ||
| 2890 | { | 2890 | { | |||||
| 2891 | // if front is ".", we need the extra "." in the prefix | 2891 | // if front is ".", we need the extra "." in the prefix | |||||
| 2892 | // which will maintain the invariant that segments represent | 2892 | // which will maintain the invariant that segments represent | |||||
| 2893 | // {"."} | 2893 | // {"."} | |||||
| HITCBC | 2894 | 4 | prefix = 2 + absolute; | 2894 | 4 | prefix = 2 + absolute; | ||
| 2895 | } | 2895 | } | |||||
| 2896 | else | 2896 | else | |||||
| 2897 | { | 2897 | { | |||||
| 2898 | // if the "." prefix is explicitly required from set_path | 2898 | // if the "." prefix is explicitly required from set_path | |||||
| 2899 | // we do not include an extra "." segment | 2899 | // we do not include an extra "." segment | |||||
| MISUBC | 2900 | ✗ | prefix = absolute; | 2900 | ✗ | prefix = absolute; | ||
| MISUBC | 2901 | ✗ | cp_src_prefix = true; | 2901 | ✗ | cp_src_prefix = true; | ||
| 2902 | } | 2902 | } | |||||
| HITCBC | 2903 | 629 | else if(absolute) | 2903 | 629 | else if(absolute) | ||
| HITCBC | 2904 | 542 | prefix = 1; | 2904 | 542 | prefix = 1; | ||
| HITCBC | 2905 | 166 | else if(has_scheme() || | 2905 | 166 | else if(has_scheme() || | ||
| HITCBC | 2906 | 79 | ! src.front.contains(':')) | 2906 | 79 | ! src.front.contains(':')) | ||
| HITCBC | 2907 | 82 | prefix = 0; | 2907 | 82 | prefix = 0; | ||
| 2908 | else | 2908 | else | |||||
| 2909 | { | 2909 | { | |||||
| HITCBC | 2910 | 5 | prefix = 0; | 2910 | 5 | prefix = 0; | ||
| HITCBC | 2911 | 5 | encode_colons = true; | 2911 | 5 | encode_colons = true; | ||
| 2912 | } | 2912 | } | |||||
| 2913 | } | 2913 | } | |||||
| 2914 | else | 2914 | else | |||||
| 2915 | { | 2915 | { | |||||
| HITCBC | 2916 | 85 | prefix = 2 + absolute; | 2916 | 85 | prefix = 2 + absolute; | ||
| 2917 | } | 2917 | } | |||||
| 2918 | } | 2918 | } | |||||
| 2919 | else | 2919 | else | |||||
| 2920 | { | 2920 | { | |||||
| 2921 | // first segment from it1 | 2921 | // first segment from it1 | |||||
| HITCBC | 2922 | 727 | auto const p = | 2922 | 727 | auto const p = | ||
| HITCBC | 2923 | 727 | impl_.cs_ + path_pos + it1.pos; | 2923 | 727 | impl_.cs_ + path_pos + it1.pos; | ||
| HITCBC | 2924 | 1454 | switch(impl_.cs_ + | 2924 | 1454 | switch(impl_.cs_ + | ||
| HITCBC | 2925 | 727 | impl_.offset(id_query) - p) | 2925 | 727 | impl_.offset(id_query) - p) | ||
| 2926 | { | 2926 | { | |||||
| HITCBC | 2927 | 680 | case 0: | 2927 | 680 | case 0: | ||
| 2928 | // points to end | 2928 | // points to end | |||||
| HITCBC | 2929 | 680 | prefix = absolute; | 2929 | 680 | prefix = absolute; | ||
| HITCBC | 2930 | 680 | break; | 2930 | 680 | break; | ||
| HITCBC | 2931 | 36 | default: | 2931 | 36 | default: | ||
| HITCBC | 2932 | 36 | BOOST_ASSERT(*p == '/'); | 2932 | 36 | BOOST_ASSERT(*p == '/'); | ||
| HITCBC | 2933 | 36 | if(p[1] != '/') | 2933 | 36 | if(p[1] != '/') | ||
| 2934 | { | 2934 | { | |||||
| HITCBC | 2935 | 35 | if(absolute) | 2935 | 35 | if(absolute) | ||
| HITCBC | 2936 | 29 | prefix = 1; | 2936 | 29 | prefix = 1; | ||
| HITCBC | 2937 | 11 | else if(has_scheme() || | 2937 | 11 | else if(has_scheme() || | ||
| HITCBC | 2938 | 11 | ! it1.dereference().contains(':')) | 2938 | 11 | ! it1.dereference().contains(':')) | ||
| HITCBC | 2939 | 5 | prefix = 0; | 2939 | 5 | prefix = 0; | ||
| 2940 | else | 2940 | else | |||||
| HITCBC | 2941 | 1 | prefix = 2; | 2941 | 1 | prefix = 2; | ||
| HITCBC | 2942 | 35 | break; | 2942 | 35 | break; | ||
| 2943 | } | 2943 | } | |||||
| 2944 | // empty | 2944 | // empty | |||||
| 2945 | BOOST_FALLTHROUGH; | 2945 | BOOST_FALLTHROUGH; | |||||
| 2946 | case 1: | 2946 | case 1: | |||||
| 2947 | // empty | 2947 | // empty | |||||
| HITCBC | 2948 | 12 | BOOST_ASSERT(*p == '/'); | 2948 | 12 | BOOST_ASSERT(*p == '/'); | ||
| HITCBC | 2949 | 12 | prefix = 2 + absolute; | 2949 | 12 | prefix = 2 + absolute; | ||
| HITCBC | 2950 | 12 | break; | 2950 | 12 | break; | ||
| 2951 | } | 2951 | } | |||||
| 2952 | } | 2952 | } | |||||
| 2953 | 2953 | |||||||
| 2954 | // append '/' to new segs | 2954 | // append '/' to new segs | |||||
| 2955 | // if inserting at front. | 2955 | // if inserting at front. | |||||
| HITCBC | 2956 | 2315 | std::size_t const suffix = | 2956 | 2315 | std::size_t const suffix = | ||
| HITCBC | 2957 | 3234 | it1.index == 0 && | 2957 | 3234 | it1.index == 0 && | ||
| HITCBC | 2958 | 2494 | impl_.nseg_ > 0 && | 2958 | 2494 | impl_.nseg_ > 0 && | ||
| HITCBC | 2959 | 179 | src.fast_nseg > 0; | 2959 | 179 | src.fast_nseg > 0; | ||
| 2960 | 2960 | |||||||
| 2961 | //------------------------------------------------ | 2961 | //------------------------------------------------ | |||||
| 2962 | // | 2962 | // | |||||
| 2963 | // Measure the number of encoded characters | 2963 | // Measure the number of encoded characters | |||||
| 2964 | // of output, and the number of inserted | 2964 | // of output, and the number of inserted | |||||
| 2965 | // segments including internal separators. | 2965 | // segments including internal separators. | |||||
| 2966 | // | 2966 | // | |||||
| HITCBC | 2967 | 2315 | src.encode_colons = encode_colons; | 2967 | 2315 | src.encode_colons = encode_colons; | ||
| HITCBC | 2968 | 2315 | std::size_t nseg = 0; | 2968 | 2315 | std::size_t nseg = 0; | ||
| HITCBC | 2969 | 2315 | if(src.measure(nchar)) | 2969 | 2315 | if(src.measure(nchar)) | ||
| 2970 | { | 2970 | { | |||||
| HITCBC | 2971 | 1279 | src.encode_colons = false; | 2971 | 1279 | src.encode_colons = false; | ||
| 2972 | for(;;) | 2972 | for(;;) | |||||
| 2973 | { | 2973 | { | |||||
| HITCBC | 2974 | 1605 | ++nseg; | 2974 | 1605 | ++nseg; | ||
| HITCBC | 2975 | 1605 | if(! src.measure(nchar)) | 2975 | 1605 | if(! src.measure(nchar)) | ||
| HITCBC | 2976 | 1277 | break; | 2976 | 1277 | break; | ||
| HITCBC | 2977 | 326 | ++nchar; | 2977 | 326 | ++nchar; | ||
| 2978 | } | 2978 | } | |||||
| 2979 | } | 2979 | } | |||||
| 2980 | 2980 | |||||||
| HITCBC | 2981 | 2313 | switch(src.fast_nseg) | 2981 | 2313 | switch(src.fast_nseg) | ||
| 2982 | { | 2982 | { | |||||
| HITCBC | 2983 | 1036 | case 0: | 2983 | 1036 | case 0: | ||
| HITCBC | 2984 | 1036 | BOOST_ASSERT(nseg == 0); | 2984 | 1036 | BOOST_ASSERT(nseg == 0); | ||
| HITCBC | 2985 | 1036 | break; | 2985 | 1036 | break; | ||
| HITCBC | 2986 | 1089 | case 1: | 2986 | 1089 | case 1: | ||
| HITCBC | 2987 | 1089 | BOOST_ASSERT(nseg == 1); | 2987 | 1089 | BOOST_ASSERT(nseg == 1); | ||
| HITCBC | 2988 | 1089 | break; | 2988 | 1089 | break; | ||
| HITCBC | 2989 | 188 | case 2: | 2989 | 188 | case 2: | ||
| HITCBC | 2990 | 188 | BOOST_ASSERT(nseg >= 2); | 2990 | 188 | BOOST_ASSERT(nseg >= 2); | ||
| HITCBC | 2991 | 188 | break; | 2991 | 188 | break; | ||
| 2992 | } | 2992 | } | |||||
| 2993 | 2993 | |||||||
| 2994 | //------------------------------------------------ | 2994 | //------------------------------------------------ | |||||
| 2995 | // | 2995 | // | |||||
| 2996 | // Calculate [pos0, pos1) to remove | 2996 | // Calculate [pos0, pos1) to remove | |||||
| 2997 | // | 2997 | // | |||||
| HITCBC | 2998 | 2313 | auto pos0 = it0.pos; | 2998 | 2313 | auto pos0 = it0.pos; | ||
| HITCBC | 2999 | 2313 | if(it0.index == 0) | 2999 | 2313 | if(it0.index == 0) | ||
| 3000 | { | 3000 | { | |||||
| 3001 | // patch pos for prefix | 3001 | // patch pos for prefix | |||||
| HITCBC | 3002 | 1443 | pos0 = 0; | 3002 | 1443 | pos0 = 0; | ||
| 3003 | } | 3003 | } | |||||
| HITCBC | 3004 | 2313 | auto pos1 = it1.pos; | 3004 | 2313 | auto pos1 = it1.pos; | ||
| HITCBC | 3005 | 2313 | if(it1.index == 0) | 3005 | 2313 | if(it1.index == 0) | ||
| 3006 | { | 3006 | { | |||||
| 3007 | // patch pos for prefix | 3007 | // patch pos for prefix | |||||
| HITCBC | 3008 | 919 | pos1 = detail::path_prefix( | 3008 | 919 | pos1 = detail::path_prefix( | ||
| 3009 | impl_.get(id_path)); | 3009 | impl_.get(id_path)); | |||||
| 3010 | } | 3010 | } | |||||
| HITCBC | 3011 | 1394 | else if( | 3011 | 1394 | else if( | ||
| HITCBC | 3012 | 1394 | it0.index == 0 && | 3012 | 1394 | it0.index == 0 && | ||
| HITCBC | 3013 | 524 | it1.index < impl_.nseg_ && | 3013 | 524 | it1.index < impl_.nseg_ && | ||
| 3014 | nseg == 0) | 3014 | nseg == 0) | |||||
| 3015 | { | 3015 | { | |||||
| 3016 | // Remove the slash from segment it1 | 3016 | // Remove the slash from segment it1 | |||||
| 3017 | // if it is becoming the new first | 3017 | // if it is becoming the new first | |||||
| 3018 | // segment. | 3018 | // segment. | |||||
| HITCBC | 3019 | 47 | ++pos1; | 3019 | 47 | ++pos1; | ||
| 3020 | } | 3020 | } | |||||
| 3021 | // calc decoded size of old range | 3021 | // calc decoded size of old range | |||||
| 3022 | auto const dn0 = | 3022 | auto const dn0 = | |||||
| HITCBC | 3023 | 2313 | detail::decode_bytes_unsafe( | 3023 | 2313 | detail::decode_bytes_unsafe( | ||
| 3024 | core::string_view( | 3024 | core::string_view( | |||||
| HITCBC | 3025 | 2313 | impl_.cs_ + | 3025 | 2313 | impl_.cs_ + | ||
| HITCBC | 3026 | 2313 | impl_.offset(id_path) + | 3026 | 2313 | impl_.offset(id_path) + | ||
| 3027 | pos0, | 3027 | pos0, | |||||
| 3028 | pos1 - pos0)); | 3028 | pos1 - pos0)); | |||||
| 3029 | 3029 | |||||||
| 3030 | //------------------------------------------------ | 3030 | //------------------------------------------------ | |||||
| 3031 | // | 3031 | // | |||||
| 3032 | // Resize | 3032 | // Resize | |||||
| 3033 | // | 3033 | // | |||||
| HITCBC | 3034 | 4626 | op_t op(*this, &src.s); | 3034 | 4626 | op_t op(*this, &src.s); | ||
| 3035 | char* dest; | 3035 | char* dest; | |||||
| 3036 | char const* end; | 3036 | char const* end; | |||||
| 3037 | { | 3037 | { | |||||
| HITCBC | 3038 | 2313 | auto const nremove = pos1 - pos0; | 3038 | 2313 | auto const nremove = pos1 - pos0; | ||
| 3039 | // check overflow | 3039 | // check overflow | |||||
| HITCBC | 3040 | 4626 | if( nchar <= max_size() && ( | 3040 | 4626 | if( nchar <= max_size() && ( | ||
| HITCBC | 3041 | 2313 | prefix + suffix <= | 3041 | 2313 | prefix + suffix <= | ||
| HITCBC | 3042 | 2313 | max_size() - nchar)) | 3042 | 2313 | max_size() - nchar)) | ||
| 3043 | { | 3043 | { | |||||
| HITCBC | 3044 | 2313 | nchar = prefix + nchar + suffix; | 3044 | 2313 | nchar = prefix + nchar + suffix; | ||
| HITCBC | 3045 | 3484 | if( nchar <= nremove || | 3045 | 3484 | if( nchar <= nremove || | ||
| HITCBC | 3046 | 1171 | nchar - nremove <= | 3046 | 1171 | nchar - nremove <= | ||
| HITCBC | 3047 | 1171 | max_size() - size()) | 3047 | 1171 | max_size() - size()) | ||
| HITCBC | 3048 | 2313 | goto ok; | 3048 | 2313 | goto ok; | ||
| 3049 | } | 3049 | } | |||||
| 3050 | // too large | 3050 | // too large | |||||
| MISUBC | 3051 | ✗ | detail::throw_length_error(); | 3051 | ✗ | detail::throw_length_error(); | ||
| HITCBC | 3052 | 2313 | ok: | 3052 | 2313 | ok: | ||
| 3053 | auto const new_size = | 3053 | auto const new_size = | |||||
| HITCBC | 3054 | 2313 | size() + nchar - nremove; | 3054 | 2313 | size() + nchar - nremove; | ||
| HITCBC | 3055 | 2313 | reserve_impl(new_size, op); | 3055 | 2313 | reserve_impl(new_size, op); | ||
| HITCBC | 3056 | 2313 | dest = s_ + path_pos + pos0; | 3056 | 2313 | dest = s_ + path_pos + pos0; | ||
| HITCBC | 3057 | 2313 | op.move( | 3057 | 2313 | op.move( | ||
| HITCBC | 3058 | 2313 | dest + nchar, | 3058 | 2313 | dest + nchar, | ||
| HITCBC | 3059 | 2313 | s_ + path_pos + pos1, | 3059 | 2313 | s_ + path_pos + pos1, | ||
| HITCBC | 3060 | 2313 | size() - path_pos - pos1); | 3060 | 2313 | size() - path_pos - pos1); | ||
| HITCBC | 3061 | 4626 | impl_.set_size( | 3061 | 4626 | impl_.set_size( | ||
| 3062 | id_path, | 3062 | id_path, | |||||
| HITCBC | 3063 | 2313 | impl_.len(id_path) + nchar - nremove); | 3063 | 2313 | impl_.len(id_path) + nchar - nremove); | ||
| HITCBC | 3064 | 2313 | BOOST_ASSERT(size() == new_size); | 3064 | 2313 | BOOST_ASSERT(size() == new_size); | ||
| HITCBC | 3065 | 2313 | end = dest + nchar; | 3065 | 2313 | end = dest + nchar; | ||
| HITCBC | 3066 | 2313 | auto const nseg1 = | 3066 | 2313 | auto const nseg1 = | ||
| HITCBC | 3067 | 2313 | static_cast<std::ptrdiff_t>(impl_.nseg_) + | 3067 | 2313 | static_cast<std::ptrdiff_t>(impl_.nseg_) + | ||
| HITCBC | 3068 | 2313 | static_cast<std::ptrdiff_t>(nseg) - | 3068 | 2313 | static_cast<std::ptrdiff_t>(nseg) - | ||
| HITCBC | 3069 | 2313 | static_cast<std::ptrdiff_t>(it1.index) + | 3069 | 2313 | static_cast<std::ptrdiff_t>(it1.index) + | ||
| HITCBC | 3070 | 2313 | static_cast<std::ptrdiff_t>(it0.index) - | 3070 | 2313 | static_cast<std::ptrdiff_t>(it0.index) - | ||
| 3071 | static_cast<std::ptrdiff_t>(cp_src_prefix); | 3071 | static_cast<std::ptrdiff_t>(cp_src_prefix); | |||||
| HITCBC | 3072 | 2313 | BOOST_ASSERT(nseg1 >= 0); | 3072 | 2313 | BOOST_ASSERT(nseg1 >= 0); | ||
| HITCBC | 3073 | 2313 | impl_.nseg_ = detail::to_size_type(nseg1); | 3073 | 2313 | impl_.nseg_ = detail::to_size_type(nseg1); | ||
| HITCBC | 3074 | 2313 | if(s_) | 3074 | 2313 | if(s_) | ||
| HITCBC | 3075 | 2306 | s_[size()] = '\0'; | 3075 | 2306 | s_[size()] = '\0'; | ||
| 3076 | } | 3076 | } | |||||
| 3077 | 3077 | |||||||
| 3078 | //------------------------------------------------ | 3078 | //------------------------------------------------ | |||||
| 3079 | // | 3079 | // | |||||
| 3080 | // Output segments and internal separators: | 3080 | // Output segments and internal separators: | |||||
| 3081 | // | 3081 | // | |||||
| 3082 | // prefix [ segment [ '/' segment ] ] suffix | 3082 | // prefix [ segment [ '/' segment ] ] suffix | |||||
| 3083 | // | 3083 | // | |||||
| HITCBC | 3084 | 2313 | auto const dest0 = dest; | 3084 | 2313 | auto const dest0 = dest; | ||
| HITCBC | 3085 | 2313 | switch(prefix) | 3085 | 2313 | switch(prefix) | ||
| 3086 | { | 3086 | { | |||||
| HITCBC | 3087 | 60 | case 3: | 3087 | 60 | case 3: | ||
| HITCBC | 3088 | 60 | *dest++ = '/'; | 3088 | 60 | *dest++ = '/'; | ||
| HITCBC | 3089 | 60 | *dest++ = '.'; | 3089 | 60 | *dest++ = '.'; | ||
| HITCBC | 3090 | 60 | *dest++ = '/'; | 3090 | 60 | *dest++ = '/'; | ||
| HITCBC | 3091 | 60 | break; | 3091 | 60 | break; | ||
| HITCBC | 3092 | 42 | case 2: | 3092 | 42 | case 2: | ||
| HITCBC | 3093 | 42 | *dest++ = '.'; | 3093 | 42 | *dest++ = '.'; | ||
| 3094 | BOOST_FALLTHROUGH; | 3094 | BOOST_FALLTHROUGH; | |||||
| HITCBC | 3095 | 1193 | case 1: | 3095 | 1193 | case 1: | ||
| HITCBC | 3096 | 1193 | *dest++ = '/'; | 3096 | 1193 | *dest++ = '/'; | ||
| HITCBC | 3097 | 1193 | break; | 3097 | 1193 | break; | ||
| HITCBC | 3098 | 1060 | default: | 3098 | 1060 | default: | ||
| HITCBC | 3099 | 1060 | break; | 3099 | 1060 | break; | ||
| 3100 | } | 3100 | } | |||||
| HITCBC | 3101 | 2313 | src.rewind(); | 3101 | 2313 | src.rewind(); | ||
| HITCBC | 3102 | 2313 | if(nseg > 0) | 3102 | 2313 | if(nseg > 0) | ||
| 3103 | { | 3103 | { | |||||
| HITCBC | 3104 | 1277 | src.encode_colons = encode_colons; | 3104 | 1277 | src.encode_colons = encode_colons; | ||
| 3105 | for(;;) | 3105 | for(;;) | |||||
| 3106 | { | 3106 | { | |||||
| HITCBC | 3107 | 1603 | src.copy(dest, end); | 3107 | 1603 | src.copy(dest, end); | ||
| HITCBC | 3108 | 1603 | if(--nseg == 0) | 3108 | 1603 | if(--nseg == 0) | ||
| HITCBC | 3109 | 1277 | break; | 3109 | 1277 | break; | ||
| HITCBC | 3110 | 326 | *dest++ = '/'; | 3110 | 326 | *dest++ = '/'; | ||
| HITCBC | 3111 | 326 | src.encode_colons = false; | 3111 | 326 | src.encode_colons = false; | ||
| 3112 | } | 3112 | } | |||||
| HITCBC | 3113 | 1277 | if(suffix) | 3113 | 1277 | if(suffix) | ||
| HITCBC | 3114 | 179 | *dest++ = '/'; | 3114 | 179 | *dest++ = '/'; | ||
| 3115 | } | 3115 | } | |||||
| HITCBC | 3116 | 2313 | BOOST_ASSERT(dest == dest0 + nchar); | 3116 | 2313 | BOOST_ASSERT(dest == dest0 + nchar); | ||
| 3117 | 3117 | |||||||
| 3118 | // calc decoded size of new range, | 3118 | // calc decoded size of new range, | |||||
| 3119 | auto const dn = | 3119 | auto const dn = | |||||
| HITCBC | 3120 | 2313 | detail::decode_bytes_unsafe( | 3120 | 2313 | detail::decode_bytes_unsafe( | ||
| HITCBC | 3121 | 2313 | core::string_view(dest0, dest - dest0)); | 3121 | 2313 | core::string_view(dest0, dest - dest0)); | ||
| HITCBC | 3122 | 2313 | if(dn >= dn0) | 3122 | 2313 | if(dn >= dn0) | ||
| HITCBC | 3123 | 1401 | impl_.decoded_[id_path] += | 3123 | 1401 | impl_.decoded_[id_path] += | ||
| HITCBC | 3124 | 1401 | detail::to_size_type(dn - dn0); | 3124 | 1401 | detail::to_size_type(dn - dn0); | ||
| 3125 | else | 3125 | else | |||||
| HITCBC | 3126 | 912 | impl_.decoded_[id_path] -= | 3126 | 912 | impl_.decoded_[id_path] -= | ||
| HITCBC | 3127 | 912 | detail::to_size_type(dn0 - dn); | 3127 | 912 | detail::to_size_type(dn0 - dn); | ||
| 3128 | 3128 | |||||||
| 3129 | return detail::segments_iter_impl( | 3129 | return detail::segments_iter_impl( | |||||
| HITCBC | 3130 | 4626 | impl_, pos0, it0.index); | 3130 | 4626 | impl_, pos0, it0.index); | ||
| 3131 | } | 3131 | } | |||||
| 3132 | 3132 | |||||||
| 3133 | //------------------------------------------------ | 3133 | //------------------------------------------------ | |||||
| 3134 | 3134 | |||||||
| 3135 | inline | 3135 | inline | |||||
| 3136 | auto | 3136 | auto | |||||
| HITCBC | 3137 | 1695 | url_base:: | 3137 | 1701 | url_base:: | ||
| 3138 | edit_params( | 3138 | edit_params( | |||||
| 3139 | detail::params_iter_impl const& it0, | 3139 | detail::params_iter_impl const& it0, | |||||
| 3140 | detail::params_iter_impl const& it1, | 3140 | detail::params_iter_impl const& it1, | |||||
| 3141 | detail::any_params_iter&& src) -> | 3141 | detail::any_params_iter&& src) -> | |||||
| 3142 | detail::params_iter_impl | 3142 | detail::params_iter_impl | |||||
| 3143 | { | 3143 | { | |||||
| HITCBC | 3144 | 1695 | auto pos0 = impl_.offset(id_query); | 3144 | 1701 | auto pos0 = impl_.offset(id_query); | ||
| HITCBC | 3145 | 1695 | auto pos1 = pos0 + it1.pos; | 3145 | 1701 | auto pos1 = pos0 + it1.pos; | ||
| HITCBC | 3146 | 1695 | pos0 = pos0 + it0.pos; | 3146 | 1701 | pos0 = pos0 + it0.pos; | ||
| 3147 | 3147 | |||||||
| 3148 | // Iterators belong to this url | 3148 | // Iterators belong to this url | |||||
| HITCBC | 3149 | 1695 | BOOST_ASSERT(it0.ref.alias_of(impl_)); | 3149 | 1701 | BOOST_ASSERT(it0.ref.alias_of(impl_)); | ||
| HITCBC | 3150 | 1695 | BOOST_ASSERT(it1.ref.alias_of(impl_)); | 3150 | 1701 | BOOST_ASSERT(it1.ref.alias_of(impl_)); | ||
| 3151 | 3151 | |||||||
| 3152 | // Iterators is in the right order | 3152 | // Iterators is in the right order | |||||
| HITCBC | 3153 | 1695 | BOOST_ASSERT(it0.index <= it1.index); | 3153 | 1701 | BOOST_ASSERT(it0.index <= it1.index); | ||
| 3154 | 3154 | |||||||
| 3155 | // Iterators are within range | 3155 | // Iterators are within range | |||||
| HITCBC | 3156 | 1695 | BOOST_ASSERT(it0.index <= impl_.nparam_); | 3156 | 1701 | BOOST_ASSERT(it0.index <= impl_.nparam_); | ||
| HITCBC | 3157 | 1695 | BOOST_ASSERT(pos0 <= impl_.offset(id_frag)); | 3157 | 1701 | BOOST_ASSERT(pos0 <= impl_.offset(id_frag)); | ||
| HITCBC | 3158 | 1695 | BOOST_ASSERT(it1.index <= impl_.nparam_); | 3158 | 1701 | BOOST_ASSERT(it1.index <= impl_.nparam_); | ||
| HITCBC | 3159 | 1695 | BOOST_ASSERT(pos1 <= impl_.offset(id_frag)); | 3159 | 1701 | BOOST_ASSERT(pos1 <= impl_.offset(id_frag)); | ||
| 3160 | 3160 | |||||||
| 3161 | // calc decoded size of old range, | 3161 | // calc decoded size of old range, | |||||
| 3162 | - | // minus one if '?' or '&' prefixed | 3162 | + | // minus one for the leading '?' which is | |||
| 3163 | + | // not counted in decoded_[id_query]. | ||||||
| 3164 | + | // dn0 may be -1 here when the old range is | ||||||
| 3165 | + | // empty and the query was non-empty; the | ||||||
| 3166 | + | // matching subtraction on dn below cancels | ||||||
| 3167 | + | // that out when the delta is taken. | ||||||
| 3163 | auto dn0 = | 3168 | auto dn0 = | |||||
| 3164 | static_cast<std::ptrdiff_t>( | 3169 | static_cast<std::ptrdiff_t>( | |||||
| HITCBC | 3165 | 1695 | detail::decode_bytes_unsafe( | 3170 | 1701 | detail::decode_bytes_unsafe( | ||
| 3166 | core::string_view( | 3171 | core::string_view( | |||||
| HITCBC | 3167 | 1695 | impl_.cs_ + pos0, | 3172 | 1701 | impl_.cs_ + pos0, | ||
| HITCBC | 3168 | 1695 | pos1 - pos0))); | 3173 | 1701 | pos1 - pos0))); | ||
| HITCBC | 3169 | 1695 | if(impl_.len(id_query) > 0) | 3174 | 1701 | if(impl_.len(id_query) > 0) | ||
| DCB | 3170 | - | 1157 | if(dn0 < 0) | ||||
| DCB | 3171 | - | 1695 | dn0 = 0; | ||||
| HITCBC | 3172 | 552 | dn0 -= 1; | 3175 | 1162 | dn0 -= 1; | ||
| 3173 | 3176 | |||||||
| 3174 | //------------------------------------------------ | 3177 | //------------------------------------------------ | |||||
| 3175 | // | 3178 | // | |||||
| 3176 | // Measure the number of encoded characters | 3179 | // Measure the number of encoded characters | |||||
| 3177 | // of output, and the number of inserted | 3180 | // of output, and the number of inserted | |||||
| 3178 | // segments including internal separators. | 3181 | // segments including internal separators. | |||||
| 3179 | // | 3182 | // | |||||
| 3180 | 3183 | |||||||
| HITCBC | 3181 | 1695 | std::size_t nchar = 0; | 3184 | 1701 | std::size_t nchar = 0; | ||
| HITCBC | 3182 | 1695 | std::size_t nparam = 0; | 3185 | 1701 | std::size_t nparam = 0; | ||
| HITCBC | 3183 | 1695 | if(src.measure(nchar)) | 3186 | 1701 | if(src.measure(nchar)) | ||
| 3184 | { | 3187 | { | |||||
| HITCBC | 3185 | 1430 | ++nchar; // for '?' or '&' | 3188 | 1434 | ++nchar; // for '?' or '&' | ||
| 3186 | for(;;) | 3189 | for(;;) | |||||
| 3187 | { | 3190 | { | |||||
| HITCBC | 3188 | 1652 | ++nparam; | 3191 | 1656 | ++nparam; | ||
| HITCBC | 3189 | 1652 | if(! src.measure(nchar)) | 3192 | 1656 | if(! src.measure(nchar)) | ||
| HITCBC | 3190 | 1430 | break; | 3193 | 1434 | break; | ||
| HITCBC | 3191 | 222 | ++nchar; // for '&' | 3194 | 222 | ++nchar; // for '&' | ||
| 3192 | } | 3195 | } | |||||
| 3193 | } | 3196 | } | |||||
| 3194 | 3197 | |||||||
| 3195 | //------------------------------------------------ | 3198 | //------------------------------------------------ | |||||
| 3196 | // | 3199 | // | |||||
| 3197 | // Resize | 3200 | // Resize | |||||
| 3198 | // | 3201 | // | |||||
| HITCBC | 3199 | 1690 | op_t op(*this, &src.s0, &src.s1); | 3202 | 1696 | op_t op(*this, &src.s0, &src.s1); | ||
| 3200 | char* dest; | 3203 | char* dest; | |||||
| 3201 | char const* end; | 3204 | char const* end; | |||||
| 3202 | { | 3205 | { | |||||
| HITCBC | 3203 | 1690 | auto const nremove = pos1 - pos0; | 3206 | 1696 | auto const nremove = pos1 - pos0; | ||
| 3204 | // check overflow | 3207 | // check overflow | |||||
| HITCBC | 3205 | 2995 | if( nchar > nremove && | 3208 | 3005 | if( nchar > nremove && | ||
| HITCBC | 3206 | 1305 | nchar - nremove > | 3209 | 1309 | nchar - nremove > | ||
| HITCBC | 3207 | 1305 | max_size() - size()) | 3210 | 1309 | max_size() - size()) | ||
| 3208 | { | 3211 | { | |||||
| 3209 | // too large | 3212 | // too large | |||||
| MISUBC | 3210 | ✗ | detail::throw_length_error(); | 3213 | ✗ | detail::throw_length_error(); | ||
| 3211 | } | 3214 | } | |||||
| HITCBC | 3212 | 1690 | auto const nparam1 = | 3215 | 1696 | auto const nparam1 = | ||
| HITCBC | 3213 | 1690 | static_cast<std::ptrdiff_t>(impl_.nparam_) + | 3216 | 1696 | static_cast<std::ptrdiff_t>(impl_.nparam_) + | ||
| HITCBC | 3214 | 1690 | static_cast<std::ptrdiff_t>(nparam) - | 3217 | 1696 | static_cast<std::ptrdiff_t>(nparam) - | ||
| HITCBC | 3215 | 1690 | static_cast<std::ptrdiff_t>(it1.index) + | 3218 | 1696 | static_cast<std::ptrdiff_t>(it1.index) + | ||
| HITCBC | 3216 | 1690 | static_cast<std::ptrdiff_t>(it0.index); | 3219 | 1696 | static_cast<std::ptrdiff_t>(it0.index); | ||
| HITCBC | 3217 | 1690 | BOOST_ASSERT(nparam1 >= 0); | 3220 | 1696 | BOOST_ASSERT(nparam1 >= 0); | ||
| HITCBC | 3218 | 1690 | reserve_impl(size() + nchar - nremove, op); | 3221 | 1696 | reserve_impl(size() + nchar - nremove, op); | ||
| HITCBC | 3219 | 1690 | dest = s_ + pos0; | 3222 | 1696 | dest = s_ + pos0; | ||
| HITCBC | 3220 | 1690 | end = dest + nchar; | 3223 | 1696 | end = dest + nchar; | ||
| HITCBC | 3221 | 1690 | if(impl_.nparam_ > 0) | 3224 | 1696 | if(impl_.nparam_ > 0) | ||
| 3222 | { | 3225 | { | |||||
| 3223 | // needed when we move | 3226 | // needed when we move | |||||
| 3224 | // the beginning of the query | 3227 | // the beginning of the query | |||||
| HITCBC | 3225 | 1152 | s_[impl_.offset(id_query)] = '&'; | 3228 | 1157 | s_[impl_.offset(id_query)] = '&'; | ||
| 3226 | } | 3229 | } | |||||
| HITCBC | 3227 | 1690 | op.move( | 3230 | 1696 | op.move( | ||
| HITCBC | 3228 | 1690 | dest + nchar, | 3231 | 1696 | dest + nchar, | ||
| HITCBC | 3229 | 1690 | impl_.cs_ + pos1, | 3232 | 1696 | impl_.cs_ + pos1, | ||
| HITCBC | 3230 | 1690 | size() - pos1); | 3233 | 1696 | size() - pos1); | ||
| HITCBC | 3231 | 3380 | impl_.set_size( | 3234 | 3392 | impl_.set_size( | ||
| 3232 | id_query, | 3235 | id_query, | |||||
| HITCBC | 3233 | 1690 | impl_.len(id_query) + | 3236 | 1696 | impl_.len(id_query) + | ||
| 3234 | nchar - nremove); | 3237 | nchar - nremove); | |||||
| HITCBC | 3235 | 1690 | impl_.nparam_ = | 3238 | 1696 | impl_.nparam_ = | ||
| HITCBC | 3236 | 1690 | detail::to_size_type(nparam1); | 3239 | 1696 | detail::to_size_type(nparam1); | ||
| HITCBC | 3237 | 1690 | if(nparam1 > 0) | 3240 | 1696 | if(nparam1 > 0) | ||
| 3238 | { | 3241 | { | |||||
| 3239 | // needed when we erase | 3242 | // needed when we erase | |||||
| 3240 | // the beginning of the query | 3243 | // the beginning of the query | |||||
| HITCBC | 3241 | 1587 | s_[impl_.offset(id_query)] = '?'; | 3244 | 1593 | s_[impl_.offset(id_query)] = '?'; | ||
| 3242 | } | 3245 | } | |||||
| HITCBC | 3243 | 1690 | if(s_) | 3246 | 1696 | if(s_) | ||
| HITCBC | 3244 | 1690 | s_[size()] = '\0'; | 3247 | 1696 | s_[size()] = '\0'; | ||
| 3245 | } | 3248 | } | |||||
| HITCBC | 3246 | 1690 | auto const dest0 = dest; | 3249 | 1696 | auto const dest0 = dest; | ||
| 3247 | 3250 | |||||||
| 3248 | //------------------------------------------------ | 3251 | //------------------------------------------------ | |||||
| 3249 | // | 3252 | // | |||||
| 3250 | // Output params and internal separators: | 3253 | // Output params and internal separators: | |||||
| 3251 | // | 3254 | // | |||||
| 3252 | // [ '?' param ] [ '&' param ] | 3255 | // [ '?' param ] [ '&' param ] | |||||
| 3253 | // | 3256 | // | |||||
| HITCBC | 3254 | 1690 | if(nparam > 0) | 3257 | 1696 | if(nparam > 0) | ||
| 3255 | { | 3258 | { | |||||
| HITCBC | 3256 | 1430 | if(it0.index == 0) | 3259 | 1434 | if(it0.index == 0) | ||
| HITCBC | 3257 | 887 | *dest++ = '?'; | 3260 | 889 | *dest++ = '?'; | ||
| 3258 | else | 3261 | else | |||||
| HITCBC | 3259 | 543 | *dest++ = '&'; | 3262 | 545 | *dest++ = '&'; | ||
| HITCBC | 3260 | 1430 | src.rewind(); | 3263 | 1434 | src.rewind(); | ||
| 3261 | for(;;) | 3264 | for(;;) | |||||
| 3262 | { | 3265 | { | |||||
| HITCBC | 3263 | 1652 | src.copy(dest, end); | 3266 | 1656 | src.copy(dest, end); | ||
| HITCBC | 3264 | 1652 | if(--nparam == 0) | 3267 | 1656 | if(--nparam == 0) | ||
| HITCBC | 3265 | 1430 | break; | 3268 | 1434 | break; | ||
| HITCBC | 3266 | 222 | *dest++ = '&'; | 3269 | 222 | *dest++ = '&'; | ||
| 3267 | } | 3270 | } | |||||
| 3268 | } | 3271 | } | |||||
| 3269 | 3272 | |||||||
| 3270 | - | // calc decoded size of new range, | 3273 | + | // calc decoded size of new range; see dn0. | |||
| 3271 | - | // minus one if '?' or '&' prefixed | ||||||
| 3272 | auto dn = | 3274 | auto dn = | |||||
| 3273 | static_cast<std::ptrdiff_t>( | 3275 | static_cast<std::ptrdiff_t>( | |||||
| HITCBC | 3274 | 1690 | detail::decode_bytes_unsafe( | 3276 | 1696 | detail::decode_bytes_unsafe( | ||
| HITCBC | 3275 | 1690 | core::string_view(dest0, dest - dest0))); | 3277 | 1696 | core::string_view(dest0, dest - dest0))); | ||
| HITCBC | 3276 | 1690 | if(impl_.len(id_query) > 0) | 3278 | 1696 | if(impl_.len(id_query) > 0) | ||
| DCB | 3277 | - | 1587 | if(dn < 0) | ||||
| DCB | 3278 | - | 1690 | dn = 0; | ||||
| HITCBC | 3279 | 157 | dn -= 1; | 3279 | 1593 | dn -= 1; | ||
| 3280 | 3280 | |||||||
| HITCBC | 3281 | 1690 | if(dn >= dn0) | 3281 | 1696 | if(dn >= dn0) | ||
| HITCBC | 3282 | 1310 | impl_.decoded_[id_query] += | 3282 | 1314 | impl_.decoded_[id_query] += | ||
| HITCBC | 3283 | 1310 | detail::to_size_type(dn - dn0); | 3283 | 1314 | detail::to_size_type(dn - dn0); | ||
| 3284 | else | 3284 | else | |||||
| HITCBC | 3285 | 380 | impl_.decoded_[id_query] -= | 3285 | 382 | impl_.decoded_[id_query] -= | ||
| HITCBC | 3286 | 380 | detail::to_size_type(dn0 - dn); | 3286 | 382 | detail::to_size_type(dn0 - dn); | ||
| 3287 | 3287 | |||||||
| 3288 | return detail::params_iter_impl( | 3288 | return detail::params_iter_impl( | |||||
| HITCBC | 3289 | 1690 | impl_, | 3289 | 1696 | impl_, | ||
| HITCBC | 3290 | 1690 | pos0 - impl_.offset_[id_query], | 3290 | 1696 | pos0 - impl_.offset_[id_query], | ||
| HITCBC | 3291 | 3380 | it0.index); | 3291 | 3392 | it0.index); | ||
| HITCBC | 3292 | 1690 | } | 3292 | 1696 | } | ||
| 3293 | 3293 | |||||||
| 3294 | //------------------------------------------------ | 3294 | //------------------------------------------------ | |||||
| 3295 | 3295 | |||||||
| 3296 | inline | 3296 | inline | |||||
| 3297 | void | 3297 | void | |||||
| HITCBC | 3298 | 563 | url_base:: | 3298 | 563 | url_base:: | ||
| 3299 | decoded_to_lower_impl(int id) noexcept | 3299 | decoded_to_lower_impl(int id) noexcept | |||||
| 3300 | { | 3300 | { | |||||
| HITCBC | 3301 | 563 | char* it = s_ + impl_.offset(id); | 3301 | 563 | char* it = s_ + impl_.offset(id); | ||
| HITCBC | 3302 | 563 | char const* const end = s_ + impl_.offset(id + 1); | 3302 | 563 | char const* const end = s_ + impl_.offset(id + 1); | ||
| HITCBC | 3303 | 3559 | while(it < end) | 3303 | 3559 | while(it < end) | ||
| 3304 | { | 3304 | { | |||||
| HITCBC | 3305 | 2996 | if (*it != '%') | 3305 | 2996 | if (*it != '%') | ||
| 3306 | { | 3306 | { | |||||
| HITCBC | 3307 | 5962 | *it = grammar::to_lower( | 3307 | 5962 | *it = grammar::to_lower( | ||
| HITCBC | 3308 | 2981 | *it); | 3308 | 2981 | *it); | ||
| HITCBC | 3309 | 2981 | ++it; | 3309 | 2981 | ++it; | ||
| HITCBC | 3310 | 2981 | continue; | 3310 | 2981 | continue; | ||
| 3311 | } | 3311 | } | |||||
| HITCBC | 3312 | 15 | it += 3; | 3312 | 15 | it += 3; | ||
| 3313 | } | 3313 | } | |||||
| HITCBC | 3314 | 563 | } | 3314 | 563 | } | ||
| 3315 | 3315 | |||||||
| 3316 | inline | 3316 | inline | |||||
| 3317 | void | 3317 | void | |||||
| HITCBC | 3318 | 217 | url_base:: | 3318 | 217 | url_base:: | ||
| 3319 | to_lower_impl(int id) noexcept | 3319 | to_lower_impl(int id) noexcept | |||||
| 3320 | { | 3320 | { | |||||
| HITCBC | 3321 | 217 | char* it = s_ + impl_.offset(id); | 3321 | 217 | char* it = s_ + impl_.offset(id); | ||
| HITCBC | 3322 | 217 | char const* const end = s_ + impl_.offset(id + 1); | 3322 | 217 | char const* const end = s_ + impl_.offset(id + 1); | ||
| HITCBC | 3323 | 1088 | while(it < end) | 3323 | 1088 | while(it < end) | ||
| 3324 | { | 3324 | { | |||||
| HITCBC | 3325 | 1742 | *it = grammar::to_lower( | 3325 | 1742 | *it = grammar::to_lower( | ||
| HITCBC | 3326 | 871 | *it); | 3326 | 871 | *it); | ||
| HITCBC | 3327 | 871 | ++it; | 3327 | 871 | ++it; | ||
| 3328 | } | 3328 | } | |||||
| HITCBC | 3329 | 217 | } | 3329 | 217 | } | ||
| 3330 | 3330 | |||||||
| 3331 | } // urls | 3331 | } // urls | |||||
| 3332 | } // boost | 3332 | } // boost | |||||
| 3333 | 3333 | |||||||
| 3334 | #endif | 3334 | #endif | |||||