1
0
Fork 0
mirror of https://github.com/systemed/tilemaker synced 2025-02-21 13:24:09 +01:00
tilemaker/include/pooled_string.h
Colin Dellow b77340c870 remove PossiblyKnownTagValue
When I replaced #604 with #626, I botched extracting this part of the
code. I had the trait, which taught kaguya how to serialize
`PossiblyKnownTagValue`, but I missed updating the parameter type
of `Attribute` to actually use it, so it was a no-op.

This PR restores the behaviour of avoiding string copies, but now that
we have protozero's data_view class, we can use that rather than
our own weirdo struct.
2024-01-11 23:29:50 -05:00

64 lines
2.2 KiB
C++

#ifndef _POOLED_STRING_H
#define _POOLED_STRING_H
// std::string is quite general:
// - mutable
// - unlimited length
// - capacity can differ from size
// - can deallocate its dynamic memory
//
// Our use case, by contrast is immutable, bounded strings that live for the
// duration of the process.
//
// This gives us some room to have less memory overhead, especially on
// g++, whose implementation of std::string requires 32 bytes.
//
// Thus, we implement `PooledString`. It has a size of 16 bytes, and a small
// string optimization for strings <= 15 bytes. (We will separately teach
// AttributePair to encode Latin-character strings more efficiently, so that many
// strings of size 24 or less fit in 15 bytes.)
//
// If it needs to allocate memory, it does so from a shared pool. It is unable
// to free the memory once allocated.
// PooledString has one of three modes:
// - [126:127] = 00: small-string, length is in [120:125], lower 15 bytes are string
// - [126:127] = 10: pooled string, table is in bytes 1..3, offset in bytes 4..5, length in bytes 6..7
// - [126:127] = 11: pointer to std::string, pointer is in bytes 8..15
//
// Note that the pointer mode is not safe to be stored. It exists just to allow
// lookups in the AttributePair map before deciding to allocate a string.
#include <cstdint>
#include <vector>
#include <string>
#include <protozero/data_view.hpp>
namespace PooledStringNS {
class PooledString {
public:
// Create a short string or heap string, long-lived.
PooledString(const std::string& str);
// Wrap a protozero::data_view - only valid so long as the
// data_view that is pointed to is valid; call ensureStringIsOwned
// if you need to persist the string.
PooledString(const protozero::data_view* str);
size_t size() const;
bool operator<(const PooledString& other) const;
bool operator==(const PooledString& other) const;
bool operator!=(const PooledString& other) const;
std::string toString() const;
const char* data() const;
void ensureStringIsOwned();
private:
// 0..3 is index into table, 4..5 is offset, 6..7 is length
uint8_t storage[16];
};
}
using PooledString = PooledStringNS::PooledString;
#endif