diff --git a/d1/d98/helpers_8h_source.html b/d1/d98/helpers_8h_source.html index 205059e68..d678b16ce 100644 --- a/d1/d98/helpers_8h_source.html +++ b/d1/d98/helpers_8h_source.html @@ -124,115 +124,119 @@
12#include <string_view>
13#include <optional>
14
-
23namespace ada::helpers {
-
24
-
28template <typename out_iter>
-
29void encode_json(std::string_view view, out_iter out);
-
30
-
44ada_really_inline std::optional<std::string_view> prune_hash(
-
45 std::string_view& input) noexcept;
-
46
-
53ada_really_inline bool shorten_path(std::string& path,
-
54 ada::scheme::type type) noexcept;
-
55
-
62ada_really_inline bool shorten_path(std::string_view& path,
-
63 ada::scheme::type type) noexcept;
-
64
-
76ada_really_inline void parse_prepared_path(std::string_view input,
-
77 ada::scheme::type type,
-
78 std::string& path);
-
79
-
84ada_really_inline void remove_ascii_tab_or_newline(std::string& input) noexcept;
-
85
-
91ada_really_inline constexpr std::string_view substring(std::string_view input,
-
92 size_t pos) noexcept;
-
93
-
98bool overlaps(std::string_view input1, const std::string& input2) noexcept;
-
99
-
105ada_really_inline constexpr std::string_view substring(std::string_view input,
-
106 size_t pos1,
-
107 size_t pos2) noexcept {
-
108#if ADA_DEVELOPMENT_CHECKS
-
109 if (pos2 < pos1) {
-
110 std::cerr << "Negative-length substring: [" << pos1 << " to " << pos2 << ")"
-
111 << std::endl;
-
112 abort();
-
113 }
-
114#endif
-
115 return input.substr(pos1, pos2 - pos1);
-
116}
-
117
-
123ada_really_inline void resize(std::string_view& input, size_t pos) noexcept;
-
124
-
130ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
-
131 const bool is_special, std::string_view& view) noexcept;
-
132
-
138ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept;
-
139
-
145template <class url_type>
-
146ada_really_inline void strip_trailing_spaces_from_opaque_path(
-
147 url_type& url) noexcept;
-
148
-
153ada_really_inline size_t
-
154find_authority_delimiter_special(std::string_view view) noexcept;
-
155
-
160ada_really_inline size_t
-
161find_authority_delimiter(std::string_view view) noexcept;
-
162
-
166template <typename T, typename... Args>
-
167inline void inner_concat(std::string& buffer, T t) {
-
168 buffer.append(t);
-
169}
-
170
-
174template <typename T, typename... Args>
-
175inline void inner_concat(std::string& buffer, T t, Args... args) {
-
176 buffer.append(t);
-
177 return inner_concat(buffer, args...);
-
178}
-
179
-
185template <typename... Args>
-
186std::string concat(Args... args) {
-
187 std::string answer;
-
188 inner_concat(answer, args...);
-
189 return answer;
-
190}
-
191
-
196inline int leading_zeroes(uint32_t input_num) noexcept {
-
197#if ADA_REGULAR_VISUAL_STUDIO
-
198 unsigned long leading_zero(0);
-
199 unsigned long in(input_num);
-
200 return _BitScanReverse(&leading_zero, in) ? int(31 - leading_zero) : 32;
-
201#else
-
202 return __builtin_clz(input_num);
-
203#endif // ADA_REGULAR_VISUAL_STUDIO
-
204}
-
205
-
212inline int fast_digit_count(uint32_t x) noexcept {
-
213 auto int_log2 = [](uint32_t z) -> int {
-
214 return 31 - ada::helpers::leading_zeroes(z | 1);
-
215 };
-
216 // Compiles to very few instructions. Note that the
-
217 // table is static and thus effectively a constant.
-
218 // We leave it inside the function because it is meaningless
-
219 // outside of it (this comes at no performance cost).
-
220 const static uint64_t table[] = {
-
221 4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
-
222 12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
-
223 21474826480, 21474826480, 21474826480, 21474826480, 25769703776,
-
224 25769703776, 25769703776, 30063771072, 30063771072, 30063771072,
-
225 34349738368, 34349738368, 34349738368, 34349738368, 38554705664,
-
226 38554705664, 38554705664, 41949672960, 41949672960, 41949672960,
-
227 42949672960, 42949672960};
-
228 return int((x + table[int_log2(x)]) >> 32);
-
229}
-
230} // namespace ada::helpers
-
231
-
232#endif // ADA_HELPERS_H
+
15#if ADA_DEVELOPMENT_CHECKS
+
16#include <iostream>
+
17#endif // ADA_DEVELOPMENT_CHECKS
+
18
+
27namespace ada::helpers {
+
28
+
32template <typename out_iter>
+
33void encode_json(std::string_view view, out_iter out);
+
34
+
48ada_really_inline std::optional<std::string_view> prune_hash(
+
49 std::string_view& input) noexcept;
+
50
+
57ada_really_inline bool shorten_path(std::string& path,
+
58 ada::scheme::type type) noexcept;
+
59
+
66ada_really_inline bool shorten_path(std::string_view& path,
+
67 ada::scheme::type type) noexcept;
+
68
+
80ada_really_inline void parse_prepared_path(std::string_view input,
+
81 ada::scheme::type type,
+
82 std::string& path);
+
83
+
88ada_really_inline void remove_ascii_tab_or_newline(std::string& input) noexcept;
+
89
+
95ada_really_inline constexpr std::string_view substring(std::string_view input,
+
96 size_t pos) noexcept;
+
97
+
102bool overlaps(std::string_view input1, const std::string& input2) noexcept;
+
103
+
109ada_really_inline constexpr std::string_view substring(std::string_view input,
+
110 size_t pos1,
+
111 size_t pos2) noexcept {
+
112#if ADA_DEVELOPMENT_CHECKS
+
113 if (pos2 < pos1) {
+
114 std::cerr << "Negative-length substring: [" << pos1 << " to " << pos2 << ")"
+
115 << std::endl;
+
116 abort();
+
117 }
+
118#endif
+
119 return input.substr(pos1, pos2 - pos1);
+
120}
+
121
+
127ada_really_inline void resize(std::string_view& input, size_t pos) noexcept;
+
128
+
134ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
+
135 bool is_special, std::string_view& view) noexcept;
+
136
+
142ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept;
+
143
+
149template <class url_type>
+
150ada_really_inline void strip_trailing_spaces_from_opaque_path(
+
151 url_type& url) noexcept;
+
152
+
157ada_really_inline size_t
+
158find_authority_delimiter_special(std::string_view view) noexcept;
+
159
+
164ada_really_inline size_t
+
165find_authority_delimiter(std::string_view view) noexcept;
+
166
+
170template <typename T, typename... Args>
+
171inline void inner_concat(std::string& buffer, T t) {
+
172 buffer.append(t);
+
173}
+
174
+
178template <typename T, typename... Args>
+
179inline void inner_concat(std::string& buffer, T t, Args... args) {
+
180 buffer.append(t);
+
181 return inner_concat(buffer, args...);
+
182}
+
183
+
189template <typename... Args>
+
190std::string concat(Args... args) {
+
191 std::string answer;
+
192 inner_concat(answer, args...);
+
193 return answer;
+
194}
+
195
+
200inline int leading_zeroes(uint32_t input_num) noexcept {
+
201#if ADA_REGULAR_VISUAL_STUDIO
+
202 unsigned long leading_zero(0);
+
203 unsigned long in(input_num);
+
204 return _BitScanReverse(&leading_zero, in) ? int(31 - leading_zero) : 32;
+
205#else
+
206 return __builtin_clz(input_num);
+
207#endif // ADA_REGULAR_VISUAL_STUDIO
+
208}
+
209
+
216inline int fast_digit_count(uint32_t x) noexcept {
+
217 auto int_log2 = [](uint32_t z) -> int {
+
218 return 31 - ada::helpers::leading_zeroes(z | 1);
+
219 };
+
220 // Compiles to very few instructions. Note that the
+
221 // table is static and thus effectively a constant.
+
222 // We leave it inside the function because it is meaningless
+
223 // outside of it (this comes at no performance cost).
+
224 const static uint64_t table[] = {
+
225 4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
+
226 12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
+
227 21474826480, 21474826480, 21474826480, 21474826480, 25769703776,
+
228 25769703776, 25769703776, 30063771072, 30063771072, 30063771072,
+
229 34349738368, 34349738368, 34349738368, 34349738368, 38554705664,
+
230 38554705664, 38554705664, 41949672960, 41949672960, 41949672960,
+
231 42949672960, 42949672960};
+
232 return int((x + table[int_log2(x)]) >> 32);
+
233}
+
234} // namespace ada::helpers
+
235
+
236#endif // ADA_HELPERS_H
common_defs.h
Common definitions for cross-platform compiler support.
ada_really_inline
#define ada_really_inline
Definition common_defs.h:84
ada::helpers
Includes the definitions for helper functions.
ada::idna::table
const uint32_t table[8000][2]
Definition ada_idna.cpp:584
-
ada::scheme::type
type
Definition scheme.h:30
+
ada::scheme::type
type
Definition scheme.h:29
state.h
Definitions for the states of the URL state machine.
url_base.h
Declaration for the basic URL definitions.
diff --git a/d2/d35/url__search__params-inl_8h_source.html b/d2/d35/url__search__params-inl_8h_source.html index e592b7f7b..68451f21a 100644 --- a/d2/d35/url__search__params-inl_8h_source.html +++ b/d2/d35/url__search__params-inl_8h_source.html @@ -326,7 +326,7 @@
194
195template <typename T, url_search_params_iter_type Type>
-
196inline bool url_search_params_iter<T, Type>::has_next() {
+
196inline bool url_search_params_iter<T, Type>::has_next() const {
197 return pos < params.params.size();
198}
@@ -334,7 +334,7 @@
200template <>
201inline std::optional<std::string_view> url_search_params_keys_iter::next() {
-
202 if (!has_next()) {
+
202 if (!has_next()) {
203 return std::nullopt;
204 }
205 return params.params[pos++].first;
@@ -343,7 +343,7 @@
207
208template <>
209inline std::optional<std::string_view> url_search_params_values_iter::next() {
-
210 if (!has_next()) {
+
210 if (!has_next()) {
211 return std::nullopt;
212 }
213 return params.params[pos++].second;
@@ -352,7 +352,7 @@
216template <>
217inline std::optional<key_value_view_pair>
218url_search_params_entries_iter::next() {
-
219 if (!has_next()) {
+
219 if (!has_next()) {
220 return std::nullopt;
221 }
222 return params.params[pos++];
@@ -368,9 +368,9 @@
url_search_params_iter< std::string_view, url_search_params_iter_type::VALUES > url_search_params_values_iter
url_search_params_iter< key_value_view_pair, url_search_params_iter_type::ENTRIES > url_search_params_entries_iter
url_search_params_iter< std::string_view, url_search_params_iter_type::KEYS > url_search_params_keys_iter
-
-
bool has_next()
+
std::optional< T > next()
+
bool has_next() const
void set(std::string_view key, std::string_view value)
std::vector< std::string > get_all(std::string_view key)
void remove(std::string_view key)
diff --git a/d2/d63/namespaceada_1_1scheme.html b/d2/d63/namespaceada_1_1scheme.html index 8589f497a..2cbba621d 100644 --- a/d2/d63/namespaceada_1_1scheme.html +++ b/d2/d63/namespaceada_1_1scheme.html @@ -176,7 +176,7 @@

FILE  -

Definition at line 30 of file scheme.h.

+

Definition at line 29 of file scheme.h.

diff --git a/d2/d64/scheme_8h.html b/d2/d64/scheme_8h.html index 39be85d23..9b8cfeefe 100644 --- a/d2/d64/scheme_8h.html +++ b/d2/d64/scheme_8h.html @@ -122,7 +122,6 @@ More...

#include "ada/common_defs.h"
#include <array>
-#include <optional>
#include <string>

Go to the source code of this file.

diff --git a/d2/d64/scheme_8h_source.html b/d2/d64/scheme_8h_source.html index 4ae85511f..97d509894 100644 --- a/d2/d64/scheme_8h_source.html +++ b/d2/d64/scheme_8h_source.html @@ -120,45 +120,44 @@
8#include "ada/common_defs.h"
9
10#include <array>
-
11#include <optional>
-
12#include <string>
-
13
-
18namespace ada::scheme {
-
19
-
-
30enum type : uint8_t {
-
31 HTTP = 0,
-
32 NOT_SPECIAL = 1,
-
33 HTTPS = 2,
-
34 WS = 3,
-
35 FTP = 4,
-
36 WSS = 5,
-
37 FILE = 6
-
38};
+
11#include <string>
+
12
+
17namespace ada::scheme {
+
18
+
+
29enum type : uint8_t {
+
30 HTTP = 0,
+ +
32 HTTPS = 2,
+
33 WS = 3,
+
34 FTP = 4,
+
35 WSS = 5,
+
36 FILE = 6
+
37};
-
39
-
50ada_really_inline constexpr bool is_special(std::string_view scheme);
-
51
-
62constexpr uint16_t get_special_port(std::string_view scheme) noexcept;
-
63
-
68constexpr uint16_t get_special_port(ada::scheme::type type) noexcept;
-
73constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept;
-
74
-
75} // namespace ada::scheme
-
76
-
77#endif // ADA_SCHEME_H
+
38
+
49ada_really_inline constexpr bool is_special(std::string_view scheme);
+
50
+
61constexpr uint16_t get_special_port(std::string_view scheme) noexcept;
+
62
+
67constexpr uint16_t get_special_port(ada::scheme::type type) noexcept;
+
72constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept;
+
73
+
74} // namespace ada::scheme
+
75
+
76#endif // ADA_SCHEME_H
Common definitions for cross-platform compiler support.
#define ada_really_inline
Definition common_defs.h:84
Includes the scheme declarations.
Definition scheme-inl.h:10
constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept
Definition scheme-inl.h:72
-
type
Definition scheme.h:30
-
@ FTP
Definition scheme.h:35
-
@ WS
Definition scheme.h:34
-
@ HTTP
Definition scheme.h:31
-
@ FILE
Definition scheme.h:37
-
@ NOT_SPECIAL
Definition scheme.h:32
-
@ WSS
Definition scheme.h:36
-
@ HTTPS
Definition scheme.h:33
+
type
Definition scheme.h:29
+
@ FTP
Definition scheme.h:34
+
@ WS
Definition scheme.h:33
+
@ HTTP
Definition scheme.h:30
+
@ FILE
Definition scheme.h:36
+
@ NOT_SPECIAL
Definition scheme.h:31
+
@ WSS
Definition scheme.h:35
+
@ HTTPS
Definition scheme.h:32
constexpr uint16_t get_special_port(std::string_view scheme) noexcept
Definition scheme-inl.h:57
diff --git a/d2/d6f/url__base-inl_8h_source.html b/d2/d6f/url__base-inl_8h_source.html index 515fce1a8..9b6905734 100644 --- a/d2/d6f/url__base-inl_8h_source.html +++ b/d2/d6f/url__base-inl_8h_source.html @@ -154,7 +154,7 @@
40#endif // ADA_URL_BASE_INL_H
checkers.h
Declarations for URL specific checkers used within Ada.
ada_really_inline
#define ada_really_inline
Definition common_defs.h:84
-
ada::scheme::NOT_SPECIAL
@ NOT_SPECIAL
Definition scheme.h:32
+
ada::scheme::NOT_SPECIAL
@ NOT_SPECIAL
Definition scheme.h:31
ada::scheme::get_special_port
constexpr uint16_t get_special_port(std::string_view scheme) noexcept
Definition scheme-inl.h:57
ada
Definition ada_idna.h:13
scheme-inl.h
Definitions for the URL scheme.
diff --git a/d2/df4/helpers_8cpp_source.html b/d2/df4/helpers_8cpp_source.html index 3185780d2..7db4d20ef 100644 --- a/d2/df4/helpers_8cpp_source.html +++ b/d2/df4/helpers_8cpp_source.html @@ -213,690 +213,682 @@
96
97ada_really_inline bool shorten_path(std::string& path,
98 ada::scheme::type type) noexcept {
-
99 size_t first_delimiter = path.find_first_of('/', 1);
-
100
-
101 // Let path be url's path.
-
102 // If url's scheme is "file", path's size is 1, and path[0] is a normalized
-
103 // Windows drive letter, then return.
-
104 if (type == ada::scheme::type::FILE &&
-
105 first_delimiter == std::string_view::npos && !path.empty()) {
-
106 if (checkers::is_normalized_windows_drive_letter(
-
107 helpers::substring(path, 1))) {
-
108 return false;
-
109 }
-
110 }
-
111
-
112 // Remove path's last item, if any.
-
113 size_t last_delimiter = path.rfind('/');
-
114 if (last_delimiter != std::string::npos) {
-
115 path.erase(last_delimiter);
-
116 return true;
-
117 }
-
118
-
119 return false;
-
120}
-
121
-
122ada_really_inline bool shorten_path(std::string_view& path,
-
123 ada::scheme::type type) noexcept {
-
124 size_t first_delimiter = path.find_first_of('/', 1);
-
125
-
126 // Let path be url's path.
-
127 // If url's scheme is "file", path's size is 1, and path[0] is a normalized
-
128 // Windows drive letter, then return.
-
129 if (type == ada::scheme::type::FILE &&
-
130 first_delimiter == std::string_view::npos && !path.empty()) {
-
131 if (checkers::is_normalized_windows_drive_letter(
-
132 helpers::substring(path, 1))) {
-
133 return false;
-
134 }
-
135 }
-
136
-
137 // Remove path's last item, if any.
-
138 if (!path.empty()) {
-
139 size_t slash_loc = path.rfind('/');
-
140 if (slash_loc != std::string_view::npos) {
-
141 path.remove_suffix(path.size() - slash_loc);
-
142 return true;
-
143 }
-
144 }
-
145
-
146 return false;
-
147}
-
148
-
149ada_really_inline void remove_ascii_tab_or_newline(
-
150 std::string& input) noexcept {
-
151 // if this ever becomes a performance issue, we could use an approach similar
-
152 // to has_tabs_or_newline
-
153 input.erase(std::remove_if(input.begin(), input.end(),
-
154 [](char c) {
-
155 return ada::unicode::is_ascii_tab_or_newline(c);
-
156 }),
-
157 input.end());
+
99 // Let path be url's path.
+
100 // If url's scheme is "file", path's size is 1, and path[0] is a normalized
+
101 // Windows drive letter, then return.
+
102 if (type == ada::scheme::type::FILE &&
+
103 path.find('/', 1) == std::string_view::npos && !path.empty()) {
+
104 if (checkers::is_normalized_windows_drive_letter(
+
105 helpers::substring(path, 1))) {
+
106 return false;
+
107 }
+
108 }
+
109
+
110 // Remove path's last item, if any.
+
111 size_t last_delimiter = path.rfind('/');
+
112 if (last_delimiter != std::string::npos) {
+
113 path.erase(last_delimiter);
+
114 return true;
+
115 }
+
116
+
117 return false;
+
118}
+
119
+
120ada_really_inline bool shorten_path(std::string_view& path,
+
121 ada::scheme::type type) noexcept {
+
122 // Let path be url's path.
+
123 // If url's scheme is "file", path's size is 1, and path[0] is a normalized
+
124 // Windows drive letter, then return.
+
125 if (type == ada::scheme::type::FILE &&
+
126 path.find('/', 1) == std::string_view::npos && !path.empty()) {
+
127 if (checkers::is_normalized_windows_drive_letter(
+
128 helpers::substring(path, 1))) {
+
129 return false;
+
130 }
+
131 }
+
132
+
133 // Remove path's last item, if any.
+
134 if (!path.empty()) {
+
135 size_t slash_loc = path.rfind('/');
+
136 if (slash_loc != std::string_view::npos) {
+
137 path.remove_suffix(path.size() - slash_loc);
+
138 return true;
+
139 }
+
140 }
+
141
+
142 return false;
+
143}
+
144
+
145ada_really_inline void remove_ascii_tab_or_newline(
+
146 std::string& input) noexcept {
+
147 // if this ever becomes a performance issue, we could use an approach similar
+
148 // to has_tabs_or_newline
+
149 std::erase_if(input, ada::unicode::is_ascii_tab_or_newline);
+
150}
+
151
+
152ada_really_inline constexpr std::string_view substring(std::string_view input,
+
153 size_t pos) noexcept {
+
154 ADA_ASSERT_TRUE(pos <= input.size());
+
155 // The following is safer but unneeded if we have the above line:
+
156 // return pos > input.size() ? std::string_view() : input.substr(pos);
+
157 return input.substr(pos);
158}
159
-
160ada_really_inline constexpr std::string_view substring(std::string_view input,
-
161 size_t pos) noexcept {
-
162 ADA_ASSERT_TRUE(pos <= input.size());
-
163 // The following is safer but unneeded if we have the above line:
-
164 // return pos > input.size() ? std::string_view() : input.substr(pos);
-
165 return input.substr(pos);
-
166}
-
167
-
168ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
-
169 ADA_ASSERT_TRUE(pos <= input.size());
-
170 input.remove_suffix(input.size() - pos);
-
171}
-
172
-
173// computes the number of trailing zeroes
-
174// this is a private inline function only defined in this source file.
-
-
175ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
-
176#ifdef ADA_REGULAR_VISUAL_STUDIO
-
177 unsigned long ret;
-
178 // Search the mask data from least significant bit (LSB)
-
179 // to the most significant bit (MSB) for a set bit (1).
-
180 _BitScanForward(&ret, input_num);
-
181 return (int)ret;
-
182#else // ADA_REGULAR_VISUAL_STUDIO
-
183 return __builtin_ctzl(input_num);
-
184#endif // ADA_REGULAR_VISUAL_STUDIO
-
185}
+
160ada_really_inline void resize(std::string_view& input, size_t pos) noexcept {
+
161 ADA_ASSERT_TRUE(pos <= input.size());
+
162 input.remove_suffix(input.size() - pos);
+
163}
+
164
+
165// computes the number of trailing zeroes
+
166// this is a private inline function only defined in this source file.
+
+
167ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept {
+
168#ifdef ADA_REGULAR_VISUAL_STUDIO
+
169 unsigned long ret;
+
170 // Search the mask data from least significant bit (LSB)
+
171 // to the most significant bit (MSB) for a set bit (1).
+
172 _BitScanForward(&ret, input_num);
+
173 return (int)ret;
+
174#else // ADA_REGULAR_VISUAL_STUDIO
+
175 return __builtin_ctzl(input_num);
+
176#endif // ADA_REGULAR_VISUAL_STUDIO
+
177}
-
186
-
187// starting at index location, this finds the next location of a character
-
188// :, /, \\, ? or [. If none is found, view.size() is returned.
-
189// For use within get_host_delimiter_location.
-
190#if ADA_NEON
-
191// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
-
192// support direct initialization of uint8x16_t. See
-
193// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
-
194#ifndef ada_make_uint8x16_t
-
195#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
-
196 x13, x14, x15, x16) \
-
197 ([=]() { \
-
198 static uint8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8, \
-
199 x9, x10, x11, x12, x13, x14, x15, x16}; \
-
200 return vld1q_u8(array); \
-
201 }())
-
202#endif
-
203
-
204ada_really_inline size_t find_next_host_delimiter_special(
-
205 std::string_view view, size_t location) noexcept {
-
206 // first check for short strings in which case we do it naively.
-
207 if (view.size() - location < 16) { // slow path
-
208 for (size_t i = location; i < view.size(); i++) {
-
209 if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
-
210 view[i] == '?' || view[i] == '[') {
-
211 return i;
-
212 }
-
213 }
-
214 return size_t(view.size());
-
215 }
-
216 auto to_bitmask = [](uint8x16_t input) -> uint16_t {
-
217 uint8x16_t bit_mask =
-
218 ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
-
219 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
-
220 uint8x16_t minput = vandq_u8(input, bit_mask);
-
221 uint8x16_t tmp = vpaddq_u8(minput, minput);
-
222 tmp = vpaddq_u8(tmp, tmp);
-
223 tmp = vpaddq_u8(tmp, tmp);
-
224 return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
-
225 };
-
226
-
227 // fast path for long strings (expected to be common)
-
228 size_t i = location;
-
229 uint8x16_t low_mask =
-
230 ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
231 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
-
232 uint8x16_t high_mask =
-
233 ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
-
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
-
235 uint8x16_t fmask = vmovq_n_u8(0xf);
-
236 uint8x16_t zero{0};
-
237 for (; i + 15 < view.size(); i += 16) {
-
238 uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
-
239 uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
-
240 uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
-
241 uint8x16_t classify = vandq_u8(lowpart, highpart);
-
242 if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
-
243 uint8x16_t is_zero = vceqq_u8(classify, zero);
-
244 uint16_t is_non_zero = ~to_bitmask(is_zero);
-
245 return i + trailing_zeroes(is_non_zero);
-
246 }
-
247 }
-
248
-
249 if (i < view.size()) {
-
250 uint8x16_t word =
-
251 vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
-
252 uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
-
253 uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
-
254 uint8x16_t classify = vandq_u8(lowpart, highpart);
-
255 if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
-
256 uint8x16_t is_zero = vceqq_u8(classify, zero);
-
257 uint16_t is_non_zero = ~to_bitmask(is_zero);
-
258 return view.length() - 16 + trailing_zeroes(is_non_zero);
-
259 }
-
260 }
-
261 return size_t(view.size());
-
262}
-
263#elif ADA_SSE2
-
264ada_really_inline size_t find_next_host_delimiter_special(
-
265 std::string_view view, size_t location) noexcept {
-
266 // first check for short strings in which case we do it naively.
-
267 if (view.size() - location < 16) { // slow path
-
268 for (size_t i = location; i < view.size(); i++) {
-
269 if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
-
270 view[i] == '?' || view[i] == '[') {
-
271 return i;
-
272 }
-
273 }
-
274 return size_t(view.size());
-
275 }
-
276 // fast path for long strings (expected to be common)
-
277 size_t i = location;
-
278 const __m128i mask1 = _mm_set1_epi8(':');
-
279 const __m128i mask2 = _mm_set1_epi8('/');
-
280 const __m128i mask3 = _mm_set1_epi8('\\');
-
281 const __m128i mask4 = _mm_set1_epi8('?');
-
282 const __m128i mask5 = _mm_set1_epi8('[');
-
283
-
284 for (; i + 15 < view.size(); i += 16) {
-
285 __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
-
286 __m128i m1 = _mm_cmpeq_epi8(word, mask1);
-
287 __m128i m2 = _mm_cmpeq_epi8(word, mask2);
-
288 __m128i m3 = _mm_cmpeq_epi8(word, mask3);
-
289 __m128i m4 = _mm_cmpeq_epi8(word, mask4);
-
290 __m128i m5 = _mm_cmpeq_epi8(word, mask5);
-
291 __m128i m = _mm_or_si128(
-
292 _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
-
293 int mask = _mm_movemask_epi8(m);
-
294 if (mask != 0) {
-
295 return i + trailing_zeroes(mask);
-
296 }
-
297 }
-
298 if (i < view.size()) {
-
299 __m128i word =
-
300 _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
-
301 __m128i m1 = _mm_cmpeq_epi8(word, mask1);
-
302 __m128i m2 = _mm_cmpeq_epi8(word, mask2);
-
303 __m128i m3 = _mm_cmpeq_epi8(word, mask3);
-
304 __m128i m4 = _mm_cmpeq_epi8(word, mask4);
-
305 __m128i m5 = _mm_cmpeq_epi8(word, mask5);
-
306 __m128i m = _mm_or_si128(
-
307 _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
-
308 int mask = _mm_movemask_epi8(m);
-
309 if (mask != 0) {
-
310 return view.length() - 16 + trailing_zeroes(mask);
-
311 }
-
312 }
-
313 return size_t(view.length());
-
314}
-
315#else
-
316// : / [ \\ ?
-
-
317static constexpr std::array<uint8_t, 256> special_host_delimiters =
-
318 []() consteval {
-
319 std::array<uint8_t, 256> result{};
-
320 for (int i : {':', '/', '[', '\\', '?'}) {
-
321 result[i] = 1;
-
322 }
-
323 return result;
-
324 }();
+
178
+
179// starting at index location, this finds the next location of a character
+
180// :, /, \\, ? or [. If none is found, view.size() is returned.
+
181// For use within get_host_delimiter_location.
+
182#if ADA_NEON
+
183// The ada_make_uint8x16_t macro is necessary because Visual Studio does not
+
184// support direct initialization of uint8x16_t. See
+
185// https://developercommunity.visualstudio.com/t/error-C2078:-too-many-initializers-whe/402911?q=backend+neon
+
186#ifndef ada_make_uint8x16_t
+
187#define ada_make_uint8x16_t(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, \
+
188 x13, x14, x15, x16) \
+
189 ([=]() { \
+
190 static uint8_t array[16] = {x1, x2, x3, x4, x5, x6, x7, x8, \
+
191 x9, x10, x11, x12, x13, x14, x15, x16}; \
+
192 return vld1q_u8(array); \
+
193 }())
+
194#endif
+
195
+ +
197 std::string_view view, size_t location) noexcept {
+
198 // first check for short strings in which case we do it naively.
+
199 if (view.size() - location < 16) { // slow path
+
200 for (size_t i = location; i < view.size(); i++) {
+
201 if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
+
202 view[i] == '?' || view[i] == '[') {
+
203 return i;
+
204 }
+
205 }
+
206 return size_t(view.size());
+
207 }
+
208 auto to_bitmask = [](uint8x16_t input) -> uint16_t {
+
209 uint8x16_t bit_mask =
+
210 ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
+
211 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
+
212 uint8x16_t minput = vandq_u8(input, bit_mask);
+
213 uint8x16_t tmp = vpaddq_u8(minput, minput);
+
214 tmp = vpaddq_u8(tmp, tmp);
+
215 tmp = vpaddq_u8(tmp, tmp);
+
216 return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
+
217 };
+
218
+
219 // fast path for long strings (expected to be common)
+
220 size_t i = location;
+
221 uint8x16_t low_mask =
+
222 ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
223 0x00, 0x01, 0x04, 0x04, 0x00, 0x00, 0x03);
+
224 uint8x16_t high_mask =
+
225 ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
+
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+
227 uint8x16_t fmask = vmovq_n_u8(0xf);
+
228 uint8x16_t zero{0};
+
229 for (; i + 15 < view.size(); i += 16) {
+
230 uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
+
231 uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
+
232 uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
+
233 uint8x16_t classify = vandq_u8(lowpart, highpart);
+
234 if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
+
235 uint8x16_t is_zero = vceqq_u8(classify, zero);
+
236 uint16_t is_non_zero = ~to_bitmask(is_zero);
+
237 return i + trailing_zeroes(is_non_zero);
+
238 }
+
239 }
+
240
+
241 if (i < view.size()) {
+
242 uint8x16_t word =
+
243 vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
+
244 uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
+
245 uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
+
246 uint8x16_t classify = vandq_u8(lowpart, highpart);
+
247 if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
+
248 uint8x16_t is_zero = vceqq_u8(classify, zero);
+
249 uint16_t is_non_zero = ~to_bitmask(is_zero);
+
250 return view.length() - 16 + trailing_zeroes(is_non_zero);
+
251 }
+
252 }
+
253 return size_t(view.size());
+
254}
+
255#elif ADA_SSE2
+ +
257 std::string_view view, size_t location) noexcept {
+
258 // first check for short strings in which case we do it naively.
+
259 if (view.size() - location < 16) { // slow path
+
260 for (size_t i = location; i < view.size(); i++) {
+
261 if (view[i] == ':' || view[i] == '/' || view[i] == '\\' ||
+
262 view[i] == '?' || view[i] == '[') {
+
263 return i;
+
264 }
+
265 }
+
266 return size_t(view.size());
+
267 }
+
268 // fast path for long strings (expected to be common)
+
269 size_t i = location;
+
270 const __m128i mask1 = _mm_set1_epi8(':');
+
271 const __m128i mask2 = _mm_set1_epi8('/');
+
272 const __m128i mask3 = _mm_set1_epi8('\\');
+
273 const __m128i mask4 = _mm_set1_epi8('?');
+
274 const __m128i mask5 = _mm_set1_epi8('[');
+
275
+
276 for (; i + 15 < view.size(); i += 16) {
+
277 __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
+
278 __m128i m1 = _mm_cmpeq_epi8(word, mask1);
+
279 __m128i m2 = _mm_cmpeq_epi8(word, mask2);
+
280 __m128i m3 = _mm_cmpeq_epi8(word, mask3);
+
281 __m128i m4 = _mm_cmpeq_epi8(word, mask4);
+
282 __m128i m5 = _mm_cmpeq_epi8(word, mask5);
+
283 __m128i m = _mm_or_si128(
+
284 _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
+
285 int mask = _mm_movemask_epi8(m);
+
286 if (mask != 0) {
+
287 return i + trailing_zeroes(mask);
+
288 }
+
289 }
+
290 if (i < view.size()) {
+
291 __m128i word =
+
292 _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
+
293 __m128i m1 = _mm_cmpeq_epi8(word, mask1);
+
294 __m128i m2 = _mm_cmpeq_epi8(word, mask2);
+
295 __m128i m3 = _mm_cmpeq_epi8(word, mask3);
+
296 __m128i m4 = _mm_cmpeq_epi8(word, mask4);
+
297 __m128i m5 = _mm_cmpeq_epi8(word, mask5);
+
298 __m128i m = _mm_or_si128(
+
299 _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m3, m4)), m5);
+
300 int mask = _mm_movemask_epi8(m);
+
301 if (mask != 0) {
+
302 return view.length() - 16 + trailing_zeroes(mask);
+
303 }
+
304 }
+
305 return size_t(view.length());
+
306}
+
307#else
+
308// : / [ \\ ?
+
+
309static constexpr std::array<uint8_t, 256> special_host_delimiters =
+
310 []() consteval {
+
311 std::array<uint8_t, 256> result{};
+
312 for (int i : {':', '/', '[', '\\', '?'}) {
+
313 result[i] = 1;
+
314 }
+
315 return result;
+
316 }();
-
325// credit: @the-moisrex recommended a table-based approach
-
- -
327 std::string_view view, size_t location) noexcept {
-
328 auto const str = view.substr(location);
-
329 for (auto pos = str.begin(); pos != str.end(); ++pos) {
-
330 if (special_host_delimiters[(uint8_t)*pos]) {
-
331 return pos - str.begin() + location;
-
332 }
-
333 }
-
334 return size_t(view.size());
-
335}
+
317// credit: @the-moisrex recommended a table-based approach
+
+ +
319 std::string_view view, size_t location) noexcept {
+
320 auto const str = view.substr(location);
+
321 for (auto pos = str.begin(); pos != str.end(); ++pos) {
+
322 if (special_host_delimiters[(uint8_t)*pos]) {
+
323 return pos - str.begin() + location;
+
324 }
+
325 }
+
326 return size_t(view.size());
+
327}
-
336#endif
-
337
-
338// starting at index location, this finds the next location of a character
-
339// :, /, ? or [. If none is found, view.size() is returned.
-
340// For use within get_host_delimiter_location.
-
341#if ADA_NEON
-
342ada_really_inline size_t find_next_host_delimiter(std::string_view view,
-
343 size_t location) noexcept {
-
344 // first check for short strings in which case we do it naively.
-
345 if (view.size() - location < 16) { // slow path
-
346 for (size_t i = location; i < view.size(); i++) {
-
347 if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
-
348 view[i] == '[') {
-
349 return i;
-
350 }
-
351 }
-
352 return size_t(view.size());
-
353 }
-
354 auto to_bitmask = [](uint8x16_t input) -> uint16_t {
-
355 uint8x16_t bit_mask =
-
356 ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
-
357 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
-
358 uint8x16_t minput = vandq_u8(input, bit_mask);
-
359 uint8x16_t tmp = vpaddq_u8(minput, minput);
-
360 tmp = vpaddq_u8(tmp, tmp);
-
361 tmp = vpaddq_u8(tmp, tmp);
-
362 return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
-
363 };
-
364
-
365 // fast path for long strings (expected to be common)
-
366 size_t i = location;
-
367 uint8x16_t low_mask =
-
368 ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
369 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
-
370 uint8x16_t high_mask =
-
371 ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
-
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
-
373 uint8x16_t fmask = vmovq_n_u8(0xf);
-
374 uint8x16_t zero{0};
-
375 for (; i + 15 < view.size(); i += 16) {
-
376 uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
-
377 uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
-
378 uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
-
379 uint8x16_t classify = vandq_u8(lowpart, highpart);
-
380 if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
-
381 uint8x16_t is_zero = vceqq_u8(classify, zero);
-
382 uint16_t is_non_zero = ~to_bitmask(is_zero);
-
383 return i + trailing_zeroes(is_non_zero);
-
384 }
-
385 }
-
386
-
387 if (i < view.size()) {
-
388 uint8x16_t word =
-
389 vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
-
390 uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
-
391 uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
-
392 uint8x16_t classify = vandq_u8(lowpart, highpart);
-
393 if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
-
394 uint8x16_t is_zero = vceqq_u8(classify, zero);
-
395 uint16_t is_non_zero = ~to_bitmask(is_zero);
-
396 return view.length() - 16 + trailing_zeroes(is_non_zero);
-
397 }
-
398 }
-
399 return size_t(view.size());
-
400}
-
401#elif ADA_SSE2
-
402ada_really_inline size_t find_next_host_delimiter(std::string_view view,
-
403 size_t location) noexcept {
-
404 // first check for short strings in which case we do it naively.
-
405 if (view.size() - location < 16) { // slow path
-
406 for (size_t i = location; i < view.size(); i++) {
-
407 if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
-
408 view[i] == '[') {
-
409 return i;
-
410 }
-
411 }
-
412 return size_t(view.size());
-
413 }
-
414 // fast path for long strings (expected to be common)
-
415 size_t i = location;
-
416 const __m128i mask1 = _mm_set1_epi8(':');
-
417 const __m128i mask2 = _mm_set1_epi8('/');
-
418 const __m128i mask4 = _mm_set1_epi8('?');
-
419 const __m128i mask5 = _mm_set1_epi8('[');
-
420
-
421 for (; i + 15 < view.size(); i += 16) {
-
422 __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
-
423 __m128i m1 = _mm_cmpeq_epi8(word, mask1);
-
424 __m128i m2 = _mm_cmpeq_epi8(word, mask2);
-
425 __m128i m4 = _mm_cmpeq_epi8(word, mask4);
-
426 __m128i m5 = _mm_cmpeq_epi8(word, mask5);
-
427 __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
-
428 int mask = _mm_movemask_epi8(m);
-
429 if (mask != 0) {
-
430 return i + trailing_zeroes(mask);
-
431 }
-
432 }
-
433 if (i < view.size()) {
-
434 __m128i word =
-
435 _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
-
436 __m128i m1 = _mm_cmpeq_epi8(word, mask1);
-
437 __m128i m2 = _mm_cmpeq_epi8(word, mask2);
-
438 __m128i m4 = _mm_cmpeq_epi8(word, mask4);
-
439 __m128i m5 = _mm_cmpeq_epi8(word, mask5);
-
440 __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
-
441 int mask = _mm_movemask_epi8(m);
-
442 if (mask != 0) {
-
443 return view.length() - 16 + trailing_zeroes(mask);
-
444 }
-
445 }
-
446 return size_t(view.length());
-
447}
-
448#else
-
449// : / [ ?
-
-
450static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
-
451 std::array<uint8_t, 256> result{};
-
452 for (int i : {':', '/', '?', '['}) {
-
453 result[i] = 1;
-
454 }
-
455 return result;
-
456}();
+
328#endif
+
329
+
330// starting at index location, this finds the next location of a character
+
331// :, /, ? or [. If none is found, view.size() is returned.
+
332// For use within get_host_delimiter_location.
+
333#if ADA_NEON
+
334ada_really_inline size_t find_next_host_delimiter(std::string_view view,
+
335 size_t location) noexcept {
+
336 // first check for short strings in which case we do it naively.
+
337 if (view.size() - location < 16) { // slow path
+
338 for (size_t i = location; i < view.size(); i++) {
+
339 if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
+
340 view[i] == '[') {
+
341 return i;
+
342 }
+
343 }
+
344 return size_t(view.size());
+
345 }
+
346 auto to_bitmask = [](uint8x16_t input) -> uint16_t {
+
347 uint8x16_t bit_mask =
+
348 ada_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01,
+
349 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80);
+
350 uint8x16_t minput = vandq_u8(input, bit_mask);
+
351 uint8x16_t tmp = vpaddq_u8(minput, minput);
+
352 tmp = vpaddq_u8(tmp, tmp);
+
353 tmp = vpaddq_u8(tmp, tmp);
+
354 return vgetq_lane_u16(vreinterpretq_u16_u8(tmp), 0);
+
355 };
+
356
+
357 // fast path for long strings (expected to be common)
+
358 size_t i = location;
+
359 uint8x16_t low_mask =
+
360 ada_make_uint8x16_t(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
361 0x00, 0x01, 0x04, 0x00, 0x00, 0x00, 0x03);
+
362 uint8x16_t high_mask =
+
363 ada_make_uint8x16_t(0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00,
+
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
+
365 uint8x16_t fmask = vmovq_n_u8(0xf);
+
366 uint8x16_t zero{0};
+
367 for (; i + 15 < view.size(); i += 16) {
+
368 uint8x16_t word = vld1q_u8((const uint8_t*)view.data() + i);
+
369 uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
+
370 uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
+
371 uint8x16_t classify = vandq_u8(lowpart, highpart);
+
372 if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
+
373 uint8x16_t is_zero = vceqq_u8(classify, zero);
+
374 uint16_t is_non_zero = ~to_bitmask(is_zero);
+
375 return i + trailing_zeroes(is_non_zero);
+
376 }
+
377 }
+
378
+
379 if (i < view.size()) {
+
380 uint8x16_t word =
+
381 vld1q_u8((const uint8_t*)view.data() + view.length() - 16);
+
382 uint8x16_t lowpart = vqtbl1q_u8(low_mask, vandq_u8(word, fmask));
+
383 uint8x16_t highpart = vqtbl1q_u8(high_mask, vshrq_n_u8(word, 4));
+
384 uint8x16_t classify = vandq_u8(lowpart, highpart);
+
385 if (vmaxvq_u32(vreinterpretq_u32_u8(classify)) != 0) {
+
386 uint8x16_t is_zero = vceqq_u8(classify, zero);
+
387 uint16_t is_non_zero = ~to_bitmask(is_zero);
+
388 return view.length() - 16 + trailing_zeroes(is_non_zero);
+
389 }
+
390 }
+
391 return size_t(view.size());
+
392}
+
393#elif ADA_SSE2
+
394ada_really_inline size_t find_next_host_delimiter(std::string_view view,
+
395 size_t location) noexcept {
+
396 // first check for short strings in which case we do it naively.
+
397 if (view.size() - location < 16) { // slow path
+
398 for (size_t i = location; i < view.size(); i++) {
+
399 if (view[i] == ':' || view[i] == '/' || view[i] == '?' ||
+
400 view[i] == '[') {
+
401 return i;
+
402 }
+
403 }
+
404 return size_t(view.size());
+
405 }
+
406 // fast path for long strings (expected to be common)
+
407 size_t i = location;
+
408 const __m128i mask1 = _mm_set1_epi8(':');
+
409 const __m128i mask2 = _mm_set1_epi8('/');
+
410 const __m128i mask4 = _mm_set1_epi8('?');
+
411 const __m128i mask5 = _mm_set1_epi8('[');
+
412
+
413 for (; i + 15 < view.size(); i += 16) {
+
414 __m128i word = _mm_loadu_si128((const __m128i*)(view.data() + i));
+
415 __m128i m1 = _mm_cmpeq_epi8(word, mask1);
+
416 __m128i m2 = _mm_cmpeq_epi8(word, mask2);
+
417 __m128i m4 = _mm_cmpeq_epi8(word, mask4);
+
418 __m128i m5 = _mm_cmpeq_epi8(word, mask5);
+
419 __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
+
420 int mask = _mm_movemask_epi8(m);
+
421 if (mask != 0) {
+
422 return i + trailing_zeroes(mask);
+
423 }
+
424 }
+
425 if (i < view.size()) {
+
426 __m128i word =
+
427 _mm_loadu_si128((const __m128i*)(view.data() + view.length() - 16));
+
428 __m128i m1 = _mm_cmpeq_epi8(word, mask1);
+
429 __m128i m2 = _mm_cmpeq_epi8(word, mask2);
+
430 __m128i m4 = _mm_cmpeq_epi8(word, mask4);
+
431 __m128i m5 = _mm_cmpeq_epi8(word, mask5);
+
432 __m128i m = _mm_or_si128(_mm_or_si128(m1, m2), _mm_or_si128(m4, m5));
+
433 int mask = _mm_movemask_epi8(m);
+
434 if (mask != 0) {
+
435 return view.length() - 16 + trailing_zeroes(mask);
+
436 }
+
437 }
+
438 return size_t(view.length());
+
439}
+
440#else
+
441// : / [ ?
+
+
442static constexpr std::array<uint8_t, 256> host_delimiters = []() consteval {
+
443 std::array<uint8_t, 256> result{};
+
444 for (int i : {':', '/', '?', '['}) {
+
445 result[i] = 1;
+
446 }
+
447 return result;
+
448}();
-
457// credit: @the-moisrex recommended a table-based approach
-
-
458ada_really_inline size_t find_next_host_delimiter(std::string_view view,
-
459 size_t location) noexcept {
-
460 auto const str = view.substr(location);
-
461 for (auto pos = str.begin(); pos != str.end(); ++pos) {
-
462 if (host_delimiters[(uint8_t)*pos]) {
-
463 return pos - str.begin() + location;
-
464 }
-
465 }
-
466 return size_t(view.size());
-
467}
+
449// credit: @the-moisrex recommended a table-based approach
+
+
450ada_really_inline size_t find_next_host_delimiter(std::string_view view,
+
451 size_t location) noexcept {
+
452 auto const str = view.substr(location);
+
453 for (auto pos = str.begin(); pos != str.end(); ++pos) {
+
454 if (host_delimiters[(uint8_t)*pos]) {
+
455 return pos - str.begin() + location;
+
456 }
+
457 }
+
458 return size_t(view.size());
+
459}
-
468#endif
-
469
-
470ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
-
471 const bool is_special, std::string_view& view) noexcept {
-
480 const size_t view_size = view.size();
-
481 size_t location = 0;
-
482 bool found_colon = false;
-
502 if (is_special) {
-
503 // We move to the next delimiter.
-
504 location = find_next_host_delimiter_special(view, location);
-
505 // Unless we find '[' then we are going only going to have to call
-
506 // find_next_host_delimiter_special once.
-
507 for (; location < view_size;
-
508 location = find_next_host_delimiter_special(view, location)) {
-
509 if (view[location] == '[') {
-
510 location = view.find(']', location);
-
511 if (location == std::string_view::npos) {
-
512 // performance: view.find might get translated to a memchr, which
-
513 // has no notion of std::string_view::npos, so the code does not
-
514 // reflect the assembly.
-
515 location = view_size;
-
516 break;
-
517 }
-
518 } else {
-
519 found_colon = view[location] == ':';
-
520 break;
-
521 }
-
522 }
-
523 } else {
-
524 // We move to the next delimiter.
-
525 location = find_next_host_delimiter(view, location);
-
526 // Unless we find '[' then we are going only going to have to call
-
527 // find_next_host_delimiter_special once.
-
528 for (; location < view_size;
-
529 location = find_next_host_delimiter(view, location)) {
-
530 if (view[location] == '[') {
-
531 location = view.find(']', location);
-
532 if (location == std::string_view::npos) {
-
533 // performance: view.find might get translated to a memchr, which
-
534 // has no notion of std::string_view::npos, so the code does not
-
535 // reflect the assembly.
-
536 location = view_size;
-
537 break;
-
538 }
-
539 } else {
-
540 found_colon = view[location] == ':';
-
541 break;
-
542 }
-
543 }
-
544 }
-
545 // performance: remove_suffix may translate into a single instruction.
-
546 view.remove_suffix(view_size - location);
-
547 return {location, found_colon};
-
548}
-
549
-
550ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept {
-
551 while (!input.empty() &&
-
552 ada::unicode::is_c0_control_or_space(input.front())) {
-
553 input.remove_prefix(1);
-
554 }
-
555 while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
-
556 input.remove_suffix(1);
-
557 }
-
558}
-
559
-
560ada_really_inline void parse_prepared_path(std::string_view input,
- -
562 std::string& path) {
-
563 ada_log("parse_prepared_path ", input);
-
564 uint8_t accumulator = checkers::path_signature(input);
-
565 // Let us first detect a trivial case.
-
566 // If it is special, we check that we have no dot, no %, no \ and no
-
567 // character needing percent encoding. Otherwise, we check that we have no %,
-
568 // no dot, and no character needing percent encoding.
-
569 constexpr uint8_t need_encoding = 1;
-
570 constexpr uint8_t backslash_char = 2;
-
571 constexpr uint8_t dot_char = 4;
-
572 constexpr uint8_t percent_char = 8;
-
573 bool special = type != ada::scheme::NOT_SPECIAL;
-
574 bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
- -
576 bool trivial_path =
-
577 (special ? (accumulator == 0)
-
578 : ((accumulator & (need_encoding | dot_char | percent_char)) ==
-
579 0)) &&
-
580 (!may_need_slow_file_handling);
-
581 if (accumulator == dot_char && !may_need_slow_file_handling) {
-
582 // '4' means that we have at least one dot, but nothing that requires
-
583 // percent encoding or decoding. The only part that is not trivial is
-
584 // that we may have single dots and double dots path segments.
-
585 // If we have such segments, then we either have a path that begins
-
586 // with '.' (easy to check), or we have the sequence './'.
-
587 // Note: input cannot be empty, it must at least contain one character ('.')
-
588 // Note: we know that '\' is not present.
-
589 if (input[0] != '.') {
-
590 size_t slashdot = input.find("/.");
-
591 if (slashdot == std::string_view::npos) { // common case
-
592 trivial_path = true;
-
593 } else { // uncommon
-
594 // only three cases matter: /./, /.. or a final /
-
595 trivial_path =
-
596 !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
-
597 input[slashdot + 2] == '/');
-
598 }
-
599 }
-
600 }
-
601 if (trivial_path) {
-
602 ada_log("parse_path trivial");
-
603 path += '/';
-
604 path += input;
-
605 return;
-
606 }
-
607 // We are going to need to look a bit at the path, but let us see if we can
-
608 // ignore percent encoding *and* backslashes *and* percent characters.
-
609 // Except for the trivial case, this is likely to capture 99% of paths out
-
610 // there.
-
611 bool fast_path =
-
612 (special &&
-
613 (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
-
614 (type != ada::scheme::type::FILE);
-
615 if (fast_path) {
-
616 ada_log("parse_prepared_path fast");
-
617 // Here we don't need to worry about \ or percent encoding.
-
618 // We also do not have a file protocol. We might have dots, however,
-
619 // but dots must as appear as '.', and they cannot be encoded because
-
620 // the symbol '%' is not present.
-
621 size_t previous_location = 0; // We start at 0.
-
622 do {
-
623 size_t new_location = input.find('/', previous_location);
-
624 // std::string_view path_view = input;
-
625 // We process the last segment separately:
-
626 if (new_location == std::string_view::npos) {
-
627 std::string_view path_view = input.substr(previous_location);
-
628 if (path_view == "..") { // The path ends with ..
-
629 // e.g., if you receive ".." with an empty path, you go to "/".
-
630 if (path.empty()) {
-
631 path = '/';
-
632 return;
-
633 }
-
634 // Fast case where we have nothing to do:
-
635 if (path.back() == '/') {
-
636 return;
-
637 }
-
638 // If you have the path "/joe/myfriend",
-
639 // then you delete 'myfriend'.
-
640 path.resize(path.rfind('/') + 1);
-
641 return;
-
642 }
-
643 path += '/';
-
644 if (path_view != ".") {
-
645 path.append(path_view);
-
646 }
-
647 return;
-
648 } else {
-
649 // This is a non-final segment.
-
650 std::string_view path_view =
-
651 input.substr(previous_location, new_location - previous_location);
-
652 previous_location = new_location + 1;
-
653 if (path_view == "..") {
-
654 size_t last_delimiter = path.rfind('/');
-
655 if (last_delimiter != std::string::npos) {
-
656 path.erase(last_delimiter);
-
657 }
-
658 } else if (path_view != ".") {
-
659 path += '/';
-
660 path.append(path_view);
-
661 }
-
662 }
-
663 } while (true);
-
664 } else {
-
665 ada_log("parse_path slow");
-
666 // we have reached the general case
-
667 bool needs_percent_encoding = (accumulator & 1);
-
668 std::string path_buffer_tmp;
-
669 do {
-
670 size_t location = (special && (accumulator & 2))
-
671 ? input.find_first_of("/\\")
-
672 : input.find('/');
-
673 std::string_view path_view = input;
-
674 if (location != std::string_view::npos) {
-
675 path_view.remove_suffix(path_view.size() - location);
-
676 input.remove_prefix(location + 1);
-
677 }
-
678 // path_buffer is either path_view or it might point at a percent encoded
-
679 // temporary file.
-
680 std::string_view path_buffer =
-
681 (needs_percent_encoding &&
-
682 ada::unicode::percent_encode<false>(
-
683 path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
-
684 ? path_buffer_tmp
-
685 : path_view;
-
686 if (unicode::is_double_dot_path_segment(path_buffer)) {
-
687 if ((helpers::shorten_path(path, type) || special) &&
-
688 location == std::string_view::npos) {
-
689 path += '/';
-
690 }
-
691 } else if (unicode::is_single_dot_path_segment(path_buffer) &&
-
692 (location == std::string_view::npos)) {
-
693 path += '/';
-
694 }
-
695 // Otherwise, if path_buffer is not a single-dot path segment, then:
-
696 else if (!unicode::is_single_dot_path_segment(path_buffer)) {
-
697 // If url's scheme is "file", url's path is empty, and path_buffer is a
-
698 // Windows drive letter, then replace the second code point in
-
699 // path_buffer with U+003A (:).
-
700 if (type == ada::scheme::type::FILE && path.empty() &&
- -
702 path += '/';
-
703 path += path_buffer[0];
-
704 path += ':';
-
705 path_buffer.remove_prefix(2);
-
706 path.append(path_buffer);
-
707 } else {
-
708 // Append path_buffer to url's path.
-
709 path += '/';
-
710 path.append(path_buffer);
-
711 }
-
712 }
-
713 if (location == std::string_view::npos) {
-
714 return;
-
715 }
-
716 } while (true);
-
717 }
+
460#endif
+
461
+
462ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
+
463 const bool is_special, std::string_view& view) noexcept {
+
472 const size_t view_size = view.size();
+
473 size_t location = 0;
+
474 bool found_colon = false;
+
494 if (is_special) {
+
495 // We move to the next delimiter.
+
496 location = find_next_host_delimiter_special(view, location);
+
497 // Unless we find '[' then we are going only going to have to call
+
498 // find_next_host_delimiter_special once.
+
499 for (; location < view_size;
+
500 location = find_next_host_delimiter_special(view, location)) {
+
501 if (view[location] == '[') {
+
502 location = view.find(']', location);
+
503 if (location == std::string_view::npos) {
+
504 // performance: view.find might get translated to a memchr, which
+
505 // has no notion of std::string_view::npos, so the code does not
+
506 // reflect the assembly.
+
507 location = view_size;
+
508 break;
+
509 }
+
510 } else {
+
511 found_colon = view[location] == ':';
+
512 break;
+
513 }
+
514 }
+
515 } else {
+
516 // We move to the next delimiter.
+
517 location = find_next_host_delimiter(view, location);
+
518 // Unless we find '[' then we are going only going to have to call
+
519 // find_next_host_delimiter_special once.
+
520 for (; location < view_size;
+
521 location = find_next_host_delimiter(view, location)) {
+
522 if (view[location] == '[') {
+
523 location = view.find(']', location);
+
524 if (location == std::string_view::npos) {
+
525 // performance: view.find might get translated to a memchr, which
+
526 // has no notion of std::string_view::npos, so the code does not
+
527 // reflect the assembly.
+
528 location = view_size;
+
529 break;
+
530 }
+
531 } else {
+
532 found_colon = view[location] == ':';
+
533 break;
+
534 }
+
535 }
+
536 }
+
537 // performance: remove_suffix may translate into a single instruction.
+
538 view.remove_suffix(view_size - location);
+
539 return {location, found_colon};
+
540}
+
541
+
542ada_really_inline void trim_c0_whitespace(std::string_view& input) noexcept {
+
543 while (!input.empty() &&
+
544 ada::unicode::is_c0_control_or_space(input.front())) {
+
545 input.remove_prefix(1);
+
546 }
+
547 while (!input.empty() && ada::unicode::is_c0_control_or_space(input.back())) {
+
548 input.remove_suffix(1);
+
549 }
+
550}
+
551
+
552ada_really_inline void parse_prepared_path(std::string_view input,
+ +
554 std::string& path) {
+
555 ada_log("parse_prepared_path ", input);
+
556 uint8_t accumulator = checkers::path_signature(input);
+
557 // Let us first detect a trivial case.
+
558 // If it is special, we check that we have no dot, no %, no \ and no
+
559 // character needing percent encoding. Otherwise, we check that we have no %,
+
560 // no dot, and no character needing percent encoding.
+
561 constexpr uint8_t need_encoding = 1;
+
562 constexpr uint8_t backslash_char = 2;
+
563 constexpr uint8_t dot_char = 4;
+
564 constexpr uint8_t percent_char = 8;
+
565 bool special = type != ada::scheme::NOT_SPECIAL;
+
566 bool may_need_slow_file_handling = (type == ada::scheme::type::FILE &&
+ +
568 bool trivial_path =
+
569 (special ? (accumulator == 0)
+
570 : ((accumulator & (need_encoding | dot_char | percent_char)) ==
+
571 0)) &&
+
572 (!may_need_slow_file_handling);
+
573 if (accumulator == dot_char && !may_need_slow_file_handling) {
+
574 // '4' means that we have at least one dot, but nothing that requires
+
575 // percent encoding or decoding. The only part that is not trivial is
+
576 // that we may have single dots and double dots path segments.
+
577 // If we have such segments, then we either have a path that begins
+
578 // with '.' (easy to check), or we have the sequence './'.
+
579 // Note: input cannot be empty, it must at least contain one character ('.')
+
580 // Note: we know that '\' is not present.
+
581 if (input[0] != '.') {
+
582 size_t slashdot = input.find("/.");
+
583 if (slashdot == std::string_view::npos) { // common case
+
584 trivial_path = true;
+
585 } else { // uncommon
+
586 // only three cases matter: /./, /.. or a final /
+
587 trivial_path =
+
588 !(slashdot + 2 == input.size() || input[slashdot + 2] == '.' ||
+
589 input[slashdot + 2] == '/');
+
590 }
+
591 }
+
592 }
+
593 if (trivial_path) {
+
594 ada_log("parse_path trivial");
+
595 path += '/';
+
596 path += input;
+
597 return;
+
598 }
+
599 // We are going to need to look a bit at the path, but let us see if we can
+
600 // ignore percent encoding *and* backslashes *and* percent characters.
+
601 // Except for the trivial case, this is likely to capture 99% of paths out
+
602 // there.
+
603 bool fast_path =
+
604 (special &&
+
605 (accumulator & (need_encoding | backslash_char | percent_char)) == 0) &&
+
606 (type != ada::scheme::type::FILE);
+
607 if (fast_path) {
+
608 ada_log("parse_prepared_path fast");
+
609 // Here we don't need to worry about \ or percent encoding.
+
610 // We also do not have a file protocol. We might have dots, however,
+
611 // but dots must as appear as '.', and they cannot be encoded because
+
612 // the symbol '%' is not present.
+
613 size_t previous_location = 0; // We start at 0.
+
614 do {
+
615 size_t new_location = input.find('/', previous_location);
+
616 // std::string_view path_view = input;
+
617 // We process the last segment separately:
+
618 if (new_location == std::string_view::npos) {
+
619 std::string_view path_view = input.substr(previous_location);
+
620 if (path_view == "..") { // The path ends with ..
+
621 // e.g., if you receive ".." with an empty path, you go to "/".
+
622 if (path.empty()) {
+
623 path = '/';
+
624 return;
+
625 }
+
626 // Fast case where we have nothing to do:
+
627 if (path.back() == '/') {
+
628 return;
+
629 }
+
630 // If you have the path "/joe/myfriend",
+
631 // then you delete 'myfriend'.
+
632 path.resize(path.rfind('/') + 1);
+
633 return;
+
634 }
+
635 path += '/';
+
636 if (path_view != ".") {
+
637 path.append(path_view);
+
638 }
+
639 return;
+
640 } else {
+
641 // This is a non-final segment.
+
642 std::string_view path_view =
+
643 input.substr(previous_location, new_location - previous_location);
+
644 previous_location = new_location + 1;
+
645 if (path_view == "..") {
+
646 size_t last_delimiter = path.rfind('/');
+
647 if (last_delimiter != std::string::npos) {
+
648 path.erase(last_delimiter);
+
649 }
+
650 } else if (path_view != ".") {
+
651 path += '/';
+
652 path.append(path_view);
+
653 }
+
654 }
+
655 } while (true);
+
656 } else {
+
657 ada_log("parse_path slow");
+
658 // we have reached the general case
+
659 bool needs_percent_encoding = (accumulator & 1);
+
660 std::string path_buffer_tmp;
+
661 do {
+
662 size_t location = (special && (accumulator & 2))
+
663 ? input.find_first_of("/\\")
+
664 : input.find('/');
+
665 std::string_view path_view = input;
+
666 if (location != std::string_view::npos) {
+
667 path_view.remove_suffix(path_view.size() - location);
+
668 input.remove_prefix(location + 1);
+
669 }
+
670 // path_buffer is either path_view or it might point at a percent encoded
+
671 // temporary file.
+
672 std::string_view path_buffer =
+
673 (needs_percent_encoding &&
+
674 ada::unicode::percent_encode<false>(
+
675 path_view, character_sets::PATH_PERCENT_ENCODE, path_buffer_tmp))
+
676 ? path_buffer_tmp
+
677 : path_view;
+
678 if (unicode::is_double_dot_path_segment(path_buffer)) {
+
679 if ((helpers::shorten_path(path, type) || special) &&
+
680 location == std::string_view::npos) {
+
681 path += '/';
+
682 }
+
683 } else if (unicode::is_single_dot_path_segment(path_buffer) &&
+
684 (location == std::string_view::npos)) {
+
685 path += '/';
+
686 }
+
687 // Otherwise, if path_buffer is not a single-dot path segment, then:
+
688 else if (!unicode::is_single_dot_path_segment(path_buffer)) {
+
689 // If url's scheme is "file", url's path is empty, and path_buffer is a
+
690 // Windows drive letter, then replace the second code point in
+
691 // path_buffer with U+003A (:).
+
692 if (type == ada::scheme::type::FILE && path.empty() &&
+ +
694 path += '/';
+
695 path += path_buffer[0];
+
696 path += ':';
+
697 path_buffer.remove_prefix(2);
+
698 path.append(path_buffer);
+
699 } else {
+
700 // Append path_buffer to url's path.
+
701 path += '/';
+
702 path.append(path_buffer);
+
703 }
+
704 }
+
705 if (location == std::string_view::npos) {
+
706 return;
+
707 }
+
708 } while (true);
+
709 }
+
710}
+
711
+
712bool overlaps(std::string_view input1, const std::string& input2) noexcept {
+
713 ada_log("helpers::overlaps check if string_view '", input1, "' [",
+
714 input1.size(), " bytes] is part of string '", input2, "' [",
+
715 input2.size(), " bytes]");
+
716 return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
+
717 input1.data() < input2.data() + input2.size();
718}
719
-
720bool overlaps(std::string_view input1, const std::string& input2) noexcept {
-
721 ada_log("helpers::overlaps check if string_view '", input1, "' [",
-
722 input1.size(), " bytes] is part of string '", input2, "' [",
-
723 input2.size(), " bytes]");
-
724 return !input1.empty() && !input2.empty() && input1.data() >= input2.data() &&
-
725 input1.data() < input2.data() + input2.size();
-
726}
+
720template <class url_type>
+
721ada_really_inline void strip_trailing_spaces_from_opaque_path(
+
722 url_type& url) noexcept {
+
723 ada_log("helpers::strip_trailing_spaces_from_opaque_path");
+
724 if (!url.has_opaque_path) return;
+
725 if (url.has_hash()) return;
+
726 if (url.has_search()) return;
727
-
728template <class url_type>
-
729ada_really_inline void strip_trailing_spaces_from_opaque_path(
-
730 url_type& url) noexcept {
-
731 ada_log("helpers::strip_trailing_spaces_from_opaque_path");
-
732 if (!url.has_opaque_path) return;
-
733 if (url.has_hash()) return;
-
734 if (url.has_search()) return;
-
735
-
736 auto path = std::string(url.get_pathname());
-
737 while (!path.empty() && path.back() == ' ') {
-
738 path.resize(path.size() - 1);
-
739 }
-
740 url.update_base_pathname(path);
-
741}
-
742
-
743// @ / \\ ?
-
-
744static constexpr std::array<uint8_t, 256> authority_delimiter_special =
-
745 []() consteval {
-
746 std::array<uint8_t, 256> result{};
-
747 for (uint8_t i : {'@', '/', '\\', '?'}) {
-
748 result[i] = 1;
-
749 }
-
750 return result;
-
751 }();
+
728 auto path = std::string(url.get_pathname());
+
729 while (!path.empty() && path.back() == ' ') {
+
730 path.resize(path.size() - 1);
+
731 }
+
732 url.update_base_pathname(path);
+
733}
+
734
+
735// @ / \\ ?
+
+
736static constexpr std::array<uint8_t, 256> authority_delimiter_special =
+
737 []() consteval {
+
738 std::array<uint8_t, 256> result{};
+
739 for (uint8_t i : {'@', '/', '\\', '?'}) {
+
740 result[i] = 1;
+
741 }
+
742 return result;
+
743 }();
-
752// credit: @the-moisrex recommended a table-based approach
- -
754find_authority_delimiter_special(std::string_view view) noexcept {
-
755 // performance note: we might be able to gain further performance
-
756 // with SIMD instrinsics.
-
757 for (auto pos = view.begin(); pos != view.end(); ++pos) {
-
758 if (authority_delimiter_special[(uint8_t)*pos]) {
-
759 return pos - view.begin();
-
760 }
-
761 }
-
762 return size_t(view.size());
-
763}
-
764
-
765// @ / ?
-
-
766static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
-
767 std::array<uint8_t, 256> result{};
-
768 for (uint8_t i : {'@', '/', '?'}) {
-
769 result[i] = 1;
-
770 }
-
771 return result;
-
772}();
+
744// credit: @the-moisrex recommended a table-based approach
+ +
746find_authority_delimiter_special(std::string_view view) noexcept {
+
747 // performance note: we might be able to gain further performance
+
748 // with SIMD instrinsics.
+
749 for (auto pos = view.begin(); pos != view.end(); ++pos) {
+
750 if (authority_delimiter_special[(uint8_t)*pos]) {
+
751 return pos - view.begin();
+
752 }
+
753 }
+
754 return size_t(view.size());
+
755}
+
756
+
757// @ / ?
+
+
758static constexpr std::array<uint8_t, 256> authority_delimiter = []() consteval {
+
759 std::array<uint8_t, 256> result{};
+
760 for (uint8_t i : {'@', '/', '?'}) {
+
761 result[i] = 1;
+
762 }
+
763 return result;
+
764}();
-
773// credit: @the-moisrex recommended a table-based approach
- -
775find_authority_delimiter(std::string_view view) noexcept {
-
776 // performance note: we might be able to gain further performance
-
777 // with SIMD instrinsics.
-
778 for (auto pos = view.begin(); pos != view.end(); ++pos) {
-
779 if (authority_delimiter[(uint8_t)*pos]) {
-
780 return pos - view.begin();
-
781 }
-
782 }
-
783 return size_t(view.size());
-
784}
-
785
-
786} // namespace ada::helpers
-
787
-
788namespace ada {
-
- - -
791}
+
765// credit: @the-moisrex recommended a table-based approach
+ +
767find_authority_delimiter(std::string_view view) noexcept {
+
768 // performance note: we might be able to gain further performance
+
769 // with SIMD instrinsics.
+
770 for (auto pos = view.begin(); pos != view.end(); ++pos) {
+
771 if (authority_delimiter[(uint8_t)*pos]) {
+
772 return pos - view.begin();
+
773 }
+
774 }
+
775 return size_t(view.size());
+
776}
+
777
+
778} // namespace ada::helpers
+
779
+
780namespace ada {
+ -
792#undef ada_make_uint8x16_t
-
793} // namespace ada
+
784#undef ada_make_uint8x16_t
+
785} // namespace ada
Includes all definitions for Ada.
Definitions for URL specific checkers used within Ada.
Common definitions for cross-platform compiler support.
@@ -908,17 +900,17 @@
constexpr bool is_normalized_windows_drive_letter(std::string_view input) noexcept
constexpr bool is_windows_drive_letter(std::string_view input) noexcept
Includes the definitions for helper functions.
-
ada_really_inline size_t find_next_host_delimiter(std::string_view view, size_t location) noexcept
Definition helpers.cpp:458
-
static constexpr std::array< uint8_t, 256 > authority_delimiter_special
Definition helpers.cpp:744
-
static constexpr std::array< uint8_t, 256 > host_delimiters
Definition helpers.cpp:450
-
ada_really_inline size_t find_next_host_delimiter_special(std::string_view view, size_t location) noexcept
Definition helpers.cpp:326
+
ada_really_inline size_t find_next_host_delimiter(std::string_view view, size_t location) noexcept
Definition helpers.cpp:450
+
static constexpr std::array< uint8_t, 256 > authority_delimiter_special
Definition helpers.cpp:736
+
static constexpr std::array< uint8_t, 256 > host_delimiters
Definition helpers.cpp:442
+
ada_really_inline size_t find_next_host_delimiter_special(std::string_view view, size_t location) noexcept
Definition helpers.cpp:318
ada_unused std::string get_state(ada::state s)
Definition helpers.cpp:36
-
static constexpr std::array< uint8_t, 256 > authority_delimiter
Definition helpers.cpp:766
-
static constexpr std::array< uint8_t, 256 > special_host_delimiters
Definition helpers.cpp:317
-
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept
Definition helpers.cpp:175
- - -
@ NOT_SPECIAL
Definition scheme.h:32
+
static constexpr std::array< uint8_t, 256 > authority_delimiter
Definition helpers.cpp:758
+
static constexpr std::array< uint8_t, 256 > special_host_delimiters
Definition helpers.cpp:309
+
ada_really_inline int trailing_zeroes(uint32_t input_num) noexcept
Definition helpers.cpp:167
+ + +
@ NOT_SPECIAL
Definition scheme.h:31
Definition ada_idna.h:13
ada_warn_unused std::string to_string(encoding_type type)
state
Definition state.h:17
diff --git a/d3/d37/unicode-inl_8h_source.html b/d3/d37/unicode-inl_8h_source.html index dc4ced541..7faf789a8 100644 --- a/d3/d37/unicode-inl_8h_source.html +++ b/d3/d37/unicode-inl_8h_source.html @@ -124,15 +124,14 @@
19ada_really_inline size_t percent_encode_index(const std::string_view input,
20 const uint8_t character_set[]) {
21 return std::distance(
-
22 input.begin(),
-
23 std::find_if(input.begin(), input.end(), [character_set](const char c) {
-
24 return character_sets::bit_at(character_set, c);
-
25 }));
-
26}
+
22 input.begin(), std::ranges::find_if(input, [character_set](const char c) {
+
23 return character_sets::bit_at(character_set, c);
+
24 }));
+
25}
-
27} // namespace ada::unicode
-
28
-
29#endif // ADA_UNICODE_INL_H
+
26} // namespace ada::unicode
+
27
+
28#endif // ADA_UNICODE_INL_H
#define ada_really_inline
Definition common_defs.h:84
Includes the declarations for unicode operations.
ada_really_inline size_t percent_encode_index(const std::string_view input, const uint8_t character_set[])
Definition unicode-inl.h:19
diff --git a/d3/dbe/namespaceada_1_1checkers.html b/d3/dbe/namespaceada_1_1checkers.html index 0810651b0..33e9c35da 100644 --- a/d3/dbe/namespaceada_1_1checkers.html +++ b/d3/dbe/namespaceada_1_1checkers.html @@ -410,7 +410,7 @@

}()

