mirror of https://github.com/stenzek/duckstation
Add StringPool and BumpStringPool classes
parent
84806d3055
commit
ac4634c289
@ -0,0 +1,116 @@
|
||||
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#include "string_pool.h"
|
||||
|
||||
BumpStringPool::BumpStringPool() = default;
|
||||
|
||||
BumpStringPool::~BumpStringPool() = default;
|
||||
|
||||
std::string_view BumpStringPool::GetString(Offset offset) const
|
||||
{
|
||||
if (offset == InvalidOffset || offset >= m_buffer.size())
|
||||
return {};
|
||||
|
||||
const char* str = m_buffer.data() + offset;
|
||||
return std::string_view(str);
|
||||
}
|
||||
|
||||
void BumpStringPool::Clear()
|
||||
{
|
||||
m_buffer.clear();
|
||||
}
|
||||
|
||||
size_t BumpStringPool::GetSize() const
|
||||
{
|
||||
return m_buffer.size();
|
||||
}
|
||||
|
||||
bool BumpStringPool::IsEmpty() const
|
||||
{
|
||||
return m_buffer.empty();
|
||||
}
|
||||
|
||||
void BumpStringPool::Reserve(size_t size)
|
||||
{
|
||||
m_buffer.reserve(size);
|
||||
}
|
||||
|
||||
BumpStringPool::Offset BumpStringPool::AddString(std::string_view str)
|
||||
{
|
||||
if (str.empty())
|
||||
return InvalidOffset;
|
||||
|
||||
const Offset offset = static_cast<Offset>(m_buffer.size());
|
||||
const size_t required_size = str.size() + 1; // +1 for null terminator
|
||||
|
||||
m_buffer.reserve(m_buffer.size() + required_size);
|
||||
m_buffer.insert(m_buffer.end(), str.begin(), str.end());
|
||||
m_buffer.push_back('\0');
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
std::string_view StringPool::GetString(Offset offset) const
|
||||
{
|
||||
if (offset == InvalidOffset || offset >= m_buffer.size())
|
||||
return {};
|
||||
|
||||
const char* str = m_buffer.data() + offset;
|
||||
return std::string_view(str);
|
||||
}
|
||||
|
||||
void StringPool::Clear()
|
||||
{
|
||||
m_buffer.clear();
|
||||
m_string_map.clear();
|
||||
}
|
||||
|
||||
size_t StringPool::GetSize() const
|
||||
{
|
||||
return m_buffer.size();
|
||||
}
|
||||
|
||||
bool StringPool::IsEmpty() const
|
||||
{
|
||||
return m_buffer.empty();
|
||||
}
|
||||
|
||||
size_t StringPool::GetCount() const
|
||||
{
|
||||
return m_string_map.size();
|
||||
}
|
||||
|
||||
void StringPool::Reserve(size_t size)
|
||||
{
|
||||
m_buffer.reserve(size);
|
||||
}
|
||||
|
||||
StringPool::StringPool() = default;
|
||||
|
||||
StringPool::~StringPool() = default;
|
||||
|
||||
StringPool::Offset StringPool::AddString(std::string_view str)
|
||||
{
|
||||
if (str.empty())
|
||||
return InvalidOffset;
|
||||
|
||||
// Check if string already exists
|
||||
auto it = m_string_map.find(str);
|
||||
if (it != m_string_map.end())
|
||||
return it->second;
|
||||
|
||||
// Add new string to buffer
|
||||
const Offset offset = static_cast<Offset>(m_buffer.size());
|
||||
const size_t required_size = str.size() + 1; // +1 for null terminator
|
||||
|
||||
m_buffer.reserve(m_buffer.size() + required_size);
|
||||
m_buffer.insert(m_buffer.end(), str.begin(), str.end());
|
||||
m_buffer.push_back('\0');
|
||||
|
||||
// Store string_view pointing to buffer in map
|
||||
std::string_view stored_str(m_buffer.data() + offset, str.size());
|
||||
m_string_map.emplace(stored_str, offset);
|
||||
|
||||
return offset;
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "heterogeneous_containers.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class BumpStringPool
|
||||
{
|
||||
public:
|
||||
using Offset = size_t;
|
||||
static constexpr Offset InvalidOffset = static_cast<Offset>(-1);
|
||||
|
||||
BumpStringPool();
|
||||
~BumpStringPool();
|
||||
|
||||
// Adds a string to the pool and returns its offset
|
||||
[[nodiscard]] Offset AddString(std::string_view str);
|
||||
|
||||
// Retrieves a string view from the pool using an offset
|
||||
[[nodiscard]] std::string_view GetString(Offset offset) const;
|
||||
|
||||
// Clears all strings from the pool
|
||||
void Clear();
|
||||
|
||||
// Returns the total size of the pool in bytes
|
||||
[[nodiscard]] size_t GetSize() const;
|
||||
|
||||
// Returns whether the pool is empty
|
||||
[[nodiscard]] bool IsEmpty() const;
|
||||
|
||||
// Reserves space in the buffer to avoid frequent reallocations
|
||||
void Reserve(size_t size);
|
||||
|
||||
private:
|
||||
std::vector<char> m_buffer;
|
||||
};
|
||||
|
||||
class StringPool
|
||||
{
|
||||
public:
|
||||
using Offset = size_t;
|
||||
static constexpr Offset InvalidOffset = static_cast<Offset>(-1);
|
||||
|
||||
StringPool();
|
||||
~StringPool();
|
||||
|
||||
// Adds a string to the pool and returns its offset. If the string already exists, returns the existing offset.
|
||||
[[nodiscard]] Offset AddString(std::string_view str);
|
||||
|
||||
// Retrieves a string view from the pool using an offset
|
||||
[[nodiscard]] std::string_view GetString(Offset offset) const;
|
||||
|
||||
// Clears all strings from the pool
|
||||
void Clear();
|
||||
|
||||
// Returns the total size of the pool in bytes
|
||||
[[nodiscard]] size_t GetSize() const;
|
||||
|
||||
// Returns whether the pool is empty
|
||||
[[nodiscard]] bool IsEmpty() const;
|
||||
|
||||
// Returns the number of unique strings in the pool
|
||||
[[nodiscard]] size_t GetCount() const;
|
||||
|
||||
// Reserves space in the buffer to avoid frequent reallocations
|
||||
void Reserve(size_t size);
|
||||
|
||||
private:
|
||||
std::vector<char> m_buffer;
|
||||
PreferUnorderedStringMap<Offset> m_string_map;
|
||||
};
|
Loading…
Reference in New Issue