aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-06-01 20:31:57 +0200
committerFelix Morgner <felix.morgner@ost.ch>2026-06-02 16:30:20 +0200
commit6c8b068c15e28e91117f84cb8d5789f5fe6fcbd0 (patch)
tree9ded4e40fe8e7d3cf8c77d12d29dc7b45c123263
parent568e9586c036fc319fc36b12495e5deacb167be9 (diff)
downloadkernel-6c8b068c15e28e91117f84cb8d5789f5fe6fcbd0.tar.xz
kernel-6c8b068c15e28e91117f84cb8d5789f5fe6fcbd0.zip
kstd/string: simplify comparisons
-rw-r--r--kernel/kapi/filesystem.cpp2
-rw-r--r--kernel/src/filesystem/dentry.cpp2
-rw-r--r--kernel/src/filesystem/vfs.cpp8
-rw-r--r--kernel/src/filesystem/vfs.tests.cpp32
-rw-r--r--libs/kstd/kstd/string105
-rw-r--r--libs/kstd/kstd/string.test.cpp44
6 files changed, 89 insertions, 104 deletions
diff --git a/kernel/kapi/filesystem.cpp b/kernel/kapi/filesystem.cpp
index 838d2cb..68b51c9 100644
--- a/kernel/kapi/filesystem.cpp
+++ b/kernel/kapi/filesystem.cpp
@@ -45,7 +45,7 @@ namespace kapi::filesystem
{
if (auto open_file_descriptor = kernel::filesystem::open_file_table::get().file(file_descriptor))
{
- if (kernel::filesystem::vfs::get().close(open_file_descriptor->get_dentry()->absolute_path().view()) ==
+ if (kernel::filesystem::vfs::get().close(open_file_descriptor->get_dentry()->absolute_path()) ==
kernel::filesystem::vfs::operation_result::success)
{
return kernel::filesystem::open_file_table::get().remove_file(file_descriptor);
diff --git a/kernel/src/filesystem/dentry.cpp b/kernel/src/filesystem/dentry.cpp
index 14de875..3d8e01a 100644
--- a/kernel/src/filesystem/dentry.cpp
+++ b/kernel/src/filesystem/dentry.cpp
@@ -41,7 +41,7 @@ namespace kernel::filesystem
auto dentry::name() const -> std::string_view
{
- return m_name.view();
+ return m_name;
}
auto dentry::absolute_path() const -> kstd::string
diff --git a/kernel/src/filesystem/vfs.cpp b/kernel/src/filesystem/vfs.cpp
index 91afc13..b0d63a2 100644
--- a/kernel/src/filesystem/vfs.cpp
+++ b/kernel/src/filesystem/vfs.cpp
@@ -241,22 +241,22 @@ namespace kernel::filesystem
continue;
}
- auto next_dentry = current_dentry->find_child(part.view());
+ auto next_dentry = current_dentry->find_child(part);
if (!next_dentry)
{
auto current_fs = current_mount->get_filesystem();
- auto found_inode = current_fs->lookup(current_dentry->get_inode(), part.view());
+ auto found_inode = current_fs->lookup(current_dentry->get_inode(), part);
if (!found_inode)
{
return {nullptr, nullptr};
}
- next_dentry = kstd::make_shared<dentry>(current_dentry, found_inode, part.view());
+ next_dentry = kstd::make_shared<dentry>(current_dentry, found_inode, part);
current_dentry->add_child(next_dentry);
}
else if (next_dentry->has_flag(dentry::dentry_flags::is_mount_point))
{
- current_mount = m_mount_table.find_mount(next_dentry->absolute_path().view());
+ current_mount = m_mount_table.find_mount(next_dentry->absolute_path());
if (!current_mount)
{
kapi::system::panic("[FILESYSTEM] mount for dentry with mounted flag not found.");
diff --git a/kernel/src/filesystem/vfs.tests.cpp b/kernel/src/filesystem/vfs.tests.cpp
index 962e067..f1d0df0 100644
--- a/kernel/src/filesystem/vfs.tests.cpp
+++ b/kernel/src/filesystem/vfs.tests.cpp
@@ -106,8 +106,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
auto mounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt");
REQUIRE(mounted_monkey_1 != nullptr);
- REQUIRE(vfs.close(mounted_monkey_1->absolute_path().view()) ==
- kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(mounted_monkey_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success);
auto unmounted_monkey_1 = vfs.open("/information/monkey_house/monkey_1.txt");
@@ -129,9 +128,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
REQUIRE(mounted_monkey_1 != nullptr);
REQUIRE(mounted_fish1 != nullptr);
- REQUIRE(vfs.close(mounted_monkey_1->absolute_path().view()) ==
- kernel::filesystem::vfs::operation_result::success);
- REQUIRE(vfs.close(mounted_fish1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(mounted_monkey_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(mounted_fish1->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed);
REQUIRE(vfs.unmount("/information/monkey_house/infrastructure") ==
@@ -148,8 +146,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed);
- REQUIRE(vfs.close(mounted_monkey_1->absolute_path().view()) ==
- kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(mounted_monkey_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success);
}
@@ -165,8 +162,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
auto info_1 = vfs.open("/information/info_1.txt");
REQUIRE(info_1 != nullptr);
- REQUIRE(vfs.close(info_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success);
- REQUIRE_THROWS_AS(vfs.close(info_1->absolute_path().view()), std::runtime_error);
+ REQUIRE(vfs.close(info_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE_THROWS_AS(vfs.close(info_1->absolute_path()), std::runtime_error);
}
THEN("images can be stacked mounted and correct file system is unmounted again")
@@ -177,7 +174,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
auto mounted_tickets = vfs.open("/information/entrance/tickets.txt");
REQUIRE(mounted_tickets != nullptr);
- REQUIRE(vfs.close(mounted_tickets->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(mounted_tickets->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success);
mounted_tickets = vfs.open("/information/entrance/tickets.txt");
@@ -200,7 +197,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
auto water = vfs.open("/monkey_house/infrastructure/water.txt");
REQUIRE(water != nullptr);
- REQUIRE(vfs.close(water->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(water->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success);
@@ -221,7 +218,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
auto water = vfs.open("/monkey_house/infrastructure/water.txt");
REQUIRE(water != nullptr);
- REQUIRE(vfs.close(water->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(water->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
auto dev_ram_16 = vfs.open("/dev/ram16");
REQUIRE(dev_ram_16 == nullptr);
@@ -239,7 +236,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
auto info_1 = vfs.open("/information/info_1.txt");
REQUIRE(info_1 != nullptr);
- REQUIRE(vfs.close(info_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(info_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/dev") == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/") == kernel::filesystem::vfs::operation_result::success);
@@ -362,7 +359,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
std::string_view buffer_as_str{reinterpret_cast<char *>(buffer.data()), bytes_read};
REQUIRE(buffer_as_str == "sheep_1");
- REQUIRE(vfs.close(dentry->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(dentry->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success);
auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt");
@@ -395,8 +392,8 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
buffer_as_str = std::string_view{reinterpret_cast<char *>(goat_buffer.data()), bytes_read};
REQUIRE(buffer_as_str == "goat_1");
- REQUIRE(vfs.close(sheep_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success);
- REQUIRE(vfs.close(goat_1->absolute_path().view()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(sheep_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(goat_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::unmount_failed);
@@ -407,8 +404,7 @@ SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_vfs_fixture, "VFS
auto still_mounted_sheep_1 = vfs.open("/information/sheep_1.txt");
REQUIRE(still_mounted_sheep_1 != nullptr);
- REQUIRE(vfs.close(still_mounted_sheep_1->absolute_path().view()) ==
- kernel::filesystem::vfs::operation_result::success);
+ REQUIRE(vfs.close(still_mounted_sheep_1->absolute_path()) == kernel::filesystem::vfs::operation_result::success);
REQUIRE(vfs.unmount("/information") == kernel::filesystem::vfs::operation_result::success);
auto unmounted_sheep_1 = vfs.open("/information/sheep_1.txt");
diff --git a/libs/kstd/kstd/string b/libs/kstd/kstd/string
index e228a04..9343b42 100644
--- a/libs/kstd/kstd/string
+++ b/libs/kstd/kstd/string
@@ -9,6 +9,7 @@
#include <kstd/vector>
#include <algorithm>
+#include <compare>
#include <concepts>
#include <cstddef>
#include <string_view>
@@ -52,7 +53,7 @@ namespace kstd
* @brief Constructs a string from a string view by copying the characters into owned storage.
* @param view The string view to copy the characters from.
*/
- string(std::string_view view)
+ explicit string(std::string_view view)
: string()
{
append(view);
@@ -101,6 +102,26 @@ namespace kstd
*/
constexpr auto operator=(string const & other) -> string & = default;
+ constexpr auto operator=(std::string_view const & other) -> string &
+ {
+ clear();
+ append(other);
+ return *this;
+ }
+
+ constexpr auto operator=(char const * other) -> string &
+ {
+ clear();
+ append(std::string_view{other});
+ return *this;
+ }
+
+ //! Create a string view from this string.
+ constexpr operator std::string_view() const noexcept
+ {
+ return {data(), size()};
+ }
+
/**
* @brief Returns the number of characters in this string, not including the null terminator.
*/
@@ -224,6 +245,7 @@ namespace kstd
{
if (!view.empty())
{
+ m_storage.reserve(size() + view.size() + 1);
std::ranges::for_each(view, [this](auto const ch) { push_back(ch); });
}
@@ -237,7 +259,7 @@ namespace kstd
*/
constexpr auto append(string const & other) -> string &
{
- return append(other.view());
+ return append(static_cast<std::string_view>(other));
}
/**
@@ -261,12 +283,29 @@ namespace kstd
return *this;
}
- /**
- * @brief Returns a string view of this string, which is a non-owning view into the characters of this string.
- */
- [[nodiscard]] constexpr auto view() const noexcept -> std::string_view
+ //! Compare this string lexicographically to another string.
+ //!
+ //! @param other The string to compare to this one.
+ [[nodiscard]] constexpr auto operator<=>(string const & other) const noexcept -> std::strong_ordering = default;
+
+ [[nodiscard]] constexpr auto operator==(string const & other) const noexcept -> bool = default;
+
+ //! Compare this string lexicographically to a C-style string.
+ //!
+ //! @param other The C-style string to compare to this one.
+ //! @return The result of the comparison.
+ [[nodiscard]] constexpr auto operator<=>(char const * other) const noexcept
+ {
+ return static_cast<std::string_view>(*this) <=> other;
+ }
+
+ //! Check if this string compares equal to a C-style string.
+ //!
+ //! @param other The C-style string to compare to this one.
+ //! @return @p true iff. this string compares equal to @p other, @p false otherwise.
+ [[nodiscard]] constexpr auto operator==(char const * other) const noexcept -> bool
{
- return std::string_view{data(), size()};
+ return static_cast<std::string_view>(*this) == other;
}
private:
@@ -316,62 +355,12 @@ namespace kstd
return result;
}
- [[nodiscard]] constexpr auto inline operator==(string const & lhs, string const & rhs) -> bool
- {
- return lhs.view() == rhs.view();
- }
-
- [[nodiscard]] constexpr auto inline operator!=(string const & lhs, string const & rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
- [[nodiscard]] constexpr auto inline operator==(string const & lhs, std::string_view rhs) -> bool
- {
- return lhs.view() == rhs;
- }
-
- [[nodiscard]] constexpr auto inline operator!=(string const & lhs, std::string_view rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
- [[nodiscard]] constexpr auto inline operator==(std::string_view lhs, string const & rhs) -> bool
- {
- return lhs == rhs.view();
- }
-
- [[nodiscard]] constexpr auto inline operator!=(std::string_view lhs, string const & rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
- [[nodiscard]] constexpr auto inline operator==(string const & lhs, char const * rhs) -> bool
- {
- return lhs.view() == std::string_view{rhs};
- }
-
- [[nodiscard]] constexpr auto inline operator!=(string const & lhs, char const * rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
- [[nodiscard]] constexpr auto inline operator==(char const * lhs, string const & rhs) -> bool
- {
- return std::string_view{lhs} == rhs.view();
- }
-
- [[nodiscard]] constexpr auto inline operator!=(char const * lhs, string const & rhs) -> bool
- {
- return !(lhs == rhs);
- }
-
template<>
struct formatter<string> : formatter<std::string_view>
{
auto format(string const & str, format_context & context) const -> void
{
- formatter<std::string_view>::format(str.view(), context);
+ formatter<std::string_view>::format(static_cast<std::string_view>(str), context);
}
};
diff --git a/libs/kstd/kstd/string.test.cpp b/libs/kstd/kstd/string.test.cpp
index 9755676..b81cd3a 100644
--- a/libs/kstd/kstd/string.test.cpp
+++ b/libs/kstd/kstd/string.test.cpp
@@ -22,7 +22,7 @@ SCENARIO("String initialization and construction", "[string]")
THEN("the string is empty")
{
- REQUIRE(str.view() == std::string_view{});
+ REQUIRE(str == std::string_view{});
}
}
}
@@ -43,7 +43,7 @@ SCENARIO("String initialization and construction", "[string]")
THEN("the string contains the same characters as the view")
{
- REQUIRE(str.view() == view);
+ REQUIRE(str == view);
}
}
}
@@ -64,7 +64,7 @@ SCENARIO("String initialization and construction", "[string]")
THEN("the string contains the same characters as the C-style string")
{
- REQUIRE(str.view() == c_str);
+ REQUIRE(str == c_str);
}
}
}
@@ -85,7 +85,7 @@ SCENARIO("String initialization and construction", "[string]")
THEN("the string contains the same character as the given character")
{
- REQUIRE(str.view() == std::string_view{&ch, 1});
+ REQUIRE(str == std::string_view{&ch, 1});
}
}
}
@@ -100,7 +100,7 @@ SCENARIO("String initialization and construction", "[string]")
THEN("the new string contains the same characters as the original")
{
- REQUIRE(str.view() == other.view());
+ REQUIRE(static_cast<std::string_view>(str) == static_cast<std::string_view>(other));
}
}
@@ -113,7 +113,7 @@ SCENARIO("String initialization and construction", "[string]")
THEN("the string contains the same characters as the assigned string")
{
- REQUIRE(str.view() == other.view());
+ REQUIRE(static_cast<std::string_view>(str) == static_cast<std::string_view>(other));
}
}
}
@@ -129,7 +129,7 @@ SCENARIO("String initialization and construction", "[string]")
THEN("the string contains the same characters as the assigned view")
{
- REQUIRE(str.view() == view);
+ REQUIRE(str == view);
}
}
}
@@ -145,7 +145,7 @@ SCENARIO("String initialization and construction", "[string]")
THEN("the string contains the same characters as the assigned C-style string")
{
- REQUIRE(str.view() == c_str);
+ REQUIRE(str == c_str);
}
}
}
@@ -164,7 +164,7 @@ SCENARIO("String concatenation", "[string]")
THEN("the first string contains the characters of both strings concatenated")
{
- REQUIRE(str1.view() == "Blub Blub");
+ REQUIRE(str1 == "Blub Blub");
}
THEN("the size of the first string is the sum of the sizes of both strings")
@@ -179,7 +179,7 @@ SCENARIO("String concatenation", "[string]")
THEN("the first string contains the characters of both strings concatenated")
{
- REQUIRE(str1.view() == "Blub Blub");
+ REQUIRE(str1 == "Blub Blub");
}
THEN("the size of the first string is the sum of the sizes of both strings")
@@ -194,7 +194,7 @@ SCENARIO("String concatenation", "[string]")
THEN("the new string contains the characters of both strings concatenated")
{
- REQUIRE(str3.view() == "Blub Blub");
+ REQUIRE(str3 == "Blub Blub");
}
THEN("the size of the new string is the sum of the sizes of both strings")
@@ -215,7 +215,7 @@ SCENARIO("String concatenation", "[string]")
THEN("the string contains the characters of both the original string and the appended view concatenated")
{
- REQUIRE(str.view() == "Blub Blub");
+ REQUIRE(str == "Blub Blub");
}
THEN("the size of the string is the sum of the sizes of the original string and the appended view")
@@ -236,7 +236,7 @@ SCENARIO("String concatenation", "[string]")
THEN("the string contains the original characters followed by the appended character")
{
- REQUIRE(str.view() == "Blub!");
+ REQUIRE(str == "Blub!");
}
THEN("the size of the string is one more than the original size")
@@ -251,7 +251,7 @@ SCENARIO("String concatenation", "[string]")
THEN("the string contains the original characters followed by the appended character")
{
- REQUIRE(str.view() == "Blub!");
+ REQUIRE(str == "Blub!");
}
THEN("the size of the string is one more than the original size")
@@ -276,8 +276,8 @@ SCENARIO("String conversion and comparison", "[string]")
THEN("the string contains the decimal representation of the unsigned integer")
{
- REQUIRE(str1.view() == "12345");
- REQUIRE(str2.view() == "0");
+ REQUIRE(str1 == "12345");
+ REQUIRE(str2 == "0");
}
}
}
@@ -335,7 +335,7 @@ SCENARIO("String clearing", "[string]")
THEN("the string contains no characters")
{
- REQUIRE(str.view() == std::string_view{});
+ REQUIRE(str == std::string_view{});
}
}
}
@@ -351,7 +351,7 @@ SCENARIO("String iteration", "[string]")
{
kstd::string result;
- for (auto ch : str.view())
+ for (auto ch : static_cast<std::string_view>(str))
{
result.push_back(ch);
}
@@ -396,14 +396,14 @@ SCENARIO("String iteration", "[string]")
{
kstd::string result;
- for (auto ch : str.view())
+ for (auto ch : static_cast<std::string_view>(str))
{
result.push_back(ch);
}
THEN("the iterated characters are the same as the characters in the string")
{
- REQUIRE(result == str.view());
+ REQUIRE(result == static_cast<std::string_view>(str));
}
}
@@ -429,7 +429,7 @@ SCENARIO("String iteration", "[string]")
{
kstd::string result;
- for (auto ch : str.view())
+ for (auto ch : static_cast<std::string_view>(str))
{
result.push_back(ch);
}
@@ -438,7 +438,7 @@ SCENARIO("String iteration", "[string]")
{
REQUIRE(result.empty());
REQUIRE(result.size() == 0);
- REQUIRE(result.view() == std::string_view{});
+ REQUIRE(static_cast<std::string_view>(result) == std::string_view{});
}
}
}