#pragma once #include #include class BookMetadataCache { public: struct BookMetadata { std::string title; std::string author; std::string coverItemHref; }; struct SpineEntry { std::string href; size_t cumulativeSize; int16_t tocIndex; SpineEntry() : cumulativeSize(0), tocIndex(-1) {} SpineEntry(std::string href, const size_t cumulativeSize, const int16_t tocIndex) : href(std::move(href)), cumulativeSize(cumulativeSize), tocIndex(tocIndex) {} }; struct TocEntry { std::string title; std::string href; std::string anchor; uint8_t level; int16_t spineIndex; TocEntry() : level(0), spineIndex(-1) {} TocEntry(std::string title, std::string href, std::string anchor, const uint8_t level, const int16_t spineIndex) : title(std::move(title)), href(std::move(href)), anchor(std::move(anchor)), level(level), spineIndex(spineIndex) {} }; private: std::string cachePath; size_t lutOffset; uint16_t spineCount; uint16_t tocCount; bool loaded; bool buildMode; FsFile bookFile; // Temp file handles during build FsFile spineFile; FsFile tocFile; uint32_t writeSpineEntry(FsFile& file, const SpineEntry& entry) const; uint32_t writeTocEntry(FsFile& file, const TocEntry& entry) const; SpineEntry readSpineEntry(FsFile& file) const; TocEntry readTocEntry(FsFile& file) const; public: BookMetadata coreMetadata; explicit BookMetadataCache(std::string cachePath) : cachePath(std::move(cachePath)), lutOffset(0), spineCount(0), tocCount(0), loaded(false), buildMode(false) {} ~BookMetadataCache() = default; // Building phase (stream to disk immediately) bool beginWrite(); bool beginContentOpfPass(); void createSpineEntry(const std::string& href); bool endContentOpfPass(); bool beginTocPass(); void createTocEntry(const std::string& title, const std::string& href, const std::string& anchor, uint8_t level); bool endTocPass(); bool endWrite(); bool cleanupTmpFiles() const; // Post-processing to update mappings and sizes bool buildBookBin(const std::string& epubPath, const BookMetadata& metadata); // Reading phase (read mode) bool load(); SpineEntry getSpineEntry(int index); TocEntry getTocEntry(int index); int getSpineCount() const { return spineCount; } int getTocCount() const { return tocCount; } bool isLoaded() const { return loaded; } };