New book.bin spine and table of contents cache (#104)
## Summary * Use single unified cache file for book spine, table of contents, and core metadata (title, author, cover image) * Use new temp item store file in OPF parsing to store items to be rescaned when parsing spine * This avoids us holding these items in memory * Use new toc.bin.tmp and spine.bin.tmp to build out partial toc / spine data as part of parsing content.opf and the NCX file * These files are re-read multiple times to ultimately build book.bin ## Additional Context * Spec for file format included below as an image * This should help with: * #10 * #60 * #99
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
|
||||
#include <SD.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
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;
|
||||
|
||||
File bookFile;
|
||||
// Temp file handles during build
|
||||
File spineFile;
|
||||
File tocFile;
|
||||
|
||||
size_t writeSpineEntry(File& file, const SpineEntry& entry) const;
|
||||
size_t writeTocEntry(File& file, const TocEntry& entry) const;
|
||||
SpineEntry readSpineEntry(File& file) const;
|
||||
TocEntry readTocEntry(File& 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; }
|
||||
};
|
||||
Reference in New Issue
Block a user