Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
4f6dd96
test,doc: do not indicate that non-functions "return" values
Trott Nov 22, 2017
b8a5d6d
tools: remove useless function declaration
tniessen Nov 18, 2017
1d70602
tools: make doc tool a bit more readable
tniessen Nov 18, 2017
ef0213c
doc: move Code of Conduct to admin repo
MylesBorins Oct 23, 2017
b6ce918
stream: fix disparity between buffer and the count
jlvivero Sep 28, 2017
521dc25
tls: properly track writeQueueSize during writes
apapirovski Oct 5, 2017
a301c1a
net: fix timeouts during long writes
apapirovski Oct 12, 2017
a09e2fd
net: fix timeout with null handle
apapirovski Oct 25, 2017
00b2790
tls: accept `lookup` option for `tls.connect()`
indutny May 4, 2017
7af1ad0
util: add %i and %f formatting specifiers
silverwind Dec 16, 2016
6f62f83
crypto: add randomFill and randomFillSync
evanlucas Dec 9, 2016
43a2bc0
doc: improve randomfill and fix broken link
thefourtheye Apr 20, 2017
063c4fa
lib: return this from net.Socket.end()
sam-github Jun 5, 2017
6a27774
net: return this from getConnections()
sam-github Jun 7, 2017
3b9fea0
repl: improve require() autocompletion
aqrln Jul 21, 2017
ce13639
console: add console.count() and console.clear()
jasnell Apr 26, 2017
8f2e52a
dgram: added setMulticastInterface()
lostnet Jul 23, 2016
7b801b5
test: don't skip when common.mustCall() is pending
cjihrig Sep 14, 2017
d29a620
test: crypto createClass instanceof Class
bengl Aug 19, 2016
f3b3437
crypto: expose ECDH class
bengl Aug 19, 2016
365dba2
test: fix flaky test-crypto-classes.js
bengl Sep 28, 2017
18803bc
tools, build: refactor macOS installer
jpwesselink Sep 4, 2017
a1d7469
deps: upgrade libuv to 1.16.1
cjihrig Nov 10, 2017
2d4fca2
src: add process.ppid
cjihrig Oct 30, 2017
758dc81
src: add --use-bundled-ca --use-openssl-ca check
danbev Mar 28, 2017
2b29cea
src: guard bundled_ca/openssl_ca with HAVE_OPENSSL
danbev Apr 10, 2017
9f3b4ad
src: fix incorrect macro comment
danbev Apr 27, 2017
ddd9d85
crypto: remove BIO_set_shutdown
danbev Dec 7, 2017
a6d2384
src: clean up MaybeStackBuffer
TimothyGu Nov 28, 2017
699c663
test: add common.hasIntl
jasnell Oct 23, 2016
60b10f0
url: update IDNA handling
TimothyGu Jun 1, 2017
24def19
url: adding WHATWG URL support
jasnell Nov 28, 2017
c64a73b
promises: more robust stringification
TimothyGu Jun 19, 2017
5f79448
test: fix truncation of argv
danbev Mar 29, 2017
1390c28
http: overridable keep-alive behavior of `Agent`
indutny Jan 15, 2018
2268d00
src: add openssl-system-ca-path configure option
danbev Nov 6, 2017
cdf4a9c
module: add builtinModules
maclover7 Nov 24, 2017
b3b2456
test: add test description to fs.readFile tests
davisjam Dec 7, 2017
83fe79c
doc: correct pbkdf2 salt length recommendation
willclarktech Dec 7, 2017
fb0bd8a
test: fix flaky test-child-process-pass-fd
Trott Dec 11, 2017
7821a4c
tools: add lowercase-name-for-primitive eslint rule
starkwang Dec 9, 2017
af3e074
test: add `makeDuplexPair()` helper
addaleax Oct 22, 2017
56e1586
tls: unconsume stream on destroy
addaleax Dec 6, 2017
1eac405
doc: include Daniel Bevenius as a TSC member
Trott Dec 13, 2017
928b7c8
tools: simplify lowercase-name-for-primitive rule
cjihrig Dec 13, 2017
2d77241
test: change callback function to arrow function
skanamaru Dec 15, 2017
81e6569
test: change callback function to arrow function
you12724 Dec 15, 2017
cc03470
test: change callback function to arrow function
routerman Dec 15, 2017
d0b89a1
doc: add countdown module to writing tests guide
Bamieh Dec 12, 2017
31c5db6
test: update test-http-content-length to use countdown
Bamieh Dec 12, 2017
bdb535c
test: Use countdown in test file
sreepurnajasti Dec 13, 2017
6abd459
doc: improve documentation.md
Fishrock123 Dec 15, 2017
9c8d036
doc: fix fs.existsSync description
Fishrock123 Dec 15, 2017
14ffddd
doc: add isTTY property documentation
sonaysevik Nov 6, 2017
c683efb
doc: adjust TTY wording & add inter-doc links
Fishrock123 Dec 15, 2017
423ef3d
doc: not all example code can be run without 1:1
Fishrock123 Dec 15, 2017
4cba432
doc: improve release guide
evanlucas Dec 14, 2017
df48a5d
doc: fix typo in child_process.md
Trott Dec 18, 2017
a6f7ba4
doc: fix typo in README.md
starkwang Dec 18, 2017
5cc6dd6
doc: remove duplicate the from onboarding.md
sreepurnajasti Dec 18, 2017
979af51
src: remove nonexistent method from header file
addaleax Dec 19, 2017
cb78543
test: change callback function to arrow function
rt33 Dec 18, 2017
c377d22
crypto: remove unused header in clienthello.h
danbev Dec 19, 2017
ffc1444
net: remove ADDRCONFIG DNS hint on Windows
bzoz Dec 13, 2017
d85840d
doc: require CI status indicator in PRs
seishun Nov 20, 2017
2260795
doc: use american spelling as per style guide
sreepurnajasti Dec 22, 2017
1553c73
doc: removed extra explanation in api/buffer.md
WaleedAshraf Dec 20, 2017
a08925d
tls: comment about old-style errors
Xavier-J-Ortiz Dec 19, 2017
f291bc1
test: refactor test-repl-definecommand
Trott Dec 20, 2017
722640f
doc: instructions on how to make membership public
mhdawson Dec 14, 2017
6816414
doc: improve fs api descriptions
evanlucas Dec 14, 2017
5314754
test: use common module API in test-child-process-exec-stdout-stderr-…
sreepurnajasti Dec 19, 2017
653c026
doc: add starkwang to collaborators
starkwang Dec 24, 2017
038e526
test: remove undefined function
Trott Dec 23, 2017
6187aec
tools: autofixer for lowercase-name-for-primitive
shobhitchittora Dec 17, 2017
f6b4aa6
doc: update AUTHORS list
BridgeAR Dec 21, 2017
0ce48f9
doc: use dashes instead of asterisks
BridgeAR Dec 17, 2017
32f528a
tools: fix AttributeError: __exit__ on Python 2.6
dkasyanov Dec 13, 2017
b3e625d
test: refactor test-tls-securepair-fiftharg
addaleax Dec 23, 2017
4b4e4db
crypto: add ocsp_request ClientHelloParser::Reset
danbev Dec 11, 2017
8c1f41f
test: make test-tls-invoke-queued use public API
addaleax Dec 25, 2017
5b00ee3
doc: use my legal name in README
TimothyGu Dec 28, 2017
3c3a631
doc: fix typo
tniessen Dec 28, 2017
2c554a9
test: improve to use template string
sreepurnajasti Dec 28, 2017
e16d01f
gitignore: ignore *.VC.db files
tniessen Dec 28, 2017
21c5d82
doc: add references to PR communication articles
Dec 28, 2017
bb022db
doc: fix spelling of contributors
Trott Dec 31, 2017
7628640
doc: improve alt text
Trott Dec 31, 2017
b79189b
doc: copy-edit COLLABORATOR_GUIDE.md
Trott Dec 31, 2017
12db4d9
doc: improve security section of README.md
Trott Jan 1, 2018
15d0ed5
doc: move joshgav to TSC emeriti list
Trott Jan 2, 2018
6f33953
benchmark: fix timeout in write-stream-throughput
apapirovski Jan 3, 2018
1c4aa61
test: simplify test-buffer-slice.js
starkwang Jan 3, 2018
9e76028
test: fix crypto test case to use correct encoding
tniessen Jan 2, 2018
0c3f23e
test: fix flaky test-pipe-unref
apapirovski Jan 2, 2018
001b672
test: rename regression tests
tniessen Jan 2, 2018
4473c6c
test: fix flaky test-http-pipeline-flood
apapirovski Jan 3, 2018
8f80548
doc: move matthewloring to emeriti
Trott Jan 5, 2018
51bfd32
tools: do not override V8's gitignore
hashseed Jan 5, 2018
1b68986
doc: remove x86 from os.arch() options
gibfahn Dec 28, 2017
d66f469
src: minor cleanups to node_url.cc
addaleax Dec 5, 2017
1976c7c
src: move url internals into anonymous namespace
addaleax Dec 5, 2017
f306d3e
src: make url host a proper C++ class
addaleax Dec 5, 2017
57865a9
src: use correct OOB check for IPv6 parsing
addaleax Dec 5, 2017
9181fbb
src: dumb down code by removing std::move
addaleax Jan 23, 2018
fce10f7
test: fix test-tls-server-verify.js on Windows CI
Trott Jan 25, 2018
5668403
test: improve flaky test-listen-fd-ebadf.js
Trott Dec 20, 2017
694828d
test: mark test-inspector-stop-profile-after-done flaky
MylesBorins Feb 1, 2018
734ce67
test: use valid authentication tag length
tniessen Dec 9, 2017
691cd5a
crypto: warn on invalid authentication tag length
tniessen Dec 9, 2017
a4e2ced
test: decrease duration of test-cli-syntax
evanlucas Jul 12, 2017
f82065f
test: make test-cli-syntax engine agnostic
Trott Oct 17, 2017
9441526
2018-01-13, Version 6.13.0 'Boron' (LTS)
MylesBorins Jan 24, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
src: move url internals into anonymous namespace
This helps because `static` doesn’t work for C++ classes,
but refactoring `url_host` into a proper C++ class seems the
most reasonable soluation for the memory leak fixed by the next commit.