tl::expected< result_type, ada::errors > result
-

Definition at line 61 of file checkers.cpp.

+

Definition at line 60 of file checkers.cpp.

diff --git a/d4/dd6/checkers_8cpp_source.html b/d4/dd6/checkers_8cpp_source.html index a264ac979..2636e00cb 100644 --- a/d4/dd6/checkers_8cpp_source.html +++ b/d4/dd6/checkers_8cpp_source.html @@ -126,124 +126,123 @@
11 // with 'x' or a lowercase hex character.
12 // Most of the time, this will be false so this simple check will save a lot
13 // of effort.
-
14 char last_char = view.back();
-
15 // If the address ends with a dot, we need to prune it (special case).
-
16 if (last_char == '.') {
-
17 view.remove_suffix(1);
-
18 if (view.empty()) {
-
19 return false;
-
20 }
-
21 last_char = view.back();
-
22 }
-
23 bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
-
24 (last_char >= 'a' && last_char <= 'f') ||
-
25 last_char == 'x';
-
26 if (!possible_ipv4) {
-
27 return false;
-
28 }
-
29 // From the last character, find the last dot.
-
30 size_t last_dot = view.rfind('.');
-
31 if (last_dot != std::string_view::npos) {
-
32 // We have at least one dot.
-
33 view = view.substr(last_dot + 1);
-
34 }
-
38 if (std::all_of(view.begin(), view.end(), ada::checkers::is_digit)) {
-
39 return true;
-
40 }
-
41 // It could be hex (0x), but not if there is a single character.
-
42 if (view.size() == 1) {
-
43 return false;
-
44 }
-
45 // It must start with 0x.
-
46 if (!view.starts_with("0x")) {
-
47 return false;
-
48 }
-
49 // We must allow "0x".
-
50 if (view.size() == 2) {
-
51 return true;
-
52 }
-
53 // We have 0x followed by some characters, we need to check that they are
-
54 // hexadecimals.
-
55 return std::all_of(view.begin() + 2, view.end(),
-
56 ada::unicode::is_lowercase_hex);
-
57}
-
58
-
59// for use with path_signature, we include all characters that need percent
-
60// encoding.
-
-
61static constexpr std::array<uint8_t, 256> path_signature_table =
-
62 []() consteval {
-
63 std::array<uint8_t, 256> result{};
-
64 for (size_t i = 0; i < 256; i++) {
-
65 if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
-
66 i == 0x3f || i == 0x60 || i == 0x7b || i == 0x7d || i > 0x7e) {
-
67 result[i] = 1;
-
68 } else if (i == 0x25) {
-
69 result[i] = 8;
-
70 } else if (i == 0x2e) {
-
71 result[i] = 4;
-
72 } else if (i == 0x5c) {
-
73 result[i] = 2;
-
74 } else {
-
75 result[i] = 0;
-
76 }
-
77 }
-
78 return result;
-
79 }();
+
14 // If the address ends with a dot, we need to prune it (special case).
+
15 if (view.ends_with('.')) {
+
16 view.remove_suffix(1);
+
17 if (view.empty()) {
+
18 return false;
+
19 }
+
20 }
+
21 char last_char = view.back();
+
22 bool possible_ipv4 = (last_char >= '0' && last_char <= '9') ||
+
23 (last_char >= 'a' && last_char <= 'f') ||
+
24 last_char == 'x';
+
25 if (!possible_ipv4) {
+
26 return false;
+
27 }
+
28 // From the last character, find the last dot.
+
29 size_t last_dot = view.rfind('.');
+
30 if (last_dot != std::string_view::npos) {
+
31 // We have at least one dot.
+
32 view = view.substr(last_dot + 1);
+
33 }
+
37 if (std::ranges::all_of(view, ada::checkers::is_digit)) {
+
38 return true;
+
39 }
+
40 // It could be hex (0x), but not if there is a single character.
+
41 if (view.size() == 1) {
+
42 return false;
+
43 }
+
44 // It must start with 0x.
+
45 if (!view.starts_with("0x")) {
+
46 return false;
+
47 }
+
48 // We must allow "0x".
+
49 if (view.size() == 2) {
+
50 return true;
+
51 }
+
52 // We have 0x followed by some characters, we need to check that they are
+
53 // hexadecimals.
+
54 return std::all_of(view.begin() + 2, view.end(),
+
55 ada::unicode::is_lowercase_hex);
+
56}
+
57
+
58// for use with path_signature, we include all characters that need percent
+
59// encoding.
+
+
60static constexpr std::array<uint8_t, 256> path_signature_table =
+
61 []() consteval {
+
62 std::array<uint8_t, 256> result{};
+
63 for (size_t i = 0; i < 256; i++) {
+
64 if (i <= 0x20 || i == 0x22 || i == 0x23 || i == 0x3c || i == 0x3e ||
+
65 i == 0x3f || i == 0x60 || i == 0x7b || i == 0x7d || i > 0x7e) {
+
66 result[i] = 1;
+
67 } else if (i == 0x25) {
+
68 result[i] = 8;
+
69 } else if (i == 0x2e) {
+
70 result[i] = 4;
+
71 } else if (i == 0x5c) {
+
72 result[i] = 2;
+
73 } else {
+
74 result[i] = 0;
+
75 }
+
76 }
+
77 return result;
+
78 }();
-
80
-
81ada_really_inline constexpr uint8_t path_signature(
-
82 std::string_view input) noexcept {
-
83 // The path percent-encode set is the query percent-encode set and U+003F (?),
-
84 // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
-
85 // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
-
86 // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
-
87 // controls and all code points greater than U+007E (~).
-
88 size_t i = 0;
-
89 uint8_t accumulator{};
-
90 for (; i + 7 < input.size(); i += 8) {
-
91 accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
-
92 path_signature_table[uint8_t(input[i + 1])] |
-
93 path_signature_table[uint8_t(input[i + 2])] |
-
94 path_signature_table[uint8_t(input[i + 3])] |
-
95 path_signature_table[uint8_t(input[i + 4])] |
-
96 path_signature_table[uint8_t(input[i + 5])] |
-
97 path_signature_table[uint8_t(input[i + 6])] |
-
98 path_signature_table[uint8_t(input[i + 7])]);
-
99 }
-
100 for (; i < input.size(); i++) {
-
101 accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
-
102 }
-
103 return accumulator;
-
104}
-
105
-
106ada_really_inline constexpr bool verify_dns_length(
-
107 std::string_view input) noexcept {
-
108 if (input.back() == '.') {
-
109 if (input.size() > 254) return false;
-
110 } else if (input.size() > 253)
-
111 return false;
-
112
-
113 size_t start = 0;
-
114 while (start < input.size()) {
-
115 auto dot_location = input.find('.', start);
-
116 // If not found, it's likely the end of the domain
-
117 if (dot_location == std::string_view::npos) dot_location = input.size();
-
118
-
119 auto label_size = dot_location - start;
-
120 if (label_size > 63 || label_size == 0) return false;
-
121
-
122 start = dot_location + 1;
-
123 }
-
124
-
125 return true;
-
126}
-
127} // namespace ada::checkers
+
79
+
80ada_really_inline constexpr uint8_t path_signature(
+
81 std::string_view input) noexcept {
+
82 // The path percent-encode set is the query percent-encode set and U+003F (?),
+
83 // U+0060 (`), U+007B ({), and U+007D (}). The query percent-encode set is the
+
84 // C0 control percent-encode set and U+0020 SPACE, U+0022 ("), U+0023 (#),
+
85 // U+003C (<), and U+003E (>). The C0 control percent-encode set are the C0
+
86 // controls and all code points greater than U+007E (~).
+
87 size_t i = 0;
+
88 uint8_t accumulator{};
+
89 for (; i + 7 < input.size(); i += 8) {
+
90 accumulator |= uint8_t(path_signature_table[uint8_t(input[i])] |
+
91 path_signature_table[uint8_t(input[i + 1])] |
+
92 path_signature_table[uint8_t(input[i + 2])] |
+
93 path_signature_table[uint8_t(input[i + 3])] |
+
94 path_signature_table[uint8_t(input[i + 4])] |
+
95 path_signature_table[uint8_t(input[i + 5])] |
+
96 path_signature_table[uint8_t(input[i + 6])] |
+
97 path_signature_table[uint8_t(input[i + 7])]);
+
98 }
+
99 for (; i < input.size(); i++) {
+
100 accumulator |= uint8_t(path_signature_table[uint8_t(input[i])]);
+
101 }
+
102 return accumulator;
+
103}
+
104
+
105ada_really_inline constexpr bool verify_dns_length(
+
106 std::string_view input) noexcept {
+
107 if (input.back() == '.') {
+
108 if (input.size() > 254) return false;
+
109 } else if (input.size() > 253)
+
110 return false;
+
111
+
112 size_t start = 0;
+
113 while (start < input.size()) {
+
114 auto dot_location = input.find('.', start);
+
115 // If not found, it's likely the end of the domain
+
116 if (dot_location == std::string_view::npos) dot_location = input.size();
+
117
+
118 auto label_size = dot_location - start;
+
119 if (label_size > 63 || label_size == 0) return false;
+
120
+
121 start = dot_location + 1;
+
122 }
+
123
+
124 return true;
+
125}
+
126} // namespace ada::checkers
Declarations for URL specific checkers used within Ada.
#define ada_constexpr
#define ada_really_inline
Definition common_defs.h:84
Includes the definitions for validation functions.
-
static constexpr std::array< uint8_t, 256 > path_signature_table
Definition checkers.cpp:61
+
static constexpr std::array< uint8_t, 256 > path_signature_table
Definition checkers.cpp:60
constexpr bool is_digit(char x) noexcept
tl::expected< result_type, ada::errors > result
diff --git a/d5/d25/url-getters_8cpp_source.html b/d5/d25/url-getters_8cpp_source.html index 88a80d16a..3bce83684 100644 --- a/d5/d25/url-getters_8cpp_source.html +++ b/d5/d25/url-getters_8cpp_source.html @@ -223,9 +223,9 @@
Definitions for helper functions used within Ada.
Definitions for user facing functions for parsing URL and it's components.
constexpr std::string_view is_special_list[]
Definition scheme-inl.h:19
- - - + + +
Definition ada_idna.h:13
tl::expected< result_type, ada::errors > result
ada_warn_unused ada::result< result_type > parse(std::string_view input, const result_type *base_url=nullptr)
diff --git a/d5/d36/parser_8h_source.html b/d5/d36/parser_8h_source.html index 4b6f23298..cc81bd571 100644 --- a/d5/d36/parser_8h_source.html +++ b/d5/d36/parser_8h_source.html @@ -153,7 +153,7 @@
Definition for supported encoding types.
Includes the definitions for supported parsers.
template url parse_url< url >(std::string_view user_input, const url *base_url)
-
result_type parse_url(std::string_view user_input, const result_type *base_url=nullptr)
Definition parser.cpp:927
+
result_type parse_url(std::string_view user_input, const result_type *base_url=nullptr)
Definition parser.cpp:920
template url parse_url_impl< url >(std::string_view user_input, const url *base_url)
template url_aggregator parse_url_impl< url_aggregator >(std::string_view user_input, const url_aggregator *base_url)
template url_aggregator parse_url< url_aggregator >(std::string_view user_input, const url_aggregator *base_url)
diff --git a/d5/dee/url-setters_8cpp_source.html b/d5/dee/url-setters_8cpp_source.html index 9e6e1dbd8..8531737bf 100644 --- a/d5/dee/url-setters_8cpp_source.html +++ b/d5/dee/url-setters_8cpp_source.html @@ -302,70 +302,60 @@
179
-
180 query = ada::unicode::percent_encode(std::string_view(new_value),
-
181 query_percent_encode_set);
-
182}
+
180 query = ada::unicode::percent_encode(new_value, query_percent_encode_set);
+
181}
-
183
-
-
184bool url::set_pathname(const std::string_view input) {
-
185 if (has_opaque_path) {
-
186 return false;
-
187 }
-
188 path = "";
-
189 parse_path(input);
-
190 return true;
-
191}
+
182
+
+
183bool url::set_pathname(const std::string_view input) {
+
184 if (has_opaque_path) {
+
185 return false;
+
186 }
+
187 path = "";
+
188 parse_path(input);
+
189 return true;
+
190}
-
192
-
-
193bool url::set_protocol(const std::string_view input) {
-
194 std::string view(input);
-
195 helpers::remove_ascii_tab_or_newline(view);
-
196 if (view.empty()) {
-
197 return true;
-
198 }
-
199
-
200 // Schemes should start with alpha values.
-
201 if (!checkers::is_alpha(view[0])) {
-
202 return false;
-
203 }
-
204
-
205 view.append(":");
-
206
-
207 std::string::iterator pointer =
-
208 std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
-
209
-
210 if (pointer != view.end() && *pointer == ':') {
-
211 return parse_scheme<true>(
-
212 std::string_view(view.data(), pointer - view.begin()));
-
213 }
-
214 return false;
-
215}
+
191
+
+
192bool url::set_protocol(const std::string_view input) {
+
193 std::string view(input);
+
194 helpers::remove_ascii_tab_or_newline(view);
+
195 if (view.empty()) {
+
196 return true;
+
197 }
+
198
+
199 // Schemes should start with alpha values.
+
200 if (!checkers::is_alpha(view[0])) {
+
201 return false;
+
202 }
+
203
+
204 view.append(":");
+
205
+
206 std::string::iterator pointer =
+
207 std::ranges::find_if_not(view, unicode::is_alnum_plus);
+
208
+
209 if (pointer != view.end() && *pointer == ':') {
+
210 return parse_scheme<true>(
+
211 std::string_view(view.data(), pointer - view.begin()));
+
212 }
+
213 return false;
+
214}
-
216
-
-
217bool url::set_href(const std::string_view input) {
- -
219
-
220 if (out) {
-
221 username = out->username;
-
222 password = out->password;
-
223 host = out->host;
-
224 port = out->port;
-
225 path = out->path;
-
226 query = out->query;
-
227 hash = out->hash;
-
228 type = out->type;
-
229 non_special_scheme = out->non_special_scheme;
-
230 has_opaque_path = out->has_opaque_path;
-
231 }
-
232
-
233 return out.has_value();
-
234}
+
215
+
+
216bool url::set_href(const std::string_view input) {
+ +
218
+
219 if (out) {
+
220 *this = *out;
+
221 }
+
222
+
223 return out.has_value();
+
224}
-
235
-
236} // namespace ada
+
225
+
226} // namespace ada
Includes all definitions for Ada.
Definitions for helper functions used within Ada.
constexpr uint8_t QUERY_PERCENT_ENCODE[32]
@@ -373,7 +363,7 @@
constexpr uint8_t USERINFO_PERCENT_ENCODE[32]
constexpr uint8_t FRAGMENT_PERCENT_ENCODE[32]
constexpr bool is_alpha(char x) noexcept
- +
Definition ada_idna.h:13
tl::expected< result_type, ada::errors > result
ada_warn_unused ada::result< result_type > parse(std::string_view input, const result_type *base_url=nullptr)
@@ -386,10 +376,10 @@
ada_really_inline bool has_credentials() const noexcept
Definition url-inl.h:19
bool set_password(std::string_view input)
void set_search(std::string_view input)
-
bool set_href(std::string_view input)
+
bool set_href(std::string_view input)
bool set_username(std::string_view input)
-
bool set_pathname(std::string_view input)
-
bool set_protocol(std::string_view input)
+
bool set_pathname(std::string_view input)
+
bool set_protocol(std::string_view input)
bool set_port(std::string_view input)
diff --git a/d6/d0e/url_8cpp.html b/d6/d0e/url_8cpp.html index 4b71cedb5..766c5cd4c 100644 --- a/d6/d0e/url_8cpp.html +++ b/d6/d0e/url_8cpp.html @@ -121,6 +121,7 @@ #include <numeric>
#include <algorithm>
#include <string>
+#include <string_view>

