Fix but also trim shared strings.

This commit is contained in:
Skyth 2024-12-20 02:25:37 +03:00
parent 56c7ca9092
commit bacfe02d0e
5 changed files with 25 additions and 549 deletions

View file

@ -2,14 +2,14 @@
#include "SWA.inl"
inline static void* __HH_ALLOC(const uint32_t in_Size)
inline void* __HH_ALLOC(const uint32_t in_Size)
{
return GuestToHostFunction<void*>(0x82DFA0B0, in_Size, nullptr, 0, 0);
return GuestToHostFunction<void*>(sub_822C0988, in_Size);
}
inline static void __HH_FREE(const void* in_pData)
inline void __HH_FREE(const void* in_pData)
{
GuestToHostFunction<void>(0x82DF9E50, in_pData);
GuestToHostFunction<void>(sub_822C0270, in_pData);
}
namespace Hedgehog::Base

View file

@ -6,38 +6,16 @@ namespace Hedgehog::Base
{
struct SStringHolder
{
union
{
struct
{
be<uint16_t> Length;
be<uint16_t> RefCount;
};
be<uint32_t> RefCountAndLength;
};
char aStr[1u];
be<uint32_t> RefCount;
char aStr[];
static SStringHolder* GetHolder(const char* in_pStr);
static size_t GetMemorySize(const size_t in_Length);
static size_t GetMemorySizeAligned(const size_t in_Length);
static SStringHolder* Make(const char* in_pStr, const size_t in_Length);
static SStringHolder* Concat(
const char* in_pStrA, const size_t in_LengthA,
const char* in_pStrB, const size_t in_LengthB);
static SStringHolder* Make(const char* in_pStr);
void AddRef();
void Release();
bool IsUnique() const;
bool TryInplaceAssign(const char* in_pStr, const size_t in_Length);
bool TryInplaceAppend(const char* in_pStr, const size_t in_Length);
bool TryInplacePrepend(const char* in_pStr, const size_t in_Length);
};
}

View file

@ -2,70 +2,41 @@ namespace Hedgehog::Base
{
inline SStringHolder* SStringHolder::GetHolder(const char* in_pStr)
{
return (SStringHolder*)((size_t)in_pStr - sizeof(RefCountAndLength));
return (SStringHolder*)((size_t)in_pStr - sizeof(RefCount));
}
inline size_t SStringHolder::GetMemorySize(const size_t in_Length)
inline SStringHolder* SStringHolder::Make(const char* in_pStr)
{
return sizeof(RefCountAndLength) + in_Length;
}
inline size_t SStringHolder::GetMemorySizeAligned(const size_t in_Length)
{
return (GetMemorySize(in_Length) + 0x10) & ~0x0F;
}
inline SStringHolder* SStringHolder::Make(const char* in_pStr, const size_t in_Length)
{
const size_t memSize = GetMemorySize(in_Length);
const size_t memSizeAligned = GetMemorySizeAligned(in_Length);
auto pHolder = (SStringHolder*)__HH_ALLOC(memSizeAligned);
auto pHolder = (SStringHolder*)__HH_ALLOC(sizeof(RefCount) + strlen(in_pStr) + 1);
pHolder->RefCount = 1;
pHolder->Length = (uint16_t)in_Length;
if (in_pStr)
memcpy(pHolder->aStr, in_pStr, in_Length);
memset(&pHolder->aStr[in_Length], 0, memSizeAligned - memSize);
return pHolder;
}
inline SStringHolder* SStringHolder::Concat(const char* in_pStrA, const size_t in_LengthA, const char* in_pStrB, const size_t in_LengthB)
{
SStringHolder* pHolder = Make(nullptr, in_LengthA + in_LengthB);
memcpy(pHolder->aStr, in_pStrA, in_LengthA);
memcpy(&pHolder->aStr[in_LengthA], in_pStrB, in_LengthB);
strcpy(pHolder->aStr, in_pStr);
return pHolder;
}
inline void SStringHolder::AddRef()
{
std::atomic_ref atomicRef(RefCountAndLength.value);
std::atomic_ref refCount(RefCount.value);
uint32_t originalValue, incrementedValue;
be<uint32_t> original, incremented;
do
{
originalValue = RefCountAndLength.value;
incrementedValue = ByteSwap(ByteSwap(originalValue) + 1);
} while (!atomicRef.compare_exchange_weak(originalValue, incrementedValue));
original = RefCount;
incremented = original + 1;
} while (!refCount.compare_exchange_weak(original.value, incremented.value));
}
inline void SStringHolder::Release()
{
std::atomic_ref atomicRef(RefCountAndLength.value);
std::atomic_ref refCount(RefCount.value);
uint32_t originalValue, decrementedValue;
be<uint32_t> original, decremented;
do
{
originalValue = RefCountAndLength.value;
decrementedValue = ByteSwap(ByteSwap(originalValue) - 1);
} while (!atomicRef.compare_exchange_weak(originalValue, decrementedValue));
original = RefCount;
decremented = original - 1;
} while (!refCount.compare_exchange_weak(original.value, decremented.value));
if ((decrementedValue & 0xFFFF0000) == 0)
if (decremented == 0)
__HH_FREE(this);
}
@ -73,66 +44,4 @@ namespace Hedgehog::Base
{
return RefCount == 1;
}
inline bool SStringHolder::TryInplaceAssign(const char* in_pStr, const size_t in_Length)
{
if (!IsUnique())
return false;
const size_t memSizeAligned = GetMemorySizeAligned(in_Length);
if (memSizeAligned > GetMemorySizeAligned(Length))
return false;
if (in_pStr)
memcpy(aStr, in_pStr, in_Length);
memset(&aStr[in_Length], 0, memSizeAligned - GetMemorySize(in_Length));
Length = (uint16_t)in_Length;
return true;
}
inline bool SStringHolder::TryInplaceAppend(const char* in_pStr, const size_t in_Length)
{
if (!IsUnique())
return false;
const size_t memSizeAligned = GetMemorySizeAligned(Length + in_Length);
if (memSizeAligned > GetMemorySizeAligned(Length))
return false;
if (in_pStr)
memcpy(&aStr[Length], in_pStr, in_Length);
memset(&aStr[Length + in_Length], 0, memSizeAligned - GetMemorySize(Length + in_Length));
Length = (uint16_t)(Length + in_Length);
return true;
}
inline bool SStringHolder::TryInplacePrepend(const char* in_pStr, const size_t in_Length)
{
if (!IsUnique())
return false;
const size_t memSizeAligned = GetMemorySizeAligned(in_Length + Length);
if (memSizeAligned > GetMemorySizeAligned(Length))
return false;
memmove(&aStr[in_Length], aStr, Length);
if (in_pStr)
memcpy(aStr, in_pStr, in_Length);
memset(&aStr[in_Length + Length], 0, memSizeAligned - GetMemorySize(in_Length + Length));
Length = (uint16_t)(in_Length + Length);
return true;
}
}

