mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-25 14:05:15 +00:00
LibUnicode: Generalize the generators' unique string storage
UniqueStringStorage is used to ensure only one copy of a string will be generated, and interested parties store just an index into the generated storage. Generalize this class to allow any* type to be stored uniquely. * To actually be storable, the type must have both an AK::Format and an AK::Traits overload available.
This commit is contained in:
parent
152d455143
commit
d8e6beb14f
Notes:
sideshowbarker
2024-07-17 23:07:28 +09:00
Author: https://github.com/trflynn89 Commit: https://github.com/SerenityOS/serenity/commit/d8e6beb14f0 Pull-request: https://github.com/SerenityOS/serenity/pull/11160
1 changed files with 51 additions and 33 deletions
|
@ -19,60 +19,67 @@
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
#include <LibUnicode/Locale.h>
|
#include <LibUnicode/Locale.h>
|
||||||
|
|
||||||
template<typename StringIndexType>
|
template<typename StorageType, typename IndexType>
|
||||||
class UniqueStringStorage {
|
class UniqueStorage {
|
||||||
public:
|
public:
|
||||||
StringIndexType ensure(String string)
|
IndexType ensure(StorageType value)
|
||||||
{
|
{
|
||||||
// We maintain a set of unique strings in two structures: a vector which owns the unique string,
|
// We maintain a set of unique values in two structures: a vector which stores the values in
|
||||||
// and a hash map which maps that string to its index in the vector. The vector is to ensure the
|
// the order they are added, and a hash map which maps that value to its index in the vetor.
|
||||||
// strings are generated in an easily known order, and the map is to allow quickly deciding if a
|
// The vector is to ensure the values are generated in an easily known order, and the map is
|
||||||
// string is actually unique (otherwise, we'd have to linear-search the vector for each string).
|
// to allow quickly deciding if a value is actually unique (otherwise, we'd have to linearly
|
||||||
|
// search the vector for each value).
|
||||||
//
|
//
|
||||||
// Also note that index 0 will be reserved for the empty string, so the index returned from this
|
// Also note that index 0 will be reserved for the default-initialized value, so the index
|
||||||
// method is actually the real index in the vector + 1.
|
// returned from this method is actually the real index in the vector + 1.
|
||||||
if (auto index = m_unique_string_indices.get(string); index.has_value())
|
if (auto index = m_storage_indices.get(value); index.has_value())
|
||||||
return *index;
|
return *index;
|
||||||
|
|
||||||
m_unique_strings.append(move(string));
|
m_storage.append(move(value));
|
||||||
size_t index = m_unique_strings.size();
|
size_t index = m_storage.size();
|
||||||
|
|
||||||
VERIFY(index < NumericLimits<StringIndexType>::max());
|
VERIFY(index < NumericLimits<IndexType>::max());
|
||||||
|
|
||||||
auto string_index = static_cast<StringIndexType>(index);
|
auto storage_index = static_cast<IndexType>(index);
|
||||||
m_unique_string_indices.set(m_unique_strings.last(), string_index);
|
m_storage_indices.set(m_storage.last(), storage_index);
|
||||||
|
|
||||||
return string_index;
|
return storage_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringView get(StringIndexType index) const
|
StorageType const& get(IndexType index) const
|
||||||
{
|
{
|
||||||
if (index == 0)
|
if (index == 0) {
|
||||||
return {};
|
static StorageType empty {};
|
||||||
|
return empty;
|
||||||
VERIFY(index <= m_unique_strings.size());
|
|
||||||
return m_unique_strings.at(index - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate(SourceGenerator& generator)
|
VERIFY(index <= m_storage.size());
|
||||||
|
return m_storage.at(index - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate(SourceGenerator& generator, StringView type, StringView name, size_t max_values_per_row)
|
||||||
{
|
{
|
||||||
generator.set("size"sv, String::number(m_unique_strings.size()));
|
generator.set("type"sv, type);
|
||||||
|
generator.set("name"sv, name);
|
||||||
|
generator.set("size"sv, String::number(m_storage.size()));
|
||||||
|
|
||||||
generator.append(R"~~~(
|
generator.append(R"~~~(
|
||||||
static constexpr Array<StringView, @size@ + 1> s_string_list { {
|
static constexpr Array<@type@, @size@ + 1> @name@ { {
|
||||||
{})~~~");
|
{})~~~");
|
||||||
|
|
||||||
constexpr size_t max_strings_per_row = 40;
|
size_t values_in_current_row = 1;
|
||||||
size_t strings_in_current_row = 1;
|
|
||||||
|
|
||||||
for (auto const& string : m_unique_strings) {
|
for (auto const& value : m_storage) {
|
||||||
if (strings_in_current_row++ > 0)
|
if (values_in_current_row++ > 0)
|
||||||
generator.append(", ");
|
generator.append(", ");
|
||||||
|
|
||||||
generator.append(String::formatted("\"{}\"sv", string));
|
if constexpr (IsSame<StorageType, String>)
|
||||||
|
generator.append(String::formatted("\"{}\"sv", value));
|
||||||
|
else
|
||||||
|
generator.append(String::formatted("{}", value));
|
||||||
|
|
||||||
if (strings_in_current_row == max_strings_per_row) {
|
if (values_in_current_row == max_values_per_row) {
|
||||||
strings_in_current_row = 0;
|
values_in_current_row = 0;
|
||||||
generator.append(",\n ");
|
generator.append(",\n ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,8 +90,19 @@ static constexpr Array<StringView, @size@ + 1> s_string_list { {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<String> m_unique_strings;
|
Vector<StorageType> m_storage;
|
||||||
HashMap<StringView, StringIndexType> m_unique_string_indices;
|
HashMap<StorageType, IndexType> m_storage_indices;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename StringIndexType>
|
||||||
|
class UniqueStringStorage : public UniqueStorage<String, StringIndexType> {
|
||||||
|
using Base = UniqueStorage<String, StringIndexType>;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void generate(SourceGenerator& generator)
|
||||||
|
{
|
||||||
|
Base::generate(generator, "StringView"sv, "s_string_list"sv, 40);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Alias {
|
struct Alias {
|
||||||
|
|
Loading…
Add table
Reference in a new issue