Go to the source code of this file.

diff --git a/d6/d0e/url_8cpp_source.html b/d6/d0e/url_8cpp_source.html index a0f197b99..7830d0cc1 100644 --- a/d6/d0e/url_8cpp_source.html +++ b/d6/d0e/url_8cpp_source.html @@ -120,600 +120,597 @@
5#include <numeric>
6#include <algorithm>
7#include <string>
-
8
-
9namespace ada {
-
10
-
11bool url::parse_opaque_host(std::string_view input) {
-
12 ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
-
13 if (std::any_of(input.begin(), input.end(),
-
14 ada::unicode::is_forbidden_host_code_point)) {
-
15 return is_valid = false;
-
16 }
-
17
-
18 // Return the result of running UTF-8 percent-encode on input using the C0
-
19 // control percent-encode set.
-
20 host = ada::unicode::percent_encode(
-
21 input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
-
22 return true;
-
23}
-
24
-
25bool url::parse_ipv4(std::string_view input) {
-
26 ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
-
27 if (input.back() == '.') {
-
28 input.remove_suffix(1);
-
29 }
-
30 size_t digit_count{0};
-
31 int pure_decimal_count = 0; // entries that are decimal
-
32 std::string_view original_input =
-
33 input; // we might use this if pure_decimal_count == 4.
-
34 uint64_t ipv4{0};
-
35 // we could unroll for better performance?
-
36 for (; (digit_count < 4) && !(input.empty()); digit_count++) {
-
37 uint32_t
-
38 segment_result{}; // If any number exceeds 32 bits, we have an error.
-
39 bool is_hex = checkers::has_hex_prefix(input);
-
40 if (is_hex && ((input.length() == 2) ||
-
41 ((input.length() > 2) && (input[2] == '.')))) {
-
42 // special case
-
43 segment_result = 0;
-
44 input.remove_prefix(2);
-
45 } else {
-
46 std::from_chars_result r{};
-
47 if (is_hex) {
-
48 r = std::from_chars(input.data() + 2, input.data() + input.size(),
-
49 segment_result, 16);
-
50 } else if ((input.length() >= 2) && input[0] == '0' &&
-
51 checkers::is_digit(input[1])) {
-
52 r = std::from_chars(input.data() + 1, input.data() + input.size(),
-
53 segment_result, 8);
-
54 } else {
-
55 pure_decimal_count++;
-
56 r = std::from_chars(input.data(), input.data() + input.size(),
-
57 segment_result, 10);
-
58 }
-
59 if (r.ec != std::errc()) {
-
60 return is_valid = false;
-
61 }
-
62 input.remove_prefix(r.ptr - input.data());
-
63 }
-
64 if (input.empty()) {
-
65 // We have the last value.
-
66 // At this stage, ipv4 contains digit_count*8 bits.
-
67 // So we have 32-digit_count*8 bits left.
-
68 if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
-
69 return is_valid = false;
-
70 }
-
71 ipv4 <<= (32 - digit_count * 8);
-
72 ipv4 |= segment_result;
-
73 goto final;
-
74 } else {
-
75 // There is more, so that the value must no be larger than 255
-
76 // and we must have a '.'.
-
77 if ((segment_result > 255) || (input[0] != '.')) {
-
78 return is_valid = false;
-
79 }
-
80 ipv4 <<= 8;
-
81 ipv4 |= segment_result;
-
82 input.remove_prefix(1); // remove '.'
-
83 }
-
84 }
-
85 if ((digit_count != 4) || (!input.empty())) {
-
86 return is_valid = false;
-
87 }
-
88final:
-
89 // We could also check r.ptr to see where the parsing ended.
-
90 if (pure_decimal_count == 4) {
-
91 host = original_input; // The original input was already all decimal and we
-
92 // validated it.
-
93 } else {
-
94 host = ada::serializers::ipv4(ipv4); // We have to reserialize the address.
-
95 }
-
96 host_type = IPV4;
-
97 return true;
-
98}
-
99
-
100bool url::parse_ipv6(std::string_view input) {
-
101 ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
-
102
-
103 if (input.empty()) {
-
104 return is_valid = false;
-
105 }
-
106 // Let address be a new IPv6 address whose IPv6 pieces are all 0.
-
107 std::array<uint16_t, 8> address{};
-
108
-
109 // Let pieceIndex be 0.
-
110 int piece_index = 0;
-
111
-
112 // Let compress be null.
-
113 std::optional<int> compress{};
-
114
-
115 // Let pointer be a pointer for input.
-
116 std::string_view::iterator pointer = input.begin();
-
117
-
118 // If c is U+003A (:), then:
-
119 if (input[0] == ':') {
-
120 // If remaining does not start with U+003A (:), validation error, return
-
121 // failure.
-
122 if (input.size() == 1 || input[1] != ':') {
-
123 ada_log("parse_ipv6 starts with : but the rest does not start with :");
-
124 return is_valid = false;
-
125 }
-
126
-
127 // Increase pointer by 2.
-
128 pointer += 2;
-
129
-
130 // Increase pieceIndex by 1 and then set compress to pieceIndex.
-
131 compress = ++piece_index;
-
132 }
-
133
-
134 // While c is not the EOF code point:
-
135 while (pointer != input.end()) {
-
136 // If pieceIndex is 8, validation error, return failure.
-
137 if (piece_index == 8) {
-
138 ada_log("parse_ipv6 piece_index == 8");
-
139 return is_valid = false;
-
140 }
-
141
-
142 // If c is U+003A (:), then:
-
143 if (*pointer == ':') {
-
144 // If compress is non-null, validation error, return failure.
-
145 if (compress.has_value()) {
-
146 ada_log("parse_ipv6 compress is non-null");
-
147 return is_valid = false;
-
148 }
-
149
-
150 // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
-
151 // then continue.
-
152 pointer++;
-
153 compress = ++piece_index;
-
154 continue;
-
155 }
-
156
-
157 // Let value and length be 0.
-
158 uint16_t value = 0, length = 0;
-
159
-
160 // While length is less than 4 and c is an ASCII hex digit,
-
161 // set value to value times 0x10 + c interpreted as hexadecimal number, and
-
162 // increase pointer and length by 1.
-
163 while (length < 4 && pointer != input.end() &&
-
164 unicode::is_ascii_hex_digit(*pointer)) {
-
165 // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
-
166 value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
-
167 pointer++;
-
168 length++;
-
169 }
-
170
-
171 // If c is U+002E (.), then:
-
172 if (pointer != input.end() && *pointer == '.') {
-
173 // If length is 0, validation error, return failure.
-
174 if (length == 0) {
-
175 ada_log("parse_ipv6 length is 0");
-
176 return is_valid = false;
-
177 }
-
178
-
179 // Decrease pointer by length.
-
180 pointer -= length;
-
181
-
182 // If pieceIndex is greater than 6, validation error, return failure.
-
183 if (piece_index > 6) {
-
184 ada_log("parse_ipv6 piece_index > 6");
-
185 return is_valid = false;
-
186 }
-
187
-
188 // Let numbersSeen be 0.
-
189 int numbers_seen = 0;
-
190
-
191 // While c is not the EOF code point:
-
192 while (pointer != input.end()) {
-
193 // Let ipv4Piece be null.
-
194 std::optional<uint16_t> ipv4_piece{};
-
195
-
196 // If numbersSeen is greater than 0, then:
-
197 if (numbers_seen > 0) {
-
198 // If c is a U+002E (.) and numbersSeen is less than 4, then increase
-
199 // pointer by 1.
-
200 if (*pointer == '.' && numbers_seen < 4) {
-
201 pointer++;
-
202 }
-
203 // Otherwise, validation error, return failure.
-
204 else {
-
205 ada_log("parse_ipv6 Otherwise, validation error, return failure");
-
206 return is_valid = false;
-
207 }
-
208 }
-
209
-
210 // If c is not an ASCII digit, validation error, return failure.
-
211 if (pointer == input.end() || !checkers::is_digit(*pointer)) {
-
212 ada_log(
-
213 "parse_ipv6 If c is not an ASCII digit, validation error, return "
-
214 "failure");
-
215 return is_valid = false;
-
216 }
-
217
-
218 // While c is an ASCII digit:
-
219 while (pointer != input.end() && checkers::is_digit(*pointer)) {
-
220 // Let number be c interpreted as decimal number.
-
221 int number = *pointer - '0';
-
222
-
223 // If ipv4Piece is null, then set ipv4Piece to number.
-
224 if (!ipv4_piece.has_value()) {
-
225 ipv4_piece = number;
-
226 }
-
227 // Otherwise, if ipv4Piece is 0, validation error, return failure.
-
228 else if (ipv4_piece == 0) {
-
229 ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
-
230 return is_valid = false;
-
231 }
-
232 // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
-
233 else {
-
234 ipv4_piece = *ipv4_piece * 10 + number;
-
235 }
-
236
-
237 // If ipv4Piece is greater than 255, validation error, return failure.
-
238 if (ipv4_piece > 255) {
-
239 ada_log("parse_ipv6 ipv4_piece > 255");
-
240 return is_valid = false;
-
241 }
-
242
-
243 // Increase pointer by 1.
-
244 pointer++;
-
245 }
-
246
-
247 // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
-
248 // ipv4Piece.
-
249 // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
-
250 address[piece_index] =
-
251 uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
-
252
-
253 // Increase numbersSeen by 1.
-
254 numbers_seen++;
-
255
-
256 // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
-
257 if (numbers_seen == 2 || numbers_seen == 4) {
-
258 piece_index++;
-
259 }
-
260 }
-
261
-
262 // If numbersSeen is not 4, validation error, return failure.
-
263 if (numbers_seen != 4) {
-
264 return is_valid = false;
-
265 }
-
266
-
267 // Break.
-
268 break;
-
269 }
-
270 // Otherwise, if c is U+003A (:):
-
271 else if ((pointer != input.end()) && (*pointer == ':')) {
-
272 // Increase pointer by 1.
-
273 pointer++;
-
274
-
275 // If c is the EOF code point, validation error, return failure.
-
276 if (pointer == input.end()) {
-
277 ada_log(
-
278 "parse_ipv6 If c is the EOF code point, validation error, return "
-
279 "failure");
-
280 return is_valid = false;
-
281 }
-
282 }
-
283 // Otherwise, if c is not the EOF code point, validation error, return
-
284 // failure.
-
285 else if (pointer != input.end()) {
-
286 ada_log(
-
287 "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
-
288 "error, return failure");
-
289 return is_valid = false;
-
290 }
-
291
-
292 // Set address[pieceIndex] to value.
-
293 address[piece_index] = value;
-
294
-
295 // Increase pieceIndex by 1.
-
296 piece_index++;
-
297 }
-
298
-
299 // If compress is non-null, then:
-
300 if (compress.has_value()) {
-
301 // Let swaps be pieceIndex - compress.
-
302 int swaps = piece_index - *compress;
-
303
-
304 // Set pieceIndex to 7.
-
305 piece_index = 7;
-
306
-
307 // While pieceIndex is not 0 and swaps is greater than 0,
-
308 // swap address[pieceIndex] with address[compress + swaps - 1], and then
-
309 // decrease both pieceIndex and swaps by 1.
-
310 while (piece_index != 0 && swaps > 0) {
-
311 std::swap(address[piece_index], address[*compress + swaps - 1]);
-
312 piece_index--;
-
313 swaps--;
-
314 }
-
315 }
-
316 // Otherwise, if compress is null and pieceIndex is not 8, validation error,
-
317 // return failure.
-
318 else if (piece_index != 8) {
-
319 ada_log(
-
320 "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
-
321 "error, return failure");
-
322 return is_valid = false;
-
323 }
-
324 host = ada::serializers::ipv6(address);
-
325 ada_log("parse_ipv6 ", *host);
-
326 host_type = IPV6;
-
327 return true;
-
328}
-
329
-
330template <bool has_state_override>
-
331ada_really_inline bool url::parse_scheme(const std::string_view input) {
-
332 auto parsed_type = ada::scheme::get_scheme_type(input);
-
333 bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
-
338 if (is_input_special) { // fast path!!!
-
339 if constexpr (has_state_override) {
-
340 // If url's scheme is not a special scheme and buffer is a special scheme,
-
341 // then return.
-
342 if (is_special() != is_input_special) {
-
343 return false;
-
344 }
-
345
-
346 // If url includes credentials or has a non-null port, and buffer is
-
347 // "file", then return.
-
348 if ((has_credentials() || port.has_value()) &&
-
349 parsed_type == ada::scheme::type::FILE) {
-
350 return false;
-
351 }
-
352
-
353 // If url's scheme is "file" and its host is an empty host, then return.
-
354 // An empty host is the empty string.
-
355 if (type == ada::scheme::type::FILE && host.has_value() &&
-
356 host.value().empty()) {
-
357 return false;
-
358 }
-
359 }
-
360
-
361 type = parsed_type;
-
362
-
363 if constexpr (has_state_override) {
-
364 // This is uncommon.
-
365 uint16_t urls_scheme_port = get_special_port();
-
366
-
367 if (urls_scheme_port) {
-
368 // If url's port is url's scheme's default port, then set url's port to
-
369 // null.
-
370 if (port.has_value() && *port == urls_scheme_port) {
-
371 port = std::nullopt;
-
372 }
-
373 }
-
374 }
-
375 } else { // slow path
-
376 std::string _buffer(input);
-
377 // Next function is only valid if the input is ASCII and returns false
-
378 // otherwise, but it seems that we always have ascii content so we do not
-
379 // need to check the return value.
-
380 // bool is_ascii =
-
381 unicode::to_lower_ascii(_buffer.data(), _buffer.size());
-
382
-
383 if constexpr (has_state_override) {
-
384 // If url's scheme is a special scheme and buffer is not a special scheme,
-
385 // then return. If url's scheme is not a special scheme and buffer is a
-
386 // special scheme, then return.
-
387 if (is_special() != ada::scheme::is_special(_buffer)) {
-
388 return true;
-
389 }
-
390
-
391 // If url includes credentials or has a non-null port, and buffer is
-
392 // "file", then return.
-
393 if ((has_credentials() || port.has_value()) && _buffer == "file") {
-
394 return true;
-
395 }
-
396
-
397 // If url's scheme is "file" and its host is an empty host, then return.
-
398 // An empty host is the empty string.
-
399 if (type == ada::scheme::type::FILE && host.has_value() &&
-
400 host.value().empty()) {
-
401 return true;
-
402 }
-
403 }
-
404
-
405 set_scheme(std::move(_buffer));
-
406
-
407 if constexpr (has_state_override) {
-
408 // This is uncommon.
-
409 uint16_t urls_scheme_port = get_special_port();
-
410
-
411 if (urls_scheme_port) {
-
412 // If url's port is url's scheme's default port, then set url's port to
-
413 // null.
-
414 if (port.has_value() && *port == urls_scheme_port) {
-
415 port = std::nullopt;
-
416 }
-
417 }
-
418 }
-
419 }
-
420
-
421 return true;
-
422}
-
423
-
424ada_really_inline bool url::parse_host(std::string_view input) {
-
425 ada_log("parse_host ", input, " [", input.size(), " bytes]");
-
426 if (input.empty()) {
-
427 return is_valid = false;
-
428 } // technically unnecessary.
-
429 // If input starts with U+005B ([), then:
-
430 if (input[0] == '[') {
-
431 // If input does not end with U+005D (]), validation error, return failure.
-
432 if (input.back() != ']') {
-
433 return is_valid = false;
-
434 }
-
435 ada_log("parse_host ipv6");
-
436
-
437 // Return the result of IPv6 parsing input with its leading U+005B ([) and
-
438 // trailing U+005D (]) removed.
-
439 input.remove_prefix(1);
-
440 input.remove_suffix(1);
-
441 return parse_ipv6(input);
-
442 }
-
443
-
444 // If isNotSpecial is true, then return the result of opaque-host parsing
-
445 // input.
-
446 if (!is_special()) {
-
447 return parse_opaque_host(input);
-
448 }
-
449 // Let domain be the result of running UTF-8 decode without BOM on the
-
450 // percent-decoding of input. Let asciiDomain be the result of running domain
-
451 // to ASCII with domain and false. The most common case is an ASCII input, in
-
452 // which case we do not need to call the expensive 'to_ascii' if a few
-
453 // conditions are met: no '%' and no 'xn-' subsequence.
-
454 std::string buffer = std::string(input);
-
455 // This next function checks that the result is ascii, but we are going to
-
456 // to check anyhow with is_forbidden.
-
457 // bool is_ascii =
-
458 unicode::to_lower_ascii(buffer.data(), buffer.size());
-
459 bool is_forbidden = unicode::contains_forbidden_domain_code_point(
-
460 buffer.data(), buffer.size());
-
461 if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
-
462 // fast path
-
463 host = std::move(buffer);
-
464 if (checkers::is_ipv4(host.value())) {
-
465 ada_log("parse_host fast path ipv4");
-
466 return parse_ipv4(host.value());
-
467 }
-
468 ada_log("parse_host fast path ", *host);
-
469 return true;
-
470 }
-
471 ada_log("parse_host calling to_ascii");
-
472 is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
-
473 if (!is_valid) {
-
474 ada_log("parse_host to_ascii returns false");
-
475 return is_valid = false;
-
476 }
-
477 ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
-
478 " bytes]");
-
479
-
480 if (std::any_of(host.value().begin(), host.value().end(),
-
481 ada::unicode::is_forbidden_domain_code_point)) {
-
482 host = std::nullopt;
-
483 return is_valid = false;
-
484 }
-
485
-
486 // If asciiDomain ends in a number, then return the result of IPv4 parsing
-
487 // asciiDomain.
-
488 if (checkers::is_ipv4(host.value())) {
-
489 ada_log("parse_host got ipv4 ", *host);
-
490 return parse_ipv4(host.value());
-
491 }
-
492
-
493 return true;
-
494}
-
495
-
496ada_really_inline void url::parse_path(std::string_view input) {
-
497 ada_log("parse_path ", input);
-
498 std::string tmp_buffer;
-
499 std::string_view internal_input;
-
500 if (unicode::has_tabs_or_newline(input)) {
-
501 tmp_buffer = input;
-
502 // Optimization opportunity: Instead of copying and then pruning, we could
-
503 // just directly build the string from user_input.
-
504 helpers::remove_ascii_tab_or_newline(tmp_buffer);
-
505 internal_input = tmp_buffer;
-
506 } else {
-
507 internal_input = input;
-
508 }
-
509
-
510 // If url is special, then:
-
511 if (is_special()) {
-
512 if (internal_input.empty()) {
-
513 path = "/";
-
514 } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
-
515 helpers::parse_prepared_path(internal_input.substr(1), type, path);
-
516 return;
+
8#include <string_view>
+
9
+
10namespace ada {
+
11
+
12bool url::parse_opaque_host(std::string_view input) {
+
13 ada_log("parse_opaque_host ", input, " [", input.size(), " bytes]");
+
14 if (std::ranges::any_of(input.begin(), input.end(),
+
15 ada::unicode::is_forbidden_host_code_point)) {
+
16 return is_valid = false;
+
17 }
+
18
+
19 // Return the result of running UTF-8 percent-encode on input using the C0
+
20 // control percent-encode set.
+
21 host = ada::unicode::percent_encode(
+
22 input, ada::character_sets::C0_CONTROL_PERCENT_ENCODE);
+
23 return true;
+
24}
+
25
+
26bool url::parse_ipv4(std::string_view input) {
+
27 ada_log("parse_ipv4 ", input, " [", input.size(), " bytes]");
+
28 if (input.back() == '.') {
+
29 input.remove_suffix(1);
+
30 }
+
31 size_t digit_count{0};
+
32 int pure_decimal_count = 0; // entries that are decimal
+
33 std::string_view original_input =
+
34 input; // we might use this if pure_decimal_count == 4.
+
35 uint64_t ipv4{0};
+
36 // we could unroll for better performance?
+
37 for (; (digit_count < 4) && !(input.empty()); digit_count++) {
+
38 uint32_t
+
39 segment_result{}; // If any number exceeds 32 bits, we have an error.
+
40 bool is_hex = checkers::has_hex_prefix(input);
+
41 if (is_hex && ((input.length() == 2) ||
+
42 ((input.length() > 2) && (input[2] == '.')))) {
+
43 // special case
+
44 segment_result = 0;
+
45 input.remove_prefix(2);
+
46 } else {
+
47 std::from_chars_result r{};
+
48 if (is_hex) {
+
49 r = std::from_chars(input.data() + 2, input.data() + input.size(),
+
50 segment_result, 16);
+
51 } else if ((input.length() >= 2) && input[0] == '0' &&
+
52 checkers::is_digit(input[1])) {
+
53 r = std::from_chars(input.data() + 1, input.data() + input.size(),
+
54 segment_result, 8);
+
55 } else {
+
56 pure_decimal_count++;
+
57 r = std::from_chars(input.data(), input.data() + input.size(),
+
58 segment_result, 10);
+
59 }
+
60 if (r.ec != std::errc()) {
+
61 return is_valid = false;
+
62 }
+
63 input.remove_prefix(r.ptr - input.data());
+
64 }
+
65 if (input.empty()) {
+
66 // We have the last value.
+
67 // At this stage, ipv4 contains digit_count*8 bits.
+
68 // So we have 32-digit_count*8 bits left.
+
69 if (segment_result >= (uint64_t(1) << (32 - digit_count * 8))) {
+
70 return is_valid = false;
+
71 }
+
72 ipv4 <<= (32 - digit_count * 8);
+
73 ipv4 |= segment_result;
+
74 goto final;
+
75 } else {
+
76 // There is more, so that the value must no be larger than 255
+
77 // and we must have a '.'.
+
78 if ((segment_result > 255) || (input[0] != '.')) {
+
79 return is_valid = false;
+
80 }
+
81 ipv4 <<= 8;
+
82 ipv4 |= segment_result;
+
83 input.remove_prefix(1); // remove '.'
+
84 }
+
85 }
+
86 if ((digit_count != 4) || (!input.empty())) {
+
87 return is_valid = false;
+
88 }
+
89final:
+
90 // We could also check r.ptr to see where the parsing ended.
+
91 if (pure_decimal_count == 4) {
+
92 host = original_input; // The original input was already all decimal and we
+
93 // validated it.
+
94 } else {
+
95 host = ada::serializers::ipv4(ipv4); // We have to reserialize the address.
+
96 }
+
97 host_type = IPV4;
+
98 return true;
+
99}
+
100
+
101bool url::parse_ipv6(std::string_view input) {
+
102 ada_log("parse_ipv6 ", input, " [", input.size(), " bytes]");
+
103
+
104 if (input.empty()) {
+
105 return is_valid = false;
+
106 }
+
107 // Let address be a new IPv6 address whose IPv6 pieces are all 0.
+
108 std::array<uint16_t, 8> address{};
+
109
+
110 // Let pieceIndex be 0.
+
111 int piece_index = 0;
+
112
+
113 // Let compress be null.
+
114 std::optional<int> compress{};
+
115
+
116 // Let pointer be a pointer for input.
+
117 std::string_view::iterator pointer = input.begin();
+
118
+
119 // If c is U+003A (:), then:
+
120 if (input[0] == ':') {
+
121 // If remaining does not start with U+003A (:), validation error, return
+
122 // failure.
+
123 if (input.size() == 1 || input[1] != ':') {
+
124 ada_log("parse_ipv6 starts with : but the rest does not start with :");
+
125 return is_valid = false;
+
126 }
+
127
+
128 // Increase pointer by 2.
+
129 pointer += 2;
+
130
+
131 // Increase pieceIndex by 1 and then set compress to pieceIndex.
+
132 compress = ++piece_index;
+
133 }
+
134
+
135 // While c is not the EOF code point:
+
136 while (pointer != input.end()) {
+
137 // If pieceIndex is 8, validation error, return failure.
+
138 if (piece_index == 8) {
+
139 ada_log("parse_ipv6 piece_index == 8");
+
140 return is_valid = false;
+
141 }
+
142
+
143 // If c is U+003A (:), then:
+
144 if (*pointer == ':') {
+
145 // If compress is non-null, validation error, return failure.
+
146 if (compress.has_value()) {
+
147 ada_log("parse_ipv6 compress is non-null");
+
148 return is_valid = false;
+
149 }
+
150
+
151 // Increase pointer and pieceIndex by 1, set compress to pieceIndex, and
+
152 // then continue.
+
153 pointer++;
+
154 compress = ++piece_index;
+
155 continue;
+
156 }
+
157
+
158 // Let value and length be 0.
+
159 uint16_t value = 0, length = 0;
+
160
+
161 // While length is less than 4 and c is an ASCII hex digit,
+
162 // set value to value times 0x10 + c interpreted as hexadecimal number, and
+
163 // increase pointer and length by 1.
+
164 while (length < 4 && pointer != input.end() &&
+
165 unicode::is_ascii_hex_digit(*pointer)) {
+
166 // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
+
167 value = uint16_t(value * 0x10 + unicode::convert_hex_to_binary(*pointer));
+
168 pointer++;
+
169 length++;
+
170 }
+
171
+
172 // If c is U+002E (.), then:
+
173 if (pointer != input.end() && *pointer == '.') {
+
174 // If length is 0, validation error, return failure.
+
175 if (length == 0) {
+
176 ada_log("parse_ipv6 length is 0");
+
177 return is_valid = false;
+
178 }
+
179
+
180 // Decrease pointer by length.
+
181 pointer -= length;
+
182
+
183 // If pieceIndex is greater than 6, validation error, return failure.
+
184 if (piece_index > 6) {
+
185 ada_log("parse_ipv6 piece_index > 6");
+
186 return is_valid = false;
+
187 }
+
188
+
189 // Let numbersSeen be 0.
+
190 int numbers_seen = 0;
+
191
+
192 // While c is not the EOF code point:
+
193 while (pointer != input.end()) {
+
194 // Let ipv4Piece be null.
+
195 std::optional<uint16_t> ipv4_piece{};
+
196
+
197 // If numbersSeen is greater than 0, then:
+
198 if (numbers_seen > 0) {
+
199 // If c is a U+002E (.) and numbersSeen is less than 4, then increase
+
200 // pointer by 1.
+
201 if (*pointer == '.' && numbers_seen < 4) {
+
202 pointer++;
+
203 }
+
204 // Otherwise, validation error, return failure.
+
205 else {
+
206 ada_log("parse_ipv6 Otherwise, validation error, return failure");
+
207 return is_valid = false;
+
208 }
+
209 }
+
210
+
211 // If c is not an ASCII digit, validation error, return failure.
+
212 if (pointer == input.end() || !checkers::is_digit(*pointer)) {
+
213 ada_log(
+
214 "parse_ipv6 If c is not an ASCII digit, validation error, return "
+
215 "failure");
+
216 return is_valid = false;
+
217 }
+
218
+
219 // While c is an ASCII digit:
+
220 while (pointer != input.end() && checkers::is_digit(*pointer)) {
+
221 // Let number be c interpreted as decimal number.
+
222 int number = *pointer - '0';
+
223
+
224 // If ipv4Piece is null, then set ipv4Piece to number.
+
225 if (!ipv4_piece.has_value()) {
+
226 ipv4_piece = number;
+
227 }
+
228 // Otherwise, if ipv4Piece is 0, validation error, return failure.
+
229 else if (ipv4_piece == 0) {
+
230 ada_log("parse_ipv6 if ipv4Piece is 0, validation error");
+
231 return is_valid = false;
+
232 }
+
233 // Otherwise, set ipv4Piece to ipv4Piece times 10 + number.
+
234 else {
+
235 ipv4_piece = *ipv4_piece * 10 + number;
+
236 }
+
237
+
238 // If ipv4Piece is greater than 255, validation error, return failure.
+
239 if (ipv4_piece > 255) {
+
240 ada_log("parse_ipv6 ipv4_piece > 255");
+
241 return is_valid = false;
+
242 }
+
243
+
244 // Increase pointer by 1.
+
245 pointer++;
+
246 }
+
247
+
248 // Set address[pieceIndex] to address[pieceIndex] times 0x100 +
+
249 // ipv4Piece.
+
250 // https://stackoverflow.com/questions/39060852/why-does-the-addition-of-two-shorts-return-an-int
+
251 address[piece_index] =
+
252 uint16_t(address[piece_index] * 0x100 + *ipv4_piece);
+
253
+
254 // Increase numbersSeen by 1.
+
255 numbers_seen++;
+
256
+
257 // If numbersSeen is 2 or 4, then increase pieceIndex by 1.
+
258 if (numbers_seen == 2 || numbers_seen == 4) {
+
259 piece_index++;
+
260 }
+
261 }
+
262
+
263 // If numbersSeen is not 4, validation error, return failure.
+
264 if (numbers_seen != 4) {
+
265 return is_valid = false;
+
266 }
+
267
+
268 // Break.
+
269 break;
+
270 }
+
271 // Otherwise, if c is U+003A (:):
+
272 else if ((pointer != input.end()) && (*pointer == ':')) {
+
273 // Increase pointer by 1.
+
274 pointer++;
+
275
+
276 // If c is the EOF code point, validation error, return failure.
+
277 if (pointer == input.end()) {
+
278 ada_log(
+
279 "parse_ipv6 If c is the EOF code point, validation error, return "
+
280 "failure");
+
281 return is_valid = false;
+
282 }
+
283 }
+
284 // Otherwise, if c is not the EOF code point, validation error, return
+
285 // failure.
+
286 else if (pointer != input.end()) {
+
287 ada_log(
+
288 "parse_ipv6 Otherwise, if c is not the EOF code point, validation "
+
289 "error, return failure");
+
290 return is_valid = false;
+
291 }
+
292
+
293 // Set address[pieceIndex] to value.
+
294 address[piece_index] = value;
+
295
+
296 // Increase pieceIndex by 1.
+
297 piece_index++;
+
298 }
+
299
+
300 // If compress is non-null, then:
+
301 if (compress.has_value()) {
+
302 // Let swaps be pieceIndex - compress.
+
303 int swaps = piece_index - *compress;
+
304
+
305 // Set pieceIndex to 7.
+
306 piece_index = 7;
+
307
+
308 // While pieceIndex is not 0 and swaps is greater than 0,
+
309 // swap address[pieceIndex] with address[compress + swaps - 1], and then
+
310 // decrease both pieceIndex and swaps by 1.
+
311 while (piece_index != 0 && swaps > 0) {
+
312 std::swap(address[piece_index], address[*compress + swaps - 1]);
+
313 piece_index--;
+
314 swaps--;
+
315 }
+
316 }
+
317 // Otherwise, if compress is null and pieceIndex is not 8, validation error,
+
318 // return failure.
+
319 else if (piece_index != 8) {
+
320 ada_log(
+
321 "parse_ipv6 if compress is null and pieceIndex is not 8, validation "
+
322 "error, return failure");
+
323 return is_valid = false;
+
324 }
+
325 host = ada::serializers::ipv6(address);
+
326 ada_log("parse_ipv6 ", *host);
+
327 host_type = IPV6;
+
328 return true;
+
329}
+
330
+
331template <bool has_state_override>
+
332ada_really_inline bool url::parse_scheme(const std::string_view input) {
+
333 auto parsed_type = ada::scheme::get_scheme_type(input);
+
334 bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
+
339 if (is_input_special) { // fast path!!!
+
340 if constexpr (has_state_override) {
+
341 // If url's scheme is not a special scheme and buffer is a special scheme,
+
342 // then return.
+
343 if (is_special() != is_input_special) {
+
344 return false;
+
345 }
+
346
+
347 // If url includes credentials or has a non-null port, and buffer is
+
348 // "file", then return.
+
349 if ((has_credentials() || port.has_value()) &&
+
350 parsed_type == ada::scheme::type::FILE) {
+
351 return false;
+
352 }
+
353
+
354 // If url's scheme is "file" and its host is an empty host, then return.
+
355 // An empty host is the empty string.
+
356 if (type == ada::scheme::type::FILE && host.has_value() &&
+
357 host.value().empty()) {
+
358 return false;
+
359 }
+
360 }
+
361
+
362 type = parsed_type;
+
363
+
364 if constexpr (has_state_override) {
+
365 // This is uncommon.
+
366 uint16_t urls_scheme_port = get_special_port();
+
367
+
368 if (urls_scheme_port) {
+
369 // If url's port is url's scheme's default port, then set url's port to
+
370 // null.
+
371 if (port.has_value() && *port == urls_scheme_port) {
+
372 port = std::nullopt;
+
373 }
+
374 }
+
375 }
+
376 } else { // slow path
+
377 std::string _buffer(input);
+
378 // Next function is only valid if the input is ASCII and returns false
+
379 // otherwise, but it seems that we always have ascii content so we do not
+
380 // need to check the return value.
+
381 // bool is_ascii =
+
382 unicode::to_lower_ascii(_buffer.data(), _buffer.size());
+
383
+
384 if constexpr (has_state_override) {
+
385 // If url's scheme is a special scheme and buffer is not a special scheme,
+
386 // then return. If url's scheme is not a special scheme and buffer is a
+
387 // special scheme, then return.
+
388 if (is_special() != ada::scheme::is_special(_buffer)) {
+
389 return true;
+
390 }
+
391
+
392 // If url includes credentials or has a non-null port, and buffer is
+
393 // "file", then return.
+
394 if ((has_credentials() || port.has_value()) && _buffer == "file") {
+
395 return true;
+
396 }
+
397
+
398 // If url's scheme is "file" and its host is an empty host, then return.
+
399 // An empty host is the empty string.
+
400 if (type == ada::scheme::type::FILE && host.has_value() &&
+
401 host.value().empty()) {
+
402 return true;
+
403 }
+
404 }
+
405
+
406 set_scheme(std::move(_buffer));
+
407
+
408 if constexpr (has_state_override) {
+
409 // This is uncommon.
+
410 uint16_t urls_scheme_port = get_special_port();
+
411
+
412 if (urls_scheme_port) {
+
413 // If url's port is url's scheme's default port, then set url's port to
+
414 // null.
+
415 if (port.has_value() && *port == urls_scheme_port) {
+
416 port = std::nullopt;
+
417 }
+
418 }
+
419 }
+
420 }
+
421
+
422 return true;
+
423}
+
424
+
425ada_really_inline bool url::parse_host(std::string_view input) {
+
426 ada_log("parse_host ", input, " [", input.size(), " bytes]");
+
427 if (input.empty()) {
+
428 return is_valid = false;
+
429 } // technically unnecessary.
+
430 // If input starts with U+005B ([), then:
+
431 if (input[0] == '[') {
+
432 // If input does not end with U+005D (]), validation error, return failure.
+
433 if (input.back() != ']') {
+
434 return is_valid = false;
+
435 }
+
436 ada_log("parse_host ipv6");
+
437
+
438 // Return the result of IPv6 parsing input with its leading U+005B ([) and
+
439 // trailing U+005D (]) removed.
+
440 input.remove_prefix(1);
+
441 input.remove_suffix(1);
+
442 return parse_ipv6(input);
+
443 }
+
444
+
445 // If isNotSpecial is true, then return the result of opaque-host parsing
+
446 // input.
+
447 if (!is_special()) {
+
448 return parse_opaque_host(input);
+
449 }
+
450 // Let domain be the result of running UTF-8 decode without BOM on the
+
451 // percent-decoding of input. Let asciiDomain be the result of running domain
+
452 // to ASCII with domain and false. The most common case is an ASCII input, in
+
453 // which case we do not need to call the expensive 'to_ascii' if a few
+
454 // conditions are met: no '%' and no 'xn-' subsequence.
+
455 std::string buffer = std::string(input);
+
456 // This next function checks that the result is ascii, but we are going to
+
457 // to check anyhow with is_forbidden.
+
458 // bool is_ascii =
+
459 unicode::to_lower_ascii(buffer.data(), buffer.size());
+
460 bool is_forbidden = unicode::contains_forbidden_domain_code_point(
+
461 buffer.data(), buffer.size());
+
462 if (is_forbidden == 0 && buffer.find("xn-") == std::string_view::npos) {
+
463 // fast path
+
464 host = std::move(buffer);
+
465 if (checkers::is_ipv4(host.value())) {
+
466 ada_log("parse_host fast path ipv4");
+
467 return parse_ipv4(host.value());
+
468 }
+
469 ada_log("parse_host fast path ", *host);
+
470 return true;
+
471 }
+
472 ada_log("parse_host calling to_ascii");
+
473 is_valid = ada::unicode::to_ascii(host, input, input.find('%'));
+
474 if (!is_valid) {
+
475 ada_log("parse_host to_ascii returns false");
+
476 return is_valid = false;
+
477 }
+
478 ada_log("parse_host to_ascii succeeded ", *host, " [", host->size(),
+
479 " bytes]");
+
480
+
481 if (std::any_of(host.value().begin(), host.value().end(),
+
482 ada::unicode::is_forbidden_domain_code_point)) {
+
483 host = std::nullopt;
+
484 return is_valid = false;
+
485 }
+
486
+
487 // If asciiDomain ends in a number, then return the result of IPv4 parsing
+
488 // asciiDomain.
+
489 if (checkers::is_ipv4(host.value())) {
+
490 ada_log("parse_host got ipv4 ", *host);
+
491 return parse_ipv4(host.value());
+
492 }
+
493
+
494 return true;
+
495}
+
496
+
497ada_really_inline void url::parse_path(std::string_view input) {
+
498 ada_log("parse_path ", input);
+
499 std::string tmp_buffer;
+
500 std::string_view internal_input;
+
501 if (unicode::has_tabs_or_newline(input)) {
+
502 tmp_buffer = input;
+
503 // Optimization opportunity: Instead of copying and then pruning, we could
+
504 // just directly build the string from user_input.
+
505 helpers::remove_ascii_tab_or_newline(tmp_buffer);
+
506 internal_input = tmp_buffer;
+
507 } else {
+
508 internal_input = input;
+
509 }
+
510
+
511 // If url is special, then:
+
512 if (is_special()) {
+
513 if (internal_input.empty()) {
+
514 path = "/";
+
515 } else if ((internal_input[0] == '/') || (internal_input[0] == '\\')) {
+
516 helpers::parse_prepared_path(internal_input.substr(1), type, path);
517 } else {
518 helpers::parse_prepared_path(internal_input, type, path);
-
519 return;
-
520 }
-
521 } else if (!internal_input.empty()) {
-
522 if (internal_input[0] == '/') {
-
523 helpers::parse_prepared_path(internal_input.substr(1), type, path);
-
524 return;
-
525 } else {
-
526 helpers::parse_prepared_path(internal_input, type, path);
-
527 return;
-
528 }
-
529 } else {
-
530 if (!host.has_value()) {
-
531 path = "/";
-
532 }
-
533 }
-
534}
-
535
-
-
536[[nodiscard]] std::string url::to_string() const {
-
537 if (!is_valid) {
-
538 return "null";
-
539 }
-
540 std::string answer;
-
541 auto back = std::back_insert_iterator(answer);
-
542 answer.append("{\n");
-
543 answer.append("\t\"protocol\":\"");
-
544 helpers::encode_json(get_protocol(), back);
-
545 answer.append("\",\n");
-
546 if (has_credentials()) {
-
547 answer.append("\t\"username\":\"");
-
548 helpers::encode_json(username, back);
+
519 }
+
520 } else if (!internal_input.empty()) {
+
521 if (internal_input[0] == '/') {
+
522 helpers::parse_prepared_path(internal_input.substr(1), type, path);
+
523 } else {
+
524 helpers::parse_prepared_path(internal_input, type, path);
+
525 }
+
526 } else {
+
527 if (!host.has_value()) {
+
528 path = "/";
+
529 }
+
530 }
+
531}
+
532
+
+
533[[nodiscard]] std::string url::to_string() const {
+
534 if (!is_valid) {
+
535 return "null";
+
536 }
+
537 std::string answer;
+
538 auto back = std::back_insert_iterator(answer);
+
539 answer.append("{\n");
+
540 answer.append("\t\"protocol\":\"");
+
541 helpers::encode_json(get_protocol(), back);
+
542 answer.append("\",\n");
+
543 if (has_credentials()) {
+
544 answer.append("\t\"username\":\"");
+
545 helpers::encode_json(username, back);
+
546 answer.append("\",\n");
+
547 answer.append("\t\"password\":\"");
+
548 helpers::encode_json(password, back);
549 answer.append("\",\n");
-
550 answer.append("\t\"password\":\"");
-
551 helpers::encode_json(password, back);
-
552 answer.append("\",\n");
-
553 }
-
554 if (host.has_value()) {
-
555 answer.append("\t\"host\":\"");
-
556 helpers::encode_json(host.value(), back);
-
557 answer.append("\",\n");
-
558 }
-
559 if (port.has_value()) {
-
560 answer.append("\t\"port\":\"");
-
561 answer.append(std::to_string(port.value()));
-
562 answer.append("\",\n");
-
563 }
-
564 answer.append("\t\"path\":\"");
-
565 helpers::encode_json(path, back);
-
566 answer.append("\",\n");
-
567 answer.append("\t\"opaque path\":");
-
568 answer.append((has_opaque_path ? "true" : "false"));
-
569 if (has_search()) {
-
570 answer.append(",\n");
-
571 answer.append("\t\"query\":\"");
-
572 helpers::encode_json(query.value(), back);
-
573 answer.append("\"");
-
574 }
-
575 if (hash.has_value()) {
-
576 answer.append(",\n");
-
577 answer.append("\t\"hash\":\"");
-
578 helpers::encode_json(hash.value(), back);
-
579 answer.append("\"");
-
580 }
-
581 answer.append("\n}");
-
582 return answer;
-
583}
+
550 }
+
551 if (host.has_value()) {
+
552 answer.append("\t\"host\":\"");
+
553 helpers::encode_json(host.value(), back);
+
554 answer.append("\",\n");
+
555 }
+
556 if (port.has_value()) {
+
557 answer.append("\t\"port\":\"");
+
558 answer.append(std::to_string(port.value()));
+
559 answer.append("\",\n");
+
560 }
+
561 answer.append("\t\"path\":\"");
+
562 helpers::encode_json(path, back);
+
563 answer.append("\",\n");
+
564 answer.append("\t\"opaque path\":");
+
565 answer.append((has_opaque_path ? "true" : "false"));
+
566 if (has_search()) {
+
567 answer.append(",\n");
+
568 answer.append("\t\"query\":\"");
+
569 helpers::encode_json(query.value(), back);
+
570 answer.append("\"");
+
571 }
+
572 if (hash.has_value()) {
+
573 answer.append(",\n");
+
574 answer.append("\t\"hash\":\"");
+
575 helpers::encode_json(hash.value(), back);
+
576 answer.append("\"");
+
577 }
+
578 answer.append("\n}");
+
579 return answer;
+
580}
-
584
-
-
585[[nodiscard]] bool url::has_valid_domain() const noexcept {
-
586 if (!host.has_value()) {
-
587 return false;
-
588 }
-
589 return checkers::verify_dns_length(host.value());
-
590}
+
581
+
+
582[[nodiscard]] bool url::has_valid_domain() const noexcept {
+
583 if (!host.has_value()) {
+
584 return false;
+
585 }
+
586 return checkers::verify_dns_length(host.value());
+
587}
-
591
-
592} // namespace ada
+
588
+
589} // namespace ada
Includes all definitions for Ada.
#define ada_really_inline
Definition common_defs.h:84
constexpr uint8_t C0_CONTROL_PERCENT_ENCODE[32]
constexpr bool has_hex_prefix(std::string_view input)
constexpr bool is_digit(char x) noexcept
constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept
Definition scheme-inl.h:72
- - -
@ NOT_SPECIAL
Definition scheme.h:32
+ + +
@ NOT_SPECIAL
Definition scheme.h:31
constexpr uint16_t get_special_port(std::string_view scheme) noexcept
Definition scheme-inl.h:57
std::string ipv6(const std::array< uint16_t, 8 > &address) noexcept
std::string ipv4(uint64_t address) noexcept
@@ -727,9 +724,9 @@
bool has_opaque_path
Definition url_base.h:55
ada_really_inline bool has_credentials() const noexcept
Definition url-inl.h:19
constexpr bool has_search() const noexcept override
Definition url-inl.h:163
-
std::string to_string() const override
Definition url.cpp:536
+
std::string to_string() const override
Definition url.cpp:533
std::string get_protocol() const noexcept
-
bool has_valid_domain() const noexcept override
Definition url.cpp:585
+
bool has_valid_domain() const noexcept override
Definition url.cpp:582
diff --git a/d6/da3/namespaceada_1_1parser.html b/d6/da3/namespaceada_1_1parser.html index feee5e9e7..a944901fe 100644 --- a/d6/da3/namespaceada_1_1parser.html +++ b/d6/da3/namespaceada_1_1parser.html @@ -165,7 +165,7 @@

