#pragma once #include #include #include #include #include #include struct Metadata { TagLib::String artist; TagLib::String title; TagLib::String album; TagLib::String albumArtist; unsigned int year; TagLib::VariantList artwork; TagLib::String genre; unsigned int trackNr; double length; std::string format; unsigned int sampleRate; unsigned int bitRate; }; struct Track { TagLib::String artist; TagLib::String title; TagLib::String album; unsigned int trackNr; unsigned int length; unsigned int year; std::string filePath; TagLib::VariantMap artwork; TagLib::String genre; std::string format; uint64_t hash; }; using trackPtr = std::shared_ptr; class HashTable { public: static constexpr uint8_t EMPTY = 0x80; static constexpr uint8_t DELETED = 0xFE; explicit HashTable ( size_t capacity = 64 ); // delete disabled - requires rehash HashTable ( const HashTable & ) = delete; HashTable &operator= ( const HashTable & ) = delete; HashTable ( HashTable && ) noexcept = default; HashTable &operator= ( HashTable && ) noexcept = default; void ht_insert ( const std::string &key, trackPtr track ); trackPtr ht_lookup ( const std::string &key ) const; bool ht_delete ( const std::string &key ); std::vector listAll () const; void save ( const std::string &filename ) const; std::vector> load ( const std::string &filename ); std::size_t size () const noexcept { return size_; } std::size_t capacity () const noexcept { return ctrl_.size(); } private: static constexpr double MAX_LOAD = 0.75; static constexpr std::size_t GROUP_SIZE = 32; struct Entry { std::string key; uint64_t hash = 0; trackPtr track; }; // helpers static uint64_t hashString ( const std::string &key ) noexcept; static uint8_t fingerprint ( uint64_t hash ) noexcept; std::ptrdiff_t probe ( const std::string &key, uint64_t hash, bool insert ) const noexcept; void rehash ( std::size_t newCapacity ); std::vector ctrl_; std::vector entries_; std::size_t size_ = 0; double loadFactor_ = static_cast ( size_ ) / static_cast ( ctrl_.size()); }; // Class HashTable