Serenity Operating System
1/*
2 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/Format.h>
10#include <AK/OwnPtr.h>
11
12namespace Kernel {
13
14class KString {
15 AK_MAKE_NONCOPYABLE(KString);
16 AK_MAKE_NONMOVABLE(KString);
17
18public:
19 [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> try_create_uninitialized(size_t, char*&);
20 [[nodiscard]] static NonnullOwnPtr<KString> must_create_uninitialized(size_t, char*&);
21 [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> try_create(StringView);
22 [[nodiscard]] static NonnullOwnPtr<KString> must_create(StringView);
23
24 [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> vformatted(StringView fmtstr, AK::TypeErasedFormatParams&);
25
26 template<typename... Parameters>
27 [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> formatted(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
28 {
29 AK::VariadicFormatParams<AK::AllowDebugOnlyFormatters::No, Parameters...> variadic_format_parameters { parameters... };
30 return vformatted(fmtstr.view(), variadic_format_parameters);
31 }
32
33 [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> number(Arithmetic auto value)
34 {
35 return formatted("{}", value);
36 }
37
38 void operator delete(void*);
39
40 ErrorOr<NonnullOwnPtr<KString>> try_clone() const;
41
42 [[nodiscard]] bool is_empty() const { return m_length == 0; }
43 [[nodiscard]] size_t length() const { return m_length; }
44 [[nodiscard]] char const* characters() const { return m_characters; }
45 [[nodiscard]] StringView view() const { return { characters(), length() }; }
46 [[nodiscard]] ReadonlyBytes bytes() const { return { characters(), length() }; }
47
48private:
49 explicit KString(size_t length)
50 : m_length(length)
51 {
52 }
53
54 size_t m_length { 0 };
55 char m_characters[0];
56};
57
58}
59
60namespace AK {
61
62template<>
63struct Formatter<Kernel::KString> : Formatter<StringView> {
64 ErrorOr<void> format(FormatBuilder& builder, Kernel::KString const& value)
65 {
66 return Formatter<StringView>::format(builder, value.view());
67 }
68};
69
70template<>
71struct Formatter<OwnPtr<Kernel::KString>> : Formatter<StringView> {
72 ErrorOr<void> format(FormatBuilder& builder, OwnPtr<Kernel::KString> const& value)
73 {
74 if (value)
75 return Formatter<StringView>::format(builder, value->view());
76 return Formatter<StringView>::format(builder, "[out of memory]"sv);
77 }
78};
79
80template<>
81struct Formatter<NonnullOwnPtr<Kernel::KString>> : Formatter<StringView> {
82 ErrorOr<void> format(FormatBuilder& builder, NonnullOwnPtr<Kernel::KString> const& value)
83 {
84 return Formatter<StringView>::format(builder, value->view());
85 }
86};
87
88template<>
89struct Traits<NonnullOwnPtr<Kernel::KString>> : public GenericTraits<NonnullOwnPtr<Kernel::KString>> {
90 using PeekType = Kernel::KString*;
91 using ConstPeekType = Kernel::KString const*;
92 static unsigned hash(NonnullOwnPtr<Kernel::KString> const& p) { return string_hash(p->characters(), p->length()); }
93 static bool equals(NonnullOwnPtr<Kernel::KString> const& a, NonnullOwnPtr<Kernel::KString> const& b) { return a->view() == b->view(); }
94 static bool equals(StringView a, NonnullOwnPtr<Kernel::KString> const& b) { return a == b->view(); }
95};
96
97template<>
98struct Traits<OwnPtr<Kernel::KString>> : public GenericTraits<OwnPtr<Kernel::KString>> {
99 using PeekType = Kernel::KString*;
100 using ConstPeekType = Kernel::KString const*;
101 static unsigned hash(OwnPtr<Kernel::KString> const& p)
102 {
103 if (!p)
104 return ptr_hash(nullptr);
105 return string_hash(p->characters(), p->length());
106 }
107 static bool equals(OwnPtr<Kernel::KString> const& a, OwnPtr<Kernel::KString> const& b)
108 {
109 if (!a || !b)
110 return a.ptr() == b.ptr();
111 if (a == b)
112 return true;
113
114 return a->view() == b->view();
115 }
116 static bool equals(StringView a, OwnPtr<Kernel::KString> const& b)
117 {
118 if (!b)
119 return a.is_null();
120 return a == b->view();
121 }
122};
123
124namespace Detail {
125template<>
126inline constexpr bool IsHashCompatible<StringView, NonnullOwnPtr<Kernel::KString>> = true;
127template<>
128inline constexpr bool IsHashCompatible<StringView, OwnPtr<Kernel::KString>> = true;
129}
130
131}