#include "StringRepository.h" #include "Profiling.h" #include #include 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(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(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(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(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; }