KDE/app/src/main/cpp/StringRepository.cpp
2022-12-16 12:18:47 +01:00

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;
}