AK: Add LexicalPath::is_child_of

This API checks whether this path is a child of (or the same as) another
path.
This commit is contained in:
kleines Filmröllchen 2022-06-24 00:40:21 +02:00 committed by Linus Groh
parent 4625f7aab5
commit 16ca41ec10
Notes: sideshowbarker 2024-07-17 03:27:13 +09:00
3 changed files with 58 additions and 0 deletions

View file

@ -72,6 +72,22 @@ bool LexicalPath::has_extension(StringView extension) const
return m_string.ends_with(extension, CaseSensitivity::CaseInsensitive);
}
bool LexicalPath::is_child_of(LexicalPath const& possible_parent) const
{
// Any relative path is a child of an absolute path.
if (!this->is_absolute() && possible_parent.is_absolute())
return true;
// An absolute path can't meaningfully be a child of a relative path.
if (this->is_absolute() && !possible_parent.is_absolute())
return false;
// Two relative paths and two absolute paths can be meaningfully compared.
if (possible_parent.parts_view().size() > this->parts_view().size())
return false;
auto common_parts_with_parent = this->parts_view().span().trim(possible_parent.parts_view().size());
return common_parts_with_parent == possible_parent.parts_view().span();
}
DeprecatedString LexicalPath::canonicalized_path(DeprecatedString path)
{
if (path.is_null())

View file

@ -33,6 +33,7 @@ public:
[[nodiscard]] Vector<DeprecatedString> parts() const;
bool has_extension(StringView) const;
bool is_child_of(LexicalPath const& possible_parent) const;
[[nodiscard]] LexicalPath append(StringView) const;
[[nodiscard]] LexicalPath prepend(StringView) const;

View file

@ -208,3 +208,44 @@ TEST_CASE(parent)
EXPECT_EQ(parent.string(), "/");
}
}
TEST_CASE(is_child_of)
{
{
LexicalPath parent("/a/parent/directory");
LexicalPath child("/a/parent/directory/a/child");
LexicalPath mismatching("/not/a/child/directory");
EXPECT(child.is_child_of(parent));
EXPECT(child.is_child_of(child));
EXPECT(parent.is_child_of(parent));
EXPECT(!parent.is_child_of(child));
EXPECT(!mismatching.is_child_of(parent));
EXPECT(parent.is_child_of(parent.parent()));
EXPECT(child.parent().parent().is_child_of(parent));
EXPECT(!child.parent().parent().parent().is_child_of(parent));
}
{
LexicalPath root("/");
EXPECT(LexicalPath("/").is_child_of(root));
EXPECT(LexicalPath("/any").is_child_of(root));
EXPECT(LexicalPath("/child/directory").is_child_of(root));
}
{
LexicalPath relative("folder");
LexicalPath relative_child("folder/sub");
LexicalPath absolute("/folder");
LexicalPath absolute_child("/folder/sub");
EXPECT(relative_child.is_child_of(relative));
EXPECT(absolute_child.is_child_of(absolute));
EXPECT(relative.is_child_of(absolute));
EXPECT(relative.is_child_of(absolute_child));
EXPECT(relative_child.is_child_of(absolute));
EXPECT(relative_child.is_child_of(absolute_child));
EXPECT(!absolute.is_child_of(relative));
EXPECT(!absolute_child.is_child_of(relative));
EXPECT(!absolute_child.is_child_of(relative_child));
}
}