1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 05:25:09 +00:00
serenity/Kernel/KLexicalPath.cpp
Max Wipfli 87a62f4def Kernel: Add KLexicalPath
This adds KLexicalPath, which are a few static functions which aim to
mostly emulate AK::LexicalPath. They are however constrained to work
with absolute paths only, containing no '.' or '..' path segments and no
consecutive slashes. This way, it is possible to avoid use StringView
for the return values and thus avoid allocating new String objects.

As explained above, the functions are currently very strict about the
allowed input paths. This seems to not be a problem currently. Since the
functions VERIFY this, potential bugs caused by this will become
immediately obvious.
2021-07-07 15:32:17 +02:00

58 lines
1.4 KiB
C++

/*
* Copyright (c) 2021, Max Wipfli <max.wipfli@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <Kernel/KLexicalPath.h>
namespace Kernel::KLexicalPath {
bool is_absolute(StringView const& path)
{
return !path.is_empty() && path[0] == '/';
}
bool is_canonical(StringView const& path)
{
// FIXME: This can probably be done more efficiently.
if (path.is_empty())
return false;
if (path.ends_with('/') && path.length() != 1)
return false;
if (path.starts_with("./"sv) || path.contains("/./"sv) || path.ends_with("/."sv))
return false;
if (path.starts_with("../"sv) || path.contains("/../"sv) || path.ends_with("/.."))
return false;
if (path.contains("//"sv))
return false;
return true;
}
StringView basename(StringView const& path)
{
auto slash_index = path.find_last('/');
if (!slash_index.has_value()) {
VERIFY(!path.is_empty());
return path;
}
auto basename = path.substring_view(*slash_index + 1);
VERIFY(!basename.is_empty() && basename != "."sv && basename != ".."sv);
return basename;
}
StringView dirname(StringView const& path)
{
VERIFY(is_canonical(path));
auto slash_index = path.find_last('/');
VERIFY(slash_index.has_value());
return path.substring_view(0, *slash_index);
}
Vector<StringView> parts(StringView const& path)
{
VERIFY(is_canonical(path));
return path.split_view('/');
}
}