summaryrefslogtreecommitdiff
path: root/src/database/index.cpp
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-05-02 19:12:26 +1000
committerjacqueline <me@jacqueline.id.au>2024-05-02 19:12:26 +1000
commit1573a8c4cde1cd9528b422b2dcc598e37ffe94a7 (patch)
treed162822b8fd7054f81bace0c7a65ab4d5e6f93ef /src/database/index.cpp
parenta231fd1c8afedbeb14b0bc77d76bad61db986059 (diff)
downloadtangara-fw-1573a8c4cde1cd9528b422b2dcc598e37ffe94a7.tar.gz
WIP merge cyclically dependent components into one big component
Diffstat (limited to 'src/database/index.cpp')
-rw-r--r--src/database/index.cpp206
1 files changed, 0 insertions, 206 deletions
diff --git a/src/database/index.cpp b/src/database/index.cpp
deleted file mode 100644
index 328c3b43..00000000
--- a/src/database/index.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright 2023 jacqueline <me@jacqueline.id.au>
- *
- * SPDX-License-Identifier: GPL-3.0-only
- */
-
-#include "index.hpp"
-#include <sys/_stdint.h>
-
-#include <cstdint>
-#include <iomanip>
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <variant>
-#include <vector>
-
-#include "collation.hpp"
-#include "cppbor.h"
-#include "esp_log.h"
-#include "komihash.h"
-#include "leveldb/write_batch.h"
-
-#include "records.hpp"
-#include "track.hpp"
-
-namespace database {
-
-[[maybe_unused]] static const char* kTag = "index";
-
-const IndexInfo kAlbumsByArtist{
- .id = 1,
- .name = "Albums by Artist",
- .components = {Tag::kAlbumArtist, Tag::kAlbum, Tag::kAlbumOrder},
-};
-
-const IndexInfo kTracksByGenre{
- .id = 2,
- .name = "Tracks by Genre",
- .components = {Tag::kGenres, Tag::kTitle},
-};
-
-const IndexInfo kAllTracks{
- .id = 3,
- .name = "All Tracks",
- .components = {Tag::kTitle},
-};
-
-const IndexInfo kAllAlbums{
- .id = 4,
- .name = "All Albums",
- .components = {Tag::kAlbum, Tag::kAlbumOrder},
-};
-
-class Indexer {
- public:
- Indexer(locale::ICollator& collator, const Track& t, const IndexInfo& idx)
- : collator_(collator), track_(t), index_(idx) {}
-
- auto index() -> std::vector<std::pair<IndexKey, std::string>>;
-
- private:
- auto handleLevel(const IndexKey::Header& header,
- std::span<const Tag> components) -> void;
-
- auto handleItem(const IndexKey::Header& header,
- std::variant<std::pmr::string, uint32_t> item,
- std::span<const Tag> components) -> void;
-
- auto missing_value(Tag tag) -> TagValue {
- switch (tag) {
- case Tag::kTitle:
- return track_.TitleOrFilename();
- case Tag::kArtist:
- return "Unknown Artist";
- case Tag::kAlbum:
- return "Unknown Album";
- case Tag::kAlbumArtist:
- return track_.tags().artist().value_or("Unknown Artist");
- return "Unknown Album";
- case Tag::kGenres:
- return std::pmr::vector<std::pmr::string>{};
- case Tag::kDisc:
- return 0u;
- case Tag::kTrack:
- return 0u;
- case Tag::kAlbumOrder:
- return 0u;
- }
- return std::monostate{};
- }
-
- locale::ICollator& collator_;
- const Track& track_;
- const IndexInfo index_;
-
- std::vector<std::pair<IndexKey, std::string>> out_;
-};
-
-auto Indexer::index() -> std::vector<std::pair<IndexKey, std::string>> {
- out_.clear();
-
- IndexKey::Header root_header{
- .id = index_.id,
- .depth = 0,
- .components_hash = 0,
- };
- handleLevel(root_header, index_.components);
-
- return out_;
-}
-
-auto Indexer::handleLevel(const IndexKey::Header& header,
- std::span<const Tag> components) -> void {
- Tag component = components.front();
- TagValue value = track_.tags().get(component);
- if (std::holds_alternative<std::monostate>(value)) {
- value = missing_value(component);
- }
-
- std::visit(
- [&](auto&& arg) {
- using T = std::decay_t<decltype(arg)>;
- if constexpr (std::is_same_v<T, std::monostate>) {
- ESP_LOGW(kTag, "dropping component without value: %s",
- tagName(components.front()).c_str());
- } else if constexpr (std::is_same_v<T, std::pmr::string>) {
- handleItem(header, arg, components);
- } else if constexpr (std::is_same_v<T, uint32_t>) {
- handleItem(header, arg, components);
- } else if constexpr (std::is_same_v<
- T, std::span<const std::pmr::string>>) {
- for (const auto& i : arg) {
- handleItem(header, i, components);
- }
- }
- },
- value);
-}
-
-auto Indexer::handleItem(const IndexKey::Header& header,
- std::variant<std::pmr::string, uint32_t> item,
- std::span<const Tag> components) -> void {
- IndexKey key{
- .header = header,
- .item = {},
- .track = {},
- };
- std::string value;
-
- std::string item_text;
- std::visit(
- [&](auto&& arg) {
- using T = std::decay_t<decltype(arg)>;
- if constexpr (std::is_same_v<T, std::pmr::string>) {
- value = {arg.data(), arg.size()};
- auto xfrm = collator_.Transform(value);
- key.item = {xfrm.data(), xfrm.size()};
- } else if constexpr (std::is_same_v<T, uint32_t>) {
- value = std::to_string(arg);
- // FIXME: this sucks lol. we should just write the number directly,
- // LSB-first, but then we need to be able to parse it back properly.
- std::ostringstream str;
- str << std::setw(8) << std::setfill('0') << arg;
- std::string encoded = str.str();
- key.item = {encoded.data(), encoded.size()};
- }
- },
- item);
-
- std::optional<IndexKey::Header> next_level;
- if (components.size() == 1) {
- value = track_.TitleOrFilename();
- key.track = track_.data().id;
- } else {
- next_level = ExpandHeader(key.header, key.item);
- }
-
- out_.emplace_back(key, value);
-
- if (next_level) {
- handleLevel(*next_level, components.subspan(1));
- }
-}
-
-auto Index(locale::ICollator& c, const IndexInfo& i, const Track& t)
- -> std::vector<std::pair<IndexKey, std::string>> {
- Indexer indexer{c, t, i};
- return indexer.index();
-}
-
-auto ExpandHeader(const IndexKey::Header& header,
- const std::optional<std::pmr::string>& component)
- -> IndexKey::Header {
- IndexKey::Header ret{header};
- ret.depth++;
- if (component) {
- ret.components_hash =
- komihash(component->data(), component->size(), ret.components_hash);
- } else {
- ret.components_hash = komihash(NULL, 0, ret.components_hash);
- }
- return ret;
-}
-
-} // namespace database