From 279383a8f3cc9b9570a329ee7b0ed8844d26ba27 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 28 May 2021 09:25:02 +0200 Subject: [PATCH] Kernel: Add KString, a single-owner string with OOM failure exposion This is a simple string class for use in the kernel. It encapsulates a length + character array in a single-allocation object. Main differences from AK::String: - Single-owner (no reference counting.) - Allocation failures are exposed, not hidden. The basic idea is to allow better and more precise string management in the kernel. --- Kernel/CMakeLists.txt | 1 + Kernel/KString.cpp | 40 ++++++++++++++++++++++++++++++++++++ Kernel/KString.h | 48 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 Kernel/KString.cpp create mode 100644 Kernel/KString.h diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index d7204d83cb..023ab811fe 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -112,6 +112,7 @@ set(KERNEL_SOURCES Interrupts/SpuriousInterruptHandler.cpp Interrupts/UnhandledInterruptHandler.cpp KBufferBuilder.cpp + KString.cpp KSyms.cpp Lock.cpp Net/E1000NetworkAdapter.cpp diff --git a/Kernel/KString.cpp b/Kernel/KString.cpp new file mode 100644 index 0000000000..e652282ab2 --- /dev/null +++ b/Kernel/KString.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Kernel { + +OwnPtr KString::try_create(StringView const& string) +{ + char* characters = nullptr; + size_t length = string.length(); + auto new_string = KString::try_create_uninitialized(length, characters); + if (!new_string) + return {}; + if (!string.is_empty()) + __builtin_memcpy(characters, string.characters_without_null_termination(), length); + characters[length] = '\0'; + return new_string; +} + +OwnPtr KString::try_create_uninitialized(size_t length, char*& characters) +{ + size_t allocation_size = sizeof(KString) + (sizeof(char) * length) + sizeof(char); + auto* slot = kmalloc(allocation_size); + if (!slot) + return {}; + auto* new_string = new (slot) KString(length); + characters = new_string->m_characters; + return adopt_own(*new_string); +} + +OwnPtr KString::try_clone() const +{ + return try_create(view()); +} + +} diff --git a/Kernel/KString.h b/Kernel/KString.h new file mode 100644 index 0000000000..c753d11af4 --- /dev/null +++ b/Kernel/KString.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2021, Andreas Kling + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Kernel { + +class KString { +public: + static OwnPtr try_create_uninitialized(size_t, char*&); + static OwnPtr try_create(StringView const&); + + OwnPtr try_clone() const; + + bool is_empty() const { return m_length == 0; } + size_t length() const { return m_length; } + char const* characters() const { return m_characters; } + StringView view() const { return { characters(), length() }; } + +private: + explicit KString(size_t length) + : m_length(length) + { + } + + size_t m_length { 0 }; + char m_characters[0]; +}; + +} + +namespace AK { + +template<> +struct Formatter : Formatter { + void format(FormatBuilder& builder, Kernel::KString const& value) + { + Formatter::format(builder, value.characters()); + } +}; + +}