Merge pull request #251 from vibe-d/path_opt

InetPath optimization
This commit is contained in:
Leonid Kramer 2021-01-20 15:04:39 +01:00 committed by GitHub
commit 38a50dde8e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -333,7 +333,7 @@ struct GenericPath(F) {
if (m_path.length) { if (m_path.length) {
auto ap = Format.getAbsolutePrefix(m_path); auto ap = Format.getAbsolutePrefix(m_path);
if (ap.length && !Format.isSeparator(ap[0])) if (ap.length && !Format.isSeparator(ap[0]))
m_front = Segment.fromTrustedString(null, '/'); m_front = Segment.fromTrustedString(null, Format.defaultSeparator);
else readFront(); else readFront();
} }
} }
@ -677,7 +677,7 @@ struct GenericPath(F) {
if (m_path.length) { if (m_path.length) {
auto ap = Format.getAbsolutePrefix(m_path); auto ap = Format.getAbsolutePrefix(m_path);
if (ap.length && !Format.isSeparator(ap[0])) if (ap.length && !Format.isSeparator(ap[0]))
m_front = Segment2.fromTrustedEncodedString(null, '/'); m_front = Segment2.fromTrustedEncodedString(null, Format.defaultSeparator);
else readFront(); else readFront();
} }
} }
@ -1303,8 +1303,7 @@ struct WindowsPathFormat {
static bool isSeparator(dchar ch) static bool isSeparator(dchar ch)
@nogc { @nogc {
import std.algorithm.comparison : among; return ch == '\\' || ch == '/';
return ch.among!('\\', '/') != 0;
} }
static string getAbsolutePrefix(string path) static string getAbsolutePrefix(string path)
@ -1736,13 +1735,13 @@ struct InetPathFormat {
static string validatePath(string path) static string validatePath(string path)
@nogc { @nogc {
for (size_t i = 0; i < path.length; i++) { for (size_t i = 0; i < path.length; i++) {
if (isAsciiAlphaNum(path[i]))
continue;
switch (path[i]) { switch (path[i]) {
default: default:
return "Invalid character in internet path."; return "Invalid character in internet path.";
// unreserved // unreserved
case 'A': .. case 'Z':
case 'a': .. case 'z':
case '0': .. case '9':
case '-', '.', '_', '~': case '-', '.', '_', '~':
// subdelims // subdelims
case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=': case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=':
@ -1881,15 +1880,13 @@ struct InetPathFormat {
import std.array : appender; import std.array : appender;
foreach (i, char c; segment) { foreach (i, char c; segment) {
if (isAsciiAlphaNum(c)) continue;
switch (c) { switch (c) {
default: default:
auto ret = appender!string; auto ret = appender!string;
ret.put(segment[0 .. i]); ret.put(segment[0 .. i]);
encodeSegment(ret, segment[i .. $]); encodeSegment(ret, segment[i .. $]);
return ret.data; return ret.data;
case 'a': .. case 'z':
case 'A': .. case 'Z':
case '0': .. case '9':
case '-', '.', '_', '~': case '-', '.', '_', '~':
case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=': case '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=':
case ':', '@': case ':', '@':
@ -2029,6 +2026,25 @@ unittest { // test range based path
assert(stripExtension(InetPath("foo.bar.txt").head2.name).equal("foo.bar")); assert(stripExtension(InetPath("foo.bar.txt").head2.name).equal("foo.bar"));
} }
private static bool isAsciiAlphaNum(char ch)
@safe nothrow pure @nogc {
return (uint(ch) & 0xDF) - 0x41 < 26 || uint(ch) - '0' <= 9;
}
unittest {
assert(!isAsciiAlphaNum('@'));
assert(isAsciiAlphaNum('A'));
assert(isAsciiAlphaNum('Z'));
assert(!isAsciiAlphaNum('['));
assert(!isAsciiAlphaNum('`'));
assert(isAsciiAlphaNum('a'));
assert(isAsciiAlphaNum('z'));
assert(!isAsciiAlphaNum('{'));
assert(!isAsciiAlphaNum('/'));
assert(isAsciiAlphaNum('0'));
assert(isAsciiAlphaNum('9'));
assert(!isAsciiAlphaNum(':'));
}
unittest { // regression tests unittest { // regression tests
assert(NativePath("").bySegment.empty); assert(NativePath("").bySegment.empty);