diff --git a/lib/Epub/Epub.cpp b/lib/Epub/Epub.cpp index a3edac8..ebf10ca 100644 --- a/lib/Epub/Epub.cpp +++ b/lib/Epub/Epub.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "Epub/FsHelpers.h" #include "Epub/parsers/ContainerParser.h" @@ -154,6 +155,41 @@ bool Epub::load() { return true; } +std::string normalisePath(const std::string& path) { + std::vector components; + std::string component; + + for (const auto c : path) { + if (c == '/') { + if (!component.empty()) { + if (component == "..") { + if (!components.empty()) { + components.pop_back(); + } + } else { + components.push_back(component); + } + component.clear(); + } + } else { + component += c; + } + } + + if (!component.empty()) { + components.push_back(component); + } + + std::string result; + for (const auto& c : components) { + if (!result.empty()) { + result += "/"; + } + result += c; + } + + return result; +} void Epub::initializeSpineItemSizes() { setupCacheDir(); @@ -174,10 +210,18 @@ void Epub::initializeSpineItemSizes() { File f = SD.open((getCachePath() + "/spine_size.bin").c_str(), FILE_WRITE); uint8_t data[4]; // determine size of spine items + const ZipFile zip("/sd" + filepath); + for (size_t i = 0; i < spineItemsCount; i++) { std::string spineItem = getSpineItem(i); size_t s = 0; - getItemSize(spineItem, &s); + unsigned long last = millis(); + const std::string path = normalisePath(spineItem); + // TODO: This is still too slow, because zip opens zipfile every time? + zip.getInflatedFileSize(path.c_str(), &s); + // getItemSize(spineItem, &s); + Serial.printf("[%lu] [EBP] Determining size %d of item %d took %lu ms\n", millis(), cumSpineItemSize, i, + millis() - last); cumSpineItemSize += s; cumulativeSpineItemSize.emplace_back(cumSpineItemSize); @@ -186,8 +230,6 @@ void Epub::initializeSpineItemSizes() { data[1] = (cumSpineItemSize >> 8) & 0xFF; data[2] = (cumSpineItemSize >> 16) & 0xFF; data[3] = (cumSpineItemSize >> 24) & 0xFF; - // Serial.printf("[%lu] [EBP] Persisting item %d size %u to %u %u\n", millis(), - // i, cumSpineItemSize, data[1], data[0]); f.write(data, 4); } @@ -233,42 +275,6 @@ const std::string& Epub::getTitle() const { return title; } const std::string& Epub::getCoverImageItem() const { return coverImageItem; } -std::string normalisePath(const std::string& path) { - std::vector components; - std::string component; - - for (const auto c : path) { - if (c == '/') { - if (!component.empty()) { - if (component == "..") { - if (!components.empty()) { - components.pop_back(); - } - } else { - components.push_back(component); - } - component.clear(); - } - } else { - component += c; - } - } - - if (!component.empty()) { - components.push_back(component); - } - - std::string result; - for (const auto& c : components) { - if (!result.empty()) { - result += "/"; - } - result += c; - } - - return result; -} - uint8_t* Epub::readItemContentsToBytes(const std::string& itemHref, size_t* size, bool trailingNullByte) const { const ZipFile zip("/sd" + filepath); const std::string path = normalisePath(itemHref); diff --git a/lib/ZipFile/ZipFile.cpp b/lib/ZipFile/ZipFile.cpp index f55bb85..6096168 100644 --- a/lib/ZipFile/ZipFile.cpp +++ b/lib/ZipFile/ZipFile.cpp @@ -28,30 +28,18 @@ bool inflateOneShot(const uint8_t* inputBuf, const size_t deflatedSize, uint8_t* } bool ZipFile::loadFileStat(const char* filename, mz_zip_archive_file_stat* fileStat) const { - mz_zip_archive zipArchive = {}; - const bool status = mz_zip_reader_init_file(&zipArchive, filePath.c_str(), 0); - - if (!status) { - Serial.printf("[%lu] [ZIP] mz_zip_reader_init_file() failed! Error: %s\n", millis(), - mz_zip_get_error_string(zipArchive.m_last_error)); - return false; - } - // find the file mz_uint32 fileIndex = 0; if (!mz_zip_reader_locate_file_v2(&zipArchive, filename, nullptr, 0, &fileIndex)) { Serial.printf("[%lu] [ZIP] Could not find file %s\n", millis(), filename); - mz_zip_reader_end(&zipArchive); return false; } if (!mz_zip_reader_file_stat(&zipArchive, fileIndex, fileStat)) { Serial.printf("[%lu] [ZIP] mz_zip_reader_file_stat() failed! Error: %s\n", millis(), mz_zip_get_error_string(zipArchive.m_last_error)); - mz_zip_reader_end(&zipArchive); return false; } - mz_zip_reader_end(&zipArchive); return true; } diff --git a/lib/ZipFile/ZipFile.h b/lib/ZipFile/ZipFile.h index e452ec5..494d4c7 100644 --- a/lib/ZipFile/ZipFile.h +++ b/lib/ZipFile/ZipFile.h @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #include #include @@ -8,12 +10,20 @@ class ZipFile { std::string filePath; + mutable mz_zip_archive zipArchive = {}; bool loadFileStat(const char* filename, mz_zip_archive_file_stat* fileStat) const; long getDataOffset(const mz_zip_archive_file_stat& fileStat) const; public: - explicit ZipFile(std::string filePath) : filePath(std::move(filePath)) {} - ~ZipFile() = default; + explicit ZipFile(std::string filePath) : filePath(std::move(filePath)) { + const bool status = mz_zip_reader_init_file(&zipArchive, this->filePath.c_str(), 0); + + if (!status) { + Serial.printf("[%lu] [ZIP] mz_zip_reader_init_file() failed for %s! Error: %s\n", millis(), + this->filePath.c_str(), mz_zip_get_error_string(zipArchive.m_last_error)); + } + } + ~ZipFile() { mz_zip_reader_end(&zipArchive); } bool getInflatedFileSize(const char* filename, size_t* size) const; uint8_t* readFileToMemory(const char* filename, size_t* size = nullptr, bool trailingNullByte = false) const; bool readFileToStream(const char* filename, Print& out, size_t chunkSize) const;