Backport-PR-URL: #18324
PR-URL: #17470
Reviewed-By: Timothy Gu <timothygu99@gmail.com>
  • Loading branch information
addaleax authored and MylesBorins committed Feb 13, 2018
commit 1976c7c7a5f8b38ade0b39937604114f6055d6d0
117 changes: 58 additions & 59 deletions src/node_url.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ using v8::Value;

namespace url {

namespace {

// https://url.spec.whatwg.org/#eof-code-point
static const char kEOL = -1;
const char kEOL = -1;

// Used in ToUSVString().
static const char16_t kUnicodeReplacementCharacter = 0xFFFD;
const char16_t kUnicodeReplacementCharacter = 0xFFFD;

// https://url.spec.whatwg.org/#concept-host
union url_host_value {
Expand Down Expand Up @@ -103,21 +105,21 @@ enum url_error_cb_args {

#define CHAR_TEST(bits, name, expr) \
template <typename T> \
static inline bool name(const T ch) { \
inline bool name(const T ch) { \
static_assert(sizeof(ch) >= (bits) / 8, \
"Character must be wider than " #bits " bits"); \
return (expr); \
}

#define TWO_CHAR_STRING_TEST(bits, name, expr) \
template <typename T> \
static inline bool name(const T ch1, const T ch2) { \
inline bool name(const T ch1, const T ch2) { \
static_assert(sizeof(ch1) >= (bits) / 8, \
"Character must be wider than " #bits " bits"); \
return (expr); \
} \
template <typename T> \
static inline bool name(const std::basic_string<T>& str) { \
inline bool name(const std::basic_string<T>& str) { \
static_assert(sizeof(str[0]) >= (bits) / 8, \
"Character must be wider than " #bits " bits"); \
return str.length() >= 2 && name(str[0], str[1]); \
Expand Down Expand Up @@ -146,7 +148,7 @@ CHAR_TEST(8, IsASCIIAlphanumeric, (IsASCIIDigit(ch) || IsASCIIAlpha(ch)))

// https://infra.spec.whatwg.org/#ascii-lowercase
template <typename T>
static inline T ASCIILowercase(T ch) {
inline T ASCIILowercase(T ch) {
return IsASCIIAlpha(ch) ? (ch | 0x20) : ch;
}

Expand Down Expand Up @@ -177,7 +179,7 @@ CHAR_TEST(16, IsUnicodeSurrogateTrail, (ch & 0x400) != 0)
#undef CHAR_TEST
#undef TWO_CHAR_STRING_TEST

static const char* hex[256] = {
const char* hex[256] = {
"%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
"%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F",
"%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
Expand Down Expand Up @@ -212,7 +214,7 @@ static const char* hex[256] = {
"%F8", "%F9", "%FA", "%FB", "%FC", "%FD", "%FE", "%FF"
};

static const uint8_t C0_CONTROL_ENCODE_SET[32] = {
const uint8_t C0_CONTROL_ENCODE_SET[32] = {
// 00 01 02 03 04 05 06 07
0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
// 08 09 0A 0B 0C 0D 0E 0F
Expand Down Expand Up @@ -279,7 +281,7 @@ static const uint8_t C0_CONTROL_ENCODE_SET[32] = {
0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80
};

static const uint8_t PATH_ENCODE_SET[32] = {
const uint8_t PATH_ENCODE_SET[32] = {
// 00 01 02 03 04 05 06 07
0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
// 08 09 0A 0B 0C 0D 0E 0F
Expand Down Expand Up @@ -346,7 +348,7 @@ static const uint8_t PATH_ENCODE_SET[32] = {
0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80
};

static const uint8_t USERINFO_ENCODE_SET[32] = {
const uint8_t USERINFO_ENCODE_SET[32] = {
// 00 01 02 03 04 05 06 07
0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
// 08 09 0A 0B 0C 0D 0E 0F
Expand Down Expand Up @@ -413,7 +415,7 @@ static const uint8_t USERINFO_ENCODE_SET[32] = {
0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80
};

static const uint8_t QUERY_ENCODE_SET[32] = {
const uint8_t QUERY_ENCODE_SET[32] = {
// 00 01 02 03 04 05 06 07
0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80,
// 08 09 0A 0B 0C 0D 0E 0F
Expand Down Expand Up @@ -480,23 +482,23 @@ static const uint8_t QUERY_ENCODE_SET[32] = {
0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80
};

static inline bool BitAt(const uint8_t a[], const uint8_t i) {
inline bool BitAt(const uint8_t a[], const uint8_t i) {
return !!(a[i >> 3] & (1 << (i & 7)));
}

// Appends ch to str. If ch position in encode_set is set, the ch will
// be percent-encoded then appended.
static inline void AppendOrEscape(std::string* str,
const unsigned char ch,
const uint8_t encode_set[]) {
inline void AppendOrEscape(std::string* str,
const unsigned char ch,
const uint8_t encode_set[]) {
if (BitAt(encode_set, ch))
*str += hex[ch];
else
*str += ch;
}

template <typename T>
static inline unsigned hex2bin(const T ch) {
inline unsigned hex2bin(const T ch) {
if (ch >= '0' && ch <= '9')
return ch - '0';
if (ch >= 'A' && ch <= 'F')
Expand Down Expand Up @@ -544,16 +546,15 @@ inline std::string PercentDecode(const char* input, size_t len) {
XX("ws:", 80) \
XX("wss:", 443)

static inline bool IsSpecial(std::string scheme) {
inline bool IsSpecial(std::string scheme) {
#define XX(name, _) if (scheme == name) return true;
SPECIALS(XX);
#undef XX
return false;
}

// https://url.spec.whatwg.org/#start-with-a-windows-drive-letter
static inline bool StartsWithWindowsDriveLetter(const char* p,
const char* end) {
inline bool StartsWithWindowsDriveLetter(const char* p, const char* end) {
const size_t length = end - p;
return length >= 2 &&
IsWindowsDriveLetter(p[0], p[1]) &&
Expand All @@ -564,23 +565,23 @@ static inline bool StartsWithWindowsDriveLetter(const char* p,
p[2] == '#');
}

static inline int NormalizePort(std::string scheme, int p) {
inline int NormalizePort(std::string scheme, int p) {
#define XX(name, port) if (scheme == name && p == port) return -1;
SPECIALS(XX);
#undef XX
return p;
}

#if defined(NODE_HAVE_I18N_SUPPORT)
static inline bool ToUnicode(const std::string& input, std::string* output) {
inline bool ToUnicode(const std::string& input, std::string* output) {
MaybeStackBuffer<char> buf;
if (i18n::ToUnicode(&buf, input.c_str(), input.length()) < 0)
return false;
output->assign(*buf, buf.length());
return true;
}

static inline bool ToASCII(const std::string& input, std::string* output) {
inline bool ToASCII(const std::string& input, std::string* output) {
MaybeStackBuffer<char> buf;
if (i18n::ToASCII(&buf, input.c_str(), input.length()) < 0)
return false;
Expand All @@ -589,20 +590,18 @@ static inline bool ToASCII(const std::string& input, std::string* output) {
}
#else
// Intentional non-ops if ICU is not present.
static inline bool ToUnicode(const std::string& input, std::string* output) {
inline bool ToUnicode(const std::string& input, std::string* output) {
*output = input;
return true;
}

static inline bool ToASCII(const std::string& input, std::string* output) {
inline bool ToASCII(const std::string& input, std::string* output) {
*output = input;
return true;
}
#endif

static url_host_type ParseIPv6Host(url_host* host,
const char* input,
size_t length) {
url_host_type ParseIPv6Host(url_host* host, const char* input, size_t length) {
url_host_type type = HOST_TYPE_FAILED;
for (unsigned n = 0; n < 8; n++)
host->value.ipv6[n] = 0;
Expand Down Expand Up @@ -720,7 +719,7 @@ static url_host_type ParseIPv6Host(url_host* host,
return type;
}

static inline int64_t ParseNumber(const char* start, const char* end) {
inline int64_t ParseNumber(const char* start, const char* end) {
unsigned R = 10;
if (end - start >= 2 && start[0] == '0' && (start[1] | 0x20) == 'x') {
start += 2;
Expand Down Expand Up @@ -755,9 +754,7 @@ static inline int64_t ParseNumber(const char* start, const char* end) {
return strtoll(start, NULL, R);
}

static url_host_type ParseIPv4Host(url_host* host,
const char* input,
size_t length) {
url_host_type ParseIPv4Host(url_host* host, const char* input, size_t length) {
url_host_type type = HOST_TYPE_DOMAIN;
const char* pointer = input;
const char* mark = input;
Expand Down Expand Up @@ -816,9 +813,9 @@ static url_host_type ParseIPv4Host(url_host* host,
return type;
}

static url_host_type ParseOpaqueHost(url_host* host,
const char* input,
size_t length) {
url_host_type ParseOpaqueHost(url_host* host,
const char* input,
size_t length) {
url_host_type type = HOST_TYPE_OPAQUE;
std::string output;
output.reserve(length * 3);
Expand All @@ -838,11 +835,11 @@ static url_host_type ParseOpaqueHost(url_host* host,
return type;
}

static url_host_type ParseHost(url_host* host,
const char* input,
size_t length,
bool is_special,
bool unicode = false) {
url_host_type ParseHost(url_host* host,
const char* input,
size_t length,
bool is_special,
bool unicode = false) {
url_host_type type = HOST_TYPE_FAILED;
const char* pointer = input;
std::string decoded;
Expand Down Expand Up @@ -895,7 +892,7 @@ static url_host_type ParseHost(url_host* host,
// Locates the longest sequence of 0 segments in an IPv6 address
// in order to use the :: compression when serializing
template<typename T>
static inline T* FindLongestZeroSequence(T* values, size_t len) {
inline T* FindLongestZeroSequence(T* values, size_t len) {
T* start = values;
T* end = start + len;
T* result = nullptr;
Expand Down Expand Up @@ -923,7 +920,7 @@ static inline T* FindLongestZeroSequence(T* values, size_t len) {
return result;
}

static url_host_type WriteHost(const url_host* host, std::string* dest) {
url_host_type WriteHost(const url_host* host, std::string* dest) {
dest->clear();
switch (host->type) {
case HOST_TYPE_DOMAIN:
Expand Down Expand Up @@ -978,10 +975,10 @@ static url_host_type WriteHost(const url_host* host, std::string* dest) {
return host->type;
}

static bool ParseHost(const std::string& input,
std::string* output,
bool is_special,
bool unicode = false) {
bool ParseHost(const std::string& input,
std::string* output,
bool is_special,
bool unicode = false) {
if (input.length() == 0) {
output->clear();
return true;
Expand All @@ -994,9 +991,9 @@ static bool ParseHost(const std::string& input,
return true;
}

static inline void Copy(Environment* env,
Local<Array> ary,
std::vector<std::string>* vec) {
inline void Copy(Environment* env,
Local<Array> ary,
std::vector<std::string>* vec) {
const int32_t len = ary->Length();
if (len == 0)
return; // nothing to copy
Expand All @@ -1010,18 +1007,18 @@ static inline void Copy(Environment* env,
}
}

static inline Local<Array> Copy(Environment* env,
const std::vector<std::string>& vec) {
inline Local<Array> Copy(Environment* env,
const std::vector<std::string>& vec) {
Isolate* isolate = env->isolate();
Local<Array> ary = Array::New(isolate, vec.size());
for (size_t n = 0; n < vec.size(); n++)
ary->Set(env->context(), n, UTF8STRING(isolate, vec[n])).FromJust();
return ary;
}

static inline void HarvestBase(Environment* env,
struct url_data* base,
Local<Object> base_obj) {
inline void HarvestBase(Environment* env,
struct url_data* base,
Local<Object> base_obj) {
Local<Context> context = env->context();
Local<Value> flags = GET(env, base_obj, "flags");
if (flags->IsInt32())
Expand All @@ -1045,9 +1042,9 @@ static inline void HarvestBase(Environment* env,
}
}

static inline void HarvestContext(Environment* env,
struct url_data* context,
Local<Object> context_obj) {
inline void HarvestContext(Environment* env,
struct url_data* context,
Local<Object> context_obj) {
Local<Value> flags = GET(env, context_obj, "flags");
if (flags->IsInt32()) {
int32_t _flags = flags->Int32Value(env->context()).FromJust();
Expand Down Expand Up @@ -1090,7 +1087,7 @@ static inline void HarvestContext(Environment* env,
}

// Single dot segment can be ".", "%2e", or "%2E"
static inline bool IsSingleDotSegment(const std::string& str) {
inline bool IsSingleDotSegment(const std::string& str) {
switch (str.size()) {
case 1:
return str == ".";
Expand All @@ -1106,7 +1103,7 @@ static inline bool IsSingleDotSegment(const std::string& str) {
// Double dot segment can be:
// "..", ".%2e", ".%2E", "%2e.", "%2E.",
// "%2e%2e", "%2E%2E", "%2e%2E", or "%2E%2e"
static inline bool IsDoubleDotSegment(const std::string& str) {
inline bool IsDoubleDotSegment(const std::string& str) {
switch (str.size()) {
case 2:
return str == "..";
Expand All @@ -1133,13 +1130,15 @@ static inline bool IsDoubleDotSegment(const std::string& str) {
}
}

static inline void ShortenUrlPath(struct url_data* url) {
inline void ShortenUrlPath(struct url_data* url) {
if (url->path.empty()) return;
if (url->path.size() == 1 && url->scheme == "file:" &&
IsNormalizedWindowsDriveLetter(url->path[0])) return;
url->path.pop_back();
}

} // anonymous namespace

void URL::Parse(const char* input,
size_t len,
enum url_parse_state state_override,
Expand Down