View file

@ -32,56 +32,6 @@ namespace Hedgehog::Base
const char* begin() const;
const char* end() const;
CSharedString substr(size_t pos = 0, size_t len = npos) const;
size_t find(char c, size_t pos = 0) const;
size_t find(const char* s, size_t pos = 0) const;
size_t rfind(char c, size_t pos = npos) const;
size_t find_first_of(const char* s, size_t pos = 0) const;
size_t find_last_of(const char* s, size_t pos = npos) const;
size_t find_first_not_of(const char* s, size_t pos = 0) const;
size_t find_last_not_of(const char* s, size_t pos = npos) const;
size_t find(const CSharedString& str, size_t pos = 0) const;
size_t rfind(const CSharedString& str, size_t pos = npos) const;
size_t find_first_of(const CSharedString& str, size_t pos = 0) const;
size_t find_last_of(const CSharedString& str, size_t pos = npos) const;
size_t find_first_not_of(const CSharedString& str, size_t pos = 0) const;
size_t find_last_not_of(const CSharedString& str, size_t pos = npos) const;
void assign(const CSharedString& in_rOther);
void assign(const char* in_pStr);
void assign(CSharedString&& io_rOther);
void append(const CSharedString& in_rOther);
void append(const char* in_pStr);
void prepend(const CSharedString& in_rOther);
void prepend(const char* in_pStr);
int compare(const CSharedString& in_rOther) const;
CSharedString& operator=(const CSharedString& in_rOther);
CSharedString& operator=(const char* in_pStr);
CSharedString& operator=(CSharedString&& io_rOther);
CSharedString& operator+=(const CSharedString& in_rOther);
CSharedString& operator+=(const char* in_pStr);
friend CSharedString operator+(const CSharedString& in_rLeft, const CSharedString& in_rRight);
friend CSharedString operator+(const CSharedString& in_rLeft, const char* in_pRight);
friend CSharedString operator+(const char* in_pLeft, const CSharedString& in_pRight);
bool operator>(const CSharedString& in_rOther) const;
bool operator>=(const CSharedString& in_rOther) const;
bool operator<(const CSharedString& in_rOther) const;
bool operator<=(const CSharedString& in_rOther) const;
bool operator==(const CSharedString& in_rOther) const;
bool operator!=(const CSharedString& in_rOther) const;
bool operator==(const char* in_pOther) const;
bool operator!=(const char* in_pOther) const;
};
}

View file

