96 lines
2.5 KiB
C++
96 lines
2.5 KiB
C++
#include "StringRepository.h"
|
|
#include "Profiling.h"
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
static StringRepository g_global_repository;
|
|
StringRepository* StringRepository::global = &g_global_repository;
|
|
|
|
static uint64_t hashString(const char* string, unsigned int length)
|
|
{
|
|
ZoneScoped;
|
|
uint64_t hash = 0xcbf29ce484222325;
|
|
for (unsigned int i = 0; i < length; ++i) {
|
|
hash = hash ^ string[i];
|
|
hash = hash * 0x00000100000001B3;
|
|
}
|
|
if (hash == HASH_EMPTY_KEY || hash == HASH_TOMBSTONE_KEY)
|
|
hash = ~hash;
|
|
return hash;
|
|
}
|
|
|
|
StringRepository::StringRepository(const StringRepository& copy)
|
|
{
|
|
ZoneScoped;
|
|
if (m_buffer)
|
|
free(m_buffer);
|
|
m_one_past_last_char = copy.m_one_past_last_char;
|
|
m_buffer_size = copy.m_buffer_size;
|
|
m_hash = copy.m_hash;
|
|
m_buffer = reinterpret_cast<char*>(malloc(m_buffer_size));
|
|
memcpy(m_buffer, copy.m_buffer, m_buffer_size);
|
|
}
|
|
|
|
StringRepository::~StringRepository()
|
|
{
|
|
ZoneScoped;
|
|
m_one_past_last_char = 0;
|
|
m_buffer_size = 0;
|
|
free(m_buffer);
|
|
}
|
|
|
|
StringHandle StringRepository::internStringLength(const char* string, unsigned int length)
|
|
{
|
|
ZoneScoped;
|
|
uint64_t hash = hashString(string, length);
|
|
uint32_t offset = static_cast<uint32_t>(m_hash.lookup(hash, UINT32_MAX));
|
|
if (offset == UINT32_MAX) {
|
|
offset = m_one_past_last_char;
|
|
if ((offset + length + 1) >= m_buffer_size) {
|
|
uint32_t new_size = (m_buffer_size > 0) ? 2 * m_buffer_size : 1024;
|
|
void* tmp = realloc(m_buffer, new_size);
|
|
if (!tmp)
|
|
return 0;
|
|
m_buffer = reinterpret_cast<char*>(tmp);
|
|
m_buffer_size = new_size;
|
|
}
|
|
char* dest = m_buffer + offset;
|
|
memcpy(dest, string, length);
|
|
dest[length] = '\0';
|
|
m_one_past_last_char += length + 1;
|
|
if (!m_hash.insert(hash, offset))
|
|
return 0;
|
|
}
|
|
return static_cast<StringHandle>(offset + 1);
|
|
}
|
|
|
|
StringHandle StringRepository::internString(const char* string)
|
|
{
|
|
ZoneScoped;
|
|
return internStringLength(string, strlen(string));
|
|
}
|
|
|
|
const char* StringRepository::getString(StringHandle handle)
|
|
{
|
|
ZoneScoped;
|
|
if (handle == 0 || handle >= m_one_past_last_char)
|
|
return nullptr;
|
|
uint32_t offset = handle - 1;
|
|
return &m_buffer[offset];
|
|
}
|
|
|
|
void StringRepository::releaseString(StringHandle)
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
void StringRepository::freeAll()
|
|
{
|
|
ZoneScoped;
|
|
m_one_past_last_char = 0;
|
|
m_hash = Hash();
|
|
m_buffer_size = 0;
|
|
free(m_buffer);
|
|
m_buffer = nullptr;
|
|
}
|