fix(eventsub/string): minor cleanups (#5973)

This commit is contained in:
nerix
2025-02-22 13:49:38 +01:00
committed by GitHub
parent 8a639c2dc3
commit 22c6c8dba8
3 changed files with 54 additions and 26 deletions
@@ -24,19 +24,22 @@ namespace chatterino::eventsub::lib {
/// is **not** null-terminated.
struct String {
constexpr String() noexcept = default;
constexpr String(std::string_view sv)
String(std::string_view sv)
: flags(sv.length() & LENGTH_MASK)
{
if (sv.length() <= SSO_CAPACITY)
char *data = this->storage.inPlace;
if (sv.length() > SSO_CAPACITY)
{
std::memcpy(this->storage.inPlace, sv.data(), sv.length());
return;
data = new char[sv.length()];
this->flags |= ALLOC_BIT;
this->storage.data = data;
}
this->flags |= ALLOC_BIT;
auto *data = new char[sv.length()];
std::memcpy(data, sv.data(), sv.length());
this->storage.data = data;
for (size_t i = 0; i < sv.length(); i++)
{
data[i] = sv[i];
}
}
~String()
@@ -117,7 +120,7 @@ struct String {
return this->storage.qt;
}
QAnyStringView view() const noexcept
constexpr QAnyStringView view() const noexcept
{
if (this->isQt())
{
@@ -158,15 +161,6 @@ private:
static_assert((LENGTH_MASK & ALLOC_BIT) == 0);
static_assert((LENGTH_MASK & QT_BIT) == 0);
constexpr size_t length() const noexcept
{
if ((this->flags & QT_BIT) != 0)
{
return this->storage.qt.length();
}
return this->flags & LENGTH_MASK;
}
mutable union Storage {
constexpr Storage() noexcept
{
@@ -178,9 +172,6 @@ private:
Storage(const Storage &) = delete;
Storage &operator=(const Storage &) = delete;
// we can memcpy QStrings as they're relocatable
static_assert(QTypeInfo<QString>::isRelocatable != 0);
Storage(Storage &&other) noexcept
{
Storage::move(std::addressof(other), this);
@@ -198,10 +189,18 @@ private:
private:
static void move(Storage *from, Storage *to)
{
// we can memcpy QStrings as they're relocatable
static_assert(QTypeInfo<QString>::isRelocatable != 0);
// copy `from` -> `to`
std::memcpy(to, from, sizeof(Storage));
// clear `from`
std::memset(from, 0, sizeof(Storage));
std::memcpy(static_cast<void *>(to), from, sizeof(Storage));
#ifndef NDEBUG
// Mark `from` as unused.
// Because the parent `String` sets the flags to 0,
// we don't _need_ to overwrite the data. In debug mode we write a
// tombstone value here.
std::memset(static_cast<void *>(from), 0xff, sizeof(Storage));
#endif
}
} storage;
static_assert(sizeof(Storage) == sizeof(QString));
+30 -1
View File
@@ -479,10 +479,39 @@ TEST(String, MoveAssign)
TEST(String, QtLifetime)
{
QString qt;
{
String s(REALLY_LONG);
qt = s.qt();
ASSERT_TRUE(!qt.isDetached()); // s holds the string too
ASSERT_FALSE(qt.isDetached()); // s holds the string too
}
ASSERT_TRUE(qt.isDetached());
// move assignments
{
String s(REALLY_LONG);
qt = s.qt();
ASSERT_FALSE(qt.isDetached());
s = {};
ASSERT_TRUE(qt.isDetached());
}
ASSERT_TRUE(qt.isDetached());
{
String s(REALLY_LONG);
qt = s.qt();
ASSERT_FALSE(qt.isDetached());
s = {LONGEST_SSO};
ASSERT_TRUE(qt.isDetached());
}
ASSERT_TRUE(qt.isDetached());
{
String s(REALLY_LONG);
qt = s.qt();
ASSERT_FALSE(qt.isDetached());
s = {REALLY_LONG};
ASSERT_TRUE(qt.isDetached());
}
ASSERT_TRUE(qt.isDetached());
}