diff options
Diffstat (limited to 'src/locale')
| -rw-r--r-- | src/locale/collation.cpp | 15 | ||||
| -rw-r--r-- | src/locale/include/collation.hpp | 32 |
2 files changed, 40 insertions, 7 deletions
diff --git a/src/locale/collation.cpp b/src/locale/collation.cpp index f5e8272a..2d787b5a 100644 --- a/src/locale/collation.cpp +++ b/src/locale/collation.cpp @@ -58,19 +58,26 @@ auto GLibCollator::create() -> GLibCollator* { return nullptr; } + // We reserve the first 8 bytes of the partition for an identifier / name. + // Copy it out, then crop the rest of the region so that the LC_COLLATE parser + // doesn't see it. + std::string name{static_cast<const char*>(region)}; + region = static_cast<const std::byte*>(region) + 8; + auto data = std::make_unique<locale_data_t>(); - if (!parse_locale_data(region, partition->size, data.get())) { + if (!parse_locale_data(region, partition->size - 8, data.get())) { ESP_LOGE(kTag, "parsing locale data failed"); esp_partition_munmap(handle); return nullptr; } - return new GLibCollator(handle, std::move(data)); + return new GLibCollator(name, handle, std::move(data)); } -GLibCollator::GLibCollator(const esp_partition_mmap_handle_t handle, +GLibCollator::GLibCollator(const std::string& name, + const esp_partition_mmap_handle_t handle, std::unique_ptr<locale_data_t> locale) - : handle_(handle), locale_data_(std::move(locale)) {} + : name_(name), handle_(handle), locale_data_(std::move(locale)) {} GLibCollator::~GLibCollator() { esp_partition_munmap(handle_); diff --git a/src/locale/include/collation.hpp b/src/locale/include/collation.hpp index e8b6fa17..b666860d 100644 --- a/src/locale/include/collation.hpp +++ b/src/locale/include/collation.hpp @@ -8,6 +8,7 @@ #include <cstddef> #include <memory> +#include <optional> #include <string> #include "esp_partition.h" @@ -17,31 +18,56 @@ namespace locale { +/* + * Interface for sorting database entries. + * For performance, our database exclusively orders entries via byte + * comparisons of each key. Our collators therefore work by transforming keys + * such that a byte-order comparison results in a natural ordering. + */ class ICollator { public: virtual ~ICollator() {} + /* + * Returns an identify that uniquely describes this collator. Does not need + * to be human readable. + */ + virtual auto Describe() -> std::optional<std::string> = 0; virtual auto Transform(const std::string&) -> std::string = 0; }; +/* Creates and returns the best available collator. */ +auto CreateCollator() -> std::unique_ptr<ICollator>; + +/* + * Collator that doesn't do anything. Used only when there is no available + * locale data. + */ class NoopCollator : public ICollator { public: + auto Describe() -> std::optional<std::string> override { return {}; } auto Transform(const std::string& in) -> std::string override { return in; } }; -auto CreateCollator() -> std::unique_ptr<ICollator>; - +/* + * Collator that uses glibc's `strxfrm` to transform keys. Relies on an + * LC_COLLATE file (+ 8 byte name header) flashed on a partition in internal + * flash. + */ class GLibCollator : public ICollator { public: static auto create() -> GLibCollator*; ~GLibCollator(); + auto Describe() -> std::optional<std::string> override { return name_; } auto Transform(const std::string& in) -> std::string override; private: - GLibCollator(const esp_partition_mmap_handle_t, + GLibCollator(const std::string& name, + const esp_partition_mmap_handle_t, std::unique_ptr<locale_data_t>); + const std::string name_; const esp_partition_mmap_handle_t handle_; std::unique_ptr<locale_data_t> locale_data_; }; |
