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

View file

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