stringcache: add a simple bulk string cache
This commit is contained in:
parent
5c3df6cd4c
commit
d099a159fb
@ -520,6 +520,8 @@ list (
|
||||
stream.hpp
|
||||
string.cpp
|
||||
string.hpp
|
||||
stringcache.cpp
|
||||
stringcache.hpp
|
||||
stringid.cpp
|
||||
stringid.hpp
|
||||
strongdef.cpp
|
||||
@ -734,6 +736,7 @@ if (TESTS)
|
||||
stream
|
||||
string
|
||||
stringid
|
||||
stringcache
|
||||
strongdef
|
||||
thread/condition_variable
|
||||
thread/event
|
||||
|
68
stringcache.cpp
Normal file
68
stringcache.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
/******************************************************************************
|
||||
_ _
|
||||
| | | |
|
||||
| | ___ | |__ ___
|
||||
| |/ _ \| '_ \ / _ \
|
||||
| | (_) | |_) | (_) |
|
||||
|_|\___/|_.__/ \___/
|
||||
Copyright:
|
||||
Danny Robson, 2020
|
||||
*****************************************************************************/
|
||||
|
||||
#include "stringcache.hpp"
|
||||
|
||||
#include "cast.hpp"
|
||||
|
||||
using cruft::stringcache;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
stringcache::id_t
|
||||
stringcache::add (std::string_view val)
|
||||
{
|
||||
auto const required_size = std::ssize (val);
|
||||
|
||||
if (m_values.size () > std::numeric_limits<value_type>::max ())
|
||||
throw std::bad_alloc ();
|
||||
if (m_store.size () + required_size > std::numeric_limits<value_type>::max ())
|
||||
throw std::bad_alloc ();
|
||||
|
||||
slot_t allocation {
|
||||
.start = value_type (m_store.size ()),
|
||||
.length = value_type (required_size),
|
||||
};
|
||||
|
||||
m_store.resize (m_store.size () + allocation.length);
|
||||
std::copy (
|
||||
std::begin (val),
|
||||
std::end (val),
|
||||
std::begin (m_store) + allocation.start
|
||||
);
|
||||
|
||||
m_values.push_back (allocation);
|
||||
return id_t (m_values.size () - 1);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
stringcache::id_t
|
||||
stringcache::add (std::string const &val)
|
||||
{
|
||||
return add (std::string_view (val));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
stringcache::id_t
|
||||
stringcache::add (char const *val)
|
||||
{
|
||||
return add (std::string_view (val));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
std::string_view
|
||||
stringcache::operator[] (id_t idx)
|
||||
{
|
||||
slot_t const entry = m_values[value_type (idx)];
|
||||
return std::string_view (m_store.data () + entry.start, entry.length);
|
||||
}
|
45
stringcache.hpp
Normal file
45
stringcache.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/******************************************************************************
|
||||
_ _
|
||||
| | | |
|
||||
| | ___ | |__ ___
|
||||
| |/ _ \| '_ \ / _ \
|
||||
| | (_) | |_) | (_) |
|
||||
|_|\___/|_.__/ \___/
|
||||
Copyright:
|
||||
Danny Robson, 2020
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "./std.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace cruft {
|
||||
/// Stores strings in a single block of memory where they can be indexed
|
||||
/// by an integral id, and compacted to save space as required.
|
||||
class stringcache {
|
||||
using value_type = i16;
|
||||
|
||||
public:
|
||||
enum id_t : value_type {};
|
||||
|
||||
std::string_view operator[] (id_t);
|
||||
|
||||
id_t add (std::string_view);
|
||||
id_t add (std::string const &);
|
||||
id_t add (char const*);
|
||||
|
||||
private:
|
||||
struct slot_t {
|
||||
value_type start;
|
||||
value_type length;
|
||||
};
|
||||
|
||||
std::vector<slot_t> m_values;
|
||||
std::vector<char> m_store;
|
||||
};
|
||||
}
|
40
test/stringcache.cpp
Normal file
40
test/stringcache.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include <cruft/util/tap.hpp>
|
||||
#include <cruft/util/stringcache.hpp>
|
||||
#include <cruft/util/iterator/zip.hpp>
|
||||
|
||||
|
||||
int main ()
|
||||
{
|
||||
cruft::TAP::logger tap;
|
||||
|
||||
{
|
||||
static constexpr const char* VALUES[] = {
|
||||
"foo",
|
||||
"bar",
|
||||
"qux",
|
||||
"the",
|
||||
"quick",
|
||||
"brown",
|
||||
"fox",
|
||||
};
|
||||
|
||||
cruft::stringcache cache;
|
||||
|
||||
std::vector<cruft::stringcache::id_t> indices;
|
||||
for (auto const v: VALUES)
|
||||
indices.push_back (cache.add (v));
|
||||
|
||||
bool success = true;
|
||||
for (auto const [expected, idx]: cruft::iterator::zip (VALUES, indices)) {
|
||||
auto const actual = cache[idx];
|
||||
if (actual != expected) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tap.expect (success, "cache holds values");
|
||||
}
|
||||
|
||||
return tap.status ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user