From 9df852e48b9123c58a4193cc484147eeae307708 Mon Sep 17 00:00:00 2001 From: DH Date: Thu, 16 Oct 2025 11:33:37 +0300 Subject: [PATCH] rx/StaticString: split to StaticString and StaticCString --- kernel/orbis/include/orbis/KernelContext.hpp | 4 +- kernel/orbis/include/orbis/thread/Thread.hpp | 2 +- kernel/orbis/src/sys/sys_environment.cpp | 2 +- rx/include/rx/StaticString.hpp | 240 +++++++++++++++++-- 4 files changed, 223 insertions(+), 25 deletions(-) diff --git a/kernel/orbis/include/orbis/KernelContext.hpp b/kernel/orbis/include/orbis/KernelContext.hpp index 23314d545..7ecd665db 100644 --- a/kernel/orbis/include/orbis/KernelContext.hpp +++ b/kernel/orbis/include/orbis/KernelContext.hpp @@ -109,7 +109,7 @@ public: return {}; } - std::tuple> &, std::unique_lock> + std::tuple> &, std::unique_lock> getKernelEnv() { std::unique_lock lock(m_kenv_mtx); return {m_kenv, std::move(lock)}; @@ -171,7 +171,7 @@ private: kmap> mIpmiServers; rx::shared_mutex m_kenv_mtx; - kmap> m_kenv; // max size: 127 + '\0' + kmap> m_kenv; }; extern GlobalObjectRef g_context; diff --git a/kernel/orbis/include/orbis/thread/Thread.hpp b/kernel/orbis/include/orbis/thread/Thread.hpp index e4ce01855..7963c4335 100644 --- a/kernel/orbis/include/orbis/thread/Thread.hpp +++ b/kernel/orbis/include/orbis/thread/Thread.hpp @@ -36,7 +36,7 @@ struct Thread final { ptr stackEnd; uint64_t fsBase{}; uint64_t gsBase{}; - rx::StaticString<32> name; + rx::StaticString<31> name; cpuset affinity{~0u}; SigSet sigMask = {0x7fff'ffff, ~0u, ~0u, ~0u}; diff --git a/kernel/orbis/src/sys/sys_environment.cpp b/kernel/orbis/src/sys/sys_environment.cpp index e0ebbda37..392890194 100644 --- a/kernel/orbis/src/sys/sys_environment.cpp +++ b/kernel/orbis/src/sys/sys_environment.cpp @@ -66,7 +66,7 @@ orbis::SysResult orbis::sys_kenv(Thread *thread, sint what, } auto &_value_buf = kenv[kstring(_name)]; ORBIS_RET_ON_ERROR( - ureadString(_value_buf.data(), _value_buf.max_size() + 1, value)); + ureadString(_value_buf.data(), _value_buf.max_size(), value)); break; } case kenv_unset: { diff --git a/rx/include/rx/StaticString.hpp b/rx/include/rx/StaticString.hpp index 58474803f..c2f329a6a 100644 --- a/rx/include/rx/StaticString.hpp +++ b/rx/include/rx/StaticString.hpp @@ -9,14 +9,183 @@ #include namespace rx { +template class StaticCString { +private: + char m_data[N]{}; + +public: + // Reserve space for null terminator + static constexpr std::size_t capacity = N - 1; + + constexpr StaticCString() noexcept = default; + constexpr StaticCString(std::string_view sv) noexcept { assign(sv); } + + template + requires(OtherN <= N) + constexpr StaticCString(const StaticCString &other) noexcept { + std::memcpy(m_data, other.m_data, + other.size() + 1); // +1 for null terminator + } + + template + requires(OtherN <= N) + constexpr StaticCString & + operator=(const StaticCString &other) noexcept { + if (this != &other) { + std::memcpy(m_data, other.m_data, other.size() + 1); + } + return *this; + } + + constexpr StaticCString &operator=(std::string_view sv) noexcept { + assign(sv); + return *this; + } + + constexpr void assign(std::string_view sv) noexcept { + if (sv.size() > capacity) { + // Truncate if too long + sv = sv.substr(0, capacity); + } + auto size = sv.size(); + sv.copy(m_data, size); + m_data[size] = '\0'; + } + + constexpr void append(std::string_view sv) noexcept { + auto selfSize = size(); + std::size_t available = capacity - selfSize; + if (sv.size() > available) { + sv = sv.substr(0, available); + } + sv.copy(m_data + selfSize, sv.size()); + selfSize += sv.size(); + m_data[selfSize] = '\0'; + } + + constexpr StaticCString &operator+=(std::string_view sv) noexcept { + append(sv); + return *this; + } + + constexpr void remove_suffix(std::size_t n) { m_data[size() - n] = 0; } + + constexpr void clear() noexcept { m_data[0] = '\0'; } + + [[nodiscard]] constexpr const char *data() const noexcept { return m_data; } + [[nodiscard]] constexpr char *data() noexcept { return m_data; } + [[nodiscard]] constexpr const char *c_str() const noexcept { return m_data; } + [[nodiscard]] constexpr std::size_t size() const noexcept { + return std::strlen(m_data); + } + [[nodiscard]] constexpr std::size_t length() const noexcept { return size(); } + [[nodiscard]] constexpr bool empty() const noexcept { + return m_data[0] == '\0'; + } + [[nodiscard]] constexpr std::size_t max_size() const noexcept { + return capacity; + } + + constexpr operator std::string_view() const noexcept { + return std::string_view(m_data, size()); + } + + [[nodiscard]] constexpr const char *begin() const noexcept { return m_data; } + [[nodiscard]] constexpr const char *end() const noexcept { + return m_data + size(); + } + [[nodiscard]] constexpr char *begin() noexcept { return m_data; } + [[nodiscard]] constexpr char *end() noexcept { return m_data + size(); } + [[nodiscard]] constexpr const char *cbegin() const noexcept { return m_data; } + [[nodiscard]] constexpr const char *cend() const noexcept { + return m_data + size(); + } + + constexpr char &operator[](std::size_t pos) noexcept { return m_data[pos]; } + + constexpr const char &operator[](std::size_t pos) const noexcept { + return m_data[pos]; + } + + [[nodiscard]] char &at(std::size_t pos) { + dieIf(pos >= size(), "StaticCString::at: index out of range"); + return m_data[pos]; + } + + [[nodiscard]] constexpr char &at(std::size_t pos) const { + dieIf(pos >= size(), "StaticCString::at: index out of range"); + return m_data[pos]; + } + + constexpr std::size_t find(char c, std::size_t pos = 0) const noexcept { + return std::string_view(*this).find(c, pos); + } + + constexpr std::size_t find(std::string_view sv, + std::size_t pos = 0) const noexcept { + return std::string_view(*this).find(sv, pos); + } + + [[nodiscard]] constexpr std::string_view + substr(std::size_t pos = 0, std::size_t len = std::string_view::npos) const { + return std::string_view(*this).substr(pos, len); + } + + void resize(std::size_t size, char c = ' ') { + assert(size <= capacity); + + auto selfSize = this->size(); + if (size < selfSize) { + m_data[size] = '\0'; + return; + } + + for (std::size_t i = selfSize; i < size; ++i) { + m_data[i] = c; + } + + m_data[size] = '\0'; + } + + template + [[nodiscard]] constexpr static StaticCString + format(format_string fmt, Args &&...args) { + StaticCString result; + auto [ptr, size] = format_to_n(result.m_data, result.capacity, fmt, + std::forward(args)...); + result.m_data[std::min(size, capacity)] = '\0'; + return result; + } + + [[nodiscard]] constexpr static StaticCString vformat(std::string_view fmt, + format_args args) { + StaticCString result; + auto [ptr, size] = + vformat_to(result.m_data, result.capacity, fmt, std::move(args)); + result.m_data[std::min(size, capacity)] = '\0'; + return result; + } + + template + constexpr void assignFormat(format_string fmt, Args &&...args) { + auto [ptr, size] = + format_to_n(m_data, capacity, fmt, std::forward(args)...); + m_data[std::min(size, capacity)] = '\0'; + } + + constexpr void assignVFormat(std::string_view fmt, format_args args) { + auto [ptr, size] = vformat_to(m_data, capacity, fmt, std::move(args)); + m_data[std::min(size, capacity)] = '\0'; + } +}; + template class StaticString { private: char m_data[N]{}; std::size_t m_size = 0; public: - // Reserve space for null terminator - static constexpr std::size_t capacity = N - 1; + static constexpr std::size_t capacity = N; constexpr StaticString() noexcept = default; constexpr StaticString(std::string_view sv) noexcept { assign(sv); } @@ -25,7 +194,7 @@ public: requires(OtherN <= N) constexpr StaticString(const StaticString &other) noexcept : m_size(other.m_size) { - std::memcpy(m_data, other.m_data, m_size + 1); // +1 for null terminator + std::memcpy(m_data, other.m_data, m_size); } template @@ -34,7 +203,7 @@ public: operator=(const StaticString &other) noexcept { if (this != &other) { m_size = other.m_size; - std::memcpy(m_data, other.m_data, m_size + 1); + std::memcpy(m_data, other.m_data, m_size); } return *this; } @@ -51,7 +220,6 @@ public: } m_size = sv.size(); sv.copy(m_data, m_size); - m_data[m_size] = '\0'; } constexpr void append(std::string_view sv) noexcept { @@ -61,7 +229,6 @@ public: } sv.copy(m_data + m_size, sv.size()); m_size += sv.size(); - m_data[m_size] = '\0'; } constexpr StaticString &operator+=(std::string_view sv) noexcept { @@ -81,7 +248,6 @@ public: [[nodiscard]] constexpr const char *data() const noexcept { return m_data; } [[nodiscard]] constexpr char *data() noexcept { return m_data; } - [[nodiscard]] constexpr const char *c_str() const noexcept { return m_data; } [[nodiscard]] constexpr std::size_t size() const noexcept { return m_size; } [[nodiscard]] constexpr std::size_t length() const noexcept { return m_size; } [[nodiscard]] constexpr bool empty() const noexcept { return m_size == 0; } @@ -134,21 +300,10 @@ public: return std::string_view(*this).substr(pos, len); } - template - [[nodiscard]] constexpr static StaticString format(format_string fmt, - Args &&...args) { - StaticString result; - auto [ptr, size] = format_to_n(result.m_data, result.capacity, fmt, - std::forward(args)...); - result.m_data[size] = '\0'; - return result; - } - void resize(std::size_t size, char c = ' ') { assert(size <= capacity); if (size < m_size) { - m_data[size] = 0; m_size = size; return; } @@ -160,12 +315,22 @@ public: m_size = size; } + template + [[nodiscard]] constexpr static StaticString format(format_string fmt, + Args &&...args) { + StaticString result; + auto [ptr, size] = format_to_n(result.m_data, result.capacity, fmt, + std::forward(args)...); + result.m_size = std::min(size, capacity); + return result; + } + [[nodiscard]] constexpr static StaticString vformat(std::string_view fmt, format_args args) { StaticString result; auto [ptr, size] = vformat_to(result.m_data, result.capacity, fmt, std::move(args)); - result.m_data[size] = '\0'; + result.m_size = std::min(size, capacity); return result; } @@ -173,12 +338,12 @@ public: constexpr void assignFormat(format_string fmt, Args &&...args) { auto [ptr, size] = format_to_n(m_data, capacity, fmt, std::forward(args)...); - m_data[size] = '\0'; + m_size = std::min(size, capacity); } constexpr void assignVFormat(std::string_view fmt, format_args args) { auto [ptr, size] = vformat_to(m_data, capacity, fmt, std::move(args)); - m_data[size] = '\0'; + m_size = std::min(size, capacity); } }; @@ -208,6 +373,32 @@ constexpr auto operator<=>(const StaticString &lhs, template StaticString(const char (&)[N]) -> StaticString; +template +constexpr bool operator==(const StaticCString &lhs, + const StaticCString &rhs) noexcept { + return std::strcmp(lhs.c_str(), rhs.c_str()) == 0; +} + +template +constexpr bool operator==(const StaticCString &lhs, + std::string_view sv) noexcept { + return lhs.c_str() == sv; +} + +template +constexpr auto operator<=>(const StaticCString &lhs, + const StaticCString &rhs) noexcept { + return std::strcmp(lhs.c_str(), rhs.c_str()); +} + +template +constexpr auto operator<=>(const StaticCString &lhs, + std::string_view sv) noexcept { + return lhs.c_str() <=> sv; +} + +template StaticCString(const char (&)[N]) -> StaticCString; + template auto formatStatic(format_string fmt, Args &&...args) { return StaticString::format(fmt, std::forward(args)...); @@ -220,3 +411,10 @@ struct rx::formatter> : rx::formatter { return rx::formatter::format(std::string_view(str), ctx); } }; + +template +struct rx::formatter> : rx::formatter { + auto format(const rx::StaticCString &str, rx::format_context &ctx) const { + return rx::formatter::format(str.c_str(), ctx); + } +};