14
14
15
15
namespace ada {
16
16
template <bool has_state_override>
17
- [[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme (const std::string_view input ) {
18
- ada_log (" url_aggregator::parse_scheme " , input );
17
+ [[nodiscard]] ada_really_inline bool url_aggregator::parse_scheme_with_colon (const std::string_view input_with_colon ) {
18
+ ada_log (" url_aggregator::parse_scheme_with_colon " , input_with_colon );
19
19
ADA_ASSERT_TRUE (validate ());
20
- ADA_ASSERT_TRUE (!helpers::overlaps (input, buffer));
20
+ ADA_ASSERT_TRUE (!helpers::overlaps (input_with_colon, buffer));
21
+ std::string_view input{input_with_colon};
22
+ input.remove_suffix (1 );
21
23
auto parsed_type = ada::scheme::get_scheme_type (input);
22
24
bool is_input_special = (parsed_type != ada::scheme::NOT_SPECIAL);
23
25
/* *
@@ -36,16 +38,15 @@ template <bool has_state_override>
36
38
if (type == ada::scheme::type::FILE && components.host_start == components.host_end ) { return true ; }
37
39
}
38
40
39
- set_scheme (input);
41
+ type = parsed_type;
42
+ set_scheme_from_view_with_colon (input_with_colon);
40
43
41
44
if (has_state_override) {
42
45
// This is uncommon.
43
46
uint16_t urls_scheme_port = get_special_port ();
44
47
45
- if (urls_scheme_port) {
46
- // If url’s port is url’s scheme’s default port, then set url’s port to null.
47
- if (components.port == urls_scheme_port) { components.port = url_components::omitted; }
48
- }
48
+ // If url’s port is url’s scheme’s default port, then set url’s port to null.
49
+ if (components.port == urls_scheme_port) { components.port = url_components::omitted; }
49
50
}
50
51
} else { // slow path
51
52
std::string _buffer = std::string (input);
@@ -69,16 +70,14 @@ template <bool has_state_override>
69
70
if (type == ada::scheme::type::FILE && components.host_start == components.host_end ) { return true ; }
70
71
}
71
72
72
- set_scheme (std::move ( _buffer) );
73
+ set_scheme (_buffer);
73
74
74
75
if (has_state_override) {
75
76
// This is uncommon.
76
77
uint16_t urls_scheme_port = get_special_port ();
77
78
78
- if (urls_scheme_port) {
79
- // If url’s port is url’s scheme’s default port, then set url’s port to null.
80
- if (components.port == urls_scheme_port) { components.port = url_components::omitted; }
81
- }
79
+ // If url’s port is url’s scheme’s default port, then set url’s port to null.
80
+ if (components.port == urls_scheme_port) { components.port = url_components::omitted; }
82
81
}
83
82
}
84
83
ADA_ASSERT_TRUE (validate ());
@@ -88,6 +87,7 @@ template <bool has_state_override>
88
87
inline void url_aggregator::copy_scheme (const url_aggregator& u) noexcept {
89
88
ada_log (" url_aggregator::copy_scheme " , u.buffer );
90
89
ADA_ASSERT_TRUE (validate ());
90
+ // next line could overflow but unsigned arithmetic has well-defined overflows.
91
91
uint32_t new_difference = u.components .protocol_end - components.protocol_end ;
92
92
type = u.type ;
93
93
buffer.erase (0 , components.protocol_end );
@@ -107,22 +107,48 @@ inline void url_aggregator::copy_scheme(const url_aggregator& u) noexcept {
107
107
ADA_ASSERT_TRUE (validate ());
108
108
}
109
109
110
+ inline void url_aggregator::set_scheme_from_view_with_colon (std::string_view new_scheme_with_colon) noexcept {
111
+ ada_log (" url_aggregator::set_scheme_from_view_with_colon " , new_scheme_with_colon);
112
+ ADA_ASSERT_TRUE (validate ());
113
+ ADA_ASSERT_TRUE (!new_scheme_with_colon.empty () && new_scheme_with_colon.back () == ' :' );
114
+ // next line could overflow but unsigned arithmetic has well-defined overflows.
115
+ uint32_t new_difference = uint32_t (new_scheme_with_colon.size ()) - components.protocol_end ;
116
+
117
+ if (buffer.empty ()) {
118
+ buffer.append (new_scheme_with_colon);
119
+ } else {
120
+ buffer.erase (0 , components.protocol_end );
121
+ buffer.insert (0 , new_scheme_with_colon);
122
+ }
123
+ components.protocol_end += new_difference;
124
+
125
+ // Update the rest of the components.
126
+ components.username_end += new_difference;
127
+ components.host_start += new_difference;
128
+ components.host_end += new_difference;
129
+ components.pathname_start += new_difference;
130
+ if (components.search_start != url_components::omitted) { components.search_start += new_difference; }
131
+ if (components.hash_start != url_components::omitted) { components.hash_start += new_difference; }
132
+ ADA_ASSERT_TRUE (validate ());
133
+ }
134
+
135
+
110
136
inline void url_aggregator::set_scheme (std::string_view new_scheme) noexcept {
111
137
ada_log (" url_aggregator::set_scheme " , new_scheme);
112
138
ADA_ASSERT_TRUE (validate ());
113
- uint32_t new_difference = uint32_t (new_scheme.size ()) - components.protocol_end ;
114
-
115
- // Optimization opportunity: Get rid of this branch
116
- if (new_scheme.back () != ' :' ) { new_difference += 1 ; }
139
+ ADA_ASSERT_TRUE (new_scheme.empty () || new_scheme.back () != ' :' );
140
+ // next line could overflow but unsigned arithmetic has well-defined overflows.
141
+ uint32_t new_difference = uint32_t (new_scheme.size ()) - components.protocol_end + 1 ;
117
142
118
143
type = ada::scheme::get_scheme_type (new_scheme);
119
- buffer.erase (0 , components.protocol_end );
120
- buffer.insert (0 , helpers::concat (new_scheme, " :" ));
144
+ if (buffer.empty ()) {
145
+ buffer.append (helpers::concat (new_scheme, " :" ));
146
+ } else {
147
+ buffer.erase (0 , components.protocol_end );
148
+ buffer.insert (0 , helpers::concat (new_scheme, " :" ));
149
+ }
121
150
components.protocol_end = uint32_t (new_scheme.size () + 1 );
122
151
123
- // No need to update the components
124
- if (new_difference == 0 ) { return ; }
125
-
126
152
// Update the rest of the components.
127
153
components.username_end += new_difference;
128
154
components.host_start += new_difference;
@@ -149,7 +175,7 @@ bool url_aggregator::set_protocol(const std::string_view input) {
149
175
std::string::iterator pointer = std::find_if_not (view.begin (), view.end (), unicode::is_alnum_plus);
150
176
151
177
if (pointer != view.end () && *pointer == ' :' ) {
152
- return parse_scheme <true >(std::string_view (view.data (), pointer - view.begin ()));
178
+ return parse_scheme_with_colon <true >(std::string_view (view.data (), pointer - view.begin () + 1 ));
153
179
}
154
180
return false ;
155
181
}
@@ -1001,9 +1027,10 @@ std::string url_aggregator::to_diagram() const {
1001
1027
line2[i] = ' -' ;
1002
1028
}
1003
1029
line2.append (" hash_start" );
1030
+ answer.append (line2);
1031
+ answer.append (" \n " );
1004
1032
}
1005
- answer.append (line2);
1006
- answer.append (" \n " );
1033
+
1007
1034
1008
1035
std::string line3 = line1;
1009
1036
if (components.search_start != url_components::omitted) {
@@ -1015,9 +1042,10 @@ std::string url_aggregator::to_diagram() const {
1015
1042
}
1016
1043
line3.append (" search_start " );
1017
1044
line3.append (std::to_string (components.search_start ));
1045
+ answer.append (line3);
1046
+ answer.append (" \n " );
1018
1047
}
1019
- answer.append (line3);
1020
- answer.append (" \n " );
1048
+
1021
1049
1022
1050
std::string line4 = line1;
1023
1051
if (components.pathname_start != buffer.size ()) {
@@ -1028,9 +1056,10 @@ std::string url_aggregator::to_diagram() const {
1028
1056
}
1029
1057
line4.append (" pathname_start " );
1030
1058
line4.append (std::to_string (components.pathname_start ));
1059
+ answer.append (line4);
1060
+ answer.append (" \n " );
1031
1061
}
1032
- answer.append (line4);
1033
- answer.append (" \n " );
1062
+
1034
1063
1035
1064
std::string line5 = line1;
1036
1065
if (components.host_end != buffer.size ()) {
@@ -1042,9 +1071,10 @@ std::string url_aggregator::to_diagram() const {
1042
1071
}
1043
1072
line5.append (" host_end " );
1044
1073
line5.append (std::to_string (components.host_end ));
1074
+ answer.append (line5);
1075
+ answer.append (" \n " );
1045
1076
}
1046
- answer.append (line5);
1047
- answer.append (" \n " );
1077
+
1048
1078
1049
1079
std::string line6 = line1;
1050
1080
if (components.host_start != buffer.size ()) {
@@ -1056,9 +1086,10 @@ std::string url_aggregator::to_diagram() const {
1056
1086
}
1057
1087
line6.append (" host_start " );
1058
1088
line6.append (std::to_string (components.host_start ));
1089
+ answer.append (line6);
1090
+ answer.append (" \n " );
1059
1091
}
1060
- answer.append (line6);
1061
- answer.append (" \n " );
1092
+
1062
1093
1063
1094
std::string line7 = line1;
1064
1095
if (components.username_end != buffer.size ()) {
@@ -1070,9 +1101,10 @@ std::string url_aggregator::to_diagram() const {
1070
1101
}
1071
1102
line7.append (" username_end " );
1072
1103
line7.append (std::to_string (components.username_end ));
1104
+ answer.append (line7);
1105
+ answer.append (" \n " );
1073
1106
}
1074
- answer.append (line7);
1075
- answer.append (" \n " );
1107
+
1076
1108
1077
1109
std::string line8 = line1;
1078
1110
if (components.protocol_end != buffer.size ()) {
@@ -1084,9 +1116,10 @@ std::string url_aggregator::to_diagram() const {
1084
1116
}
1085
1117
line8.append (" protocol_end " );
1086
1118
line8.append (std::to_string (components.protocol_end ));
1119
+ answer.append (line8);
1120
+ answer.append (" \n " );
1087
1121
}
1088
- answer.append (line8);
1089
- answer.append (" \n " );
1122
+
1090
1123
1091
1124
if (components.hash_start == url_components::omitted) {
1092
1125
answer.append (" note: hash omitted\n " );
0 commit comments