Common/String: Don't copy StaticStrings when not writing

This commit is contained in:
Connor McLaughlin 2020-02-28 17:00:02 +10:00
parent 4fe57e64d7
commit 86094b8080
2 changed files with 18 additions and 24 deletions

View File

@ -124,7 +124,7 @@ static String::StringData* StringDataReallocate(String::StringData* pStringData,
static bool StringDataIsSharable(const String::StringData* pStringData)
{
return pStringData->ReferenceCount != -1;
return pStringData->ReadOnly || pStringData->ReferenceCount != -1;
}
static bool StringDataIsShared(const String::StringData* pStringData)
@ -145,7 +145,8 @@ String::String(const String& copyString)
else if (StringDataIsSharable(copyString.m_pStringData))
{
m_pStringData = copyString.m_pStringData;
StringDataAddRef(m_pStringData);
if (!m_pStringData->ReadOnly)
StringDataAddRef(m_pStringData);
}
// create a clone for ourselves
else
@ -525,7 +526,8 @@ void String::Assign(const String& copyString)
else if (StringDataIsSharable(copyString.m_pStringData))
{
m_pStringData = copyString.m_pStringData;
StringDataAddRef(m_pStringData);
if (!m_pStringData->ReadOnly)
StringDataAddRef(m_pStringData);
}
// create a clone for ourselves
else

View File

@ -1,6 +1,6 @@
#pragma once
#include "types.h"
#include <atomic>
#include <algorithm>
#include <cstdarg>
#include <cstring>
#include <limits>
@ -29,7 +29,7 @@ public:
// Reference count of this data object. If set to -1,
// it is considered noncopyable and any copies of the string
// will always create their own copy.
std::atomic<s32> ReferenceCount;
s32 ReferenceCount;
// Whether the memory pointed to by pBuffer is writable.
bool ReadOnly;
@ -50,6 +50,9 @@ public:
// Move constructor, take reference from other string.
String(String&& moveString);
// Construct a string from a data object, does not increment the reference count on the string data, use carefully.
explicit String(StringData* pStringData) : m_pStringData(pStringData) {}
// Destructor. Child classes may not have any destructors, as this is not virtual.
~String();
@ -251,10 +254,6 @@ public:
bool operator>(const char* compString) const { return (NumericCompare(compString) > 0); }
protected:
// Hidden constructor for creating string child classes.
// It does not increment the reference count on the string data, therefore dangerous to be public.
String(StringData* pStringData) : m_pStringData(pStringData) {}
// Internal append function.
void InternalPrepend(const char* pString, u32 Length);
void InternalAppend(const char* pString, u32 Length);
@ -267,21 +266,14 @@ protected:
};
// static string, stored in .rodata
class StaticString : public String
{
public:
StaticString(const char* Text)
{
m_sStringData.pBuffer = const_cast<char*>(Text);
m_sStringData.StringLength = static_cast<u32>(std::strlen(Text));
m_sStringData.BufferSize = m_sStringData.StringLength + 1;
m_sStringData.ReadOnly = true;
m_sStringData.ReferenceCount = -1;
}
private:
StringData m_sStringData;
};
#define StaticString(Text) \
[]() noexcept -> String { \
static constexpr u32 buffer_size = sizeof(Text); \
static constexpr u32 length = buffer_size - 1; \
static constexpr String::StringData data{const_cast<char*>(Text), length, buffer_size, static_cast<s32>(-1), \
true}; \
return String(const_cast<String::StringData*>(&data)); \
}()
// stack-allocated string
template<u32 L>