/* * Copyright (c) 2021, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include namespace Kernel { class KString { AK_MAKE_NONCOPYABLE(KString); AK_MAKE_NONMOVABLE(KString); public: [[nodiscard]] static ErrorOr> try_create_uninitialized(size_t, char*&); [[nodiscard]] static NonnullOwnPtr must_create_uninitialized(size_t, char*&); [[nodiscard]] static ErrorOr> try_create(StringView); [[nodiscard]] static NonnullOwnPtr must_create(StringView); [[nodiscard]] static ErrorOr> vformatted(StringView fmtstr, AK::TypeErasedFormatParams&); template [[nodiscard]] static ErrorOr> formatted(CheckedFormatString&& fmtstr, Parameters const&... parameters) { AK::VariadicFormatParams variadic_format_parameters { parameters... }; return vformatted(fmtstr.view(), variadic_format_parameters); } [[nodiscard]] static ErrorOr> number(Arithmetic auto value) { return formatted("{}", value); } void operator delete(void*); ErrorOr> try_clone() const; [[nodiscard]] bool is_empty() const { return m_length == 0; } [[nodiscard]] size_t length() const { return m_length; } [[nodiscard]] char const* characters() const { return m_characters; } [[nodiscard]] StringView view() const { return { characters(), length() }; } [[nodiscard]] ReadonlyBytes bytes() 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 { ErrorOr format(FormatBuilder& builder, Kernel::KString const& value) { return Formatter::format(builder, value.view()); } }; template<> struct Formatter> : Formatter { ErrorOr format(FormatBuilder& builder, OwnPtr const& value) { if (value) return Formatter::format(builder, value->view()); return Formatter::format(builder, "[out of memory]"sv); } }; template<> struct Formatter> : Formatter { ErrorOr format(FormatBuilder& builder, NonnullOwnPtr const& value) { return Formatter::format(builder, value->view()); } }; template<> struct Traits> : public GenericTraits> { using PeekType = Kernel::KString*; using ConstPeekType = Kernel::KString const*; static unsigned hash(NonnullOwnPtr const& p) { return string_hash(p->characters(), p->length()); } static bool equals(NonnullOwnPtr const& a, NonnullOwnPtr const& b) { return a->view() == b->view(); } static bool equals(StringView a, NonnullOwnPtr const& b) { return a == b->view(); } }; template<> struct Traits> : public GenericTraits> { using PeekType = Kernel::KString*; using ConstPeekType = Kernel::KString const*; static unsigned hash(OwnPtr const& p) { if (!p) return ptr_hash(nullptr); return string_hash(p->characters(), p->length()); } static bool equals(OwnPtr const& a, OwnPtr const& b) { if (!a || !b) return a.ptr() == b.ptr(); if (a == b) return true; return a->view() == b->view(); } static bool equals(StringView a, OwnPtr const& b) { if (!b) return a.is_null(); return a == b->view(); } }; namespace Detail { template<> inline constexpr bool IsHashCompatible> = true; template<> inline constexpr bool IsHashCompatible> = true; } }