Coverage Report

Created: 2025-12-18 07:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/AK/StringImpl.h
Line
Count
Source
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
394M
    {
39
394M
        kfree_sized(ptr, allocation_size_for_stringimpl(static_cast<StringImpl*>(ptr)->m_length));
40
394M
    }
41
42
    static StringImpl& the_empty_stringimpl();
43
44
    ~StringImpl();
45
46
1.05G
    size_t length() const { return m_length; }
47
    // Includes NUL-terminator.
48
1.70G
    char const* characters() const { return &m_inline_buffer[0]; }
49
50
497k
    ALWAYS_INLINE ReadonlyBytes bytes() const { return { characters(), length() }; }
51
167
    ALWAYS_INLINE StringView view() const { return { characters(), length() }; }
52
53
    char const& operator[](size_t i) const
54
287M
    {
55
287M
        VERIFY(i < m_length);
56
287M
        return characters()[i];
57
287M
    }
58
59
    bool operator==(StringImpl const& other) const
60
3.46k
    {
61
3.46k
        if (length() != other.length())
62
2.83k
            return false;
63
628
        return __builtin_memcmp(characters(), other.characters(), length()) == 0;
64
3.46k
    }
65
66
    unsigned hash() const
67
16.6M
    {
68
16.6M
        if (!m_has_hash)
69
13.8M
            compute_hash();
70
16.6M
        return m_hash;
71
16.6M
    }
72
73
    unsigned existing_hash() const
74
558
    {
75
558
        return m_hash;
76
558
    }
77
78
    unsigned case_insensitive_hash() const;
79
80
951
    bool is_fly() const { return m_fly; }
81
801
    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
63
        : m_fly(true)
89
63
    {
90
63
        m_inline_buffer[0] = '\0';
91
63
    }
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
788M
{
109
788M
    return sizeof(StringImpl) + (sizeof(char) * length) + sizeof(char);
110
788M
}
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