Parses a url. The parameter user_input is the input to be parsed: it should be a valid UTF-8 string. The parameter base_url is an optional parameter that can be used to resolve relative URLs. If the base_url is provided, the user_input is resolved against the base_url.

-

Definition at line 927 of file parser.cpp.

+

Definition at line 920 of file parser.cpp.

References parse_url_impl().

diff --git a/d7/d2e/serializers_8h.html b/d7/d2e/serializers_8h.html index d903e9468..d6e720fa0 100644 --- a/d7/d2e/serializers_8h.html +++ b/d7/d2e/serializers_8h.html @@ -121,7 +121,6 @@ More...

#include "ada/common_defs.h"
#include <array>
-#include <optional>
#include <string>

Go to the source code of this file.

diff --git a/d7/d2e/serializers_8h_source.html b/d7/d2e/serializers_8h_source.html index 8117c6fa1..25cb6bf43 100644 --- a/d7/d2e/serializers_8h_source.html +++ b/d7/d2e/serializers_8h_source.html @@ -120,22 +120,21 @@
8#include "ada/common_defs.h"
9
10#include <array>
-
11#include <optional>
-
12#include <string>
-
13
-
18namespace ada::serializers {
-
19
- -
24 const std::array<uint16_t, 8>& address, size_t& compress,
-
25 size_t& compress_length) noexcept;
-
26
-
33std::string ipv6(const std::array<uint16_t, 8>& address) noexcept;
-
34
-
41std::string ipv4(uint64_t address) noexcept;
-
42
-
43} // namespace ada::serializers
-
44
-
45#endif // ADA_SERIALIZERS_H
+
11#include <string>
+
12
+
17namespace ada::serializers {
+
18
+ +
23 const std::array<uint16_t, 8>& address, size_t& compress,
+
24 size_t& compress_length) noexcept;
+
25
+
32std::string ipv6(const std::array<uint16_t, 8>& address) noexcept;
+
33
+
40std::string ipv4(uint64_t address) noexcept;
+
41
+
42} // namespace ada::serializers
+
43
+
44#endif // ADA_SERIALIZERS_H
Common definitions for cross-platform compiler support.
Includes the definitions for URL serializers.
std::string ipv6(const std::array< uint16_t, 8 > &address) noexcept
diff --git a/d7/d34/structada_1_1url__search__params__iter-members.html b/d7/d34/structada_1_1url__search__params__iter-members.html index 7150f5abb..cbce35092 100644 --- a/d7/d34/structada_1_1url__search__params__iter-members.html +++ b/d7/d34/structada_1_1url__search__params__iter-members.html @@ -116,7 +116,7 @@

