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