Coverage Report

Created: 2025-09-05 06:52

/src/serenity/AK/StringImpl.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include <AK/Badge.h>
10
#include <AK/RefCounted.h>
11
#include <AK/RefPtr.h>
12
#include <AK/Span.h>
13
#include <AK/Types.h>
14
#include <AK/kmalloc.h>
15
16
namespace AK {
17
18
enum ShouldChomp {
19
    NoChomp,
20
    Chomp
21
};
22
23
size_t allocation_size_for_stringimpl(size_t length);
24
25
class StringImpl : public RefCounted<StringImpl> {
26
public:
27
    static NonnullRefPtr<StringImpl const> create_uninitialized(size_t length, char*& buffer);
28
    static RefPtr<StringImpl const> create(char const* cstring, ShouldChomp = NoChomp);
29
    static RefPtr<StringImpl const> create(char const* cstring, size_t length, ShouldChomp = NoChomp);
30
    static RefPtr<StringImpl const> create(ReadonlyBytes, ShouldChomp = NoChomp);
31
    static RefPtr<StringImpl const> create_lowercased(char const* cstring, size_t length);
32
    static RefPtr<StringImpl const> create_uppercased(char const* cstring, size_t length);
33
34
    NonnullRefPtr<StringImpl const> to_lowercase() const;
35
    NonnullRefPtr<StringImpl const> to_uppercase() const;
36
37
    void operator delete(void* ptr)
38
436M
    {
39
436M
        kfree_sized(ptr, allocation_size_for_stringimpl(static_cast<StringImpl*>(ptr)->m_length));
40
436M
    }
41
42
    static StringImpl& the_empty_stringimpl();
43
44
    ~StringImpl();
45
46
1.46G
    size_t length() const { return m_length; }
47
    // Includes NUL-terminator.
48
1.99G
    char const* characters() const { return &m_inline_buffer[0]; }
49
50
460k
    ALWAYS_INLINE ReadonlyBytes bytes() const { return { characters(), length() }; }
51
1.99M
    ALWAYS_INLINE StringView view() const { return { characters(), length() }; }
52
53
    char const& operator[](size_t i) const
54
363M
    {
55
363M
        VERIFY(i < m_length);
56
363M
        return characters()[i];
57
363M
    }
58
59
    bool operator==(StringImpl const& other) const
60
128k
    {
61
128k
        if (length() != other.length())
62
75.9k
            return false;
63
52.9k
        return __builtin_memcmp(characters(), other.characters(), length()) == 0;
64
128k
    }
65
66
    unsigned hash() const
67
17.3M
    {
68
17.3M
        if (!m_has_hash)
69
14.7M
            compute_hash();
70
17.3M
        return m_hash;
71
17.3M
    }
72
73
    unsigned existing_hash() const
74
3.38M
    {
75
3.38M
        return m_hash;
76
3.38M
    }
77
78
    unsigned case_insensitive_hash() const;
79
80
1.14M
    bool is_fly() const { return m_fly; }
81
46.0k
    void set_fly(Badge<DeprecatedFlyString>, bool fly) const { m_fly = fly; }
82
83
private:
84
    enum ConstructTheEmptyStringImplTag {
85
        ConstructTheEmptyStringImpl
86
    };
87
    explicit StringImpl(ConstructTheEmptyStringImplTag)
88
64
        : m_fly(true)
89
64
    {
90
64
        m_inline_buffer[0] = '\0';
91
64
    }
92
93
    enum ConstructWithInlineBufferTag {
94
        ConstructWithInlineBuffer
95
    };
96
    StringImpl(ConstructWithInlineBufferTag, size_t length);
97
98
    void compute_hash() const;
99
100
    size_t m_length { 0 };
101
    mutable unsigned m_hash { 0 };
102
    mutable bool m_has_hash { false };
103
    mutable bool m_fly { false };
104
    char m_inline_buffer[0];
105
};
106
107
inline size_t allocation_size_for_stringimpl(size_t length)
108
872M
{
109
872M
    return sizeof(StringImpl) + (sizeof(char) * length) + sizeof(char);
110
872M
}
111
112
template<>
113
struct Formatter<StringImpl> : Formatter<StringView> {
114
    ErrorOr<void> format(FormatBuilder& builder, StringImpl const& value)
115
0
    {
116
0
        return Formatter<StringView>::format(builder, { value.characters(), value.length() });
117
0
    }
118
};
119
120
}
121
122
#if USING_AK_GLOBALLY
123
using AK::Chomp;
124
using AK::NoChomp;
125
using AK::StringImpl;
126
#endif