This is the complete list of members for ada::url_search_params_iter< T, Type >, including all inherited members.

- + diff --git a/d7/d6c/namespaceada_1_1helpers.html b/d7/d6c/namespaceada_1_1helpers.html index 1c6ddbe9b..f231a64b6 100644 --- a/d7/d6c/namespaceada_1_1helpers.html +++ b/d7/d6c/namespaceada_1_1helpers.html @@ -173,7 +173,7 @@

-

Definition at line 458 of file helpers.cpp.

+

Definition at line 450 of file helpers.cpp.

References host_delimiters.

@@ -206,7 +206,7 @@

-

Definition at line 326 of file helpers.cpp.

+

Definition at line 318 of file helpers.cpp.

References special_host_delimiters.

@@ -258,7 +258,7 @@

-

Definition at line 175 of file helpers.cpp.

+

Definition at line 167 of file helpers.cpp.

@@ -291,7 +291,7 @@

}()
tl::expected< result_type, ada::errors > result
-

Definition at line 766 of file helpers.cpp.

+

Definition at line 758 of file helpers.cpp.

@@ -323,7 +323,7 @@

return result;
}()
-

Definition at line 744 of file helpers.cpp.

+

Definition at line 736 of file helpers.cpp.

@@ -354,7 +354,7 @@

return result;
}()
-

Definition at line 450 of file helpers.cpp.

+

Definition at line 442 of file helpers.cpp.

Referenced by find_next_host_delimiter().

@@ -388,7 +388,7 @@

return result;
}()
-

Definition at line 317 of file helpers.cpp.

+

Definition at line 309 of file helpers.cpp.

Referenced by find_next_host_delimiter_special().

diff --git a/d7/dcf/scheme-inl_8h_source.html b/d7/dcf/scheme-inl_8h_source.html index f60cf451f..08946d393 100644 --- a/d7/dcf/scheme-inl_8h_source.html +++ b/d7/dcf/scheme-inl_8h_source.html @@ -185,8 +185,8 @@
constexpr uint16_t special_ports[]
Definition scheme-inl.h:22
Includes the scheme declarations.
Definition scheme-inl.h:10
constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept
Definition scheme-inl.h:72
- -
@ NOT_SPECIAL
Definition scheme.h:32
+ +
@ NOT_SPECIAL
Definition scheme.h:31
constexpr uint16_t get_special_port(std::string_view scheme) noexcept
Definition scheme-inl.h:57
Declarations for the URL scheme.
diff --git a/d8/df6/implementation_8cpp_source.html b/d8/df6/implementation_8cpp_source.html index 204f65400..3ff7a5444 100644 --- a/d8/df6/implementation_8cpp_source.html +++ b/d8/df6/implementation_8cpp_source.html @@ -207,7 +207,7 @@
Common definitions for cross-platform compiler support.
#define ada_warn_unused
Definition common_defs.h:88
result_type parse_url_impl(std::string_view user_input, const result_type *base_url=nullptr)
Definition parser.cpp:15
- +
Definition ada_idna.h:13
bool can_parse(std::string_view input, const std::string_view *base_input=nullptr)
template ada::result< url > parse< url >(std::string_view input, const url *base_url)
diff --git a/d9/d07/url__base_8h_source.html b/d9/d07/url__base_8h_source.html index a3a7aee48..ebc5286d0 100644 --- a/d9/d07/url__base_8h_source.html +++ b/d9/d07/url__base_8h_source.html @@ -182,8 +182,8 @@
142#endif
Common definitions for cross-platform compiler support.
#define ada_really_inline
Definition common_defs.h:84
- -
@ NOT_SPECIAL
Definition scheme.h:32
+ +
@ NOT_SPECIAL
Definition scheme.h:31
Definition ada_idna.h:13
url_host_type
Definition url_base.h:19
@ IPV6
Definition url_base.h:32
diff --git a/d9/d61/url__aggregator-inl_8h_source.html b/d9/d61/url__aggregator-inl_8h_source.html index 84c58cccd..2880e39da 100644 --- a/d9/d61/url__aggregator-inl_8h_source.html +++ b/d9/d61/url__aggregator-inl_8h_source.html @@ -1259,8 +1259,8 @@
constexpr uint8_t FRAGMENT_PERCENT_ENCODE[32]
constexpr bool is_digit(char x) noexcept
constexpr int32_t base
- - + +
ada_really_inline size_t percent_encode_index(const std::string_view input, const uint8_t character_set[])
Definition unicode-inl.h:19
Definition ada_idna.h:13
std::ostream & operator<<(std::ostream &out, const ada::url &u)
Definition url-inl.h:38
diff --git a/da/d15/structada_1_1url__search__params-members.html b/da/d15/structada_1_1url__search__params-members.html index 4e9019318..56745ec10 100644 --- a/da/d15/structada_1_1url__search__params-members.html +++ b/da/d15/structada_1_1url__search__params-members.html @@ -138,7 +138,7 @@

- + diff --git a/da/dac/url__search__params_8h_source.html b/da/dac/url__search__params_8h_source.html index 56243a29b..bdfabd8e9 100644 --- a/da/dac/url__search__params_8h_source.html +++ b/da/dac/url__search__params_8h_source.html @@ -150,113 +150,117 @@
38struct url_search_params {
39 url_search_params() = default;
40
-
45 url_search_params(const std::string_view input) { initialize(input); }
-
46
-
47 url_search_params(const url_search_params &u) = default;
-
48 url_search_params(url_search_params &&u) noexcept = default;
-
49 url_search_params &operator=(url_search_params &&u) noexcept = default;
-
50 url_search_params &operator=(const url_search_params &u) = default;
-
51 ~url_search_params() = default;
-
52
-
53 [[nodiscard]] inline size_t size() const noexcept;
+
+
45 explicit url_search_params(const std::string_view input) {
+
46 initialize(input);
+
47 }
+
+
48
+
49 url_search_params(const url_search_params &u) = default;
+
50 url_search_params(url_search_params &&u) noexcept = default;
+
51 url_search_params &operator=(url_search_params &&u) noexcept = default;
+
52 url_search_params &operator=(const url_search_params &u) = default;
+
53 ~url_search_params() = default;
54
-
58 inline void append(std::string_view key, std::string_view value);
-
59
-
63 inline void remove(std::string_view key);
-
64 inline void remove(std::string_view key, std::string_view value);
-
65
-
69 inline std::optional<std::string_view> get(std::string_view key);
-
70
-
74 inline std::vector<std::string> get_all(std::string_view key);
-
75
-
79 inline bool has(std::string_view key) noexcept;
-
80 inline bool has(std::string_view key, std::string_view value) noexcept;
-
81
-
85 inline void set(std::string_view key, std::string_view value);
-
86
-
90 inline void sort();
-
91
-
95 inline std::string to_string() const;
-
96
-
104 inline url_search_params_keys_iter get_keys();
-
105
-
112 inline url_search_params_values_iter get_values();
-
113
-
121 inline url_search_params_entries_iter get_entries();
-
122
-
127 inline auto begin() const { return params.begin(); }
-
128 inline auto end() const { return params.end(); }
-
129 inline auto front() const { return params.front(); }
-
130 inline auto back() const { return params.back(); }
-
131 inline auto operator[](size_t index) const { return params[index]; }
-
132
-
139 void reset(std::string_view input);
-
140
-
141 private:
-
142 typedef std::pair<std::string, std::string> key_value_pair;
-
143 std::vector<key_value_pair> params{};
-
144
-
148 void initialize(std::string_view init);
-
149
-
150 template <typename T, url_search_params_iter_type Type>
-
151 friend struct url_search_params_iter;
-
152}; // url_search_params
+
55 [[nodiscard]] inline size_t size() const noexcept;
+
56
+
60 inline void append(std::string_view key, std::string_view value);
+
61
+
65 inline void remove(std::string_view key);
+
66 inline void remove(std::string_view key, std::string_view value);
+
67
+
71 inline std::optional<std::string_view> get(std::string_view key);
+
72
+
76 inline std::vector<std::string> get_all(std::string_view key);
+
77
+
81 inline bool has(std::string_view key) noexcept;
+
82 inline bool has(std::string_view key, std::string_view value) noexcept;
+
83
+
87 inline void set(std::string_view key, std::string_view value);
+
88
+
92 inline void sort();
+
93
+
97 inline std::string to_string() const;
+
98
+
106 inline url_search_params_keys_iter get_keys();
+
107
+
114 inline url_search_params_values_iter get_values();
+
115
+
123 inline url_search_params_entries_iter get_entries();
+
124
+
129 inline auto begin() const { return params.begin(); }
+
130 inline auto end() const { return params.end(); }
+
131 inline auto front() const { return params.front(); }
+
132 inline auto back() const { return params.back(); }
+
133 inline auto operator[](size_t index) const { return params[index]; }
+
134
+
141 void reset(std::string_view input);
+
142
+
143 private:
+
144 typedef std::pair<std::string, std::string> key_value_pair;
+
145 std::vector<key_value_pair> params{};
+
146
+
150 void initialize(std::string_view init);
+
151
+
152 template <typename T, url_search_params_iter_type Type>
+
153 friend struct url_search_params_iter;
+
154}; // url_search_params
-
153
-
160template <typename T, url_search_params_iter_type Type>
-
-
161struct url_search_params_iter {
-
162 inline url_search_params_iter() : params(EMPTY) {}
-
163 url_search_params_iter(const url_search_params_iter &u) = default;
-
164 url_search_params_iter(url_search_params_iter &&u) noexcept = default;
-
165 url_search_params_iter &operator=(url_search_params_iter &&u) noexcept =
-
166 default;
-
167 url_search_params_iter &operator=(const url_search_params_iter &u) = default;
-
168 ~url_search_params_iter() = default;
-
169
-
173 inline std::optional<T> next();
-
174
-
175 inline bool has_next();
+
155
+
162template <typename T, url_search_params_iter_type Type>
+
+ +
164 inline url_search_params_iter() : params(EMPTY) {}
+ + + +
168 default;
+ + +
171
+
175 inline std::optional<T> next();
176
-
177 private:
-
178 static url_search_params EMPTY;
-
179 inline url_search_params_iter(url_search_params &params_) : params(params_) {}
-
180
-
181 url_search_params &params;
-
182 size_t pos = 0;
-
183
-
184 friend struct url_search_params;
-
185};
+
177 inline bool has_next() const;
+
178
+
179 private:
+
180 static url_search_params EMPTY;
+
181 inline url_search_params_iter(url_search_params &params_) : params(params_) {}
+
182
+
183 url_search_params &params;
+
184 size_t pos = 0;
+
185
+
186 friend struct url_search_params;
+
187};
-
186
-
187} // namespace ada
-
188#endif
+
188
+
189} // namespace ada
+
190#endif
Definition ada_idna.h:13
url_search_params_iter_type
@ ENTRIES
@ KEYS
@ VALUES
std::pair< std::string_view, std::string_view > key_value_view_pair
-
-
bool has_next()
+
url_search_params_iter(const url_search_params_iter &u)=default
-
url_search_params_iter()
+
url_search_params_iter()
url_search_params_iter & operator=(url_search_params_iter &&u) noexcept=default
std::optional< T > next()
url_search_params_iter(url_search_params_iter &&u) noexcept=default
+
bool has_next() const
~url_search_params_iter()=default
url_search_params_iter & operator=(const url_search_params_iter &u)=default
void set(std::string_view key, std::string_view value)
-
auto begin() const
-
auto end() const
+
auto begin() const
+
auto end() const
std::vector< std::string > get_all(std::string_view key)
-
auto front() const
-
auto back() const
+
auto front() const
+
auto back() const
void remove(std::string_view key)
url_search_params(const url_search_params &u)=default
url_search_params(url_search_params &&u) noexcept=default
-
auto operator[](size_t index) const
+
auto operator[](size_t index) const
url_search_params_entries_iter get_entries()
url_search_params()=default
std::string to_string() const
diff --git a/db/d75/structada_1_1url__base.html b/db/d75/structada_1_1url__base.html index c774c996c..aa6d4e98e 100644 --- a/db/d75/structada_1_1url__base.html +++ b/db/d75/structada_1_1url__base.html @@ -350,7 +350,7 @@

Definition at line 55 of file url_base.h.

-

Referenced by ada::url::get_components(), ada::url::get_href(), ada::parser::parse_url_impl(), ada::url::set_href(), ada::url::set_pathname(), ada::url_aggregator::set_pathname(), ada::url::to_string(), and ada::url_aggregator::validate().

+

Referenced by ada::url::get_components(), ada::url::get_href(), ada::parser::parse_url_impl(), ada::url::set_pathname(), ada::url_aggregator::set_pathname(), ada::url::to_string(), and ada::url_aggregator::validate().

