Keep ZipFile open to speed up getting file stats.
This commit is contained in:
parent
cfe838e03b
commit
6b293148a5
@ -5,6 +5,7 @@
|
|||||||
#include <ZipFile.h>
|
#include <ZipFile.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <ratio>
|
||||||
|
|
||||||
#include "Epub/FsHelpers.h"
|
#include "Epub/FsHelpers.h"
|
||||||
#include "Epub/parsers/ContainerParser.h"
|
#include "Epub/parsers/ContainerParser.h"
|
||||||
@ -154,6 +155,41 @@ bool Epub::load() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string normalisePath(const std::string& path) {
|
||||||
|
std::vector<std::string> 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() {
|
void Epub::initializeSpineItemSizes() {
|
||||||
setupCacheDir();
|
setupCacheDir();
|
||||||
|
|
||||||
@ -174,10 +210,18 @@ void Epub::initializeSpineItemSizes() {
|
|||||||
File f = SD.open((getCachePath() + "/spine_size.bin").c_str(), FILE_WRITE);
|
File f = SD.open((getCachePath() + "/spine_size.bin").c_str(), FILE_WRITE);
|
||||||
uint8_t data[4];
|
uint8_t data[4];
|
||||||
// determine size of spine items
|
// determine size of spine items
|
||||||
|
const ZipFile zip("/sd" + filepath);
|
||||||
|
|
||||||
for (size_t i = 0; i < spineItemsCount; i++) {
|
for (size_t i = 0; i < spineItemsCount; i++) {
|
||||||
std::string spineItem = getSpineItem(i);
|
std::string spineItem = getSpineItem(i);
|
||||||
size_t s = 0;
|
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;
|
cumSpineItemSize += s;
|
||||||
cumulativeSpineItemSize.emplace_back(cumSpineItemSize);
|
cumulativeSpineItemSize.emplace_back(cumSpineItemSize);
|
||||||
|
|
||||||
@ -186,8 +230,6 @@ void Epub::initializeSpineItemSizes() {
|
|||||||
data[1] = (cumSpineItemSize >> 8) & 0xFF;
|
data[1] = (cumSpineItemSize >> 8) & 0xFF;
|
||||||
data[2] = (cumSpineItemSize >> 16) & 0xFF;
|
data[2] = (cumSpineItemSize >> 16) & 0xFF;
|
||||||
data[3] = (cumSpineItemSize >> 24) & 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);
|
f.write(data, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,42 +275,6 @@ const std::string& Epub::getTitle() const { return title; }
|
|||||||
|
|
||||||
const std::string& Epub::getCoverImageItem() const { return coverImageItem; }
|
const std::string& Epub::getCoverImageItem() const { return coverImageItem; }
|
||||||
|
|
||||||
std::string normalisePath(const std::string& path) {
|
|
||||||
std::vector<std::string> 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 {
|
uint8_t* Epub::readItemContentsToBytes(const std::string& itemHref, size_t* size, bool trailingNullByte) const {
|
||||||
const ZipFile zip("/sd" + filepath);
|
const ZipFile zip("/sd" + filepath);
|
||||||
const std::string path = normalisePath(itemHref);
|
const std::string path = normalisePath(itemHref);
|
||||||
|
|||||||
@ -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 {
|
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
|
// find the file
|
||||||
mz_uint32 fileIndex = 0;
|
mz_uint32 fileIndex = 0;
|
||||||
if (!mz_zip_reader_locate_file_v2(&zipArchive, filename, nullptr, 0, &fileIndex)) {
|
if (!mz_zip_reader_locate_file_v2(&zipArchive, filename, nullptr, 0, &fileIndex)) {
|
||||||
Serial.printf("[%lu] [ZIP] Could not find file %s\n", millis(), filename);
|
Serial.printf("[%lu] [ZIP] Could not find file %s\n", millis(), filename);
|
||||||
mz_zip_reader_end(&zipArchive);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mz_zip_reader_file_stat(&zipArchive, fileIndex, fileStat)) {
|
if (!mz_zip_reader_file_stat(&zipArchive, fileIndex, fileStat)) {
|
||||||
Serial.printf("[%lu] [ZIP] mz_zip_reader_file_stat() failed! Error: %s\n", millis(),
|
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_get_error_string(zipArchive.m_last_error));
|
||||||
mz_zip_reader_end(&zipArchive);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mz_zip_reader_end(&zipArchive);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <HardwareSerial.h>
|
||||||
#include <Print.h>
|
#include <Print.h>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -8,12 +10,20 @@
|
|||||||
|
|
||||||
class ZipFile {
|
class ZipFile {
|
||||||
std::string filePath;
|
std::string filePath;
|
||||||
|
mutable mz_zip_archive zipArchive = {};
|
||||||
bool loadFileStat(const char* filename, mz_zip_archive_file_stat* fileStat) const;
|
bool loadFileStat(const char* filename, mz_zip_archive_file_stat* fileStat) const;
|
||||||
long getDataOffset(const mz_zip_archive_file_stat& fileStat) const;
|
long getDataOffset(const mz_zip_archive_file_stat& fileStat) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ZipFile(std::string filePath) : filePath(std::move(filePath)) {}
|
explicit ZipFile(std::string filePath) : filePath(std::move(filePath)) {
|
||||||
~ZipFile() = default;
|
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;
|
bool getInflatedFileSize(const char* filename, size_t* size) const;
|
||||||
uint8_t* readFileToMemory(const char* filename, size_t* size = nullptr, bool trailingNullByte = false) 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;
|
bool readFileToStream(const char* filename, Print& out, size_t chunkSize) const;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user