@ -18,7 +18,7 @@ namespace Hedgehog::Base
size_t length;
if (in_pStr && (length = strlen(in_pStr)) != 0)
m_pStr.ptr = g_memory.MapVirtual(SStringHolder::Make(in_pStr, length)->aStr);
m_pStr.ptr = g_memory.MapVirtual(SStringHolder::Make(in_pStr)->aStr);
}
inline CSharedString::CSharedString(const CSharedString& in_rOther) : m_pStr(in_rOther.m_pStr)
@ -53,7 +53,7 @@ namespace Hedgehog::Base
inline size_t CSharedString::size() const
{
return GetHolder()->Length;
return strlen(m_pStr);
}
inline size_t CSharedString::length() const
@ -73,367 +73,6 @@ namespace Hedgehog::Base
inline const char* CSharedString::end() const
{
return &m_pStr[GetHolder()->Length];
}
inline CSharedString CSharedString::substr(size_t pos, size_t len) const
{
if (len == 0)
return CSharedString();
if (len > (GetHolder()->Length - pos))
len = GetHolder()->Length - pos;
if (pos == 0 && len == GetHolder()->Length)
return *this;
return SStringHolder::Make(&m_pStr[pos], len);
}
inline size_t CSharedString::find(char c, size_t pos) const
{
for (size_t i = pos; i < GetHolder()->Length; i++)
{
if (m_pStr[i] == c)
return i;
}
return npos;
}
inline size_t CSharedString::find(const char* s, size_t pos) const
{
size_t len = strlen(s);
for (size_t i = pos; i < GetHolder()->Length - len + 1; i++)
{
if (strncmp(m_pStr + i, s, len) == 0)
return i;
}
return npos;
}
inline size_t CSharedString::rfind(char c, size_t pos) const
{
if (pos >= GetHolder()->Length)
pos = GetHolder()->Length - 1;
for (size_t i = pos; i != static_cast<size_t>(-1); i--)
{
if (m_pStr[i] == c)
return i;
}
return npos;
}
inline size_t CSharedString::find_first_of(const char* s, size_t pos) const
{
size_t len = strlen(s);
for (size_t i = pos; i < GetHolder()->Length; i++)
{
for (size_t j = 0; j < len; j++)
{
if (m_pStr[i] == s[j])
return i;
}
}
return npos;
}
inline size_t CSharedString::find_last_of(const char* s, size_t pos) const
{
if (pos >= GetHolder()->Length)
pos = GetHolder()->Length - 1;
size_t len = strlen(s);
for (size_t i = pos; i != static_cast<size_t>(-1); i--)
{
for (size_t j = 0; j < len; j++)
{
if (m_pStr[i] == s[j])
return i;
}
}
return npos;
}
inline size_t CSharedString::find_first_not_of(const char* s, size_t pos) const
{
size_t len = strlen(s);
for (size_t i = pos; i < GetHolder()->Length; i++)
{
bool found = false;
for (size_t j = 0; j < len; j++)
{
if (m_pStr[i] == s[j])
{
found = true;
break;
}
}
if (!found)
return i;
}
return npos;
}
inline size_t CSharedString::find_last_not_of(const char* s, size_t pos) const
{
if (pos >= GetHolder()->Length)
pos = GetHolder()->Length - 1;
size_t len = strlen(s);
for (size_t i = pos; i != static_cast<size_t>(-1); i--)
{
bool found = false;
for (size_t j = 0; j < len; j++)
{
if (m_pStr[i] == s[j])
{
found = true;
break;
}
}
if (!found)
return i;
}
return npos;
}
inline size_t CSharedString::find(const CSharedString& str, size_t pos) const
{
return find(str.c_str(), pos);
}
inline size_t CSharedString::find_first_of(const CSharedString& str, size_t pos) const
{
return find_first_of(str.c_str(), pos);
}
inline size_t CSharedString::find_last_of(const CSharedString& str, size_t pos) const
{
return find_last_of(str.c_str(), pos);
}
inline size_t CSharedString::find_first_not_of(const CSharedString& str, size_t pos) const
{
return find_first_not_of(str.c_str(), pos);
}
inline size_t CSharedString::find_last_not_of(const CSharedString& str, size_t pos) const
{
return find_last_not_of(str.c_str(), pos);
}
inline void CSharedString::assign(const CSharedString& in_rOther)
{
GetHolder()->Release();
m_pStr = in_rOther.m_pStr;
GetHolder()->AddRef();
}
inline void CSharedString::assign(const char* in_pStr)
{
size_t length;
if (in_pStr && (length = strlen(in_pStr)) != 0)
{
if (!GetHolder()->TryInplaceAssign(in_pStr, length))
{
GetHolder()->Release();
m_pStr = SStringHolder::Make(in_pStr, length)->aStr;
}
}
else
{
GetHolder()->Release();
m_pStr = nullptr;
}
}
inline void CSharedString::assign(CSharedString&& io_rOther)
{
m_pStr = io_rOther.m_pStr;
io_rOther.m_pStr = nullptr;
}
inline void CSharedString::append(const CSharedString& in_rOther)
{
if (!GetHolder()->TryInplaceAppend(in_rOther.GetHolder()->aStr, in_rOther.GetHolder()->Length))
{
SStringHolder* pHolder = SStringHolder::Concat(
GetHolder()->aStr, GetHolder()->Length,
in_rOther.GetHolder()->aStr, in_rOther.GetHolder()->Length);
GetHolder()->Release();
m_pStr = pHolder->aStr;
}
}
inline void CSharedString::append(const char* in_pStr)
{
size_t length;
if (in_pStr && (length = strlen(in_pStr)) != 0)
{
if (!GetHolder()->TryInplaceAppend(in_pStr, length))
{
SStringHolder* pHolder = SStringHolder::Concat(
GetHolder()->aStr, GetHolder()->Length, in_pStr, length);
GetHolder()->Release();
m_pStr = pHolder->aStr;
}
}
}
inline void CSharedString::prepend(const CSharedString& in_rOther)
{
if (!GetHolder()->TryInplacePrepend(in_rOther.GetHolder()->aStr, in_rOther.GetHolder()->Length))
{
SStringHolder* pHolder = SStringHolder::Concat(
in_rOther.GetHolder()->aStr, in_rOther.GetHolder()->Length,
GetHolder()->aStr, GetHolder()->Length);
GetHolder()->Release();
m_pStr = pHolder->aStr;
}
}
inline void CSharedString::prepend(const char* in_pStr)
{
size_t length;
if (in_pStr && (length = strlen(in_pStr)) != 0)
{
if (!GetHolder()->TryInplacePrepend(in_pStr, length))
{
SStringHolder* pHolder = SStringHolder::Concat(
in_pStr, length, GetHolder()->aStr, GetHolder()->Length);
GetHolder()->Release();
m_pStr = pHolder->aStr;
}
}
}
inline int CSharedString::compare(const CSharedString& in_rOther) const
{
// TODO: DO NOT PASS BY REFERENCE.
return GuestToHostFunction<int>(0x82DFB028, this, &in_rOther);
}
inline CSharedString& CSharedString::operator=(const CSharedString& in_rOther)
{
assign(in_rOther);
return *this;
}
inline CSharedString& CSharedString::operator=(const char* in_pStr)
{
assign(in_pStr);
return *this;
}
inline CSharedString& CSharedString::operator=(CSharedString&& io_rOther)
{
assign(std::move(io_rOther));
return *this;
}
inline CSharedString& CSharedString::operator+=(const CSharedString& in_rOther)
{
append(in_rOther);
return *this;
}
inline CSharedString& CSharedString::operator+=(const char* in_pStr)
{
append(in_pStr);
return *this;
}
inline CSharedString operator+(const CSharedString& in_rLeft, const CSharedString& in_rRight)
{
return SStringHolder::Concat(
in_rLeft.GetHolder()->aStr, in_rLeft.GetHolder()->Length,
in_rRight.GetHolder()->aStr, in_rRight.GetHolder()->Length);
}
inline CSharedString operator+(const CSharedString& in_rLeft, const char* in_pRight)
{
size_t length;
if (in_pRight && (length = strlen(in_pRight)) != 0)
{
return SStringHolder::Concat(
in_rLeft.GetHolder()->aStr, in_rLeft.GetHolder()->Length, in_pRight, length);
}
else
{
return in_rLeft;
}
}
inline CSharedString operator+(const char* in_pLeft, const CSharedString& in_pRight)
{
size_t length;
if (in_pLeft && (length = strlen(in_pLeft)) != 0)
{
return SStringHolder::Concat(
in_pLeft, length, in_pRight.GetHolder()->aStr, in_pRight.GetHolder()->Length);
}
else
{
return in_pRight;
}
}
inline bool CSharedString::operator>(const CSharedString& in_rOther) const
{
return compare(in_rOther) > 0;
}
inline bool CSharedString::operator>=(const CSharedString& in_rOther) const
{
return compare(in_rOther) >= 0;
}
inline bool CSharedString::operator<(const CSharedString& in_rOther) const
{
return compare(in_rOther) < 0;
}
inline bool CSharedString::operator<=(const CSharedString& in_rOther) const
{
return compare(in_rOther) <= 0;
}
inline bool CSharedString::operator==(const CSharedString& in_rOther) const
{
return compare(in_rOther) == 0;
}
inline bool CSharedString::operator!=(const CSharedString& in_rOther) const
{
return !(*this == in_rOther);
}
inline bool CSharedString::operator==(const char* in_pOther) const
{
return strcmp(c_str(), in_pOther) == 0;
}
inline bool CSharedString::operator!=(const char* in_pOther) const
{
return !(*this == in_pOther);
return &m_pStr[size()];
}
}