diff --git a/dc/ddd/parser_8cpp_source.html b/dc/ddd/parser_8cpp_source.html index 3187fc4fc..259b5a439 100644 --- a/dc/ddd/parser_8cpp_source.html +++ b/dc/ddd/parser_8cpp_source.html @@ -351,701 +351,694 @@
237 // TODO: We could do various processing early on, using a single pass
238 // over the string to collect information about it, e.g., telling us
239 // whether there is a @ and if so, where (or how many).
-
240 const bool contains_ampersand =
-
241 (url_data.find('@', input_position) != std::string_view::npos);
-
242
-
243 if (!contains_ampersand) {
-
244 state = ada::state::HOST;
-
245 break;
-
246 }
-
247 bool at_sign_seen{false};
-
248 bool password_token_seen{false};
-
254 do {
-
255 std::string_view view = helpers::substring(url_data, input_position);
-
256 // The delimiters are @, /, ? \\.
-
257 size_t location =
-
258 url.is_special() ? helpers::find_authority_delimiter_special(view)
-
259 : helpers::find_authority_delimiter(view);
-
260 std::string_view authority_view(view.data(), location);
-
261 size_t end_of_authority = input_position + authority_view.size();
-
262 // If c is U+0040 (@), then:
-
263 if ((end_of_authority != input_size) &&
-
264 (url_data[end_of_authority] == '@')) {
-
265 // If atSignSeen is true, then prepend "%40" to buffer.
-
266 if (at_sign_seen) {
-
267 if (password_token_seen) {
-
268 if constexpr (result_type_is_ada_url) {
-
269 url.password += "%40";
-
270 } else {
-
271 url.append_base_password("%40");
-
272 }
-
273 } else {
-
274 if constexpr (result_type_is_ada_url) {
-
275 url.username += "%40";
-
276 } else {
-
277 url.append_base_username("%40");
-
278 }
-
279 }
-
280 }
-
281
-
282 at_sign_seen = true;
-
283
-
284 if (!password_token_seen) {
-
285 size_t password_token_location = authority_view.find(':');
-
286 password_token_seen =
-
287 password_token_location != std::string_view::npos;
-
288
-
289 if constexpr (store_values) {
-
290 if (!password_token_seen) {
-
291 if constexpr (result_type_is_ada_url) {
-
292 url.username += unicode::percent_encode(
-
293 authority_view,
-
294 character_sets::USERINFO_PERCENT_ENCODE);
-
295 } else {
-
296 url.append_base_username(unicode::percent_encode(
-
297 authority_view,
-
298 character_sets::USERINFO_PERCENT_ENCODE));
-
299 }
-
300 } else {
-
301 if constexpr (result_type_is_ada_url) {
-
302 url.username += unicode::percent_encode(
-
303 authority_view.substr(0, password_token_location),
-
304 character_sets::USERINFO_PERCENT_ENCODE);
-
305 url.password += unicode::percent_encode(
-
306 authority_view.substr(password_token_location + 1),
-
307 character_sets::USERINFO_PERCENT_ENCODE);
-
308 } else {
-
309 url.append_base_username(unicode::percent_encode(
-
310 authority_view.substr(0, password_token_location),
-
311 character_sets::USERINFO_PERCENT_ENCODE));
-
312 url.append_base_password(unicode::percent_encode(
-
313 authority_view.substr(password_token_location + 1),
-
314 character_sets::USERINFO_PERCENT_ENCODE));
-
315 }
-
316 }
-
317 }
-
318 } else if constexpr (store_values) {
-
319 if constexpr (result_type_is_ada_url) {
-
320 url.password += unicode::percent_encode(
-
321 authority_view, character_sets::USERINFO_PERCENT_ENCODE);
-
322 } else {
-
323 url.append_base_password(unicode::percent_encode(
-
324 authority_view, character_sets::USERINFO_PERCENT_ENCODE));
-
325 }
-
326 }
-
327 }
-
328 // Otherwise, if one of the following is true:
-
329 // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
-
330 // - url is special and c is U+005C (\‍)
-
331 else if (end_of_authority == input_size ||
-
332 url_data[end_of_authority] == '/' ||
-
333 url_data[end_of_authority] == '?' ||
-
334 (url.is_special() && url_data[end_of_authority] == '\\')) {
-
335 // If atSignSeen is true and authority_view is the empty string,
-
336 // validation error, return failure.
-
337 if (at_sign_seen && authority_view.empty()) {
-
338 url.is_valid = false;
-
339 return url;
-
340 }
-
341 state = ada::state::HOST;
-
342 break;
-
343 }
-
344 if (end_of_authority == input_size) {
-
345 if constexpr (store_values) {
-
346 if (fragment.has_value()) {
-
347 url.update_unencoded_base_hash(*fragment);
-
348 }
-
349 }
-
350 return url;
-
351 }
-
352 input_position = end_of_authority + 1;
-
353 } while (true);
-
354
-
355 break;
-
356 }
-
357 case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
-
358 ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
-
359 helpers::substring(url_data, input_position));
-
360
-
361 // If c is U+002F (/) and remaining starts with U+002F (/),
-
362 // then set state to special authority ignore slashes state and increase
-
363 // pointer by 1.
-
364 std::string_view view = helpers::substring(url_data, input_position);
-
365 if (view.starts_with("//")) {
-
366 state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
-
367 input_position += 2;
-
368 } else {
-
369 // Otherwise, validation error, set state to relative state and
-
370 // decrease pointer by 1.
-
371 state = ada::state::RELATIVE_SCHEME;
-
372 }
-
373
-
374 break;
-
375 }
-
376 case ada::state::PATH_OR_AUTHORITY: {
-
377 ada_log("PATH_OR_AUTHORITY ",
-
378 helpers::substring(url_data, input_position));
-
379
-
380 // If c is U+002F (/), then set state to authority state.
-
381 if ((input_position != input_size) &&
-
382 (url_data[input_position] == '/')) {
-
383 state = ada::state::AUTHORITY;
-
384 input_position++;
-
385 } else {
-
386 // Otherwise, set state to path state, and decrease pointer by 1.
-
387 state = ada::state::PATH;
-
388 }
-
389
-
390 break;
-
391 }
-
392 case ada::state::RELATIVE_SCHEME: {
-
393 ada_log("RELATIVE_SCHEME ",
-
394 helpers::substring(url_data, input_position));
-
395
-
396 // Set url's scheme to base's scheme.
-
397 url.copy_scheme(*base_url);
-
398
-
399 // If c is U+002F (/), then set state to relative slash state.
-
400 if ((input_position != input_size) &&
-
401 (url_data[input_position] == '/')) {
-
402 ada_log(
-
403 "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
-
404 "slash state");
-
405 state = ada::state::RELATIVE_SLASH;
-
406 } else if (url.is_special() && (input_position != input_size) &&
-
407 (url_data[input_position] == '\\')) {
-
408 // Otherwise, if url is special and c is U+005C (\‍), validation error,
-
409 // set state to relative slash state.
-
410 ada_log(
-
411 "RELATIVE_SCHEME if url is special and c is U+005C, validation "
-
412 "error, set state to relative slash state");
-
413 state = ada::state::RELATIVE_SLASH;
-
414 } else {
-
415 ada_log("RELATIVE_SCHEME otherwise");
-
416 // Set url's username to base's username, url's password to base's
-
417 // password, url's host to base's host, url's port to base's port,
-
418 // url's path to a clone of base's path, and url's query to base's
-
419 // query.
-
420 if constexpr (result_type_is_ada_url) {
-
421 url.username = base_url->username;
-
422 url.password = base_url->password;
-
423 url.host = base_url->host;
-
424 url.port = base_url->port;
-
425 // cloning the base path includes cloning the has_opaque_path flag
-
426 url.has_opaque_path = base_url->has_opaque_path;
-
427 url.path = base_url->path;
-
428 url.query = base_url->query;
-
429 } else {
-
430 url.update_base_authority(base_url->get_href(),
-
431 base_url->get_components());
-
432 // TODO: Get rid of set_hostname and replace it with
-
433 // update_base_hostname
-
434 url.set_hostname(base_url->get_hostname());
-
435 url.update_base_port(base_url->retrieve_base_port());
-
436 // cloning the base path includes cloning the has_opaque_path flag
-
437 url.has_opaque_path = base_url->has_opaque_path;
-
438 url.update_base_pathname(base_url->get_pathname());
-
439 url.update_base_search(base_url->get_search());
-
440 }
+
240
+
241 // Check if url data contains an @.
+
242 if (url_data.find('@', input_position) == std::string_view::npos) {
+
243 state = ada::state::HOST;
+
244 break;
+
245 }
+
246 bool at_sign_seen{false};
+
247 bool password_token_seen{false};
+
253 do {
+
254 std::string_view view = url_data.substr(input_position);
+
255 // The delimiters are @, /, ? \\.
+
256 size_t location =
+
257 url.is_special() ? helpers::find_authority_delimiter_special(view)
+
258 : helpers::find_authority_delimiter(view);
+
259 std::string_view authority_view = view.substr(0, location);
+
260 size_t end_of_authority = input_position + authority_view.size();
+
261 // If c is U+0040 (@), then:
+
262 if ((end_of_authority != input_size) &&
+
263 (url_data[end_of_authority] == '@')) {
+
264 // If atSignSeen is true, then prepend "%40" to buffer.
+
265 if (at_sign_seen) {
+
266 if (password_token_seen) {
+
267 if constexpr (result_type_is_ada_url) {
+
268 url.password += "%40";
+
269 } else {
+
270 url.append_base_password("%40");
+
271 }
+
272 } else {
+
273 if constexpr (result_type_is_ada_url) {
+
274 url.username += "%40";
+
275 } else {
+
276 url.append_base_username("%40");
+
277 }
+
278 }
+
279 }
+
280
+
281 at_sign_seen = true;
+
282
+
283 if (!password_token_seen) {
+
284 size_t password_token_location = authority_view.find(':');
+
285 password_token_seen =
+
286 password_token_location != std::string_view::npos;
+
287
+
288 if constexpr (store_values) {
+
289 if (!password_token_seen) {
+
290 if constexpr (result_type_is_ada_url) {
+
291 url.username += unicode::percent_encode(
+
292 authority_view,
+
293 character_sets::USERINFO_PERCENT_ENCODE);
+
294 } else {
+
295 url.append_base_username(unicode::percent_encode(
+
296 authority_view,
+
297 character_sets::USERINFO_PERCENT_ENCODE));
+
298 }
+
299 } else {
+
300 if constexpr (result_type_is_ada_url) {
+
301 url.username += unicode::percent_encode(
+
302 authority_view.substr(0, password_token_location),
+
303 character_sets::USERINFO_PERCENT_ENCODE);
+
304 url.password += unicode::percent_encode(
+
305 authority_view.substr(password_token_location + 1),
+
306 character_sets::USERINFO_PERCENT_ENCODE);
+
307 } else {
+
308 url.append_base_username(unicode::percent_encode(
+
309 authority_view.substr(0, password_token_location),
+
310 character_sets::USERINFO_PERCENT_ENCODE));
+
311 url.append_base_password(unicode::percent_encode(
+
312 authority_view.substr(password_token_location + 1),
+
313 character_sets::USERINFO_PERCENT_ENCODE));
+
314 }
+
315 }
+
316 }
+
317 } else if constexpr (store_values) {
+
318 if constexpr (result_type_is_ada_url) {
+
319 url.password += unicode::percent_encode(
+
320 authority_view, character_sets::USERINFO_PERCENT_ENCODE);
+
321 } else {
+
322 url.append_base_password(unicode::percent_encode(
+
323 authority_view, character_sets::USERINFO_PERCENT_ENCODE));
+
324 }
+
325 }
+
326 }
+
327 // Otherwise, if one of the following is true:
+
328 // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
+
329 // - url is special and c is U+005C (\‍)
+
330 else if (end_of_authority == input_size ||
+
331 url_data[end_of_authority] == '/' ||
+
332 url_data[end_of_authority] == '?' ||
+
333 (url.is_special() && url_data[end_of_authority] == '\\')) {
+
334 // If atSignSeen is true and authority_view is the empty string,
+
335 // validation error, return failure.
+
336 if (at_sign_seen && authority_view.empty()) {
+
337 url.is_valid = false;
+
338 return url;
+
339 }
+
340 state = ada::state::HOST;
+
341 break;
+
342 }
+
343 if (end_of_authority == input_size) {
+
344 if constexpr (store_values) {
+
345 if (fragment.has_value()) {
+
346 url.update_unencoded_base_hash(*fragment);
+
347 }
+
348 }
+
349 return url;
+
350 }
+
351 input_position = end_of_authority + 1;
+
352 } while (true);
+
353
+
354 break;
+
355 }
+
356 case ada::state::SPECIAL_RELATIVE_OR_AUTHORITY: {
+
357 ada_log("SPECIAL_RELATIVE_OR_AUTHORITY ",
+
358 helpers::substring(url_data, input_position));
+
359
+
360 // If c is U+002F (/) and remaining starts with U+002F (/),
+
361 // then set state to special authority ignore slashes state and increase
+
362 // pointer by 1.
+
363 if (url_data.substr(input_position, 2) == "//") {
+
364 state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
+
365 input_position += 2;
+
366 } else {
+
367 // Otherwise, validation error, set state to relative state and
+
368 // decrease pointer by 1.
+
369 state = ada::state::RELATIVE_SCHEME;
+
370 }
+
371
+
372 break;
+
373 }
+
374 case ada::state::PATH_OR_AUTHORITY: {
+
375 ada_log("PATH_OR_AUTHORITY ",
+
376 helpers::substring(url_data, input_position));
+
377
+
378 // If c is U+002F (/), then set state to authority state.
+
379 if ((input_position != input_size) &&
+
380 (url_data[input_position] == '/')) {
+
381 state = ada::state::AUTHORITY;
+
382 input_position++;
+
383 } else {
+
384 // Otherwise, set state to path state, and decrease pointer by 1.
+
385 state = ada::state::PATH;
+
386 }
+
387
+
388 break;
+
389 }
+
390 case ada::state::RELATIVE_SCHEME: {
+
391 ada_log("RELATIVE_SCHEME ",
+
392 helpers::substring(url_data, input_position));
+
393
+
394 // Set url's scheme to base's scheme.
+
395 url.copy_scheme(*base_url);
+
396
+
397 // If c is U+002F (/), then set state to relative slash state.
+
398 if ((input_position != input_size) &&
+
399 (url_data[input_position] == '/')) {
+
400 ada_log(
+
401 "RELATIVE_SCHEME if c is U+002F (/), then set state to relative "
+
402 "slash state");
+
403 state = ada::state::RELATIVE_SLASH;
+
404 } else if (url.is_special() && (input_position != input_size) &&
+
405 (url_data[input_position] == '\\')) {
+
406 // Otherwise, if url is special and c is U+005C (\‍), validation error,
+
407 // set state to relative slash state.
+
408 ada_log(
+
409 "RELATIVE_SCHEME if url is special and c is U+005C, validation "
+
410 "error, set state to relative slash state");
+
411 state = ada::state::RELATIVE_SLASH;
+
412 } else {
+
413 ada_log("RELATIVE_SCHEME otherwise");
+
414 // Set url's username to base's username, url's password to base's
+
415 // password, url's host to base's host, url's port to base's port,
+
416 // url's path to a clone of base's path, and url's query to base's
+
417 // query.
+
418 if constexpr (result_type_is_ada_url) {
+
419 url.username = base_url->username;
+
420 url.password = base_url->password;
+
421 url.host = base_url->host;
+
422 url.port = base_url->port;
+
423 // cloning the base path includes cloning the has_opaque_path flag
+
424 url.has_opaque_path = base_url->has_opaque_path;
+
425 url.path = base_url->path;
+
426 url.query = base_url->query;
+
427 } else {
+
428 url.update_base_authority(base_url->get_href(),
+
429 base_url->get_components());
+
430 // TODO: Get rid of set_hostname and replace it with
+
431 // update_base_hostname
+
432 url.set_hostname(base_url->get_hostname());
+
433 url.update_base_port(base_url->retrieve_base_port());
+
434 // cloning the base path includes cloning the has_opaque_path flag
+
435 url.has_opaque_path = base_url->has_opaque_path;
+
436 url.update_base_pathname(base_url->get_pathname());
+
437 url.update_base_search(base_url->get_search());
+
438 }
+
439
+
440 url.has_opaque_path = base_url->has_opaque_path;
441
-
442 url.has_opaque_path = base_url->has_opaque_path;
-
443
-
444 // If c is U+003F (?), then set url's query to the empty string, and
-
445 // state to query state.
-
446 if ((input_position != input_size) &&
-
447 (url_data[input_position] == '?')) {
-
448 state = ada::state::QUERY;
-
449 }
-
450 // Otherwise, if c is not the EOF code point:
-
451 else if (input_position != input_size) {
-
452 // Set url's query to null.
-
453 url.clear_search();
-
454 if constexpr (result_type_is_ada_url) {
-
455 // Shorten url's path.
-
456 helpers::shorten_path(url.path, url.type);
-
457 } else {
-
458 std::string_view path = url.get_pathname();
-
459 if (helpers::shorten_path(path, url.type)) {
-
460 url.update_base_pathname(std::string(path));
-
461 }
-
462 }
-
463 // Set state to path state and decrease pointer by 1.
-
464 state = ada::state::PATH;
-
465 break;
-
466 }
-
467 }
-
468 input_position++;
-
469 break;
-
470 }
-
471 case ada::state::RELATIVE_SLASH: {
-
472 ada_log("RELATIVE_SLASH ",
-
473 helpers::substring(url_data, input_position));
-
474
-
475 // If url is special and c is U+002F (/) or U+005C (\‍), then:
-
476 if (url.is_special() && (input_position != input_size) &&
-
477 (url_data[input_position] == '/' ||
-
478 url_data[input_position] == '\\')) {
-
479 // Set state to special authority ignore slashes state.
-
480 state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
-
481 }
-
482 // Otherwise, if c is U+002F (/), then set state to authority state.
-
483 else if ((input_position != input_size) &&
-
484 (url_data[input_position] == '/')) {
-
485 state = ada::state::AUTHORITY;
-
486 }
-
487 // Otherwise, set
-
488 // - url's username to base's username,
-
489 // - url's password to base's password,
-
490 // - url's host to base's host,
-
491 // - url's port to base's port,
-
492 // - state to path state, and then, decrease pointer by 1.
-
493 else {
-
494 if constexpr (result_type_is_ada_url) {
-
495 url.username = base_url->username;
-
496 url.password = base_url->password;
-
497 url.host = base_url->host;
-
498 url.port = base_url->port;
-
499 } else {
-
500 url.update_base_authority(base_url->get_href(),
-
501 base_url->get_components());
-
502 // TODO: Get rid of set_hostname and replace it with
-
503 // update_base_hostname
-
504 url.set_hostname(base_url->get_hostname());
-
505 url.update_base_port(base_url->retrieve_base_port());
-
506 }
-
507 state = ada::state::PATH;
-
508 break;
-
509 }
-
510
-
511 input_position++;
-
512 break;
-
513 }
-
514 case ada::state::SPECIAL_AUTHORITY_SLASHES: {
-
515 ada_log("SPECIAL_AUTHORITY_SLASHES ",
-
516 helpers::substring(url_data, input_position));
-
517
-
518 // If c is U+002F (/) and remaining starts with U+002F (/),
-
519 // then set state to special authority ignore slashes state and increase
-
520 // pointer by 1.
-
521 std::string_view view = helpers::substring(url_data, input_position);
-
522 if (view.starts_with("//")) {
-
523 input_position += 2;
-
524 }
-
525
-
526 [[fallthrough]];
-
527 }
-
528 case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
-
529 ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
-
530 helpers::substring(url_data, input_position));
-
531
-
532 // If c is neither U+002F (/) nor U+005C (\‍), then set state to
-
533 // authority state and decrease pointer by 1.
-
534 while ((input_position != input_size) &&
-
535 ((url_data[input_position] == '/') ||
-
536 (url_data[input_position] == '\\'))) {
-
537 input_position++;
-
538 }
-
539 state = ada::state::AUTHORITY;
-
540
-
541 break;
-
542 }
-
543 case ada::state::QUERY: {
-
544 ada_log("QUERY ", helpers::substring(url_data, input_position));
-
545 if constexpr (store_values) {
-
546 // Let queryPercentEncodeSet be the special-query percent-encode set
-
547 // if url is special; otherwise the query percent-encode set.
-
548 const uint8_t* query_percent_encode_set =
-
549 url.is_special()
-
550 ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
-
551 : ada::character_sets::QUERY_PERCENT_ENCODE;
-
552
-
553 // Percent-encode after encoding, with encoding, buffer, and
-
554 // queryPercentEncodeSet, and append the result to url's query.
-
555 url.update_base_search(helpers::substring(url_data, input_position),
-
556 query_percent_encode_set);
-
557 ada_log("QUERY update_base_search completed ");
-
558 if (fragment.has_value()) {
-
559 url.update_unencoded_base_hash(*fragment);
-
560 }
-
561 }
-
562 return url;
-
563 }
-
564 case ada::state::HOST: {
-
565 ada_log("HOST ", helpers::substring(url_data, input_position));
-
566
-
567 std::string_view host_view =
-
568 helpers::substring(url_data, input_position);
-
569 auto [location, found_colon] =
-
570 helpers::get_host_delimiter_location(url.is_special(), host_view);
-
571 input_position = (location != std::string_view::npos)
-
572 ? input_position + location
-
573 : input_size;
-
574 // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
-
575 // Note: the 'found_colon' value is true if and only if a colon was
-
576 // encountered while not inside brackets.
-
577 if (found_colon) {
-
578 // If buffer is the empty string, validation error, return failure.
-
579 // Let host be the result of host parsing buffer with url is not
-
580 // special.
-
581 ada_log("HOST parsing ", host_view);
-
582 if (!url.parse_host(host_view)) {
-
583 return url;
-
584 }
-
585 ada_log("HOST parsing results in ", url.get_hostname());
-
586 // Set url's host to host, buffer to the empty string, and state to
-
587 // port state.
-
588 state = ada::state::PORT;
-
589 input_position++;
-
590 }
-
591 // Otherwise, if one of the following is true:
-
592 // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
-
593 // - url is special and c is U+005C (\‍)
-
594 // The get_host_delimiter_location function either brings us to
-
595 // the colon outside of the bracket, or to one of those characters.
-
596 else {
-
597 // If url is special and host_view is the empty string, validation
-
598 // error, return failure.
-
599 if (url.is_special() && host_view.empty()) {
-
600 url.is_valid = false;
-
601 return url;
-
602 }
-
603 ada_log("HOST parsing ", host_view, " href=", url.get_href());
-
604 // Let host be the result of host parsing host_view with url is not
-
605 // special.
-
606 if (host_view.empty()) {
-
607 url.update_base_hostname("");
-
608 } else if (!url.parse_host(host_view)) {
-
609 return url;
-
610 }
-
611 ada_log("HOST parsing results in ", url.get_hostname(),
-
612 " href=", url.get_href());
+
442 // If c is U+003F (?), then set url's query to the empty string, and
+
443 // state to query state.
+
444 if ((input_position != input_size) &&
+
445 (url_data[input_position] == '?')) {
+
446 state = ada::state::QUERY;
+
447 }
+
448 // Otherwise, if c is not the EOF code point:
+
449 else if (input_position != input_size) {
+
450 // Set url's query to null.
+
451 url.clear_search();
+
452 if constexpr (result_type_is_ada_url) {
+
453 // Shorten url's path.
+
454 helpers::shorten_path(url.path, url.type);
+
455 } else {
+
456 std::string_view path = url.get_pathname();
+
457 if (helpers::shorten_path(path, url.type)) {
+
458 url.update_base_pathname(std::move(std::string(path)));
+
459 }
+
460 }
+
461 // Set state to path state and decrease pointer by 1.
+
462 state = ada::state::PATH;
+
463 break;
+
464 }
+
465 }
+
466 input_position++;
+
467 break;
+
468 }
+
469 case ada::state::RELATIVE_SLASH: {
+
470 ada_log("RELATIVE_SLASH ",
+
471 helpers::substring(url_data, input_position));
+
472
+
473 // If url is special and c is U+002F (/) or U+005C (\‍), then:
+
474 if (url.is_special() && (input_position != input_size) &&
+
475 (url_data[input_position] == '/' ||
+
476 url_data[input_position] == '\\')) {
+
477 // Set state to special authority ignore slashes state.
+
478 state = ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES;
+
479 }
+
480 // Otherwise, if c is U+002F (/), then set state to authority state.
+
481 else if ((input_position != input_size) &&
+
482 (url_data[input_position] == '/')) {
+
483 state = ada::state::AUTHORITY;
+
484 }
+
485 // Otherwise, set
+
486 // - url's username to base's username,
+
487 // - url's password to base's password,
+
488 // - url's host to base's host,
+
489 // - url's port to base's port,
+
490 // - state to path state, and then, decrease pointer by 1.
+
491 else {
+
492 if constexpr (result_type_is_ada_url) {
+
493 url.username = base_url->username;
+
494 url.password = base_url->password;
+
495 url.host = base_url->host;
+
496 url.port = base_url->port;
+
497 } else {
+
498 url.update_base_authority(base_url->get_href(),
+
499 base_url->get_components());
+
500 // TODO: Get rid of set_hostname and replace it with
+
501 // update_base_hostname
+
502 url.set_hostname(base_url->get_hostname());
+
503 url.update_base_port(base_url->retrieve_base_port());
+
504 }
+
505 state = ada::state::PATH;
+
506 break;
+
507 }
+
508
+
509 input_position++;
+
510 break;
+
511 }
+
512 case ada::state::SPECIAL_AUTHORITY_SLASHES: {
+
513 ada_log("SPECIAL_AUTHORITY_SLASHES ",
+
514 helpers::substring(url_data, input_position));
+
515
+
516 // If c is U+002F (/) and remaining starts with U+002F (/),
+
517 // then set state to special authority ignore slashes state and increase
+
518 // pointer by 1.
+
519 if (url_data.substr(input_position, 2) == "//") {
+
520 input_position += 2;
+
521 }
+
522
+
523 [[fallthrough]];
+
524 }
+
525 case ada::state::SPECIAL_AUTHORITY_IGNORE_SLASHES: {
+
526 ada_log("SPECIAL_AUTHORITY_IGNORE_SLASHES ",
+
527 helpers::substring(url_data, input_position));
+
528
+
529 // If c is neither U+002F (/) nor U+005C (\‍), then set state to
+
530 // authority state and decrease pointer by 1.
+
531 while ((input_position != input_size) &&
+
532 ((url_data[input_position] == '/') ||
+
533 (url_data[input_position] == '\\'))) {
+
534 input_position++;
+
535 }
+
536 state = ada::state::AUTHORITY;
+
537
+
538 break;
+
539 }
+
540 case ada::state::QUERY: {
+
541 ada_log("QUERY ", helpers::substring(url_data, input_position));
+
542 if constexpr (store_values) {
+
543 // Let queryPercentEncodeSet be the special-query percent-encode set
+
544 // if url is special; otherwise the query percent-encode set.
+
545 const uint8_t* query_percent_encode_set =
+
546 url.is_special()
+
547 ? ada::character_sets::SPECIAL_QUERY_PERCENT_ENCODE
+
548 : ada::character_sets::QUERY_PERCENT_ENCODE;
+
549
+
550 // Percent-encode after encoding, with encoding, buffer, and
+
551 // queryPercentEncodeSet, and append the result to url's query.
+
552 url.update_base_search(url_data.substr(input_position),
+
553 query_percent_encode_set);
+
554 ada_log("QUERY update_base_search completed ");
+
555 if (fragment.has_value()) {
+
556 url.update_unencoded_base_hash(*fragment);
+
557 }
+
558 }
+
559 return url;
+
560 }
+
561 case ada::state::HOST: {
+
562 ada_log("HOST ", helpers::substring(url_data, input_position));
+
563
+
564 std::string_view host_view = url_data.substr(input_position);
+
565 auto [location, found_colon] =
+
566 helpers::get_host_delimiter_location(url.is_special(), host_view);
+
567 input_position = (location != std::string_view::npos)
+
568 ? input_position + location
+
569 : input_size;
+
570 // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
+
571 // Note: the 'found_colon' value is true if and only if a colon was
+
572 // encountered while not inside brackets.
+
573 if (found_colon) {
+
574 // If buffer is the empty string, validation error, return failure.
+
575 // Let host be the result of host parsing buffer with url is not
+
576 // special.
+
577 ada_log("HOST parsing ", host_view);
+
578 if (!url.parse_host(host_view)) {
+
579 return url;
+
580 }
+
581 ada_log("HOST parsing results in ", url.get_hostname());
+
582 // Set url's host to host, buffer to the empty string, and state to
+
583 // port state.
+
584 state = ada::state::PORT;
+
585 input_position++;
+
586 }
+
587 // Otherwise, if one of the following is true:
+
588 // - c is the EOF code point, U+002F (/), U+003F (?), or U+0023 (#)
+
589 // - url is special and c is U+005C (\‍)
+
590 // The get_host_delimiter_location function either brings us to
+
591 // the colon outside of the bracket, or to one of those characters.
+
592 else {
+
593 // If url is special and host_view is the empty string, validation
+
594 // error, return failure.
+
595 if (host_view.empty() && url.is_special()) {
+
596 url.is_valid = false;
+
597 return url;
+
598 }
+
599 ada_log("HOST parsing ", host_view, " href=", url.get_href());
+
600 // Let host be the result of host parsing host_view with url is not
+
601 // special.
+
602 if (host_view.empty()) {
+
603 url.update_base_hostname("");
+
604 } else if (!url.parse_host(host_view)) {
+
605 return url;
+
606 }
+
607 ada_log("HOST parsing results in ", url.get_hostname(),
+
608 " href=", url.get_href());
+
609
+
610 // Set url's host to host, and state to path start state.
+
611 state = ada::state::PATH_START;
+
612 }
613
-
614 // Set url's host to host, and state to path start state.
-
615 state = ada::state::PATH_START;
-
616 }
-
617
-
618 break;
-
619 }
-
620 case ada::state::OPAQUE_PATH: {
-
621 ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
-
622 std::string_view view = helpers::substring(url_data, input_position);
-
623 // If c is U+003F (?), then set url's query to the empty string and
-
624 // state to query state.
-
625 size_t location = view.find('?');
-
626 if (location != std::string_view::npos) {
-
627 view.remove_suffix(view.size() - location);
-
628 state = ada::state::QUERY;
-
629 input_position += location + 1;
-
630 } else {
-
631 input_position = input_size + 1;
-
632 }
-
633 url.has_opaque_path = true;
-
634 // This is a really unlikely scenario in real world. We should not seek
-
635 // to optimize it.
-
636 url.update_base_pathname(unicode::percent_encode(
-
637 view, character_sets::C0_CONTROL_PERCENT_ENCODE));
-
638 break;
-
639 }
-
640 case ada::state::PORT: {
-
641 ada_log("PORT ", helpers::substring(url_data, input_position));
-
642 std::string_view port_view =
-
643 helpers::substring(url_data, input_position);
-
644 size_t consumed_bytes = url.parse_port(port_view, true);
-
645 input_position += consumed_bytes;
-
646 if (!url.is_valid) {
-
647 return url;
-
648 }
-
649 state = state::PATH_START;
-
650 [[fallthrough]];
-
651 }
-
652 case ada::state::PATH_START: {
-
653 ada_log("PATH_START ", helpers::substring(url_data, input_position));
-
654
-
655 // If url is special, then:
-
656 if (url.is_special()) {
-
657 // Set state to path state.
-
658 state = ada::state::PATH;
-
659
-
660 // Optimization: Avoiding going into PATH state improves the
-
661 // performance of urls ending with /.
-
662 if (input_position == input_size) {
-
663 if constexpr (store_values) {
-
664 url.update_base_pathname("/");
-
665 if (fragment.has_value()) {
-
666 url.update_unencoded_base_hash(*fragment);
-
667 }
-
668 }
-
669 return url;
-
670 }
-
671 // If c is neither U+002F (/) nor U+005C (\‍), then decrease pointer
-
672 // by 1. We know that (input_position == input_size) is impossible
-
673 // here, because of the previous if-check.
-
674 if ((url_data[input_position] != '/') &&
-
675 (url_data[input_position] != '\\')) {
-
676 break;
-
677 }
+
614 break;
+
615 }
+
616 case ada::state::OPAQUE_PATH: {
+
617 ada_log("OPAQUE_PATH ", helpers::substring(url_data, input_position));
+
618 std::string_view view = url_data.substr(input_position);
+
619 // If c is U+003F (?), then set url's query to the empty string and
+
620 // state to query state.
+
621 size_t location = view.find('?');
+
622 if (location != std::string_view::npos) {
+
623 view.remove_suffix(view.size() - location);
+
624 state = ada::state::QUERY;
+
625 input_position += location + 1;
+
626 } else {
+
627 input_position = input_size + 1;
+
628 }
+
629 url.has_opaque_path = true;
+
630 // This is a really unlikely scenario in real world. We should not seek
+
631 // to optimize it.
+
632 url.update_base_pathname(unicode::percent_encode(
+
633 view, character_sets::C0_CONTROL_PERCENT_ENCODE));
+
634 break;
+
635 }
+
636 case ada::state::PORT: {
+
637 ada_log("PORT ", helpers::substring(url_data, input_position));
+
638 std::string_view port_view = url_data.substr(input_position);
+
639 input_position += url.parse_port(port_view, true);
+
640 if (!url.is_valid) {
+
641 return url;
+
642 }
+
643 state = state::PATH_START;
+
644 [[fallthrough]];
+
645 }
+
646 case ada::state::PATH_START: {
+
647 ada_log("PATH_START ", helpers::substring(url_data, input_position));
+
648
+
649 // If url is special, then:
+
650 if (url.is_special()) {
+
651 // Set state to path state.
+
652 state = ada::state::PATH;
+
653
+
654 // Optimization: Avoiding going into PATH state improves the
+
655 // performance of urls ending with /.
+
656 if (input_position == input_size) {
+
657 if constexpr (store_values) {
+
658 url.update_base_pathname("/");
+
659 if (fragment.has_value()) {
+
660 url.update_unencoded_base_hash(*fragment);
+
661 }
+
662 }
+
663 return url;
+
664 }
+
665 // If c is neither U+002F (/) nor U+005C (\‍), then decrease pointer
+
666 // by 1. We know that (input_position == input_size) is impossible
+
667 // here, because of the previous if-check.
+
668 if ((url_data[input_position] != '/') &&
+
669 (url_data[input_position] != '\\')) {
+
670 break;
+
671 }
+
672 }
+
673 // Otherwise, if state override is not given and c is U+003F (?),
+
674 // set url's query to the empty string and state to query state.
+
675 else if ((input_position != input_size) &&
+
676 (url_data[input_position] == '?')) {
+
677 state = ada::state::QUERY;
678 }
-
679 // Otherwise, if state override is not given and c is U+003F (?),
-
680 // set url's query to the empty string and state to query state.
-
681 else if ((input_position != input_size) &&
-
682 (url_data[input_position] == '?')) {
-
683 state = ada::state::QUERY;
-
684 }
-
685 // Otherwise, if c is not the EOF code point:
-
686 else if (input_position != input_size) {
-
687 // Set state to path state.
-
688 state = ada::state::PATH;
+
679 // Otherwise, if c is not the EOF code point:
+
680 else if (input_position != input_size) {
+
681 // Set state to path state.
+
682 state = ada::state::PATH;
+
683
+
684 // If c is not U+002F (/), then decrease pointer by 1.
+
685 if (url_data[input_position] != '/') {
+
686 break;
+
687 }
+
688 }
689
-
690 // If c is not U+002F (/), then decrease pointer by 1.
-
691 if (url_data[input_position] != '/') {
-
692 break;
-
693 }
-
694 }
-
695
-
696 input_position++;
-
697 break;
-
698 }
-
699 case ada::state::PATH: {
-
700 std::string_view view = helpers::substring(url_data, input_position);
-
701 ada_log("PATH ", helpers::substring(url_data, input_position));
-
702
-
703 // Most time, we do not need percent encoding.
-
704 // Furthermore, we can immediately locate the '?'.
-
705 size_t locofquestionmark = view.find('?');
-
706 if (locofquestionmark != std::string_view::npos) {
-
707 state = ada::state::QUERY;
-
708 view.remove_suffix(view.size() - locofquestionmark);
-
709 input_position += locofquestionmark + 1;
-
710 } else {
-
711 input_position = input_size + 1;
-
712 }
-
713 if constexpr (store_values) {
-
714 if constexpr (result_type_is_ada_url) {
-
715 helpers::parse_prepared_path(view, url.type, url.path);
-
716 } else {
-
717 url.consume_prepared_path(view);
-
718 ADA_ASSERT_TRUE(url.validate());
-
719 }
-
720 }
-
721 break;
-
722 }
-
723 case ada::state::FILE_SLASH: {
-
724 ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
-
725
-
726 // If c is U+002F (/) or U+005C (\‍), then:
-
727 if ((input_position != input_size) &&
-
728 (url_data[input_position] == '/' ||
-
729 url_data[input_position] == '\\')) {
-
730 ada_log("FILE_SLASH c is U+002F or U+005C");
-
731 // Set state to file host state.
-
732 state = ada::state::FILE_HOST;
-
733 input_position++;
-
734 } else {
-
735 ada_log("FILE_SLASH otherwise");
-
736 // If base is non-null and base's scheme is "file", then:
-
737 // Note: it is unsafe to do base_url->scheme unless you know that
-
738 // base_url_has_value() is true.
-
739 if (base_url != nullptr &&
-
740 base_url->type == ada::scheme::type::FILE) {
-
741 // Set url's host to base's host.
-
742 if constexpr (result_type_is_ada_url) {
-
743 url.host = base_url->host;
-
744 } else {
-
745 // TODO: Optimization opportunity.
-
746 url.set_host(base_url->get_host());
-
747 }
-
748 // If the code point substring from pointer to the end of input does
-
749 // not start with a Windows drive letter and base's path[0] is a
-
750 // normalized Windows drive letter, then append base's path[0] to
-
751 // url's path.
-
752 if (!base_url->get_pathname().empty()) {
-
753 if (!checkers::is_windows_drive_letter(
-
754 helpers::substring(url_data, input_position))) {
-
755 std::string_view first_base_url_path =
-
756 base_url->get_pathname().substr(1);
-
757 size_t loc = first_base_url_path.find('/');
-
758 if (loc != std::string_view::npos) {
-
759 helpers::resize(first_base_url_path, loc);
-
760 }
-
761 if (checkers::is_normalized_windows_drive_letter(
-
762 first_base_url_path)) {
-
763 if constexpr (result_type_is_ada_url) {
-
764 url.path += '/';
-
765 url.path += first_base_url_path;
-
766 } else {
-
767 url.append_base_pathname(
-
768 helpers::concat("/", first_base_url_path));
-
769 }
-
770 }
-
771 }
-
772 }
-
773 }
-
774
-
775 // Set state to path state, and decrease pointer by 1.
-
776 state = ada::state::PATH;
-
777 }
+
690 input_position++;
+
691 break;
+
692 }
+
693 case ada::state::PATH: {
+
694 ada_log("PATH ", helpers::substring(url_data, input_position));
+
695 std::string_view view = url_data.substr(input_position);
+
696
+
697 // Most time, we do not need percent encoding.
+
698 // Furthermore, we can immediately locate the '?'.
+
699 size_t locofquestionmark = view.find('?');
+
700 if (locofquestionmark != std::string_view::npos) {
+
701 state = ada::state::QUERY;
+
702 view.remove_suffix(view.size() - locofquestionmark);
+
703 input_position += locofquestionmark + 1;
+
704 } else {
+
705 input_position = input_size + 1;
+
706 }
+
707 if constexpr (store_values) {
+
708 if constexpr (result_type_is_ada_url) {
+
709 helpers::parse_prepared_path(view, url.type, url.path);
+
710 } else {
+
711 url.consume_prepared_path(view);
+
712 ADA_ASSERT_TRUE(url.validate());
+
713 }
+
714 }
+
715 break;
+
716 }
+
717 case ada::state::FILE_SLASH: {
+
718 ada_log("FILE_SLASH ", helpers::substring(url_data, input_position));
+
719
+
720 // If c is U+002F (/) or U+005C (\‍), then:
+
721 if ((input_position != input_size) &&
+
722 (url_data[input_position] == '/' ||
+
723 url_data[input_position] == '\\')) {
+
724 ada_log("FILE_SLASH c is U+002F or U+005C");
+
725 // Set state to file host state.
+
726 state = ada::state::FILE_HOST;
+
727 input_position++;
+
728 } else {
+
729 ada_log("FILE_SLASH otherwise");
+
730 // If base is non-null and base's scheme is "file", then:
+
731 // Note: it is unsafe to do base_url->scheme unless you know that
+
732 // base_url_has_value() is true.
+
733 if (base_url != nullptr &&
+
734 base_url->type == ada::scheme::type::FILE) {
+
735 // Set url's host to base's host.
+
736 if constexpr (result_type_is_ada_url) {
+
737 url.host = base_url->host;
+
738 } else {
+
739 // TODO: Optimization opportunity.
+
740 url.set_host(base_url->get_host());
+
741 }
+
742 // If the code point substring from pointer to the end of input does
+
743 // not start with a Windows drive letter and base's path[0] is a
+
744 // normalized Windows drive letter, then append base's path[0] to
+
745 // url's path.
+
746 if (!base_url->get_pathname().empty()) {
+
747 if (!checkers::is_windows_drive_letter(
+
748 url_data.substr(input_position))) {
+
749 std::string_view first_base_url_path =
+
750 base_url->get_pathname().substr(1);
+
751 size_t loc = first_base_url_path.find('/');
+
752 if (loc != std::string_view::npos) {
+
753 helpers::resize(first_base_url_path, loc);
+
754 }
+
755 if (checkers::is_normalized_windows_drive_letter(
+
756 first_base_url_path)) {
+
757 if constexpr (result_type_is_ada_url) {
+
758 url.path += '/';
+
759 url.path += first_base_url_path;
+
760 } else {
+
761 url.append_base_pathname(
+
762 helpers::concat("/", first_base_url_path));
+
763 }
+
764 }
+
765 }
+
766 }
+
767 }
+
768
+
769 // Set state to path state, and decrease pointer by 1.
+
770 state = ada::state::PATH;
+
771 }
+
772
+
773 break;
+
774 }
+
775 case ada::state::FILE_HOST: {
+
776 ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
+
777 std::string_view view = url_data.substr(input_position);
778
-
779 break;
-
780 }
-
781 case ada::state::FILE_HOST: {
-
782 std::string_view view = helpers::substring(url_data, input_position);
-
783 ada_log("FILE_HOST ", helpers::substring(url_data, input_position));
-
784
-
785 size_t location = view.find_first_of("/\\?");
-
786 std::string_view file_host_buffer(
-
787 view.data(),
-
788 (location != std::string_view::npos) ? location : view.size());
-
789
-
790 if (checkers::is_windows_drive_letter(file_host_buffer)) {
-
791 state = ada::state::PATH;
-
792 } else if (file_host_buffer.empty()) {
-
793 // Set url's host to the empty string.
-
794 if constexpr (result_type_is_ada_url) {
-
795 url.host = "";
-
796 } else {
-
797 url.update_base_hostname("");
-
798 }
-
799 // Set state to path start state.
-
800 state = ada::state::PATH_START;
-
801 } else {
-
802 size_t consumed_bytes = file_host_buffer.size();
-
803 input_position += consumed_bytes;
-
804 // Let host be the result of host parsing buffer with url is not
-
805 // special.
-
806 if (!url.parse_host(file_host_buffer)) {
-
807 return url;
-
808 }
-
809
-
810 if constexpr (result_type_is_ada_url) {
-
811 // If host is "localhost", then set host to the empty string.
-
812 if (url.host.has_value() && url.host.value() == "localhost") {
-
813 url.host = "";
-
814 }
-
815 } else {
-
816 if (url.get_hostname() == "localhost") {
-
817 url.update_base_hostname("");
-
818 }
-
819 }
-
820
-
821 // Set buffer to the empty string and state to path start state.
-
822 state = ada::state::PATH_START;
-
823 }
+
779 size_t location = view.find_first_of("/\\?");
+
780 std::string_view file_host_buffer(
+
781 view.data(),
+
782 (location != std::string_view::npos) ? location : view.size());
+
783
+
784 if (checkers::is_windows_drive_letter(file_host_buffer)) {
+
785 state = ada::state::PATH;
+
786 } else if (file_host_buffer.empty()) {
+
787 // Set url's host to the empty string.
+
788 if constexpr (result_type_is_ada_url) {
+
789 url.host = "";
+
790 } else {
+
791 url.update_base_hostname("");
+
792 }
+
793 // Set state to path start state.
+
794 state = ada::state::PATH_START;
+
795 } else {
+
796 size_t consumed_bytes = file_host_buffer.size();
+
797 input_position += consumed_bytes;
+
798 // Let host be the result of host parsing buffer with url is not
+
799 // special.
+
800 if (!url.parse_host(file_host_buffer)) {
+
801 return url;
+
802 }
+
803
+
804 if constexpr (result_type_is_ada_url) {
+
805 // If host is "localhost", then set host to the empty string.
+
806 if (url.host.has_value() && url.host.value() == "localhost") {
+
807 url.host = "";
+
808 }
+
809 } else {
+
810 if (url.get_hostname() == "localhost") {
+
811 url.update_base_hostname("");
+
812 }
+
813 }
+
814
+
815 // Set buffer to the empty string and state to path start state.
+
816 state = ada::state::PATH_START;
+
817 }
+
818
+
819 break;
+
820 }
+
821 case ada::state::FILE: {
+
822 ada_log("FILE ", helpers::substring(url_data, input_position));
+
823 std::string_view file_view = url_data.substr(input_position);
824
-
825 break;
-
826 }
-
827 case ada::state::FILE: {
-
828 ada_log("FILE ", helpers::substring(url_data, input_position));
-
829 std::string_view file_view =
-
830 helpers::substring(url_data, input_position);
-
831
-
832 url.set_protocol_as_file();
-
833 if constexpr (result_type_is_ada_url) {
-
834 // Set url's host to the empty string.
-
835 url.host = "";
-
836 } else {
-
837 url.update_base_hostname("");
-
838 }
-
839 // If c is U+002F (/) or U+005C (\‍), then:
-
840 if (input_position != input_size &&
-
841 (url_data[input_position] == '/' ||
-
842 url_data[input_position] == '\\')) {
-
843 ada_log("FILE c is U+002F or U+005C");
-
844 // Set state to file slash state.
-
845 state = ada::state::FILE_SLASH;
-
846 }
-
847 // Otherwise, if base is non-null and base's scheme is "file":
-
848 else if (base_url != nullptr &&
-
849 base_url->type == ada::scheme::type::FILE) {
-
850 // Set url's host to base's host, url's path to a clone of base's
-
851 // path, and url's query to base's query.
-
852 ada_log("FILE base non-null");
-
853 if constexpr (result_type_is_ada_url) {
-
854 url.host = base_url->host;
-
855 url.path = base_url->path;
-
856 url.query = base_url->query;
-
857 } else {
-
858 // TODO: Get rid of set_hostname and replace it with
-
859 // update_base_hostname
-
860 url.set_hostname(base_url->get_hostname());
-
861 url.update_base_pathname(base_url->get_pathname());
-
862 url.update_base_search(base_url->get_search());
+
825 url.set_protocol_as_file();
+
826 if constexpr (result_type_is_ada_url) {
+
827 // Set url's host to the empty string.
+
828 url.host = "";
+
829 } else {
+
830 url.update_base_hostname("");
+
831 }
+
832 // If c is U+002F (/) or U+005C (\‍), then:
+
833 if (input_position != input_size &&
+
834 (url_data[input_position] == '/' ||
+
835 url_data[input_position] == '\\')) {
+
836 ada_log("FILE c is U+002F or U+005C");
+
837 // Set state to file slash state.
+
838 state = ada::state::FILE_SLASH;
+
839 }
+
840 // Otherwise, if base is non-null and base's scheme is "file":
+
841 else if (base_url != nullptr &&
+
842 base_url->type == ada::scheme::type::FILE) {
+
843 // Set url's host to base's host, url's path to a clone of base's
+
844 // path, and url's query to base's query.
+
845 ada_log("FILE base non-null");
+
846 if constexpr (result_type_is_ada_url) {
+
847 url.host = base_url->host;
+
848 url.path = base_url->path;
+
849 url.query = base_url->query;
+
850 } else {
+
851 // TODO: Get rid of set_hostname and replace it with
+
852 // update_base_hostname
+
853 url.set_hostname(base_url->get_hostname());
+
854 url.update_base_pathname(base_url->get_pathname());
+
855 url.update_base_search(base_url->get_search());
+
856 }
+
857 url.has_opaque_path = base_url->has_opaque_path;
+
858
+
859 // If c is U+003F (?), then set url's query to the empty string and
+
860 // state to query state.
+
861 if (input_position != input_size && url_data[input_position] == '?') {
+
862 state = ada::state::QUERY;
863 }
-
864 url.has_opaque_path = base_url->has_opaque_path;
-
865
-
866 // If c is U+003F (?), then set url's query to the empty string and
-
867 // state to query state.
-
868 if (input_position != input_size && url_data[input_position] == '?') {
-
869 state = ada::state::QUERY;
-
870 }
-
871 // Otherwise, if c is not the EOF code point:
-
872 else if (input_position != input_size) {
-
873 // Set url's query to null.
-
874 url.clear_search();
-
875 // If the code point substring from pointer to the end of input does
-
876 // not start with a Windows drive letter, then shorten url's path.
-
877 if (!checkers::is_windows_drive_letter(file_view)) {
-
878 if constexpr (result_type_is_ada_url) {
-
879 helpers::shorten_path(url.path, url.type);
-
880 } else {
-
881 std::string_view path = url.get_pathname();
-
882 if (helpers::shorten_path(path, url.type)) {
-
883 url.update_base_pathname(std::string(path));
-
884 }
-
885 }
-
886 }
-
887 // Otherwise:
-
888 else {
-
889 // Set url's path to an empty list.
-
890 url.clear_pathname();
-
891 url.has_opaque_path = true;
-
892 }
-
893
-
894 // Set state to path state and decrease pointer by 1.
-
895 state = ada::state::PATH;
-
896 break;
-
897 }
-
898 }
-
899 // Otherwise, set state to path state, and decrease pointer by 1.
-
900 else {
-
901 ada_log("FILE go to path");
-
902 state = ada::state::PATH;
-
903 break;
-
904 }
-
905
-
906 input_position++;
-
907 break;
-
908 }
-
909 default:
-
910 ada::unreachable();
-
911 }
-
912 }
-
913 if constexpr (store_values) {
-
914 if (fragment.has_value()) {
-
915 url.update_unencoded_base_hash(*fragment);
-
916 }
-
917 }
-
918 return url;
-
919}
+
864 // Otherwise, if c is not the EOF code point:
+
865 else if (input_position != input_size) {
+
866 // Set url's query to null.
+
867 url.clear_search();
+
868 // If the code point substring from pointer to the end of input does
+
869 // not start with a Windows drive letter, then shorten url's path.
+
870 if (!checkers::is_windows_drive_letter(file_view)) {
+
871 if constexpr (result_type_is_ada_url) {
+
872 helpers::shorten_path(url.path, url.type);
+
873 } else {
+
874 std::string_view path = url.get_pathname();
+
875 if (helpers::shorten_path(path, url.type)) {
+
876 url.update_base_pathname(std::move(std::string(path)));
+
877 }
+
878 }
+
879 }
+
880 // Otherwise:
+
881 else {
+
882 // Set url's path to an empty list.
+
883 url.clear_pathname();
+
884 url.has_opaque_path = true;
+
885 }
+
886
+
887 // Set state to path state and decrease pointer by 1.
+
888 state = ada::state::PATH;
+
889 break;
+
890 }
+
891 }
+
892 // Otherwise, set state to path state, and decrease pointer by 1.
+
893 else {
+
894 ada_log("FILE go to path");
+
895 state = ada::state::PATH;
+
896 break;
+
897 }
+
898
+
899 input_position++;
+
900 break;
+
901 }
+
902 default:
+
903 ada::unreachable();
+
904 }
+
905 }
+
906 if constexpr (store_values) {
+
907 if (fragment.has_value()) {
+
908 url.update_unencoded_base_hash(*fragment);
+
909 }
+
910 }
+
911 return url;
+
912}
-
920
-
921template url parse_url_impl(std::string_view user_input,
-
922 const url* base_url = nullptr);
-
923template url_aggregator parse_url_impl(
-
924 std::string_view user_input, const url_aggregator* base_url = nullptr);
-
925
-
926template <class result_type>
-
-
927result_type parse_url(std::string_view user_input,
-
928 const result_type* base_url) {
-
929 return parse_url_impl<result_type, true>(user_input, base_url);
-
930}
+
913
+
914template url parse_url_impl(std::string_view user_input,
+
915 const url* base_url = nullptr);
+
916template url_aggregator parse_url_impl(
+
917 std::string_view user_input, const url_aggregator* base_url = nullptr);
+
918
+
919template <class result_type>
+
+
920result_type parse_url(std::string_view user_input,
+
921 const result_type* base_url) {
+
922 return parse_url_impl<result_type, true>(user_input, base_url);
+
923}
-
931
-
932template url parse_url<url>(std::string_view user_input,
-
933 const url* base_url = nullptr);
-
934template url_aggregator parse_url<url_aggregator>(
-
935 std::string_view user_input, const url_aggregator* base_url = nullptr);
-
936} // namespace ada::parser
+
924
+
925template url parse_url<url>(std::string_view user_input,
+
926 const url* base_url = nullptr);
+
927template url_aggregator parse_url<url_aggregator>(
+
928 std::string_view user_input, const url_aggregator* base_url = nullptr);
+
929} // namespace ada::parser
Includes all definitions for Ada.
Definitions of the character sets used by unicode functions.
Common definitions for cross-platform compiler support.
@@ -1059,10 +1052,10 @@
constexpr bool is_alpha(char x) noexcept
Includes the definitions for supported parsers.
template url parse_url< url >(std::string_view user_input, const url *base_url)
-
result_type parse_url(std::string_view user_input, const result_type *base_url=nullptr)
Definition parser.cpp:927
+
result_type parse_url(std::string_view user_input, const result_type *base_url=nullptr)
Definition parser.cpp:920
template url_aggregator parse_url< url_aggregator >(std::string_view user_input, const url_aggregator *base_url)
result_type parse_url_impl(std::string_view user_input, const result_type *base_url=nullptr)
Definition parser.cpp:15
-
@ FILE
Definition scheme.h:37
+
@ FILE
Definition scheme.h:36
ada_warn_unused std::string to_string(encoding_type type)
state
Definition state.h:17
@ SPECIAL_RELATIVE_OR_AUTHORITY
diff --git a/dd/d03/structada_1_1url.html b/dd/d03/structada_1_1url.html index 71b8e501b..b21e57b77 100644 --- a/dd/d03/structada_1_1url.html +++ b/dd/d03/structada_1_1url.html @@ -956,7 +956,7 @@

