1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 04:08:11 +00:00

Meta: Do not hard-code index types for UCD/CLDR/TZDB code generators

Hand-picking the smallest index type that fits a particular generated
array started with commit 3ad159537e. This
was to reduce the size of the generated library.

Since then, the number of types using UniqueStorage has grown a ton,
creating a long list of types for which index types are manually picked.
When a new UCD/CLDR/TZDB is released, and the current index type no
longer fits the generated data, we fail to generate. Tracking down which
index caused the failure is a pretty annoying process.

Instead, we can just use size_t while in the generators themselves, then
automatically pick the size needed for the generated code.
This commit is contained in:
Timothy Flynn 2022-11-18 11:04:33 -05:00 committed by Linus Groh
parent fa2579ffa9
commit b2164ad979
9 changed files with 268 additions and 379 deletions

View file

@ -51,10 +51,10 @@ struct AK::Traits<Vector<T>> : public GenericTraits<Vector<T>> {
}
};
template<typename StorageType, typename IndexType>
template<typename StorageType>
class UniqueStorage {
public:
IndexType ensure(StorageType value)
size_t ensure(StorageType value)
{
// We maintain a set of unique values in two structures: a vector which stores the values in
// the order they are added, and a hash map which maps that value to its index in the vector.
@ -68,17 +68,14 @@ public:
return *index;
m_storage.append(move(value));
size_t index = m_storage.size();
VERIFY(index < NumericLimits<IndexType>::max());
auto storage_index = static_cast<IndexType>(index);
auto storage_index = m_storage.size();
m_storage_indices.set(m_storage.last(), storage_index);
return storage_index;
}
StorageType const& get(IndexType index) const
StorageType const& get(size_t index) const
{
if (index == 0) {
static StorageType empty {};
@ -89,6 +86,17 @@ public:
return m_storage.at(index - 1);
}
StringView type_that_fits() const
{
if (m_storage.size() <= NumericLimits<u8>::max())
return "u8"sv;
if (m_storage.size() <= NumericLimits<u16>::max())
return "u16"sv;
if (m_storage.size() <= NumericLimits<u32>::max())
return "u32"sv;
return "u64"sv;
}
void generate(SourceGenerator& generator, StringView type, StringView name, size_t max_values_per_row) requires(!StorageTypeIsList<StorageType>)
{
generator.set("type"sv, type);
@ -177,13 +185,12 @@ static constexpr Array<Span<@type@ const>, @size@ + 1> @name@ { {
// clang-format gets confused by the requires() clauses above, and formats this section very weirdly.
protected:
Vector<StorageType> m_storage;
HashMap<StorageType, IndexType> m_storage_indices;
HashMap<StorageType, size_t> m_storage_indices;
// clang-format on
};
template<typename StringIndexType>
class UniqueStringStorage : public UniqueStorage<String, StringIndexType> {
using Base = UniqueStorage<String, StringIndexType>;
class UniqueStringStorage : public UniqueStorage<String> {
using Base = UniqueStorage<String>;
public:
// The goal of the string table generator is to ensure the table is located within the read-only
@ -275,9 +282,8 @@ struct Alias {
String alias;
};
template<typename StringIndexType>
struct CanonicalLanguageID {
static ErrorOr<CanonicalLanguageID> parse(UniqueStringStorage<StringIndexType>& unique_strings, StringView language)
static ErrorOr<CanonicalLanguageID> parse(UniqueStringStorage& unique_strings, StringView language)
{
CanonicalLanguageID language_id {};
@ -314,10 +320,10 @@ struct CanonicalLanguageID {
return language_id;
}
StringIndexType language { 0 };
StringIndexType script { 0 };
StringIndexType region { 0 };
Vector<StringIndexType> variants {};
size_t language { 0 };
size_t script { 0 };
size_t region { 0 };
Vector<size_t> variants {};
};
inline ErrorOr<NonnullOwnPtr<Core::Stream::BufferedFile>> open_file(StringView path, Core::Stream::OpenMode mode)