Coverage Report

Created: 2022-05-20 06:13

/src/serenity/AK/FlyString.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <AK/FlyString.h>
8
#include <AK/HashTable.h>
9
#include <AK/Optional.h>
10
#include <AK/Singleton.h>
11
#include <AK/String.h>
12
#include <AK/StringUtils.h>
13
#include <AK/StringView.h>
14
15
namespace AK {
16
17
struct FlyStringImplTraits : public Traits<StringImpl*> {
18
0
    static unsigned hash(StringImpl const* s) { return s ? s->hash() : 0; }
19
    static bool equals(StringImpl const* a, StringImpl const* b)
20
0
    {
21
0
        VERIFY(a);
22
0
        VERIFY(b);
23
0
        return *a == *b;
24
0
    }
25
};
26
27
static Singleton<HashTable<StringImpl*, FlyStringImplTraits>> s_table;
28
29
static HashTable<StringImpl*, FlyStringImplTraits>& fly_impls()
30
0
{
31
0
    return *s_table;
32
0
}
33
34
void FlyString::did_destroy_impl(Badge<StringImpl>, StringImpl& impl)
35
0
{
36
0
    fly_impls().remove(&impl);
37
0
}
38
39
FlyString::FlyString(String const& string)
40
0
{
41
0
    if (string.is_null())
42
0
        return;
43
0
    if (string.impl()->is_fly()) {
44
0
        m_impl = string.impl();
45
0
        return;
46
0
    }
47
0
    auto it = fly_impls().find(const_cast<StringImpl*>(string.impl()));
48
0
    if (it == fly_impls().end()) {
49
0
        fly_impls().set(const_cast<StringImpl*>(string.impl()));
50
0
        string.impl()->set_fly({}, true);
51
0
        m_impl = string.impl();
52
0
    } else {
53
0
        VERIFY((*it)->is_fly());
54
0
        m_impl = *it;
55
0
    }
56
0
}
57
58
FlyString::FlyString(StringView string)
59
0
{
60
0
    if (string.is_null())
61
0
        return;
62
0
    auto it = fly_impls().find(string.hash(), [&](auto& candidate) {
63
0
        return string == candidate;
64
0
    });
65
0
    if (it == fly_impls().end()) {
66
0
        auto new_string = string.to_string();
67
0
        fly_impls().set(new_string.impl());
68
0
        new_string.impl()->set_fly({}, true);
69
0
        m_impl = new_string.impl();
70
0
    } else {
71
0
        VERIFY((*it)->is_fly());
72
0
        m_impl = *it;
73
0
    }
74
0
}
75
76
template<typename T>
77
Optional<T> FlyString::to_int(TrimWhitespace trim_whitespace) const
78
0
{
79
0
    return StringUtils::convert_to_int<T>(view(), trim_whitespace);
80
0
}
Unexecuted instantiation: AK::Optional<signed char> AK::FlyString::to_int<signed char>(AK::TrimWhitespace) const
Unexecuted instantiation: AK::Optional<short> AK::FlyString::to_int<short>(AK::TrimWhitespace) const
Unexecuted instantiation: AK::Optional<int> AK::FlyString::to_int<int>(AK::TrimWhitespace) const
Unexecuted instantiation: AK::Optional<long> AK::FlyString::to_int<long>(AK::TrimWhitespace) const
81
82
template Optional<i8> FlyString::to_int(TrimWhitespace) const;
83
template Optional<i16> FlyString::to_int(TrimWhitespace) const;
84
template Optional<i32> FlyString::to_int(TrimWhitespace) const;
85
template Optional<i64> FlyString::to_int(TrimWhitespace) const;
86
87
template<typename T>
88
Optional<T> FlyString::to_uint(TrimWhitespace trim_whitespace) const
89
0
{
90
0
    return StringUtils::convert_to_uint<T>(view(), trim_whitespace);
91
0
}
Unexecuted instantiation: AK::Optional<unsigned char> AK::FlyString::to_uint<unsigned char>(AK::TrimWhitespace) const
Unexecuted instantiation: AK::Optional<unsigned short> AK::FlyString::to_uint<unsigned short>(AK::TrimWhitespace) const
Unexecuted instantiation: AK::Optional<unsigned int> AK::FlyString::to_uint<unsigned int>(AK::TrimWhitespace) const
Unexecuted instantiation: AK::Optional<unsigned long> AK::FlyString::to_uint<unsigned long>(AK::TrimWhitespace) const
92
93
template Optional<u8> FlyString::to_uint(TrimWhitespace) const;
94
template Optional<u16> FlyString::to_uint(TrimWhitespace) const;
95
template Optional<u32> FlyString::to_uint(TrimWhitespace) const;
96
template Optional<u64> FlyString::to_uint(TrimWhitespace) const;
97
98
bool FlyString::equals_ignoring_case(StringView other) const
99
0
{
100
0
    return StringUtils::equals_ignoring_case(view(), other);
101
0
}
102
103
bool FlyString::starts_with(StringView str, CaseSensitivity case_sensitivity) const
104
0
{
105
0
    return StringUtils::starts_with(view(), str, case_sensitivity);
106
0
}
107
108
bool FlyString::ends_with(StringView str, CaseSensitivity case_sensitivity) const
109
0
{
110
0
    return StringUtils::ends_with(view(), str, case_sensitivity);
111
0
}
112
113
FlyString FlyString::to_lowercase() const
114
0
{
115
0
    return String(*m_impl).to_lowercase();
116
0
}
117
118
bool FlyString::operator==(String const& other) const
119
0
{
120
0
    return m_impl == other.impl() || view() == other.view();
121
0
}
122
123
bool FlyString::operator==(StringView string) const
124
0
{
125
0
    return view() == string;
126
0
}
127
128
bool FlyString::operator==(char const* string) const
129
0
{
130
0
    return view() == string;
131
0
}
132
133
}