ada::url_base.

-

Definition at line 585 of file url.cpp.

+

Definition at line 582 of file url.cpp.

@@ -1094,9 +1094,9 @@

See also
https://url.spec.whatwg.org/#dom-url-href
-

Definition at line 217 of file url-setters.cpp.

+

Definition at line 216 of file url-setters.cpp.

-

References ada::url_base::has_opaque_path, and ada::parse().

+

References ada::parse().

@@ -1140,7 +1140,7 @@

Returns
Returns true on success.
See also
https://url.spec.whatwg.org/#dom-url-search
-

Definition at line 184 of file url-setters.cpp.

+

Definition at line 183 of file url-setters.cpp.

References ada::url_base::has_opaque_path.

@@ -1186,7 +1186,7 @@

Returns
Returns true on success.
See also
https://url.spec.whatwg.org/#dom-url-protocol
-

Definition at line 193 of file url-setters.cpp.

+

Definition at line 192 of file url-setters.cpp.

References ada::checkers::is_alpha().

@@ -1263,7 +1263,7 @@

ada::url_base.

-

Definition at line 536 of file url.cpp.

+

Definition at line 533 of file url.cpp.

References get_protocol(), has_credentials(), ada::url_base::has_opaque_path, has_search(), and ada::url_base::is_valid.

diff --git a/dd/d64/namespaceada.html b/dd/d64/namespaceada.html index 003e18158..d1bb60f77 100644 --- a/dd/d64/namespaceada.html +++ b/dd/d64/namespaceada.html @@ -825,7 +825,7 @@

Stringify a URL state machine state.

-

Definition at line 789 of file helpers.cpp.

+

Definition at line 781 of file helpers.cpp.

References ada::helpers::get_state().

