Commit 47e755eb authored by Kenton Varda's avatar Kenton Varda

Add comparison operators and {starts,ends}With() to kj::Path.

parent ac10f36b
......@@ -86,6 +86,47 @@ KJ_TEST("Path") {
KJ_EXPECT(kj::str(Path({"foo", "bar"})) == "foo/bar");
}
KJ_TEST("Path comparisons") {
KJ_EXPECT(Path({"foo", "bar"}) == Path({"foo", "bar"}));
KJ_EXPECT(!(Path({"foo", "bar"}) != Path({"foo", "bar"})));
KJ_EXPECT(Path({"foo", "bar"}) != Path({"foo", "baz"}));
KJ_EXPECT(!(Path({"foo", "bar"}) == Path({"foo", "baz"})));
KJ_EXPECT(Path({"foo", "bar"}) != Path({"fob", "bar"}));
KJ_EXPECT(Path({"foo", "bar"}) != Path({"foo", "bar", "baz"}));
KJ_EXPECT(Path({"foo", "bar", "baz"}) != Path({"foo", "bar"}));
KJ_EXPECT(Path({"foo", "bar"}) <= Path({"foo", "bar"}));
KJ_EXPECT(Path({"foo", "bar"}) >= Path({"foo", "bar"}));
KJ_EXPECT(!(Path({"foo", "bar"}) < Path({"foo", "bar"})));
KJ_EXPECT(!(Path({"foo", "bar"}) > Path({"foo", "bar"})));
KJ_EXPECT(Path({"foo", "bar"}) < Path({"foo", "bar", "baz"}));
KJ_EXPECT(!(Path({"foo", "bar"}) > Path({"foo", "bar", "baz"})));
KJ_EXPECT(Path({"foo", "bar", "baz"}) > Path({"foo", "bar"}));
KJ_EXPECT(!(Path({"foo", "bar", "baz"}) < Path({"foo", "bar"})));
KJ_EXPECT(Path({"foo", "bar"}) < Path({"foo", "baz"}));
KJ_EXPECT(Path({"foo", "bar"}) > Path({"foo", "baa"}));
KJ_EXPECT(Path({"foo", "bar"}) > Path({"foo"}));
KJ_EXPECT(Path({"foo", "bar"}).startsWith(Path({})));
KJ_EXPECT(Path({"foo", "bar"}).startsWith(Path({"foo"})));
KJ_EXPECT(Path({"foo", "bar"}).startsWith(Path({"foo", "bar"})));
KJ_EXPECT(!Path({"foo", "bar"}).startsWith(Path({"foo", "bar", "baz"})));
KJ_EXPECT(!Path({"foo", "bar"}).startsWith(Path({"foo", "baz"})));
KJ_EXPECT(!Path({"foo", "bar"}).startsWith(Path({"baz", "foo", "bar"})));
KJ_EXPECT(!Path({"foo", "bar"}).startsWith(Path({"baz"})));
KJ_EXPECT(Path({"foo", "bar"}).endsWith(Path({})));
KJ_EXPECT(Path({"foo", "bar"}).endsWith(Path({"bar"})));
KJ_EXPECT(Path({"foo", "bar"}).endsWith(Path({"foo", "bar"})));
KJ_EXPECT(!Path({"foo", "bar"}).endsWith(Path({"baz", "foo", "bar"})));
KJ_EXPECT(!Path({"foo", "bar"}).endsWith(Path({"fob", "bar"})));
KJ_EXPECT(!Path({"foo", "bar"}).endsWith(Path({"foo", "bar", "baz"})));
KJ_EXPECT(!Path({"foo", "bar"}).endsWith(Path({"baz"})));
}
KJ_TEST("Path exceptions") {
KJ_EXPECT_THROW_MESSAGE("invalid path component", Path(""));
KJ_EXPECT_THROW_MESSAGE("invalid path component", Path("."));
......
......@@ -155,6 +155,29 @@ Path Path::slice(size_t start, size_t end) && {
return Path(KJ_MAP(p, parts.slice(start, end)) { return kj::mv(p); });
}
bool PathPtr::operator==(PathPtr other) const {
return parts == other.parts;
}
bool PathPtr::operator< (PathPtr other) const {
for (size_t i = 0; i < kj::min(parts.size(), other.parts.size()); i++) {
int comp = strcmp(parts[i].cStr(), other.parts[i].cStr());
if (comp < 0) return true;
if (comp > 0) return false;
}
return parts.size() < other.parts.size();
}
bool PathPtr::startsWith(PathPtr prefix) const {
return parts.size() >= prefix.parts.size() &&
parts.slice(0, prefix.parts.size()) == prefix.parts;
}
bool PathPtr::endsWith(PathPtr suffix) const {
return parts.size() >= suffix.parts.size() &&
parts.slice(parts.size() - suffix.parts.size(), parts.size()) == suffix.parts;
}
Path PathPtr::evalWin32(StringPtr pathText) const {
Vector<String> newParts(parts.size() + Path::countPartsWin32(pathText));
for (auto& p: parts) newParts.add(heapString(p));
......
......@@ -149,6 +149,18 @@ public:
Path slice(size_t start, size_t end) &&;
// A Path can be accessed as an array of strings.
bool operator==(PathPtr other) const;
bool operator!=(PathPtr other) const;
bool operator< (PathPtr other) const;
bool operator> (PathPtr other) const;
bool operator<=(PathPtr other) const;
bool operator>=(PathPtr other) const;
// Compare path components lexically.
bool startsWith(PathPtr prefix) const;
bool endsWith(PathPtr suffix) const;
// Compare prefix / suffix.
Path evalWin32(StringPtr pathText) const&;
Path evalWin32(StringPtr pathText) &&;
// Evaluates a Win32-style path, as might be written by a user. Differences from `eval()`
......@@ -236,6 +248,14 @@ public:
const String* begin() const;
const String* end() const;
PathPtr slice(size_t start, size_t end) const;
bool operator==(PathPtr other) const;
bool operator!=(PathPtr other) const;
bool operator< (PathPtr other) const;
bool operator> (PathPtr other) const;
bool operator<=(PathPtr other) const;
bool operator>=(PathPtr other) const;
bool startsWith(PathPtr prefix) const;
bool endsWith(PathPtr suffix) const;
Path evalWin32(StringPtr pathText) const;
String toWin32String(bool absolute = false) const;
Array<wchar_t> forWin32Api(bool absolute) const;
......@@ -927,6 +947,14 @@ inline const String* Path::end() const { return parts.end(); }
inline PathPtr Path::slice(size_t start, size_t end) const& {
return PathPtr(*this).slice(start, end);
}
inline bool Path::operator==(PathPtr other) const { return PathPtr(*this) == other; }
inline bool Path::operator!=(PathPtr other) const { return PathPtr(*this) != other; }
inline bool Path::operator< (PathPtr other) const { return PathPtr(*this) < other; }
inline bool Path::operator> (PathPtr other) const { return PathPtr(*this) > other; }
inline bool Path::operator<=(PathPtr other) const { return PathPtr(*this) <= other; }
inline bool Path::operator>=(PathPtr other) const { return PathPtr(*this) >= other; }
inline bool Path::startsWith(PathPtr prefix) const { return PathPtr(*this).startsWith(prefix); }
inline bool Path::endsWith (PathPtr suffix) const { return PathPtr(*this).endsWith (suffix); }
inline String Path::toString(bool absolute) const { return PathPtr(*this).toString(absolute); }
inline Path Path::evalWin32(StringPtr pathText) const& {
return PathPtr(*this).evalWin32(pathText);
......@@ -950,6 +978,10 @@ inline const String* PathPtr::end() const { return parts.end(); }
inline PathPtr PathPtr::slice(size_t start, size_t end) const {
return PathPtr(parts.slice(start, end));
}
inline bool PathPtr::operator!=(PathPtr other) const { return !(*this == other); }
inline bool PathPtr::operator> (PathPtr other) const { return other < *this; }
inline bool PathPtr::operator<=(PathPtr other) const { return !(other < *this); }
inline bool PathPtr::operator>=(PathPtr other) const { return !(*this < other); }
inline String PathPtr::toWin32String(bool absolute) const {
return toWin32StringImpl(absolute, false);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment