summaryrefslogtreecommitdiff
path: root/Kernel/KString.h
blob: 2639f9617b2080b26dee39b52ea5d5746e405ac1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/Format.h>
#include <AK/OwnPtr.h>

namespace Kernel {

class KString {
    AK_MAKE_NONCOPYABLE(KString);
    AK_MAKE_NONMOVABLE(KString);

public:
    [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> try_create_uninitialized(size_t, char*&);
    [[nodiscard]] static NonnullOwnPtr<KString> must_create_uninitialized(size_t, char*&);
    [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> try_create(StringView);
    [[nodiscard]] static NonnullOwnPtr<KString> must_create(StringView);

    [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> vformatted(StringView fmtstr, AK::TypeErasedFormatParams&);

    template<typename... Parameters>
    [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> formatted(CheckedFormatString<Parameters...>&& fmtstr, Parameters const&... parameters)
    {
        AK::VariadicFormatParams variadic_format_parameters { parameters... };
        return vformatted(fmtstr.view(), variadic_format_parameters);
    }

    [[nodiscard]] static ErrorOr<NonnullOwnPtr<KString>> number(Arithmetic auto value)
    {
        return formatted("{}", value);
    }

    void operator delete(void*);

    ErrorOr<NonnullOwnPtr<KString>> 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<Kernel::KString> : Formatter<StringView> {
    ErrorOr<void> format(FormatBuilder& builder, Kernel::KString const& value)
    {
        return Formatter<StringView>::format(builder, value.view());
    }
};

template<>
struct Formatter<OwnPtr<Kernel::KString>> : Formatter<StringView> {
    ErrorOr<void> format(FormatBuilder& builder, OwnPtr<Kernel::KString> const& value)
    {
        if (value)
            return Formatter<StringView>::format(builder, value->view());
        return Formatter<StringView>::format(builder, "[out of memory]"sv);
    }
};

template<>
struct Formatter<NonnullOwnPtr<Kernel::KString>> : Formatter<StringView> {
    ErrorOr<void> format(FormatBuilder& builder, NonnullOwnPtr<Kernel::KString> const& value)
    {
        return Formatter<StringView>::format(builder, value->view());
    }
};

template<>
struct Traits<NonnullOwnPtr<Kernel::KString>> : public GenericTraits<NonnullOwnPtr<Kernel::KString>> {
    using PeekType = Kernel::KString*;
    using ConstPeekType = Kernel::KString const*;
    static unsigned hash(NonnullOwnPtr<Kernel::KString> const& p) { return string_hash(p->characters(), p->length()); }
    static bool equals(NonnullOwnPtr<Kernel::KString> const& a, NonnullOwnPtr<Kernel::KString> const& b) { return a->view() == b->view(); }
    static bool equals(StringView a, NonnullOwnPtr<Kernel::KString> const& b) { return a == b->view(); }
};

template<>
struct Traits<OwnPtr<Kernel::KString>> : public GenericTraits<OwnPtr<Kernel::KString>> {
    using PeekType = Kernel::KString*;
    using ConstPeekType = Kernel::KString const*;
    static unsigned hash(OwnPtr<Kernel::KString> const& p)
    {
        if (!p)
            return ptr_hash(nullptr);
        return string_hash(p->characters(), p->length());
    }
    static bool equals(OwnPtr<Kernel::KString> const& a, OwnPtr<Kernel::KString> 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<Kernel::KString> const& b)
    {
        if (!b)
            return a.is_null();
        return a == b->view();
    }
};

namespace Detail {
template<>
inline constexpr bool IsHashCompatible<StringView, NonnullOwnPtr<Kernel::KString>> = true;
template<>
inline constexpr bool IsHashCompatible<StringView, OwnPtr<Kernel::KString>> = true;
}

}