diff --git a/dd/d9c/unicode_8cpp_source.html b/dd/d9c/unicode_8cpp_source.html index 32887ad5e..fc9541a1c 100644 --- a/dd/d9c/unicode_8cpp_source.html +++ b/dd/d9c/unicode_8cpp_source.html @@ -491,114 +491,112 @@
372 !is_ascii_hex_digit(pointer[2])))) {
373 dest += ch;
374 pointer++;
-
375 continue;
-
376 } else {
-
377 unsigned a = convert_hex_to_binary(pointer[1]);
-
378 unsigned b = convert_hex_to_binary(pointer[2]);
-
379 char c = static_cast<char>(a * 16 + b);
-
380 dest += c;
-
381 pointer += 3;
-
382 }
-
383 }
-
384 return dest;
-
385}
-
386
-
387std::string percent_encode(const std::string_view input,
-
388 const uint8_t character_set[]) {
-
389 auto pointer =
-
390 std::find_if(input.begin(), input.end(), [character_set](const char c) {
-
391 return character_sets::bit_at(character_set, c);
-
392 });
-
393 // Optimization: Don't iterate if percent encode is not required
-
394 if (pointer == input.end()) {
-
395 return std::string(input);
-
396 }
-
397
-
398 std::string result;
-
399 result.reserve(input.length()); // in the worst case, percent encoding might
-
400 // produce 3 characters.
-
401 result.append(input.substr(0, std::distance(input.begin(), pointer)));
-
402
-
403 for (; pointer != input.end(); pointer++) {
-
404 if (character_sets::bit_at(character_set, *pointer)) {
-
405 result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
-
406 } else {
-
407 result += *pointer;
-
408 }
-
409 }
-
410
-
411 return result;
-
412}
-
413
-
414template <bool append>
-
415bool percent_encode(const std::string_view input, const uint8_t character_set[],
-
416 std::string& out) {
-
417 ada_log("percent_encode ", input, " to output string while ",
-
418 append ? "appending" : "overwriting");
-
419 auto pointer =
-
420 std::find_if(input.begin(), input.end(), [character_set](const char c) {
-
421 return character_sets::bit_at(character_set, c);
-
422 });
-
423 ada_log("percent_encode done checking, moved to ",
-
424 std::distance(input.begin(), pointer));
-
425
-
426 // Optimization: Don't iterate if percent encode is not required
-
427 if (pointer == input.end()) {
-
428 ada_log("percent_encode encoding not needed.");
-
429 return false;
-
430 }
-
431 if constexpr (!append) {
-
432 out.clear();
-
433 }
-
434 ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
-
435 " bytes");
-
436 out.append(input.data(), std::distance(input.begin(), pointer));
-
437 ada_log("percent_encode processing ", std::distance(pointer, input.end()),
-
438 " bytes");
-
439 for (; pointer != input.end(); pointer++) {
-
440 if (character_sets::bit_at(character_set, *pointer)) {
-
441 out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
-
442 } else {
-
443 out += *pointer;
-
444 }
-
445 }
-
446 return true;
-
447}
-
448
-
449bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
-
450 size_t first_percent) {
-
451 std::string percent_decoded_buffer;
-
452 std::string_view input = plain;
-
453 if (first_percent != std::string_view::npos) {
-
454 percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
-
455 input = percent_decoded_buffer;
-
456 }
-
457 // input is a non-empty UTF-8 string, must be percent decoded
-
458 std::string idna_ascii = ada::idna::to_ascii(input);
-
459 if (idna_ascii.empty() || contains_forbidden_domain_code_point(
-
460 idna_ascii.data(), idna_ascii.size())) {
-
461 return false;
-
462 }
-
463 out = std::move(idna_ascii);
-
464 return true;
-
465}
-
466
-
467std::string percent_encode(const std::string_view input,
-
468 const uint8_t character_set[], size_t index) {
-
469 std::string out;
-
470 out.append(input.data(), index);
-
471 auto pointer = input.begin() + index;
-
472 for (; pointer != input.end(); pointer++) {
-
473 if (character_sets::bit_at(character_set, *pointer)) {
-
474 out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
-
475 } else {
-
476 out += *pointer;
-
477 }
-
478 }
-
479 return out;
-
480}
-
481
-
482} // namespace ada::unicode
+
375 } else {
+
376 unsigned a = convert_hex_to_binary(pointer[1]);
+
377 unsigned b = convert_hex_to_binary(pointer[2]);
+
378 char c = static_cast<char>(a * 16 + b);
+
379 dest += c;
+
380 pointer += 3;
+
381 }
+
382 }
+
383 return dest;
+
384}
+
385
+
386std::string percent_encode(const std::string_view input,
+
387 const uint8_t character_set[]) {
+
388 auto pointer = std::ranges::find_if(input, [character_set](const char c) {
+
389 return character_sets::bit_at(character_set, c);
+
390 });
+
391 // Optimization: Don't iterate if percent encode is not required
+
392 if (pointer == input.end()) {
+
393 return std::string(input);
+
394 }
+
395
+
396 std::string result;
+
397 result.reserve(input.length()); // in the worst case, percent encoding might
+
398 // produce 3 characters.
+
399 result.append(input.substr(0, std::distance(input.begin(), pointer)));
+
400
+
401 for (; pointer != input.end(); pointer++) {
+
402 if (character_sets::bit_at(character_set, *pointer)) {
+
403 result.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
+
404 } else {
+
405 result += *pointer;
+
406 }
+
407 }
+
408
+
409 return result;
+
410}
+
411
+
412template <bool append>
+
413bool percent_encode(const std::string_view input, const uint8_t character_set[],
+
414 std::string& out) {
+
415 ada_log("percent_encode ", input, " to output string while ",
+
416 append ? "appending" : "overwriting");
+
417 auto pointer =
+
418 std::find_if(input.begin(), input.end(), [character_set](const char c) {
+
419 return character_sets::bit_at(character_set, c);
+
420 });
+
421 ada_log("percent_encode done checking, moved to ",
+
422 std::distance(input.begin(), pointer));
+
423
+
424 // Optimization: Don't iterate if percent encode is not required
+
425 if (pointer == input.end()) {
+
426 ada_log("percent_encode encoding not needed.");
+
427 return false;
+
428 }
+
429 if constexpr (!append) {
+
430 out.clear();
+
431 }
+
432 ada_log("percent_encode appending ", std::distance(input.begin(), pointer),
+
433 " bytes");
+
434 out.append(input.data(), std::distance(input.begin(), pointer));
+
435 ada_log("percent_encode processing ", std::distance(pointer, input.end()),
+
436 " bytes");
+
437 for (; pointer != input.end(); pointer++) {
+
438 if (character_sets::bit_at(character_set, *pointer)) {
+
439 out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
+
440 } else {
+
441 out += *pointer;
+
442 }
+
443 }
+
444 return true;
+
445}
+
446
+
447bool to_ascii(std::optional<std::string>& out, const std::string_view plain,
+
448 size_t first_percent) {
+
449 std::string percent_decoded_buffer;
+
450 std::string_view input = plain;
+
451 if (first_percent != std::string_view::npos) {
+
452 percent_decoded_buffer = unicode::percent_decode(plain, first_percent);
+
453 input = percent_decoded_buffer;
+
454 }
+
455 // input is a non-empty UTF-8 string, must be percent decoded
+
456 std::string idna_ascii = ada::idna::to_ascii(input);
+
457 if (idna_ascii.empty() || contains_forbidden_domain_code_point(
+
458 idna_ascii.data(), idna_ascii.size())) {
+
459 return false;
+
460 }
+
461 out = std::move(idna_ascii);
+
462 return true;
+
463}
+
464
+
465std::string percent_encode(const std::string_view input,
+
466 const uint8_t character_set[], size_t index) {
+
467 std::string out;
+
468 out.append(input.data(), index);
+
469 auto pointer = input.begin() + index;
+
470 for (; pointer != input.end(); pointer++) {
+
471 if (character_sets::bit_at(character_set, *pointer)) {
+
472 out.append(character_sets::hex + uint8_t(*pointer) * 4, 3);
+
473 } else {
+
474 out += *pointer;
+
475 }
+
476 }
+
477 return out;
+
478}
+
479
+
480} // namespace ada::unicode
Includes all definitions for Ada.
Definitions of the character sets used by unicode functions.
diff --git a/dd/dc7/structada_1_1url__search__params__iter.html b/dd/dc7/structada_1_1url__search__params__iter.html index af7e4b924..7997945ee 100644 --- a/dd/dc7/structada_1_1url__search__params__iter.html +++ b/dd/dc7/structada_1_1url__search__params__iter.html @@ -136,8 +136,8 @@

- - + +
has_next()ada::url_search_params_iter< T, Type >inline
has_next() constada::url_search_params_iter< T, Type >inline
next()ada::url_search_params_iter< T, Type >inline
operator=(url_search_params_iter &&u) noexcept=defaultada::url_search_params_iter< T, Type >
operator=(const url_search_params_iter &u)=defaultada::url_search_params_iter< T, Type >
sort()ada::url_search_paramsinline
to_string() constada::url_search_paramsinline
url_search_params()=defaultada::url_search_params
url_search_params(const std::string_view input)ada::url_search_paramsinline
url_search_params(const std::string_view input)ada::url_search_paramsinlineexplicit
url_search_params(const url_search_params &u)=defaultada::url_search_params
url_search_params(url_search_params &&u) noexcept=defaultada::url_search_params
url_search_params_iterada::url_search_paramsfriend
 
std::optional< T > next ()
 
bool has_next ()
 
bool has_next () const
 
@@ -149,7 +149,7 @@ struct ada::url_search_params_iter< T, Type >

Implements a non-conventional iterator pattern that is closer in style to JavaScript's definition of an iterator.

See also
https://webidl.spec.whatwg.org/#idl-iterable
-

Definition at line 161 of file url_search_params.h.

+

Definition at line 163 of file url_search_params.h.

Constructor & Destructor Documentation

◆ url_search_params_iter() [1/3]

@@ -176,7 +176,7 @@

-

Definition at line 162 of file url_search_params.h.

+

Definition at line 164 of file url_search_params.h.

@@ -262,8 +262,8 @@

Member Function Documentation

- -

◆ has_next()

+ +

◆ has_next()

@@ -277,7 +277,7 @@

bool ada::url_search_params_iter< T, Type >::has_next

- +

Friends

( ) const
@@ -319,7 +319,7 @@

Definition at line 201 of file url_search_params-inl.h.

-

References ada::url_search_params_iter< T, Type >::has_next().

+

References ada::url_search_params_iter< T, Type >::has_next().

@@ -400,7 +400,7 @@

-

Definition at line 184 of file url_search_params.h.

+

Definition at line 186 of file url_search_params.h.

diff --git a/dd/dc7/structada_1_1url__search__params__iter.js b/dd/dc7/structada_1_1url__search__params__iter.js index a6f95d661..64b90ee44 100644 --- a/dd/dc7/structada_1_1url__search__params__iter.js +++ b/dd/dc7/structada_1_1url__search__params__iter.js @@ -4,7 +4,7 @@ var structada_1_1url__search__params__iter = [ "url_search_params_iter", "dd/dc7/structada_1_1url__search__params__iter.html#a74d28d34b008f8dc5d47ed09273d59a3", null ], [ "url_search_params_iter", "dd/dc7/structada_1_1url__search__params__iter.html#ad78e906cf73d647566c5c6e8826d7011", null ], [ "~url_search_params_iter", "dd/dc7/structada_1_1url__search__params__iter.html#af2328b090243ee67014d36d1e9cc87e9", null ], - [ "has_next", "dd/dc7/structada_1_1url__search__params__iter.html#a3dcaaa1b3dc74addd7769356524a4539", null ], + [ "has_next", "dd/dc7/structada_1_1url__search__params__iter.html#aeb4019bf7d63735d667a10eed0900e21", null ], [ "next", "dd/dc7/structada_1_1url__search__params__iter.html#abd48d5df7cc6a5cb11275c1bf5f85be8", null ], [ "operator=", "dd/dc7/structada_1_1url__search__params__iter.html#af8b1732eaf20e2480de3b18c9afe189a", null ], [ "operator=", "dd/dc7/structada_1_1url__search__params__iter.html#aaf248512f7d5fefc0cf550f51dfd95c3", null ], diff --git a/dd/dc8/url__aggregator_8cpp_source.html b/dd/dc8/url__aggregator_8cpp_source.html index 273043dd5..7469e327f 100644 --- a/dd/dc8/url__aggregator_8cpp_source.html +++ b/dd/dc8/url__aggregator_8cpp_source.html @@ -137,7 +137,7 @@
22 std::string_view input{input_with_colon};
23 input.remove_suffix(1);
24 auto parsed_type = ada::scheme::get_scheme_type(input);
-
25 bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
+
25 const bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
30 if (is_input_special) { // fast path!!!
31 if constexpr (has_state_override) {
32 // If url's scheme is not a special scheme and buffer is a special scheme,
@@ -336,7 +336,7 @@
224 view.append(":");
225
226 std::string::iterator pointer =
-
227 std::find_if_not(view.begin(), view.end(), unicode::is_alnum_plus);
+
227 std::ranges::find_if_not(view, unicode::is_alnum_plus);
228
229 if (pointer != view.end() && *pointer == ':') {
230 return parse_scheme_with_colon<true>(
@@ -1716,11 +1716,11 @@
constexpr bool is_alpha(char x) noexcept
constexpr bool is_digit(char x) noexcept
constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept
Definition scheme-inl.h:72
- - - -
@ NOT_SPECIAL
Definition scheme.h:32
- + + + +
@ NOT_SPECIAL
Definition scheme.h:31
+
constexpr uint16_t get_special_port(std::string_view scheme) noexcept
Definition scheme-inl.h:57
std::string ipv6(const std::array< uint16_t, 8 > &address) noexcept
std::string ipv4(uint64_t address) noexcept
diff --git a/dd/dcb/structada_1_1url__search__params.html b/dd/dcb/structada_1_1url__search__params.html index cfce6bd10..d4c2a954a 100644 --- a/dd/dcb/structada_1_1url__search__params.html +++ b/dd/dcb/structada_1_1url__search__params.html @@ -229,7 +229,7 @@

-inline +inlineexplicit @@ -398,7 +398,7 @@

C++ style conventional iterator support. const only because we do not really want the params to be modified via the iterator.

-

Definition at line 127 of file url_search_params.h.

+

Definition at line 129 of file url_search_params.h.

@@ -425,7 +425,7 @@

-

Definition at line 128 of file url_search_params.h.

+

Definition at line 130 of file url_search_params.h.

@@ -452,7 +452,7 @@

-

Definition at line 129 of file url_search_params.h.

+

Definition at line 131 of file url_search_params.h.

@@ -732,7 +732,7 @@

-

Definition at line 131 of file url_search_params.h.

+

Definition at line 133 of file url_search_params.h.

@@ -935,7 +935,7 @@

-

Definition at line 151 of file url_search_params.h.

+

Definition at line 153 of file url_search_params.h.

diff --git a/dd/dd6/ada__c_8cpp_source.html b/dd/dd6/ada__c_8cpp_source.html index 6b13f8f71..9e7703676 100644 --- a/dd/dd6/ada__c_8cpp_source.html +++ b/dd/dd6/ada__c_8cpp_source.html @@ -1076,7 +1076,7 @@
tl::expected< result_type, ada::errors > result
ada_warn_unused ada::result< result_type > parse(std::string_view input, const result_type *base_url=nullptr)
URL Component representations using offsets.
- +
size_t length
Definition ada_c.h:25
diff --git a/df/db8/url_8h_source.html b/df/db8/url_8h_source.html index 4bbcb58fc..904380d92 100644 --- a/df/db8/url_8h_source.html +++ b/df/db8/url_8h_source.html @@ -231,59 +231,58 @@
302
303 inline void update_unencoded_base_hash(std::string_view input);
304 inline void update_base_hostname(std::string_view input);
-
305 inline void update_base_search(std::string_view input);
-
306 inline void update_base_search(std::string_view input,
-
307 const uint8_t query_percent_encode_set[]);
-
308 inline void update_base_search(std::optional<std::string> input);
-
309 inline void update_base_pathname(std::string_view input);
-
310 inline void update_base_username(std::string_view input);
-
311 inline void update_base_password(std::string_view input);
-
312 inline void update_base_port(std::optional<uint16_t> input);
-
313
-
319 template <bool override_hostname = false>
-
320 bool set_host_or_hostname(std::string_view input);
-
321
-
326 [[nodiscard]] bool parse_ipv4(std::string_view input);
-
327
-
332 [[nodiscard]] bool parse_ipv6(std::string_view input);
-
333
-
338 [[nodiscard]] bool parse_opaque_host(std::string_view input);
-
339
-
349 std::string non_special_scheme{};
-
350
-
355 [[nodiscard]] inline bool cannot_have_credentials_or_port() const;
-
356
-
357 ada_really_inline size_t parse_port(
-
358 std::string_view view, bool check_trailing_content) noexcept override;
-
359
-
360 ada_really_inline size_t parse_port(std::string_view view) noexcept override {
-
361 return this->parse_port(view, false);
-
362 }
-
363
-
372 [[nodiscard]] ada_really_inline bool parse_host(std::string_view input);
-
373
-
374 template <bool has_state_override = false>
-
375 [[nodiscard]] ada_really_inline bool parse_scheme(std::string_view input);
-
376
-
377 constexpr void clear_pathname() override;
-
378 constexpr void clear_search() override;
-
379 constexpr void set_protocol_as_file();
-
380
-
391 ada_really_inline void parse_path(std::string_view input);
-
392
-
398 inline void set_scheme(std::string &&new_scheme) noexcept;
-
399
-
404 constexpr void copy_scheme(ada::url &&u) noexcept;
-
405
-
410 constexpr void copy_scheme(const ada::url &u);
-
411
-
412}; // struct url
+
305 inline void update_base_search(std::string_view input,
+
306 const uint8_t query_percent_encode_set[]);
+
307 inline void update_base_search(std::optional<std::string> &&input);
+
308 inline void update_base_pathname(std::string_view input);
+
309 inline void update_base_username(std::string_view input);
+
310 inline void update_base_password(std::string_view input);
+
311 inline void update_base_port(std::optional<uint16_t> input);
+
312
+
318 template <bool override_hostname = false>
+
319 bool set_host_or_hostname(std::string_view input);
+
320
+
325 [[nodiscard]] bool parse_ipv4(std::string_view input);
+
326
+
331 [[nodiscard]] bool parse_ipv6(std::string_view input);
+
332
+
337 [[nodiscard]] bool parse_opaque_host(std::string_view input);
+
338
+
348 std::string non_special_scheme{};
+
349
+
354 [[nodiscard]] inline bool cannot_have_credentials_or_port() const;
+
355
+
356 ada_really_inline size_t parse_port(
+
357 std::string_view view, bool check_trailing_content) noexcept override;
+
358
+
359 ada_really_inline size_t parse_port(std::string_view view) noexcept override {
+
360 return this->parse_port(view, false);
+
361 }
+
362
+
371 [[nodiscard]] ada_really_inline bool parse_host(std::string_view input);
+
372
+
373 template <bool has_state_override = false>
+
374 [[nodiscard]] ada_really_inline bool parse_scheme(std::string_view input);
+
375
+
376 constexpr void clear_pathname() override;
+
377 constexpr void clear_search() override;
+
378 constexpr void set_protocol_as_file();
+
379
+
390 ada_really_inline void parse_path(std::string_view input);
+
391
+
397 inline void set_scheme(std::string &&new_scheme) noexcept;
+
398
+
403 constexpr void copy_scheme(ada::url &&u) noexcept;
+
404
+
409 constexpr void copy_scheme(const ada::url &u);
+
410
+
411}; // struct url
-
413
-
414inline std::ostream &operator<<(std::ostream &out, const ada::url &u);
-
415} // namespace ada
-
416
-
417#endif // ADA_URL_H
+
412
+
413inline std::ostream &operator<<(std::ostream &out, const ada::url &u);
+
414} // namespace ada
+
415
+
416#endif // ADA_URL_H
Declarations for URL specific checkers used within Ada.
Common definitions for cross-platform compiler support.
#define ada_really_inline
Definition common_defs.h:84
@@ -309,7 +308,7 @@
url & operator=(const url &u)=default
void set_search(std::string_view input)
ada_really_inline size_t get_pathname_length() const noexcept
Definition url-inl.h:42
-
bool set_href(std::string_view input)
+
bool set_href(std::string_view input)
ada_really_inline std::string get_href() const noexcept
Definition url-inl.h:187
bool has_hostname() const noexcept
Definition url-inl.h:35
bool set_username(std::string_view input)
@@ -319,21 +318,21 @@
url()=default
std::string get_host() const noexcept
std::string get_hash() const noexcept
-
bool set_pathname(std::string_view input)
+
bool set_pathname(std::string_view input)
std::string get_origin() const noexcept override
friend void ada::helpers::strip_trailing_spaces_from_opaque_path(ada::url &url) noexcept
std::string get_hostname() const noexcept
friend ada::url ada::parser::parse_url_impl(std::string_view, const ada::url *)
const std::string & get_password() const noexcept
-
bool set_protocol(std::string_view input)
+
bool set_protocol(std::string_view input)
std::string get_port() const noexcept
const std::string & get_username() const noexcept
bool set_port(std::string_view input)
constexpr bool has_search() const noexcept override
Definition url-inl.h:163
-
std::string to_string() const override
Definition url.cpp:536
+
std::string to_string() const override
Definition url.cpp:533
std::string get_protocol() const noexcept
constexpr bool has_hash() const noexcept override
Definition url-inl.h:159
-
bool has_valid_domain() const noexcept override
Definition url.cpp:585
+
bool has_valid_domain() const noexcept override
Definition url.cpp:582
Definitions for all unicode specific functions.
Declaration for the basic URL definitions.
Declaration for the URL Components.
diff --git a/df/ddc/url-inl_8h_source.html b/df/ddc/url-inl_8h_source.html index e2207f505..114911de9 100644 --- a/df/ddc/url-inl_8h_source.html +++ b/df/ddc/url-inl_8h_source.html @@ -260,8 +260,8 @@
132 query = ada::unicode::percent_encode(input, query_percent_encode_set);
133}
134
-
135inline void url::update_base_search(std::optional<std::string> input) {
-
136 query = input;
+
135inline void url::update_base_search(std::optional<std::string> &&input) {
+
136 query = std::move(input);
137}
138
139inline void url::update_base_pathname(const std::string_view input) {
@@ -366,7 +366,7 @@
232 return 0;
233 }
234 ada_log("parse_port: ", parsed_port);
-
235 const size_t consumed = size_t(r.ptr - view.data());
+
235 const auto consumed = size_t(r.ptr - view.data());
236 ada_log("parse_port: consumed ", consumed);
237 if (check_trailing_content) {
238 is_valid &=
@@ -379,22 +379,21 @@
245 auto default_port = scheme_default_port();
246 bool is_port_valid = (default_port == 0 && parsed_port == 0) ||
247 (default_port != parsed_port);
-
248 port = (r.ec == std::errc() && is_port_valid)
-
249 ? std::optional<uint16_t>(parsed_port)
-
250 : std::nullopt;
-
251 }
-
252 return consumed;
-
253}
-
254
-
255} // namespace ada
-
256
-
257#endif // ADA_URL_H
+
248 port = (r.ec == std::errc() && is_port_valid) ? std::optional(parsed_port)
+
249 : std::nullopt;
+
250 }
+
251 return consumed;
+
252}
+
253
+
254} // namespace ada
+
255
+
256#endif // ADA_URL_H
Declarations for URL specific checkers used within Ada.
#define ada_really_inline
Definition common_defs.h:84
constexpr uint8_t FRAGMENT_PERCENT_ENCODE[32]
constexpr ada::scheme::type get_scheme_type(std::string_view scheme) noexcept
Definition scheme-inl.h:72
- - + +
Definition ada_idna.h:13
std::ostream & operator<<(std::ostream &out, const ada::url &u)
Definition url-inl.h:38
bool has_opaque_path
Definition url_base.h:55
@@ -413,7 +412,7 @@
const std::string & get_password() const noexcept
std::string get_port() const noexcept
constexpr bool has_search() const noexcept override
Definition url-inl.h:163
-
std::string to_string() const override
Definition url.cpp:536
+
std::string to_string() const override
Definition url.cpp:533
std::string get_protocol() const noexcept
constexpr bool has_hash() const noexcept override
Definition url-inl.h:159
Declaration for the URL.
diff --git a/doxygen_crawl.html b/doxygen_crawl.html index 4669f0e03..d324916af 100644 --- a/doxygen_crawl.html +++ b/doxygen_crawl.html @@ -977,12 +977,12 @@ - + diff --git a/functions.html b/functions.html index 99ea166db..3f4be844b 100644 --- a/functions.html +++ b/functions.html @@ -179,7 +179,7 @@

- h -

  • has_empty_hostname() : ada::url, ada::url_aggregator
  • has_hash() : ada::url, ada::url_aggregator
  • has_hostname() : ada::url, ada::url_aggregator
  • -
  • has_next() : ada::url_search_params_iter< T, Type >
  • +
  • has_next() : ada::url_search_params_iter< T, Type >
  • has_non_empty_password() : ada::url_aggregator
  • has_non_empty_username() : ada::url_aggregator
  • has_opaque_path : ada::url_base
  • diff --git a/functions_func.html b/functions_func.html index 609d0d19b..a25d6d462 100644 --- a/functions_func.html +++ b/functions_func.html @@ -169,7 +169,7 @@

    - h -

    • has_empty_hostname() : ada::url, ada::url_aggregator
    • has_hash() : ada::url, ada::url_aggregator
    • has_hostname() : ada::url, ada::url_aggregator
    • -
    • has_next() : ada::url_search_params_iter< T, Type >
    • +
    • has_next() : ada::url_search_params_iter< T, Type >
    • has_non_empty_password() : ada::url_aggregator
    • has_non_empty_username() : ada::url_aggregator
    • has_password() : ada::url_aggregator
    • diff --git a/navtreeindex3.js b/navtreeindex3.js index 00543e926..29e339ff1 100644 --- a/navtreeindex3.js +++ b/navtreeindex3.js @@ -95,8 +95,6 @@ var NAVTREEINDEX3 = "dd/dc7/structada_1_1url__search__params__iter.html":[8,0,0,6], "dd/dc7/structada_1_1url__search__params__iter.html#a21bdd83c3f1a44b4926dc3b045841ea7":[7,0,0,13,8], "dd/dc7/structada_1_1url__search__params__iter.html#a21bdd83c3f1a44b4926dc3b045841ea7":[8,0,0,6,8], -"dd/dc7/structada_1_1url__search__params__iter.html#a3dcaaa1b3dc74addd7769356524a4539":[7,0,0,13,4], -"dd/dc7/structada_1_1url__search__params__iter.html#a3dcaaa1b3dc74addd7769356524a4539":[8,0,0,6,4], "dd/dc7/structada_1_1url__search__params__iter.html#a74d28d34b008f8dc5d47ed09273d59a3":[7,0,0,13,1], "dd/dc7/structada_1_1url__search__params__iter.html#a74d28d34b008f8dc5d47ed09273d59a3":[8,0,0,6,1], "dd/dc7/structada_1_1url__search__params__iter.html#a7aef848d355455587f691dde5bd6f27b":[7,0,0,13,0], @@ -107,6 +105,8 @@ var NAVTREEINDEX3 = "dd/dc7/structada_1_1url__search__params__iter.html#abd48d5df7cc6a5cb11275c1bf5f85be8":[8,0,0,6,5], "dd/dc7/structada_1_1url__search__params__iter.html#ad78e906cf73d647566c5c6e8826d7011":[7,0,0,13,2], "dd/dc7/structada_1_1url__search__params__iter.html#ad78e906cf73d647566c5c6e8826d7011":[8,0,0,6,2], +"dd/dc7/structada_1_1url__search__params__iter.html#aeb4019bf7d63735d667a10eed0900e21":[7,0,0,13,4], +"dd/dc7/structada_1_1url__search__params__iter.html#aeb4019bf7d63735d667a10eed0900e21":[8,0,0,6,4], "dd/dc7/structada_1_1url__search__params__iter.html#af2328b090243ee67014d36d1e9cc87e9":[7,0,0,13,3], "dd/dc7/structada_1_1url__search__params__iter.html#af2328b090243ee67014d36d1e9cc87e9":[8,0,0,6,3], "dd/dc7/structada_1_1url__search__params__iter.html#af8b1732eaf20e2480de3b18c9afe189a":[7,0,0,13,6], diff --git a/search/all_8.js b/search/all_8.js index ae36171e7..fc52b69d8 100644 --- a/search/all_8.js +++ b/search/all_8.js @@ -16,7 +16,7 @@ var searchData= ['has_5fhex_5fprefix_13',['has_hex_prefix',['../d3/dbe/namespaceada_1_1checkers.html#a34d5be12630bcce5a782ef2f8b5e1e48',1,'ada::checkers']]], ['has_5fhex_5fprefix_5funsafe_14',['has_hex_prefix_unsafe',['../d3/dbe/namespaceada_1_1checkers.html#a078ffb35a09d688f031537ea728fe3ae',1,'ada::checkers']]], ['has_5fhostname_15',['has_hostname',['../dd/d03/structada_1_1url.html#a603d240f7f5dc42ebc9bbf9d25721d28',1,'ada::url::has_hostname()'],['../d8/d3b/structada_1_1url__aggregator.html#a7f2c7df6f89e30a498644927229aab28',1,'ada::url_aggregator::has_hostname()']]], - ['has_5fnext_16',['has_next',['../dd/dc7/structada_1_1url__search__params__iter.html#a3dcaaa1b3dc74addd7769356524a4539',1,'ada::url_search_params_iter']]], + ['has_5fnext_16',['has_next',['../dd/dc7/structada_1_1url__search__params__iter.html#aeb4019bf7d63735d667a10eed0900e21',1,'ada::url_search_params_iter']]], ['has_5fnon_5fempty_5fpassword_17',['has_non_empty_password',['../d8/d3b/structada_1_1url__aggregator.html#a08ebb60380c2cabdf6e25f3084f78b7d',1,'ada::url_aggregator']]], ['has_5fnon_5fempty_5fusername_18',['has_non_empty_username',['../d8/d3b/structada_1_1url__aggregator.html#af8d97282ee4b1765874cf3cab6ca4259',1,'ada::url_aggregator']]], ['has_5fopaque_5fpath_19',['has_opaque_path',['../db/d75/structada_1_1url__base.html#a9996c7aa6d12a6b61c05304fb51c98e2',1,'ada::url_base']]], diff --git a/search/functions_7.js b/search/functions_7.js index 671429713..ef12c68f3 100644 --- a/search/functions_7.js +++ b/search/functions_7.js @@ -7,7 +7,7 @@ var searchData= ['has_5fhex_5fprefix_4',['has_hex_prefix',['../d3/dbe/namespaceada_1_1checkers.html#a34d5be12630bcce5a782ef2f8b5e1e48',1,'ada::checkers']]], ['has_5fhex_5fprefix_5funsafe_5',['has_hex_prefix_unsafe',['../d3/dbe/namespaceada_1_1checkers.html#a078ffb35a09d688f031537ea728fe3ae',1,'ada::checkers']]], ['has_5fhostname_6',['has_hostname',['../dd/d03/structada_1_1url.html#a603d240f7f5dc42ebc9bbf9d25721d28',1,'ada::url::has_hostname()'],['../d8/d3b/structada_1_1url__aggregator.html#a7f2c7df6f89e30a498644927229aab28',1,'ada::url_aggregator::has_hostname()']]], - ['has_5fnext_7',['has_next',['../dd/dc7/structada_1_1url__search__params__iter.html#a3dcaaa1b3dc74addd7769356524a4539',1,'ada::url_search_params_iter']]], + ['has_5fnext_7',['has_next',['../dd/dc7/structada_1_1url__search__params__iter.html#aeb4019bf7d63735d667a10eed0900e21',1,'ada::url_search_params_iter']]], ['has_5fnon_5fempty_5fpassword_8',['has_non_empty_password',['../d8/d3b/structada_1_1url__aggregator.html#a08ebb60380c2cabdf6e25f3084f78b7d',1,'ada::url_aggregator']]], ['has_5fnon_5fempty_5fusername_9',['has_non_empty_username',['../d8/d3b/structada_1_1url__aggregator.html#af8d97282ee4b1765874cf3cab6ca4259',1,'ada::url_aggregator']]], ['has_5fpassword_10',['has_password',['../d8/d3b/structada_1_1url__aggregator.html#a9cfbfb9c81d8aa551f3591759253b6f7',1,'ada::url_aggregator']]],