refactor: Drop FsFile alias, use HalFile in downstream code (#2141)

This commit is contained in:
Zach Nelson
2026-05-25 16:26:54 -04:00
committed by GitHub
parent d7797baff2
commit e9120888fa
63 changed files with 201 additions and 205 deletions
+4 -5
View File
@@ -152,20 +152,19 @@ These flags in `platformio.ini` fundamentally affect firmware behavior:
#include <HalStorage.h> #include <HalStorage.h>
// Use Storage singleton (defined via macro) // Use Storage singleton (defined via macro)
FsFile file; HalFile file;
if (Storage.openFileForRead("MODULE", "/path/to/file.bin", file)) { if (Storage.openFileForRead("MODULE", "/path/to/file.bin", file)) {
// Read from file // Read from file
// No file.close() needed — DESTRUCTOR_CLOSES_FILE=1 handles it at scope exit // No file.close() needed — DESTRUCTOR_CLOSES_FILE=1 handles it at scope exit
} }
``` ```
**Usage**: See example above. Uses `FsFile` (SdFat), NOT Arduino `File`. Do NOT add `file.close()` for local variables (see DESTRUCTOR_CLOSES_FILE above). **Usage**: Use `HalFile` (the mutex-wrapping handle), NOT raw SdFat `FsFile` or Arduino `File`. Do NOT add `file.close()` for local variables (see DESTRUCTOR_CLOSES_FILE above).
**SdFat is not thread-safe; all SD access MUST go through HalStorage**: **SdFat is not thread-safe; all SD access MUST go through HalStorage**:
- SdFat's `SdSpiCard` tracks SPI bus state with an unsynchronized `m_spiActive` bool. Two tasks calling SdFat concurrently can confuse that state machine and end with one task calling `SPIClass::endTransaction()` against a paramLock the *other* task is holding. That trips FreeRTOS's `xTaskPriorityDisinherit` assert (`tasks.c:5156, pxTCB == pxCurrentTCBs[0]`) and panics the system. See SdFat issue #518. - SdFat's `SdSpiCard` tracks SPI bus state with an unsynchronized `m_spiActive` bool. Two tasks calling SdFat concurrently can confuse that state machine and end with one task calling `SPIClass::endTransaction()` against a paramLock the *other* task is holding. That trips FreeRTOS's `xTaskPriorityDisinherit` assert (`tasks.c:5156, pxTCB == pxCurrentTCBs[0]`) and panics the system. See SdFat issue #518.
- `HalStorage` serializes everything via `storageMutex`. Downstream code includes `<HalStorage.h>`, which transparently `using FsFile = HalFile;`; every method call (read, write, seek, close) takes the mutex. `HalFile`'s destructor also takes the mutex before letting the underlying SdFat `FsFile` close. - `HalStorage` serializes everything via `storageMutex`. Downstream code uses `HalFile` (declared in `<HalStorage.h>`); every method call (read, write, seek, close) takes the mutex. `HalFile`'s destructor also takes the mutex before letting the underlying SdFat `FsFile` close.
- **Never** call into `SdFat` / `SdSpiCard` / `FsBaseFile` / `SDCardManager` directly. **Never** define `HAL_STORAGE_IMPL` outside `HalStorage.cpp`; that disables the `FsFile -> HalFile` typedef and you'll get a raw SdFat handle that bypasses the mutex. - **Never** call into `SdFat` / `SdSpiCard` / `FsBaseFile` / `SDCardManager` / raw `FsFile` directly — that bypasses the mutex.
- If you're storing a raw `FsFile` in a place that won't transitively include `<HalStorage.h>` (rare), include the header explicitly so the typedef applies.
--- ---
+6 -6
View File
@@ -168,7 +168,7 @@ bool SdCardFont::loadStyleKernLigatureData(PerStyle& s) {
return true; return true;
} }
FsFile file; HalFile file;
if (!Storage.openFileForRead("SDCF", filePath_, file)) { if (!Storage.openFileForRead("SDCF", filePath_, file)) {
LOG_ERR("SDCF", "Failed to open .cpfont for kern/lig: %s", filePath_); LOG_ERR("SDCF", "Failed to open .cpfont for kern/lig: %s", filePath_);
return false; return false;
@@ -345,7 +345,7 @@ bool SdCardFont::buildMiniKernMatrix(PerStyle& s, const uint32_t* codepoints, ui
// Step 6: read the full matrix's rows for each used left class, keep only // Step 6: read the full matrix's rows for each used left class, keep only
// columns for used right classes. One SD seek + one read per used left class; // columns for used right classes. One SD seek + one read per used left class;
// a row is kernRightClassCount bytes (~200 for Literata). // a row is kernRightClassCount bytes (~200 for Literata).
FsFile file; HalFile file;
if (!Storage.openFileForRead("SDCF", filePath_, file)) { if (!Storage.openFileForRead("SDCF", filePath_, file)) {
LOG_ERR("SDCF", "Failed to open .cpfont for mini kern: %s", filePath_); LOG_ERR("SDCF", "Failed to open .cpfont for mini kern: %s", filePath_);
freeStyleMiniKern(s); freeStyleMiniKern(s);
@@ -425,7 +425,7 @@ bool SdCardFont::load(const char* path) {
strncpy(filePath_, path, sizeof(filePath_) - 1); strncpy(filePath_, path, sizeof(filePath_) - 1);
filePath_[sizeof(filePath_) - 1] = '\0'; filePath_[sizeof(filePath_) - 1] = '\0';
FsFile file; HalFile file;
if (!Storage.openFileForRead("SDCF", path, file)) { if (!Storage.openFileForRead("SDCF", path, file)) {
LOG_ERR("SDCF", "Failed to open .cpfont: %s", path); LOG_ERR("SDCF", "Failed to open .cpfont: %s", path);
return false; return false;
@@ -798,7 +798,7 @@ int SdCardFont::prewarmStyle(uint8_t styleIdx, const uint32_t* codepoints, uint3
std::sort(readOrder, readOrder + validCount, std::sort(readOrder, readOrder + validCount,
[&](uint32_t a, uint32_t b) { return mappings[a].globalIndex < mappings[b].globalIndex; }); [&](uint32_t a, uint32_t b) { return mappings[a].globalIndex < mappings[b].globalIndex; });
FsFile file; HalFile file;
if (!Storage.openFileForRead("SDCF", filePath_, file)) { if (!Storage.openFileForRead("SDCF", filePath_, file)) {
LOG_ERR("SDCF", "Failed to reopen .cpfont for prewarm (style %u)", styleIdx); LOG_ERR("SDCF", "Failed to reopen .cpfont for prewarm (style %u)", styleIdx);
delete[] readOrder; delete[] readOrder;
@@ -1104,7 +1104,7 @@ int SdCardFont::fetchAdvancesForCodepoints(uint32_t* codepoints, uint32_t cpCoun
[](const CpIdx& a, const CpIdx& b) { return a.glyphIndex < b.glyphIndex; }); [](const CpIdx& a, const CpIdx& b) { return a.glyphIndex < b.glyphIndex; });
// Open file once and read advanceX for each needed glyph. // Open file once and read advanceX for each needed glyph.
FsFile file; HalFile file;
if (!Storage.openFileForRead("SDCF", filePath_, file)) { if (!Storage.openFileForRead("SDCF", filePath_, file)) {
LOG_ERR("SDCF", "buildAdvanceTable: failed to open .cpfont for style %u", si); LOG_ERR("SDCF", "buildAdvanceTable: failed to open .cpfont for style %u", si);
continue; continue;
@@ -1277,7 +1277,7 @@ const EpdGlyph* SdCardFont::onGlyphMiss(void* ctx, uint32_t codepoint) {
bool wasAtCapacity = (self->overflowCount_ == OVERFLOW_CAPACITY); bool wasAtCapacity = (self->overflowCount_ == OVERFLOW_CAPACITY);
// Read glyph metadata into temporary // Read glyph metadata into temporary
FsFile file; HalFile file;
if (!Storage.openFileForRead("SDCF", self->filePath_, file)) { if (!Storage.openFileForRead("SDCF", self->filePath_, file)) {
LOG_ERR("SDCF", "Overflow: failed to open .cpfont"); LOG_ERR("SDCF", "Overflow: failed to open .cpfont");
return nullptr; return nullptr;
+4 -4
View File
@@ -77,12 +77,12 @@ bool SdCardFontRegistry::parseFilename(const char* filename, uint8_t& size, uint
} }
void SdCardFontRegistry::scanDirectory(const char* dirPath, SdCardFontFamilyInfo& family) { void SdCardFontRegistry::scanDirectory(const char* dirPath, SdCardFontFamilyInfo& family) {
FsFile dir = Storage.open(dirPath); HalFile dir = Storage.open(dirPath);
if (!dir || !dir.isDirectory()) return; if (!dir || !dir.isDirectory()) return;
char nameBuffer[128]; char nameBuffer[128];
while (true) { while (true) {
FsFile entry = dir.openNextFile(); HalFile entry = dir.openNextFile();
if (!entry) break; if (!entry) break;
if (entry.isDirectory()) { if (entry.isDirectory()) {
entry.close(); entry.close();
@@ -126,7 +126,7 @@ void SdCardFontRegistry::scanDirectory(const char* dirPath, SdCardFontFamilyInfo
// Skips families whose names already exist in `out` (de-duplicates between // Skips families whose names already exist in `out` (de-duplicates between
// the hidden and visible roots — first scan wins). // the hidden and visible roots — first scan wins).
void SdCardFontRegistry::scanRoot(const char* rootPath, std::vector<SdCardFontFamilyInfo>& out) { void SdCardFontRegistry::scanRoot(const char* rootPath, std::vector<SdCardFontFamilyInfo>& out) {
FsFile root = Storage.open(rootPath); HalFile root = Storage.open(rootPath);
if (!root) { if (!root) {
LOG_DBG("SDREG", "Fonts directory not found: %s", rootPath); LOG_DBG("SDREG", "Fonts directory not found: %s", rootPath);
return; return;
@@ -138,7 +138,7 @@ void SdCardFontRegistry::scanRoot(const char* rootPath, std::vector<SdCardFontFa
char nameBuffer[128]; char nameBuffer[128];
while (true) { while (true) {
FsFile entry = root.openNextFile(); HalFile entry = root.openNextFile();
if (!entry) break; if (!entry) break;
if (entry.isDirectory()) { if (entry.isDirectory()) {
entry.getName(nameBuffer, sizeof(nameBuffer)); entry.getName(nameBuffer, sizeof(nameBuffer));
+12 -12
View File
@@ -150,7 +150,7 @@ bool Epub::parseTocNcxFile() const {
LOG_DBG("EBP", "Parsing toc ncx file: %s", tocNcxItem.c_str()); LOG_DBG("EBP", "Parsing toc ncx file: %s", tocNcxItem.c_str());
const auto tmpNcxPath = getCachePath() + "/toc.ncx"; const auto tmpNcxPath = getCachePath() + "/toc.ncx";
FsFile tempNcxFile; HalFile tempNcxFile;
if (!Storage.openFileForWrite("EBP", tmpNcxPath, tempNcxFile)) { if (!Storage.openFileForWrite("EBP", tmpNcxPath, tempNcxFile)) {
return false; return false;
} }
@@ -206,7 +206,7 @@ bool Epub::parseTocNavFile() const {
LOG_DBG("EBP", "Parsing toc nav file: %s", tocNavItem.c_str()); LOG_DBG("EBP", "Parsing toc nav file: %s", tocNavItem.c_str());
const auto tmpNavPath = getCachePath() + "/toc.nav"; const auto tmpNavPath = getCachePath() + "/toc.nav";
FsFile tempNavFile; HalFile tempNavFile;
if (!Storage.openFileForWrite("EBP", tmpNavPath, tempNavFile)) { if (!Storage.openFileForWrite("EBP", tmpNavPath, tempNavFile)) {
return false; return false;
} }
@@ -297,7 +297,7 @@ void Epub::parseCssFiles() const {
// Extract CSS file to temp location // Extract CSS file to temp location
const auto tmpCssPath = getCachePath() + "/.tmp.css"; const auto tmpCssPath = getCachePath() + "/.tmp.css";
FsFile tempCssFile; HalFile tempCssFile;
if (!Storage.openFileForWrite("EBP", tmpCssPath, tempCssFile)) { if (!Storage.openFileForWrite("EBP", tmpCssPath, tempCssFile)) {
LOG_ERR("EBP", "Could not create temp CSS file"); LOG_ERR("EBP", "Could not create temp CSS file");
continue; continue;
@@ -545,7 +545,7 @@ bool Epub::generateCoverBmp(bool cropped) const {
LOG_DBG("EBP", "Generating BMP from JPG cover image (%s mode)", cropped ? "cropped" : "fit"); LOG_DBG("EBP", "Generating BMP from JPG cover image (%s mode)", cropped ? "cropped" : "fit");
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg"; const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
FsFile coverJpg; HalFile coverJpg;
if (!Storage.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) { if (!Storage.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) {
return false; return false;
} }
@@ -557,7 +557,7 @@ bool Epub::generateCoverBmp(bool cropped) const {
return false; return false;
} }
FsFile coverBmp; HalFile coverBmp;
if (!Storage.openFileForWrite("EBP", getCoverBmpPath(cropped), coverBmp)) { if (!Storage.openFileForWrite("EBP", getCoverBmpPath(cropped), coverBmp)) {
return false; return false;
} }
@@ -579,7 +579,7 @@ bool Epub::generateCoverBmp(bool cropped) const {
LOG_DBG("EBP", "Generating BMP from PNG cover image (%s mode)", cropped ? "cropped" : "fit"); LOG_DBG("EBP", "Generating BMP from PNG cover image (%s mode)", cropped ? "cropped" : "fit");
const auto coverPngTempPath = getCachePath() + "/.cover.png"; const auto coverPngTempPath = getCachePath() + "/.cover.png";
FsFile coverPng; HalFile coverPng;
if (!Storage.openFileForWrite("EBP", coverPngTempPath, coverPng)) { if (!Storage.openFileForWrite("EBP", coverPngTempPath, coverPng)) {
return false; return false;
} }
@@ -591,7 +591,7 @@ bool Epub::generateCoverBmp(bool cropped) const {
return false; return false;
} }
FsFile coverBmp; HalFile coverBmp;
if (!Storage.openFileForWrite("EBP", getCoverBmpPath(cropped), coverBmp)) { if (!Storage.openFileForWrite("EBP", getCoverBmpPath(cropped), coverBmp)) {
return false; return false;
} }
@@ -634,7 +634,7 @@ bool Epub::generateThumbBmp(int height) const {
LOG_DBG("EBP", "Generating thumb BMP from JPG cover image"); LOG_DBG("EBP", "Generating thumb BMP from JPG cover image");
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg"; const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
FsFile coverJpg; HalFile coverJpg;
if (!Storage.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) { if (!Storage.openFileForWrite("EBP", coverJpgTempPath, coverJpg)) {
return false; return false;
} }
@@ -646,7 +646,7 @@ bool Epub::generateThumbBmp(int height) const {
return false; return false;
} }
FsFile thumbBmp; HalFile thumbBmp;
if (!Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp)) { if (!Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp)) {
return false; return false;
} }
@@ -671,7 +671,7 @@ bool Epub::generateThumbBmp(int height) const {
LOG_DBG("EBP", "Generating thumb BMP from PNG cover image"); LOG_DBG("EBP", "Generating thumb BMP from PNG cover image");
const auto coverPngTempPath = getCachePath() + "/.cover.png"; const auto coverPngTempPath = getCachePath() + "/.cover.png";
FsFile coverPng; HalFile coverPng;
if (!Storage.openFileForWrite("EBP", coverPngTempPath, coverPng)) { if (!Storage.openFileForWrite("EBP", coverPngTempPath, coverPng)) {
return false; return false;
} }
@@ -683,7 +683,7 @@ bool Epub::generateThumbBmp(int height) const {
return false; return false;
} }
FsFile thumbBmp; HalFile thumbBmp;
if (!Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp)) { if (!Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp)) {
return false; return false;
} }
@@ -707,7 +707,7 @@ bool Epub::generateThumbBmp(int height) const {
} }
// Write an empty bmp file to avoid generation attempts in the future // Write an empty bmp file to avoid generation attempts in the future
FsFile thumbBmp; HalFile thumbBmp;
Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp); Storage.openFileForWrite("EBP", getThumbBmpPath(height), thumbBmp);
return false; return false;
} }
+4 -4
View File
@@ -292,7 +292,7 @@ bool BookMetadataCache::cleanupTmpFiles() const {
return true; return true;
} }
uint32_t BookMetadataCache::writeSpineEntry(FsFile& file, const SpineEntry& entry) const { uint32_t BookMetadataCache::writeSpineEntry(HalFile& file, const SpineEntry& entry) const {
const uint32_t pos = file.position(); const uint32_t pos = file.position();
serialization::writeString(file, entry.href); serialization::writeString(file, entry.href);
serialization::writePod(file, entry.cumulativeSize); serialization::writePod(file, entry.cumulativeSize);
@@ -300,7 +300,7 @@ uint32_t BookMetadataCache::writeSpineEntry(FsFile& file, const SpineEntry& entr
return pos; return pos;
} }
uint32_t BookMetadataCache::writeTocEntry(FsFile& file, const TocEntry& entry) const { uint32_t BookMetadataCache::writeTocEntry(HalFile& file, const TocEntry& entry) const {
const uint32_t pos = file.position(); const uint32_t pos = file.position();
serialization::writeString(file, entry.title); serialization::writeString(file, entry.title);
serialization::writeString(file, entry.href); serialization::writeString(file, entry.href);
@@ -438,7 +438,7 @@ BookMetadataCache::TocEntry BookMetadataCache::getTocEntry(const int index) {
return readTocEntry(bookFile); return readTocEntry(bookFile);
} }
BookMetadataCache::SpineEntry BookMetadataCache::readSpineEntry(FsFile& file) const { BookMetadataCache::SpineEntry BookMetadataCache::readSpineEntry(HalFile& file) const {
SpineEntry entry; SpineEntry entry;
serialization::readString(file, entry.href); serialization::readString(file, entry.href);
serialization::readPod(file, entry.cumulativeSize); serialization::readPod(file, entry.cumulativeSize);
@@ -446,7 +446,7 @@ BookMetadataCache::SpineEntry BookMetadataCache::readSpineEntry(FsFile& file) co
return entry; return entry;
} }
BookMetadataCache::TocEntry BookMetadataCache::readTocEntry(FsFile& file) const { BookMetadataCache::TocEntry BookMetadataCache::readTocEntry(HalFile& file) const {
TocEntry entry; TocEntry entry;
serialization::readString(file, entry.title); serialization::readString(file, entry.title);
serialization::readString(file, entry.href); serialization::readString(file, entry.href);
+7 -7
View File
@@ -50,10 +50,10 @@ class BookMetadataCache {
bool loaded; bool loaded;
bool buildMode; bool buildMode;
FsFile bookFile; HalFile bookFile;
// Temp file handles during build // Temp file handles during build
FsFile spineFile; HalFile spineFile;
FsFile tocFile; HalFile tocFile;
// Index for fast href→spineIndex lookup (used only for large EPUBs) // Index for fast href→spineIndex lookup (used only for large EPUBs)
struct SpineHrefIndexEntry { struct SpineHrefIndexEntry {
@@ -76,10 +76,10 @@ class BookMetadataCache {
return hash; return hash;
} }
uint32_t writeSpineEntry(FsFile& file, const SpineEntry& entry) const; uint32_t writeSpineEntry(HalFile& file, const SpineEntry& entry) const;
uint32_t writeTocEntry(FsFile& file, const TocEntry& entry) const; uint32_t writeTocEntry(HalFile& file, const TocEntry& entry) const;
SpineEntry readSpineEntry(FsFile& file) const; SpineEntry readSpineEntry(HalFile& file) const;
TocEntry readTocEntry(FsFile& file) const; TocEntry readTocEntry(HalFile& file) const;
public: public:
BookMetadata coreMetadata; BookMetadata coreMetadata;
+8 -8
View File
@@ -10,7 +10,7 @@ void PageLine::render(GfxRenderer& renderer, const int fontId, const int xOffset
block->render(renderer, fontId, xPos + xOffset, yPos + yOffset); block->render(renderer, fontId, xPos + xOffset, yPos + yOffset);
} }
bool PageLine::serialize(FsFile& file) { bool PageLine::serialize(HalFile& file) {
serialization::writePod(file, xPos); serialization::writePod(file, xPos);
serialization::writePod(file, yPos); serialization::writePod(file, yPos);
@@ -18,7 +18,7 @@ bool PageLine::serialize(FsFile& file) {
return block->serialize(file); return block->serialize(file);
} }
std::unique_ptr<PageLine> PageLine::deserialize(FsFile& file) { std::unique_ptr<PageLine> PageLine::deserialize(HalFile& file) {
int16_t xPos; int16_t xPos;
int16_t yPos; int16_t yPos;
serialization::readPod(file, xPos); serialization::readPod(file, xPos);
@@ -33,7 +33,7 @@ void PageImage::render(GfxRenderer& renderer, const int fontId, const int xOffse
imageBlock->render(renderer, xPos + xOffset, yPos + yOffset); imageBlock->render(renderer, xPos + xOffset, yPos + yOffset);
} }
bool PageImage::serialize(FsFile& file) { bool PageImage::serialize(HalFile& file) {
serialization::writePod(file, xPos); serialization::writePod(file, xPos);
serialization::writePod(file, yPos); serialization::writePod(file, yPos);
@@ -41,7 +41,7 @@ bool PageImage::serialize(FsFile& file) {
return imageBlock->serialize(file); return imageBlock->serialize(file);
} }
std::unique_ptr<PageImage> PageImage::deserialize(FsFile& file) { std::unique_ptr<PageImage> PageImage::deserialize(HalFile& file) {
int16_t xPos; int16_t xPos;
int16_t yPos; int16_t yPos;
serialization::readPod(file, xPos); serialization::readPod(file, xPos);
@@ -60,7 +60,7 @@ void PageHorizontalRule::render(GfxRenderer& renderer, const int fontId, const i
renderer.drawLine(xPos + xOffset, yPos + yOffset, xPos + xOffset + width - 1, yPos + yOffset, thickness, true); renderer.drawLine(xPos + xOffset, yPos + yOffset, xPos + xOffset + width - 1, yPos + yOffset, thickness, true);
} }
bool PageHorizontalRule::serialize(FsFile& file) { bool PageHorizontalRule::serialize(HalFile& file) {
serialization::writePod(file, xPos); serialization::writePod(file, xPos);
serialization::writePod(file, yPos); serialization::writePod(file, yPos);
serialization::writePod(file, width); serialization::writePod(file, width);
@@ -68,7 +68,7 @@ bool PageHorizontalRule::serialize(FsFile& file) {
return true; return true;
} }
std::unique_ptr<PageHorizontalRule> PageHorizontalRule::deserialize(FsFile& file) { std::unique_ptr<PageHorizontalRule> PageHorizontalRule::deserialize(HalFile& file) {
int16_t xPos = 0; int16_t xPos = 0;
int16_t yPos = 0; int16_t yPos = 0;
uint16_t width = 0; uint16_t width = 0;
@@ -98,7 +98,7 @@ void Page::render(GfxRenderer& renderer, const int fontId, const int xOffset, co
} }
} }
bool Page::serialize(FsFile& file) const { bool Page::serialize(HalFile& file) const {
const uint16_t count = elements.size(); const uint16_t count = elements.size();
serialization::writePod(file, count); serialization::writePod(file, count);
@@ -126,7 +126,7 @@ bool Page::serialize(FsFile& file) const {
return true; return true;
} }
std::unique_ptr<Page> Page::deserialize(FsFile& file) { std::unique_ptr<Page> Page::deserialize(HalFile& file) {
auto page = std::unique_ptr<Page>(new Page()); auto page = std::unique_ptr<Page>(new Page());
uint16_t count; uint16_t count;
+9 -9
View File
@@ -24,7 +24,7 @@ class PageElement {
explicit PageElement(const int16_t xPos, const int16_t yPos) : xPos(xPos), yPos(yPos) {} explicit PageElement(const int16_t xPos, const int16_t yPos) : xPos(xPos), yPos(yPos) {}
virtual ~PageElement() = default; virtual ~PageElement() = default;
virtual void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) = 0; virtual void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) = 0;
virtual bool serialize(FsFile& file) = 0; virtual bool serialize(HalFile& file) = 0;
virtual PageElementTag getTag() const = 0; // Add type identification virtual PageElementTag getTag() const = 0; // Add type identification
}; };
@@ -37,9 +37,9 @@ class PageLine final : public PageElement {
: PageElement(xPos, yPos), block(std::move(block)) {} : PageElement(xPos, yPos), block(std::move(block)) {}
const std::shared_ptr<TextBlock>& getBlock() const { return block; } const std::shared_ptr<TextBlock>& getBlock() const { return block; }
void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override; void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override;
bool serialize(FsFile& file) override; bool serialize(HalFile& file) override;
PageElementTag getTag() const override { return TAG_PageLine; } PageElementTag getTag() const override { return TAG_PageLine; }
static std::unique_ptr<PageLine> deserialize(FsFile& file); static std::unique_ptr<PageLine> deserialize(HalFile& file);
}; };
// New PageImage class // New PageImage class
@@ -50,9 +50,9 @@ class PageImage final : public PageElement {
PageImage(std::shared_ptr<ImageBlock> block, const int16_t xPos, const int16_t yPos) PageImage(std::shared_ptr<ImageBlock> block, const int16_t xPos, const int16_t yPos)
: PageElement(xPos, yPos), imageBlock(std::move(block)) {} : PageElement(xPos, yPos), imageBlock(std::move(block)) {}
void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override; void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override;
bool serialize(FsFile& file) override; bool serialize(HalFile& file) override;
PageElementTag getTag() const override { return TAG_PageImage; } PageElementTag getTag() const override { return TAG_PageImage; }
static std::unique_ptr<PageImage> deserialize(FsFile& file); static std::unique_ptr<PageImage> deserialize(HalFile& file);
const ImageBlock& getImageBlock() const { return *imageBlock; } const ImageBlock& getImageBlock() const { return *imageBlock; }
}; };
@@ -65,9 +65,9 @@ class PageHorizontalRule final : public PageElement {
: PageElement(xPos, yPos), width(width), thickness(thickness) {} : PageElement(xPos, yPos), width(width), thickness(thickness) {}
void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override; void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override;
bool serialize(FsFile& file) override; bool serialize(HalFile& file) override;
PageElementTag getTag() const override { return TAG_PageHorizontalRule; } PageElementTag getTag() const override { return TAG_PageHorizontalRule; }
static std::unique_ptr<PageHorizontalRule> deserialize(FsFile& file); static std::unique_ptr<PageHorizontalRule> deserialize(HalFile& file);
}; };
class Page { class Page {
@@ -88,8 +88,8 @@ class Page {
} }
void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) const; void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) const;
bool serialize(FsFile& file) const; bool serialize(HalFile& file) const;
static std::unique_ptr<Page> deserialize(FsFile& file); static std::unique_ptr<Page> deserialize(HalFile& file);
// Check if page contains any images (used to force full refresh) // Check if page contains any images (used to force full refresh)
bool hasImages() const { bool hasImages() const {
+5 -5
View File
@@ -176,7 +176,7 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
Storage.remove(tmpHtmlPath.c_str()); Storage.remove(tmpHtmlPath.c_str());
} }
FsFile tmpHtml; HalFile tmpHtml;
if (!Storage.openFileForWrite("SCT", tmpHtmlPath, tmpHtml)) { if (!Storage.openFileForWrite("SCT", tmpHtmlPath, tmpHtml)) {
continue; continue;
} }
@@ -317,7 +317,7 @@ std::unique_ptr<Page> Section::loadPageFromSectionFile() {
} }
std::optional<uint16_t> Section::getPageForAnchor(const std::string& anchor) const { std::optional<uint16_t> Section::getPageForAnchor(const std::string& anchor) const {
FsFile f; HalFile f;
if (!Storage.openFileForRead("SCT", filePath, f)) { if (!Storage.openFileForRead("SCT", filePath, f)) {
return std::nullopt; return std::nullopt;
} }
@@ -347,7 +347,7 @@ std::optional<uint16_t> Section::getPageForAnchor(const std::string& anchor) con
} }
std::optional<uint16_t> Section::getPageForParagraphIndex(const uint16_t pIndex) const { std::optional<uint16_t> Section::getPageForParagraphIndex(const uint16_t pIndex) const {
FsFile f; HalFile f;
if (!Storage.openFileForRead("SCT", filePath, f)) { if (!Storage.openFileForRead("SCT", filePath, f)) {
return std::nullopt; return std::nullopt;
} }
@@ -386,7 +386,7 @@ std::optional<uint16_t> Section::getPageForParagraphIndex(const uint16_t pIndex)
} }
std::optional<uint16_t> Section::getParagraphIndexForPage(const uint16_t page) const { std::optional<uint16_t> Section::getParagraphIndexForPage(const uint16_t page) const {
FsFile f; HalFile f;
if (!Storage.openFileForRead("SCT", filePath, f)) { if (!Storage.openFileForRead("SCT", filePath, f)) {
return std::nullopt; return std::nullopt;
} }
@@ -418,7 +418,7 @@ std::optional<uint16_t> Section::getParagraphIndexForPage(const uint16_t page) c
} }
std::optional<uint16_t> Section::getPageForListItemIndex(const uint16_t liIndex) const { std::optional<uint16_t> Section::getPageForListItemIndex(const uint16_t liIndex) const {
FsFile f; HalFile f;
if (!Storage.openFileForRead("SCT", filePath, f)) { if (!Storage.openFileForRead("SCT", filePath, f)) {
return std::nullopt; return std::nullopt;
} }
+1 -1
View File
@@ -14,7 +14,7 @@ class Section {
const int spineIndex; const int spineIndex;
GfxRenderer& renderer; GfxRenderer& renderer;
std::string filePath; std::string filePath;
FsFile file; HalFile file;
void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment, void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled,
+4 -4
View File
@@ -30,7 +30,7 @@ std::string getCachePath(const std::string& imagePath) {
bool renderFromCache(GfxRenderer& renderer, const std::string& cachePath, int x, int y, int expectedWidth, bool renderFromCache(GfxRenderer& renderer, const std::string& cachePath, int x, int y, int expectedWidth,
int expectedHeight) { int expectedHeight) {
FsFile cacheFile; HalFile cacheFile;
if (!Storage.openFileForRead("IMG", cachePath, cacheFile)) { if (!Storage.openFileForRead("IMG", cachePath, cacheFile)) {
return false; return false;
} }
@@ -112,7 +112,7 @@ void ImageBlock::render(GfxRenderer& renderer, const int x, const int y) {
// No cache - need to decode the image // No cache - need to decode the image
// Check if image file exists // Check if image file exists
FsFile file; HalFile file;
if (!Storage.openFileForRead("IMG", imagePath, file)) { if (!Storage.openFileForRead("IMG", imagePath, file)) {
LOG_ERR("IMG", "Image file not found: %s", imagePath.c_str()); LOG_ERR("IMG", "Image file not found: %s", imagePath.c_str());
return; return;
@@ -155,14 +155,14 @@ void ImageBlock::render(GfxRenderer& renderer, const int x, const int y) {
LOG_DBG("IMG", "Decode successful"); LOG_DBG("IMG", "Decode successful");
} }
bool ImageBlock::serialize(FsFile& file) { bool ImageBlock::serialize(HalFile& file) {
serialization::writeString(file, imagePath); serialization::writeString(file, imagePath);
serialization::writePod(file, width); serialization::writePod(file, width);
serialization::writePod(file, height); serialization::writePod(file, height);
return true; return true;
} }
std::unique_ptr<ImageBlock> ImageBlock::deserialize(FsFile& file) { std::unique_ptr<ImageBlock> ImageBlock::deserialize(HalFile& file) {
std::string path; std::string path;
serialization::readString(file, path); serialization::readString(file, path);
int16_t w, h; int16_t w, h;
+2 -2
View File
@@ -21,8 +21,8 @@ class ImageBlock final : public Block {
bool isEmpty() override { return false; } bool isEmpty() override { return false; }
void render(GfxRenderer& renderer, const int x, const int y); void render(GfxRenderer& renderer, const int x, const int y);
bool serialize(FsFile& file); bool serialize(HalFile& file);
static std::unique_ptr<ImageBlock> deserialize(FsFile& file); static std::unique_ptr<ImageBlock> deserialize(HalFile& file);
private: private:
std::string imagePath; std::string imagePath;
+2 -2
View File
@@ -67,7 +67,7 @@ void TextBlock::render(const GfxRenderer& renderer, const int fontId, const int
} }
} }
bool TextBlock::serialize(FsFile& file) const { bool TextBlock::serialize(HalFile& file) const {
// Focus annotations are optional; vectors are either empty (no splits in this block) // Focus annotations are optional; vectors are either empty (no splits in this block)
// or sized in lockstep with words[]. // or sized in lockstep with words[].
const bool hasFocus = !wordFocusBoundary.empty(); const bool hasFocus = !wordFocusBoundary.empty();
@@ -110,7 +110,7 @@ bool TextBlock::serialize(FsFile& file) const {
return true; return true;
} }
std::unique_ptr<TextBlock> TextBlock::deserialize(FsFile& file) { std::unique_ptr<TextBlock> TextBlock::deserialize(HalFile& file) {
uint16_t wc; uint16_t wc;
std::vector<std::string> words; std::vector<std::string> words;
std::vector<int16_t> wordXpos; std::vector<int16_t> wordXpos;
+2 -2
View File
@@ -47,6 +47,6 @@ class TextBlock final : public Block {
// given a renderer works out where to break the words into lines // given a renderer works out where to break the words into lines
void render(const GfxRenderer& renderer, int fontId, int x, int y) const; void render(const GfxRenderer& renderer, int fontId, int x, int y) const;
BlockType getType() override { return TEXT_BLOCK; } BlockType getType() override { return TEXT_BLOCK; }
bool serialize(FsFile& file) const; bool serialize(HalFile& file) const;
static std::unique_ptr<TextBlock> deserialize(FsFile& file); static std::unique_ptr<TextBlock> deserialize(HalFile& file);
}; };
@@ -19,7 +19,7 @@ namespace {
// Context struct passed through JPEGDEC callbacks to avoid global mutable state. // Context struct passed through JPEGDEC callbacks to avoid global mutable state.
// The draw callback receives this via pDraw->pUser (set by setUserPointer()). // The draw callback receives this via pDraw->pUser (set by setUserPointer()).
// The file I/O callbacks receive the FsFile* via pFile->fHandle (set by jpegOpen()). // The file I/O callbacks receive the HalFile* via pFile->fHandle (set by jpegOpen()).
struct JpegContext { struct JpegContext {
GfxRenderer* renderer{nullptr}; GfxRenderer* renderer{nullptr};
const RenderConfig* config{nullptr}; const RenderConfig* config{nullptr};
@@ -48,10 +48,10 @@ struct JpegContext {
bool caching{false}; bool caching{false};
}; };
// File I/O callbacks use pFile->fHandle to access the FsFile*, // File I/O callbacks use pFile->fHandle to access the HalFile*,
// avoiding the need for global file state. // avoiding the need for global file state.
void* jpegOpen(const char* filename, int32_t* size) { void* jpegOpen(const char* filename, int32_t* size) {
FsFile* f = new FsFile(); HalFile* f = new HalFile();
if (!Storage.openFileForRead("JPG", std::string(filename), *f)) { if (!Storage.openFileForRead("JPG", std::string(filename), *f)) {
delete f; delete f;
return nullptr; return nullptr;
@@ -61,7 +61,7 @@ void* jpegOpen(const char* filename, int32_t* size) {
} }
void jpegClose(void* handle) { void jpegClose(void* handle) {
FsFile* f = reinterpret_cast<FsFile*>(handle); HalFile* f = reinterpret_cast<HalFile*>(handle);
if (f) { if (f) {
f->close(); f->close();
delete f; delete f;
@@ -73,7 +73,7 @@ void jpegClose(void* handle) {
// MUST maintain iPos to match the actual file position, otherwise progressive // MUST maintain iPos to match the actual file position, otherwise progressive
// JPEGs with large headers fail during parsing. // JPEGs with large headers fail during parsing.
int32_t jpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) { int32_t jpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) {
FsFile* f = reinterpret_cast<FsFile*>(pFile->fHandle); HalFile* f = reinterpret_cast<HalFile*>(pFile->fHandle);
if (!f) return 0; if (!f) return 0;
int32_t bytesRead = f->read(pBuf, len); int32_t bytesRead = f->read(pBuf, len);
if (bytesRead < 0) return 0; if (bytesRead < 0) return 0;
@@ -82,7 +82,7 @@ int32_t jpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) {
} }
int32_t jpegSeek(JPEGFILE* pFile, int32_t pos) { int32_t jpegSeek(JPEGFILE* pFile, int32_t pos) {
FsFile* f = reinterpret_cast<FsFile*>(pFile->fHandle); HalFile* f = reinterpret_cast<HalFile*>(pFile->fHandle);
if (!f) return -1; if (!f) return -1;
if (!f->seek(pos)) return -1; if (!f->seek(pos)) return -1;
pFile->iPos = pos; pFile->iPos = pos;
+1 -1
View File
@@ -56,7 +56,7 @@ struct PixelCache {
bool writeToFile(const std::string& cachePath) { bool writeToFile(const std::string& cachePath) {
if (!buffer) return false; if (!buffer) return false;
FsFile cacheFile; HalFile cacheFile;
if (!Storage.openFileForWrite("IMG", cachePath, cacheFile)) { if (!Storage.openFileForWrite("IMG", cachePath, cacheFile)) {
LOG_ERR("IMG", "Failed to open cache file for writing: %s", cachePath.c_str()); LOG_ERR("IMG", "Failed to open cache file for writing: %s", cachePath.c_str());
return false; return false;
@@ -19,7 +19,7 @@ namespace {
// Context struct passed through PNGdec callbacks to avoid global mutable state. // Context struct passed through PNGdec callbacks to avoid global mutable state.
// The draw callback receives this via pDraw->pUser (set by png.decode()). // The draw callback receives this via pDraw->pUser (set by png.decode()).
// The file I/O callbacks receive the FsFile* via pFile->fHandle (set by pngOpen()). // The file I/O callbacks receive the HalFile* via pFile->fHandle (set by pngOpen()).
struct PngContext { struct PngContext {
GfxRenderer* renderer{nullptr}; GfxRenderer* renderer{nullptr};
const RenderConfig* config{nullptr}; const RenderConfig* config{nullptr};
@@ -40,10 +40,10 @@ struct PngContext {
uint8_t* grayLineBuffer{nullptr}; uint8_t* grayLineBuffer{nullptr};
}; };
// File I/O callbacks use pFile->fHandle to access the FsFile*, // File I/O callbacks use pFile->fHandle to access the HalFile*,
// avoiding the need for global file state. // avoiding the need for global file state.
void* pngOpenWithHandle(const char* filename, int32_t* size) { void* pngOpenWithHandle(const char* filename, int32_t* size) {
FsFile* f = new FsFile(); HalFile* f = new HalFile();
if (!Storage.openFileForRead("PNG", std::string(filename), *f)) { if (!Storage.openFileForRead("PNG", std::string(filename), *f)) {
delete f; delete f;
return nullptr; return nullptr;
@@ -53,7 +53,7 @@ void* pngOpenWithHandle(const char* filename, int32_t* size) {
} }
void pngCloseWithHandle(void* handle) { void pngCloseWithHandle(void* handle) {
FsFile* f = reinterpret_cast<FsFile*>(handle); HalFile* f = reinterpret_cast<HalFile*>(handle);
if (f) { if (f) {
f->close(); f->close();
delete f; delete f;
@@ -61,13 +61,13 @@ void pngCloseWithHandle(void* handle) {
} }
int32_t pngReadWithHandle(PNGFILE* pFile, uint8_t* pBuf, int32_t len) { int32_t pngReadWithHandle(PNGFILE* pFile, uint8_t* pBuf, int32_t len) {
FsFile* f = reinterpret_cast<FsFile*>(pFile->fHandle); HalFile* f = reinterpret_cast<HalFile*>(pFile->fHandle);
if (!f) return 0; if (!f) return 0;
return f->read(pBuf, len); return f->read(pBuf, len);
} }
int32_t pngSeekWithHandle(PNGFILE* pFile, int32_t pos) { int32_t pngSeekWithHandle(PNGFILE* pFile, int32_t pos) {
FsFile* f = reinterpret_cast<FsFile*>(pFile->fHandle); HalFile* f = reinterpret_cast<HalFile*>(pFile->fHandle);
if (!f) return -1; if (!f) return -1;
return f->seek(pos); return f->seek(pos);
} }
+3 -3
View File
@@ -460,7 +460,7 @@ void CssParser::processRuleBlockWithStyle(const std::string& selectorGroup, cons
// Main parsing entry point // Main parsing entry point
bool CssParser::loadFromStream(FsFile& source) { bool CssParser::loadFromStream(HalFile& source) {
if (!source) { if (!source) {
LOG_ERR("CSS", "Cannot read from invalid file"); LOG_ERR("CSS", "Cannot read from invalid file");
return false; return false;
@@ -676,7 +676,7 @@ bool CssParser::saveToCache() const {
return false; return false;
} }
FsFile file; HalFile file;
if (!Storage.openFileForWrite("CSS", cachePath + rulesCache, file)) { if (!Storage.openFileForWrite("CSS", cachePath + rulesCache, file)) {
return false; return false;
} }
@@ -751,7 +751,7 @@ bool CssParser::loadFromCache() {
return false; return false;
} }
FsFile file; HalFile file;
if (!Storage.openFileForRead("CSS", cachePath + rulesCache, file)) { if (!Storage.openFileForRead("CSS", cachePath + rulesCache, file)) {
return false; return false;
} }
+1 -1
View File
@@ -46,7 +46,7 @@ class CssParser {
* @param source Open file handle to read from * @param source Open file handle to read from
* @return true if parsing completed (even if no rules found) * @return true if parsing completed (even if no rules found)
*/ */
bool loadFromStream(FsFile& source); bool loadFromStream(HalFile& source);
/** /**
* Look up the style for an HTML element, considering tag name and class attributes. * Look up the style for an HTML element, considering tag name and class attributes.
@@ -380,7 +380,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
std::string cachedImagePath = self->imageBasePath + std::to_string(self->imageCounter++) + ext; std::string cachedImagePath = self->imageBasePath + std::to_string(self->imageCounter++) + ext;
// Extract image to cache file // Extract image to cache file
FsFile cachedImageFile; HalFile cachedImageFile;
bool extractSuccess = false; bool extractSuccess = false;
if (Storage.openFileForWrite("EHP", cachedImagePath, cachedImageFile)) { if (Storage.openFileForWrite("EHP", cachedImagePath, cachedImageFile)) {
extractSuccess = self->epub->readItemContentsToStream(resolvedPath, cachedImageFile, 4096); extractSuccess = self->epub->readItemContentsToStream(resolvedPath, cachedImageFile, 4096);
@@ -1150,7 +1150,7 @@ bool ChapterHtmlSlimParser::parseAndBuildPages() {
// Using DefaultHandlerExpand preserves normal entity expansion from DOCTYPE // Using DefaultHandlerExpand preserves normal entity expansion from DOCTYPE
XML_SetDefaultHandlerExpand(parser, defaultHandlerExpand); XML_SetDefaultHandlerExpand(parser, defaultHandlerExpand);
FsFile file; HalFile file;
if (!Storage.openFileForRead("EHP", filepath, file)) { if (!Storage.openFileForRead("EHP", filepath, file)) {
destroyXmlParser(parser); destroyXmlParser(parser);
return false; return false;
+1 -1
View File
@@ -29,7 +29,7 @@ class ContentOpfParser final : public Print {
XML_Parser parser = nullptr; XML_Parser parser = nullptr;
ParserState state = START; ParserState state = START;
BookMetadataCache* cache; BookMetadataCache* cache;
FsFile tempItemStore; HalFile tempItemStore;
std::string coverItemId; std::string coverItemId;
// Index for fast idref→href lookup (used only for large EPUBs) // Index for fast idref→href lookup (used only for large EPUBs)
+2 -2
View File
@@ -21,7 +21,7 @@ Bitmap::~Bitmap() {
delete fsDitherer; delete fsDitherer;
} }
uint16_t Bitmap::readLE16(FsFile& f) { uint16_t Bitmap::readLE16(HalFile& f) {
const int c0 = f.read(); const int c0 = f.read();
const int c1 = f.read(); const int c1 = f.read();
const auto b0 = static_cast<uint8_t>(c0 < 0 ? 0 : c0); const auto b0 = static_cast<uint8_t>(c0 < 0 ? 0 : c0);
@@ -29,7 +29,7 @@ uint16_t Bitmap::readLE16(FsFile& f) {
return static_cast<uint16_t>(b0) | (static_cast<uint16_t>(b1) << 8); return static_cast<uint16_t>(b0) | (static_cast<uint16_t>(b1) << 8);
} }
uint32_t Bitmap::readLE32(FsFile& f) { uint32_t Bitmap::readLE32(HalFile& f) {
const int c0 = f.read(); const int c0 = f.read();
const int c1 = f.read(); const int c1 = f.read();
const int c2 = f.read(); const int c2 = f.read();
+4 -4
View File
@@ -64,7 +64,7 @@ class Bitmap {
public: public:
static const char* errorToString(BmpReaderError err); static const char* errorToString(BmpReaderError err);
explicit Bitmap(FsFile& file, bool dithering = false) : file(file), dithering(dithering) {} explicit Bitmap(HalFile& file, bool dithering = false) : file(file), dithering(dithering) {}
~Bitmap(); ~Bitmap();
BmpReaderError parseHeaders(); BmpReaderError parseHeaders();
BmpReaderError readNextRow(uint8_t* data, uint8_t* rowBuffer) const; BmpReaderError readNextRow(uint8_t* data, uint8_t* rowBuffer) const;
@@ -78,10 +78,10 @@ class Bitmap {
uint16_t getBpp() const { return bpp; } uint16_t getBpp() const { return bpp; }
private: private:
static uint16_t readLE16(FsFile& f); static uint16_t readLE16(HalFile& f);
static uint32_t readLE32(FsFile& f); static uint32_t readLE32(HalFile& f);
FsFile& file; HalFile& file;
bool dithering = false; bool dithering = false;
int width = 0; int width = 0;
int height = 0; int height = 0;
+1 -1
View File
@@ -25,7 +25,7 @@ enum class InflateStatus {
// //
// struct MyCtx { // struct MyCtx {
// InflateReader reader; // must be first // InflateReader reader; // must be first
// FsFile* file; // HalFile* file;
// // ... // // ...
// }; // };
// static int myCb(struct uzlib_uncomp* u) { // static int myCb(struct uzlib_uncomp* u) {
@@ -167,7 +167,7 @@ constexpr size_t MIN_FREE_HEAP = JPEG_DECODER_SIZE + 32 * 1024;
// Static file pointer for JPEGDEC open callback. // Static file pointer for JPEGDEC open callback.
// Safe in single-threaded embedded context; never accessed concurrently. // Safe in single-threaded embedded context; never accessed concurrently.
static FsFile* s_jpegFile = nullptr; static HalFile* s_jpegFile = nullptr;
void* bmpJpegOpen(const char* /*filename*/, int32_t* size) { void* bmpJpegOpen(const char* /*filename*/, int32_t* size) {
if (!s_jpegFile || !*s_jpegFile) return nullptr; if (!s_jpegFile || !*s_jpegFile) return nullptr;
@@ -181,7 +181,7 @@ void bmpJpegClose(void* /*handle*/) {
} }
int32_t bmpJpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) { int32_t bmpJpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) {
auto* f = reinterpret_cast<FsFile*>(pFile->fHandle); auto* f = reinterpret_cast<HalFile*>(pFile->fHandle);
if (!f) return 0; if (!f) return 0;
int32_t n = f->read(pBuf, len); int32_t n = f->read(pBuf, len);
if (n < 0) n = 0; if (n < 0) n = 0;
@@ -190,7 +190,7 @@ int32_t bmpJpegRead(JPEGFILE* pFile, uint8_t* pBuf, int32_t len) {
} }
int32_t bmpJpegSeek(JPEGFILE* pFile, int32_t pos) { int32_t bmpJpegSeek(JPEGFILE* pFile, int32_t pos) {
auto* f = reinterpret_cast<FsFile*>(pFile->fHandle); auto* f = reinterpret_cast<HalFile*>(pFile->fHandle);
if (!f || !f->seek(pos)) return -1; if (!f || !f->seek(pos)) return -1;
pFile->iPos = pos; pFile->iPos = pos;
return pos; return pos;
@@ -376,8 +376,8 @@ int bmpDrawCallback(JPEGDRAW* pDraw) {
} // namespace } // namespace
// Internal implementation with configurable target size and bit depth // Internal implementation with configurable target size and bit depth
bool JpegToBmpConverter::jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight, bool JpegToBmpConverter::jpegFileToBmpStreamInternal(HalFile& jpegFile, Print& bmpOut, int targetWidth,
bool oneBit, bool crop) { int targetHeight, bool oneBit, bool crop) {
LOG_DBG("JPG", "Converting JPEG to %s BMP (target: %dx%d)", oneBit ? "1-bit" : "2-bit", targetWidth, targetHeight); LOG_DBG("JPG", "Converting JPEG to %s BMP (target: %dx%d)", oneBit ? "1-bit" : "2-bit", targetWidth, targetHeight);
if (ESP.getFreeHeap() < MIN_FREE_HEAP) { if (ESP.getFreeHeap() < MIN_FREE_HEAP) {
@@ -532,7 +532,7 @@ bool JpegToBmpConverter::jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bm
} }
// Core function: Convert JPEG file to 2-bit BMP (uses default target size) // Core function: Convert JPEG file to 2-bit BMP (uses default target size)
bool JpegToBmpConverter::jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut, bool crop) { bool JpegToBmpConverter::jpegFileToBmpStream(HalFile& jpegFile, Print& bmpOut, bool crop) {
// Use runtime display dimensions (swapped for portrait cover sizing) // Use runtime display dimensions (swapped for portrait cover sizing)
const int targetWidth = display.getDisplayHeight(); const int targetWidth = display.getDisplayHeight();
const int targetHeight = display.getDisplayWidth(); const int targetHeight = display.getDisplayWidth();
@@ -540,13 +540,13 @@ bool JpegToBmpConverter::jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut, bo
} }
// Convert with custom target size (for thumbnails, 2-bit) // Convert with custom target size (for thumbnails, 2-bit)
bool JpegToBmpConverter::jpegFileToBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, bool JpegToBmpConverter::jpegFileToBmpStreamWithSize(HalFile& jpegFile, Print& bmpOut, int targetMaxWidth,
int targetMaxHeight) { int targetMaxHeight) {
return jpegFileToBmpStreamInternal(jpegFile, bmpOut, targetMaxWidth, targetMaxHeight, false); return jpegFileToBmpStreamInternal(jpegFile, bmpOut, targetMaxWidth, targetMaxHeight, false);
} }
// Convert to 1-bit BMP (black and white only, no grays) for fast home screen rendering // Convert to 1-bit BMP (black and white only, no grays) for fast home screen rendering
bool JpegToBmpConverter::jpegFileTo1BitBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, bool JpegToBmpConverter::jpegFileTo1BitBmpStreamWithSize(HalFile& jpegFile, Print& bmpOut, int targetMaxWidth,
int targetMaxHeight) { int targetMaxHeight) {
return jpegFileToBmpStreamInternal(jpegFile, bmpOut, targetMaxWidth, targetMaxHeight, true, true); return jpegFileToBmpStreamInternal(jpegFile, bmpOut, targetMaxWidth, targetMaxHeight, true, true);
} }
+5 -4
View File
@@ -6,13 +6,14 @@ class Print;
class ZipFile; class ZipFile;
class JpegToBmpConverter { class JpegToBmpConverter {
static bool jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight, static bool jpegFileToBmpStreamInternal(HalFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight,
bool oneBit, bool crop = true); bool oneBit, bool crop = true);
public: public:
static bool jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut, bool crop = true); static bool jpegFileToBmpStream(HalFile& jpegFile, Print& bmpOut, bool crop = true);
// Convert with custom target size (for thumbnails) // Convert with custom target size (for thumbnails)
static bool jpegFileToBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); static bool jpegFileToBmpStreamWithSize(HalFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight);
// Convert to 1-bit BMP (black and white only, no grays) for fast home screen rendering // Convert to 1-bit BMP (black and white only, no grays) for fast home screen rendering
static bool jpegFileTo1BitBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); static bool jpegFileTo1BitBmpStreamWithSize(HalFile& jpegFile, Print& bmpOut, int targetMaxWidth,
int targetMaxHeight);
}; };
+1 -1
View File
@@ -73,7 +73,7 @@ bool KOReaderCredentialStore::loadFromFile() {
} }
bool KOReaderCredentialStore::loadFromBinaryFile() { bool KOReaderCredentialStore::loadFromBinaryFile() {
FsFile file; HalFile file;
if (!Storage.openFileForRead("KRS", KOREADER_FILE_BIN, file)) { if (!Storage.openFileForRead("KRS", KOREADER_FILE_BIN, file)) {
return false; return false;
} }
+1 -1
View File
@@ -42,7 +42,7 @@ size_t KOReaderDocumentId::getOffset(int i) {
} }
std::string KOReaderDocumentId::calculate(const std::string& filePath) { std::string KOReaderDocumentId::calculate(const std::string& filePath) {
FsFile file; HalFile file;
if (!Storage.openFileForRead("KODoc", filePath, file)) { if (!Storage.openFileForRead("KODoc", filePath, file)) {
LOG_DBG("KODoc", "Failed to open file: %s", filePath.c_str()); LOG_DBG("KODoc", "Failed to open file: %s", filePath.c_str());
return ""; return "";
+6 -6
View File
@@ -73,7 +73,7 @@ enum PngFilter : uint8_t {
}; };
// Read a big-endian 32-bit value from file // Read a big-endian 32-bit value from file
bool readBE32(FsFile& file, uint32_t& value) { bool readBE32(HalFile& file, uint32_t& value) {
uint8_t buf[4]; uint8_t buf[4];
if (file.read(buf, 4) != 4) return false; if (file.read(buf, 4) != 4) return false;
value = (static_cast<uint32_t>(buf[0]) << 24) | (static_cast<uint32_t>(buf[1]) << 16) | value = (static_cast<uint32_t>(buf[0]) << 24) | (static_cast<uint32_t>(buf[1]) << 16) |
@@ -177,7 +177,7 @@ void writeBmpHeader2bit(Print& bmpOut, const int width, const int height) {
// IMPORTANT: reader must be the first field - the uzlib callback casts uzlib_uncomp* to PngDecodeContext* // IMPORTANT: reader must be the first field - the uzlib callback casts uzlib_uncomp* to PngDecodeContext*
struct PngDecodeContext { struct PngDecodeContext {
InflateReader reader; // Must be first — callback casts uzlib_uncomp* to PngDecodeContext* InflateReader reader; // Must be first — callback casts uzlib_uncomp* to PngDecodeContext*
FsFile* file; HalFile* file;
// PNG image properties // PNG image properties
uint32_t width; uint32_t width;
@@ -395,7 +395,7 @@ static void convertScanlineToGray(const PngDecodeContext& ctx, uint8_t* grayRow)
} }
} }
bool PngToBmpConverter::pngFileToBmpStreamInternal(FsFile& pngFile, Print& bmpOut, int targetWidth, int targetHeight, bool PngToBmpConverter::pngFileToBmpStreamInternal(HalFile& pngFile, Print& bmpOut, int targetWidth, int targetHeight,
bool oneBit, bool crop) { bool oneBit, bool crop) {
LOG_DBG("PNG", "Converting PNG to %s BMP (target: %dx%d)", oneBit ? "1-bit" : "2-bit", targetWidth, targetHeight); LOG_DBG("PNG", "Converting PNG to %s BMP (target: %dx%d)", oneBit ? "1-bit" : "2-bit", targetWidth, targetHeight);
@@ -820,19 +820,19 @@ bool PngToBmpConverter::pngFileToBmpStreamInternal(FsFile& pngFile, Print& bmpOu
return success; return success;
} }
bool PngToBmpConverter::pngFileToBmpStream(FsFile& pngFile, Print& bmpOut, bool crop) { bool PngToBmpConverter::pngFileToBmpStream(HalFile& pngFile, Print& bmpOut, bool crop) {
// Use runtime display dimensions (swapped for portrait cover sizing) // Use runtime display dimensions (swapped for portrait cover sizing)
const int targetWidth = display.getDisplayHeight(); const int targetWidth = display.getDisplayHeight();
const int targetHeight = display.getDisplayWidth(); const int targetHeight = display.getDisplayWidth();
return pngFileToBmpStreamInternal(pngFile, bmpOut, targetWidth, targetHeight, false, crop); return pngFileToBmpStreamInternal(pngFile, bmpOut, targetWidth, targetHeight, false, crop);
} }
bool PngToBmpConverter::pngFileToBmpStreamWithSize(FsFile& pngFile, Print& bmpOut, int targetMaxWidth, bool PngToBmpConverter::pngFileToBmpStreamWithSize(HalFile& pngFile, Print& bmpOut, int targetMaxWidth,
int targetMaxHeight) { int targetMaxHeight) {
return pngFileToBmpStreamInternal(pngFile, bmpOut, targetMaxWidth, targetMaxHeight, false); return pngFileToBmpStreamInternal(pngFile, bmpOut, targetMaxWidth, targetMaxHeight, false);
} }
bool PngToBmpConverter::pngFileTo1BitBmpStreamWithSize(FsFile& pngFile, Print& bmpOut, int targetMaxWidth, bool PngToBmpConverter::pngFileTo1BitBmpStreamWithSize(HalFile& pngFile, Print& bmpOut, int targetMaxWidth,
int targetMaxHeight) { int targetMaxHeight) {
return pngFileToBmpStreamInternal(pngFile, bmpOut, targetMaxWidth, targetMaxHeight, true, true); return pngFileToBmpStreamInternal(pngFile, bmpOut, targetMaxWidth, targetMaxHeight, true, true);
} }
+5 -5
View File
@@ -5,11 +5,11 @@
class Print; class Print;
class PngToBmpConverter { class PngToBmpConverter {
static bool pngFileToBmpStreamInternal(FsFile& pngFile, Print& bmpOut, int targetWidth, int targetHeight, bool oneBit, static bool pngFileToBmpStreamInternal(HalFile& pngFile, Print& bmpOut, int targetWidth, int targetHeight,
bool crop = true); bool oneBit, bool crop = true);
public: public:
static bool pngFileToBmpStream(FsFile& pngFile, Print& bmpOut, bool crop = true); static bool pngFileToBmpStream(HalFile& pngFile, Print& bmpOut, bool crop = true);
static bool pngFileToBmpStreamWithSize(FsFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); static bool pngFileToBmpStreamWithSize(HalFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight);
static bool pngFileTo1BitBmpStreamWithSize(FsFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight); static bool pngFileTo1BitBmpStreamWithSize(HalFile& pngFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight);
}; };
+4 -4
View File
@@ -10,7 +10,7 @@ void writePod(std::ostream& os, const T& value) {
} }
template <typename T> template <typename T>
void writePod(FsFile& file, const T& value) { void writePod(HalFile& file, const T& value) {
file.write(reinterpret_cast<const uint8_t*>(&value), sizeof(T)); file.write(reinterpret_cast<const uint8_t*>(&value), sizeof(T));
} }
@@ -20,7 +20,7 @@ void readPod(std::istream& is, T& value) {
} }
template <typename T> template <typename T>
void readPod(FsFile& file, T& value) { void readPod(HalFile& file, T& value) {
file.read(reinterpret_cast<uint8_t*>(&value), sizeof(T)); file.read(reinterpret_cast<uint8_t*>(&value), sizeof(T));
} }
@@ -30,7 +30,7 @@ inline void writeString(std::ostream& os, const std::string& s) {
os.write(s.data(), len); os.write(s.data(), len);
} }
inline void writeString(FsFile& file, const std::string& s) { inline void writeString(HalFile& file, const std::string& s) {
const uint32_t len = s.size(); const uint32_t len = s.size();
writePod(file, len); writePod(file, len);
file.write(reinterpret_cast<const uint8_t*>(s.data()), len); file.write(reinterpret_cast<const uint8_t*>(s.data()), len);
@@ -43,7 +43,7 @@ inline void readString(std::istream& is, std::string& s) {
is.read(&s[0], len); is.read(&s[0], len);
} }
inline void readString(FsFile& file, std::string& s) { inline void readString(HalFile& file, std::string& s) {
uint32_t len; uint32_t len;
readPod(file, len); readPod(file, len);
s.resize(len); s.resize(len);
+4 -4
View File
@@ -21,7 +21,7 @@ bool Txt::load() {
return false; return false;
} }
FsFile file; HalFile file;
if (!Storage.openFileForRead("TXT", filepath, file)) { if (!Storage.openFileForRead("TXT", filepath, file)) {
LOG_ERR("TXT", "Failed to open file: %s", filepath.c_str()); LOG_ERR("TXT", "Failed to open file: %s", filepath.c_str());
return false; return false;
@@ -115,7 +115,7 @@ bool Txt::generateCoverBmp() const {
if (FsHelpers::hasBmpExtension(coverImagePath)) { if (FsHelpers::hasBmpExtension(coverImagePath)) {
// Copy BMP file to cache // Copy BMP file to cache
LOG_DBG("TXT", "Copying BMP cover image to cache"); LOG_DBG("TXT", "Copying BMP cover image to cache");
FsFile src, dst; HalFile src, dst;
if (!Storage.openFileForRead("TXT", coverImagePath, src)) { if (!Storage.openFileForRead("TXT", coverImagePath, src)) {
return false; return false;
} }
@@ -132,7 +132,7 @@ bool Txt::generateCoverBmp() const {
} else if (FsHelpers::hasJpgExtension(coverImagePath)) { } else if (FsHelpers::hasJpgExtension(coverImagePath)) {
// Convert JPG/JPEG to BMP (same approach as Epub) // Convert JPG/JPEG to BMP (same approach as Epub)
LOG_DBG("TXT", "Generating BMP from JPG cover image"); LOG_DBG("TXT", "Generating BMP from JPG cover image");
FsFile coverJpg, coverBmp; HalFile coverJpg, coverBmp;
if (!Storage.openFileForRead("TXT", coverImagePath, coverJpg)) { if (!Storage.openFileForRead("TXT", coverImagePath, coverJpg)) {
return false; return false;
} }
@@ -175,7 +175,7 @@ bool Txt::readContent(uint8_t* buffer, size_t offset, size_t length) const {
return false; return false;
} }
FsFile file; HalFile file;
if (!Storage.openFileForRead("TXT", filepath, file)) { if (!Storage.openFileForRead("TXT", filepath, file)) {
return false; return false;
} }
+3 -3
View File
@@ -166,7 +166,7 @@ bool Xtc::generateCoverBmp() const {
} }
// Create BMP file // Create BMP file
FsFile coverBmp; HalFile coverBmp;
if (!Storage.openFileForWrite("XTC", getCoverBmpPath(), coverBmp)) { if (!Storage.openFileForWrite("XTC", getCoverBmpPath(), coverBmp)) {
LOG_DBG("XTC", "Failed to create cover BMP file"); LOG_DBG("XTC", "Failed to create cover BMP file");
free(pageBuffer); free(pageBuffer);
@@ -306,7 +306,7 @@ bool Xtc::generateThumbBmp(int height) const {
// Page is already small enough, just use cover.bmp // Page is already small enough, just use cover.bmp
// Copy cover.bmp to thumb.bmp // Copy cover.bmp to thumb.bmp
if (generateCoverBmp()) { if (generateCoverBmp()) {
FsFile src, dst; HalFile src, dst;
if (Storage.openFileForRead("XTC", getCoverBmpPath(), src)) { if (Storage.openFileForRead("XTC", getCoverBmpPath(), src)) {
if (Storage.openFileForWrite("XTC", getThumbBmpPath(height), dst)) { if (Storage.openFileForWrite("XTC", getThumbBmpPath(height), dst)) {
uint8_t buffer[512]; uint8_t buffer[512];
@@ -350,7 +350,7 @@ bool Xtc::generateThumbBmp(int height) const {
} }
// Create thumbnail BMP file - use 1-bit format for fast home screen rendering (no gray passes) // Create thumbnail BMP file - use 1-bit format for fast home screen rendering (no gray passes)
FsFile thumbBmp; HalFile thumbBmp;
if (!Storage.openFileForWrite("XTC", getThumbBmpPath(height), thumbBmp)) { if (!Storage.openFileForWrite("XTC", getThumbBmpPath(height), thumbBmp)) {
LOG_DBG("XTC", "Failed to create thumb BMP file"); LOG_DBG("XTC", "Failed to create thumb BMP file");
free(pageBuffer); free(pageBuffer);
+1 -1
View File
@@ -530,7 +530,7 @@ XtcError XtcParser::loadPageStreaming(uint32_t pageIndex,
} }
bool XtcParser::isValidXtcFile(const char* filepath) { bool XtcParser::isValidXtcFile(const char* filepath) {
FsFile file; HalFile file;
if (!Storage.openFileForRead("XTC", filepath, file)) { if (!Storage.openFileForRead("XTC", filepath, file)) {
return false; return false;
} }
+1 -1
View File
@@ -84,7 +84,7 @@ class XtcParser {
XtcError getLastError() const { return m_lastError; } XtcError getLastError() const { return m_lastError; }
private: private:
FsFile m_file; HalFile m_file;
std::string m_filepath; std::string m_filepath;
bool m_isOpen; bool m_isOpen;
XtcHeader m_header; XtcHeader m_header;
+1 -1
View File
@@ -8,7 +8,7 @@
struct ZipInflateCtx { struct ZipInflateCtx {
InflateReader reader; // Must be first — callback casts uzlib_uncomp* to ZipInflateCtx* InflateReader reader; // Must be first — callback casts uzlib_uncomp* to ZipInflateCtx*
FsFile* file = nullptr; HalFile* file = nullptr;
size_t fileRemaining = 0; size_t fileRemaining = 0;
uint8_t* readBuf = nullptr; uint8_t* readBuf = nullptr;
size_t readBufSize = 0; size_t readBufSize = 0;
+1 -1
View File
@@ -39,7 +39,7 @@ class ZipFile {
private: private:
const std::string& filePath; const std::string& filePath;
FsFile file; HalFile file;
ZipDetails zipDetails = {0, 0, false}; ZipDetails zipDetails = {0, 0, false};
std::unordered_map<std::string, FileStatSlim> fileStatSlimCache; std::unordered_map<std::string, FileStatSlim> fileStatSlimCache;
-1
View File
@@ -1,4 +1,3 @@
#define HAL_STORAGE_IMPL
#include "HalStorage.h" #include "HalStorage.h"
#include <FS.h> // need to be included before SdFat.h for compatibility with FS.h's File class #include <FS.h> // need to be included before SdFat.h for compatibility with FS.h's File class
-7
View File
@@ -96,13 +96,6 @@ class HalFile : public Print {
operator bool() const; operator bool() const;
}; };
// Only do renaming FsFile to HalFile if this header is included by downstream code
// The renaming is to allow using the thread-safe HalFile instead of the raw FsFile, without needing to change the
// downstream code
#ifndef HAL_STORAGE_IMPL
using FsFile = HalFile;
#endif
// Downstream code must use Storage instead of SdMan // Downstream code must use Storage instead of SdMan
#ifdef SdMan #ifdef SdMan
#undef SdMan #undef SdMan
+3 -3
View File
@@ -14,7 +14,7 @@
// Initialize the static instance // Initialize the static instance
CrossPointSettings CrossPointSettings::instance; CrossPointSettings CrossPointSettings::instance;
void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) { void readAndValidate(HalFile& file, uint8_t& member, const uint8_t maxValue) {
uint8_t tempValue; uint8_t tempValue;
serialization::readPod(file, tempValue); serialization::readPod(file, tempValue);
if (tempValue < maxValue) { if (tempValue < maxValue) {
@@ -127,7 +127,7 @@ bool CrossPointSettings::migrateLanguageBinaryFile() {
// frozen enum order from 2f969a9. // frozen enum order from 2f969a9.
if (!Storage.exists(LANG_FILE_BIN)) return false; if (!Storage.exists(LANG_FILE_BIN)) return false;
FsFile f; HalFile f;
if (Storage.openFileForRead("CPS", LANG_FILE_BIN, f)) { if (Storage.openFileForRead("CPS", LANG_FILE_BIN, f)) {
uint8_t version; uint8_t version;
serialization::readPod(f, version); serialization::readPod(f, version);
@@ -146,7 +146,7 @@ bool CrossPointSettings::migrateLanguageBinaryFile() {
} }
bool CrossPointSettings::loadFromBinaryFile() { bool CrossPointSettings::loadFromBinaryFile() {
FsFile inputFile; HalFile inputFile;
if (!Storage.openFileForRead("CPS", SETTINGS_FILE_BIN, inputFile)) { if (!Storage.openFileForRead("CPS", SETTINGS_FILE_BIN, inputFile)) {
return false; return false;
} }
+1 -1
View File
@@ -269,7 +269,7 @@ class CrossPointSettings {
int getReaderFontId() const; int getReaderFontId() const;
// If count_only is true, returns the number of settings items that would be written. // If count_only is true, returns the number of settings items that would be written.
uint8_t writeSettings(FsFile& file, bool count_only = false) const; uint8_t writeSettings(HalFile& file, bool count_only = false) const;
bool saveToFile() const; bool saveToFile() const;
bool loadFromFile(); bool loadFromFile();
+1 -1
View File
@@ -63,7 +63,7 @@ bool CrossPointState::loadFromFile() {
} }
bool CrossPointState::loadFromBinaryFile() { bool CrossPointState::loadFromBinaryFile() {
FsFile inputFile; HalFile inputFile;
if (!Storage.openFileForRead("CPS", STATE_FILE_BIN, inputFile)) { if (!Storage.openFileForRead("CPS", STATE_FILE_BIN, inputFile)) {
return false; return false;
} }
+1 -1
View File
@@ -81,7 +81,7 @@ bool FontInstaller::ensureFamilyDir(const char* familyName) {
} }
bool FontInstaller::validateCpfontFile(const char* path) { bool FontInstaller::validateCpfontFile(const char* path) {
FsFile file; HalFile file;
if (!Storage.openFileForRead("FONT", path, file)) { if (!Storage.openFileForRead("FONT", path, file)) {
LOG_ERR("FONT", "Cannot open for validation: %s", path); LOG_ERR("FONT", "Cannot open for validation: %s", path);
return false; return false;
+1 -1
View File
@@ -148,7 +148,7 @@ bool RecentBooksStore::loadFromFile() {
} }
bool RecentBooksStore::loadFromBinaryFile() { bool RecentBooksStore::loadFromBinaryFile() {
FsFile inputFile; HalFile inputFile;
if (!Storage.openFileForRead("RBS", RECENT_BOOKS_FILE_BIN, inputFile)) { if (!Storage.openFileForRead("RBS", RECENT_BOOKS_FILE_BIN, inputFile)) {
return false; return false;
} }
+1 -1
View File
@@ -67,7 +67,7 @@ bool WifiCredentialStore::loadFromFile() {
} }
bool WifiCredentialStore::loadFromBinaryFile() { bool WifiCredentialStore::loadFromBinaryFile() {
FsFile file; HalFile file;
if (!Storage.openFileForRead("WCS", WIFI_FILE_BIN, file)) { if (!Storage.openFileForRead("WCS", WIFI_FILE_BIN, file)) {
return false; return false;
} }
+3 -3
View File
@@ -63,7 +63,7 @@ void SleepActivity::renderCustomSleepScreen() const {
// Look for sleep.bmp on the root of the sd card to determine if we should // Look for sleep.bmp on the root of the sd card to determine if we should
// render a custom sleep screen instead of the default. // render a custom sleep screen instead of the default.
// This takes priority over the /sleep folder. // This takes priority over the /sleep folder.
FsFile file; HalFile file;
if (Storage.openFileForRead("SLP", "/sleep.bmp", file)) { if (Storage.openFileForRead("SLP", "/sleep.bmp", file)) {
Bitmap bitmap(file, true); Bitmap bitmap(file, true);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
@@ -129,7 +129,7 @@ void SleepActivity::renderCustomSleepScreen() const {
APP_STATE.pushRecentSleep(randomFileIndex); APP_STATE.pushRecentSleep(randomFileIndex);
APP_STATE.saveToFile(); APP_STATE.saveToFile();
const auto filename = std::string(sleepDir) + "/" + files[randomFileIndex]; const auto filename = std::string(sleepDir) + "/" + files[randomFileIndex];
FsFile randFile; HalFile randFile;
if (Storage.openFileForRead("SLP", filename, randFile)) { if (Storage.openFileForRead("SLP", filename, randFile)) {
LOG_DBG("SLP", "Randomly loading: %s/%s", sleepDir, files[randomFileIndex].c_str()); LOG_DBG("SLP", "Randomly loading: %s/%s", sleepDir, files[randomFileIndex].c_str());
delay(100); delay(100);
@@ -304,7 +304,7 @@ void SleepActivity::renderCoverSleepScreen() const {
return (this->*renderNoCoverSleepScreen)(); return (this->*renderNoCoverSleepScreen)();
} }
FsFile file; HalFile file;
if (Storage.openFileForRead("SLP", coverBmpPath, file)) { if (Storage.openFileForRead("SLP", coverBmpPath, file)) {
Bitmap bitmap(file); Bitmap bitmap(file);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
+1 -1
View File
@@ -123,7 +123,7 @@ void EpubReaderActivity::onEnter() {
epub->setupCacheDir(); epub->setupCacheDir();
FsFile f; HalFile f;
if (Storage.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForRead("ERS", epub->getCachePath() + "/progress.bin", f)) {
uint8_t data[6]; uint8_t data[6];
int dataSize = f.read(data, 6); int dataSize = f.read(data, 6);
+1 -1
View File
@@ -13,7 +13,7 @@ inline bool saveProgress(Epub& epub, int spineIndex, int pageNumber, int pageCou
LOG_ERR("ERS", "Progress values out of range: spine=%d page=%d count=%d", spineIndex, pageNumber, pageCount); LOG_ERR("ERS", "Progress values out of range: spine=%d page=%d count=%d", spineIndex, pageNumber, pageCount);
return false; return false;
} }
FsFile f; HalFile f;
if (!Storage.openFileForWrite("ERS", epub.getCachePath() + "/progress.bin", f)) { if (!Storage.openFileForWrite("ERS", epub.getCachePath() + "/progress.bin", f)) {
LOG_ERR("ERS", "Could not open progress file for write!"); LOG_ERR("ERS", "Could not open progress file for write!");
return false; return false;
+4 -4
View File
@@ -415,7 +415,7 @@ void TxtReaderActivity::renderStatusBar() const {
} }
void TxtReaderActivity::saveProgress() const { void TxtReaderActivity::saveProgress() const {
FsFile f; HalFile f;
if (Storage.openFileForWrite("TRS", txt->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForWrite("TRS", txt->getCachePath() + "/progress.bin", f)) {
uint8_t data[4]; uint8_t data[4];
data[0] = currentPage & 0xFF; data[0] = currentPage & 0xFF;
@@ -427,7 +427,7 @@ void TxtReaderActivity::saveProgress() const {
} }
void TxtReaderActivity::loadProgress() { void TxtReaderActivity::loadProgress() {
FsFile f; HalFile f;
if (Storage.openFileForRead("TRS", txt->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForRead("TRS", txt->getCachePath() + "/progress.bin", f)) {
uint8_t data[4]; uint8_t data[4];
if (f.read(data, 4) == 4) { if (f.read(data, 4) == 4) {
@@ -457,7 +457,7 @@ bool TxtReaderActivity::loadPageIndexCache() {
// - N * uint32_t: page offsets // - N * uint32_t: page offsets
std::string cachePath = txt->getCachePath() + "/index.bin"; std::string cachePath = txt->getCachePath() + "/index.bin";
FsFile f; HalFile f;
if (!Storage.openFileForRead("TRS", cachePath, f)) { if (!Storage.openFileForRead("TRS", cachePath, f)) {
LOG_DBG("TRS", "No page index cache found"); LOG_DBG("TRS", "No page index cache found");
return false; return false;
@@ -540,7 +540,7 @@ bool TxtReaderActivity::loadPageIndexCache() {
void TxtReaderActivity::savePageIndexCache() const { void TxtReaderActivity::savePageIndexCache() const {
std::string cachePath = txt->getCachePath() + "/index.bin"; std::string cachePath = txt->getCachePath() + "/index.bin";
FsFile f; HalFile f;
if (!Storage.openFileForWrite("TRS", cachePath, f)) { if (!Storage.openFileForWrite("TRS", cachePath, f)) {
LOG_ERR("TRS", "Failed to save page index cache"); LOG_ERR("TRS", "Failed to save page index cache");
return; return;
+2 -2
View File
@@ -375,7 +375,7 @@ void XtcReaderActivity::renderPage() {
} }
void XtcReaderActivity::saveProgress() const { void XtcReaderActivity::saveProgress() const {
FsFile f; HalFile f;
if (Storage.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForWrite("XTR", xtc->getCachePath() + "/progress.bin", f)) {
uint8_t data[4]; uint8_t data[4];
data[0] = currentPage & 0xFF; data[0] = currentPage & 0xFF;
@@ -388,7 +388,7 @@ void XtcReaderActivity::saveProgress() const {
} }
void XtcReaderActivity::loadProgress() { void XtcReaderActivity::loadProgress() {
FsFile f; HalFile f;
if (Storage.openFileForRead("XTR", xtc->getCachePath() + "/progress.bin", f)) { if (Storage.openFileForRead("XTR", xtc->getCachePath() + "/progress.bin", f)) {
uint8_t data[4]; uint8_t data[4];
if (f.read(data, 4) == 4) { if (f.read(data, 4) == 4) {
@@ -82,7 +82,7 @@ bool FontDownloadActivity::fetchAndParseManifest() {
} }
// HTTP client is now closed — TLS buffers freed. Parse JSON from file. // HTTP client is now closed — TLS buffers freed. Parse JSON from file.
FsFile manifestFile; HalFile manifestFile;
if (!Storage.openFileForRead("FONT", MANIFEST_TMP, manifestFile)) { if (!Storage.openFileForRead("FONT", MANIFEST_TMP, manifestFile)) {
LOG_ERR("FONT", "Failed to open temp manifest"); LOG_ERR("FONT", "Failed to open temp manifest");
Storage.remove(MANIFEST_TMP); Storage.remove(MANIFEST_TMP);
@@ -149,7 +149,7 @@ bool FontDownloadActivity::fetchAndParseManifest() {
for (const auto& file : family.files) { for (const auto& file : family.files) {
char path[128]; char path[128];
FontInstaller::buildFontPath(family.name.c_str(), file.name.c_str(), path, sizeof(path)); FontInstaller::buildFontPath(family.name.c_str(), file.name.c_str(), path, sizeof(path));
FsFile f; HalFile f;
if (Storage.openFileForRead("FONT", path, f)) { if (Storage.openFileForRead("FONT", path, f)) {
size_t actual = f.fileSize(); size_t actual = f.fileSize();
f.close(); f.close();
@@ -248,7 +248,7 @@ size_t FontDownloadActivity::totalUpdateSize() const {
// Standard CRC32 matching zlib/Python zlib.crc32(). // Standard CRC32 matching zlib/Python zlib.crc32().
bool FontDownloadActivity::computeFileCrc32(const char* path, uint32_t& outCrc) { bool FontDownloadActivity::computeFileCrc32(const char* path, uint32_t& outCrc) {
FsFile f; HalFile f;
if (!Storage.openFileForRead("FONT", path, f)) { if (!Storage.openFileForRead("FONT", path, f)) {
return false; return false;
} }
+2 -2
View File
@@ -63,7 +63,7 @@ void BmpViewerActivity::onEnter() {
loadSiblingImages(); loadSiblingImages();
} }
FsFile file; HalFile file;
const auto pageWidth = renderer.getScreenWidth(); const auto pageWidth = renderer.getScreenWidth();
const auto pageHeight = renderer.getScreenHeight(); const auto pageHeight = renderer.getScreenHeight();
@@ -147,7 +147,7 @@ void BmpViewerActivity::doSetSleepCover() {
GUI.drawPopup(renderer, tr(STR_LOADING_POPUP)); GUI.drawPopup(renderer, tr(STR_LOADING_POPUP));
bool success = false; bool success = false;
FsFile inFile, outFile; HalFile inFile, outFile;
if (Storage.openFileForRead("BMP", filePath, inFile)) { if (Storage.openFileForRead("BMP", filePath, inFile)) {
if (Storage.openFileForWrite("BMP", "/sleep.bmp", outFile)) { if (Storage.openFileForWrite("BMP", "/sleep.bmp", outFile)) {
char buffer[2048]; char buffer[2048];
+2 -2
View File
@@ -426,7 +426,7 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
const std::string coverBmpPath = const std::string coverBmpPath =
UITheme::getCoverThumbPath(recentBooks[0].coverBmpPath, BaseMetrics::values.homeCoverHeight); UITheme::getCoverThumbPath(recentBooks[0].coverBmpPath, BaseMetrics::values.homeCoverHeight);
FsFile file; HalFile file;
if (Storage.openFileForRead("HOME", coverBmpPath, file)) { if (Storage.openFileForRead("HOME", coverBmpPath, file)) {
Bitmap bitmap(file); Bitmap bitmap(file);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
@@ -476,7 +476,7 @@ void BaseTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
UITheme::getCoverThumbPath(recentBooks[0].coverBmpPath, BaseMetrics::values.homeCoverHeight); UITheme::getCoverThumbPath(recentBooks[0].coverBmpPath, BaseMetrics::values.homeCoverHeight);
// First time: load cover from SD and render // First time: load cover from SD and render
FsFile file; HalFile file;
if (Storage.openFileForRead("HOME", coverBmpPath, file)) { if (Storage.openFileForRead("HOME", coverBmpPath, file)) {
Bitmap bitmap(file); Bitmap bitmap(file);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
@@ -42,7 +42,7 @@ void Lyra3CoversTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, con
UITheme::getCoverThumbPath(coverPath, Lyra3CoversMetrics::values.homeCoverHeight); UITheme::getCoverThumbPath(coverPath, Lyra3CoversMetrics::values.homeCoverHeight);
// First time: load cover from SD and render // First time: load cover from SD and render
FsFile file; HalFile file;
if (Storage.openFileForRead("HOME", coverBmpPath, file)) { if (Storage.openFileForRead("HOME", coverBmpPath, file)) {
Bitmap bitmap(file); Bitmap bitmap(file);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
+1 -1
View File
@@ -423,7 +423,7 @@ void LyraTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, const std:
const std::string coverBmpPath = UITheme::getCoverThumbPath(coverPath, LyraMetrics::values.homeCoverHeight); const std::string coverBmpPath = UITheme::getCoverThumbPath(coverPath, LyraMetrics::values.homeCoverHeight);
// First time: load cover from SD and render // First time: load cover from SD and render
FsFile file; HalFile file;
if (Storage.openFileForRead("HOME", coverBmpPath, file)) { if (Storage.openFileForRead("HOME", coverBmpPath, file)) {
Bitmap bitmap(file); Bitmap bitmap(file);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
@@ -140,7 +140,7 @@ void RoundedRaffTheme::drawRecentBookCover(GfxRenderer& renderer, Rect rect, con
UITheme::getCoverThumbPath(coverPath, RoundedRaffMetrics::values.homeCoverHeight); UITheme::getCoverThumbPath(coverPath, RoundedRaffMetrics::values.homeCoverHeight);
// First time: load cover from SD and render // First time: load cover from SD and render
FsFile file; HalFile file;
if (Storage.openFileForRead("HOME", coverBmpPath, file)) { if (Storage.openFileForRead("HOME", coverBmpPath, file)) {
Bitmap bitmap(file); Bitmap bitmap(file);
if (bitmap.parseHeaders() == BmpReaderError::Ok) { if (bitmap.parseHeaders() == BmpReaderError::Ok) {
+2 -2
View File
@@ -237,14 +237,14 @@ void waitForPowerRelease() {
constexpr char SLEEP_FRAME_FILE[] = "/.crosspoint/sleep_frame.bin"; constexpr char SLEEP_FRAME_FILE[] = "/.crosspoint/sleep_frame.bin";
static void saveSleepFrameBuffer() { static void saveSleepFrameBuffer() {
FsFile file; HalFile file;
if (!Storage.openFileForWrite("SLP", SLEEP_FRAME_FILE, file)) return; if (!Storage.openFileForWrite("SLP", SLEEP_FRAME_FILE, file)) return;
file.write(renderer.getFrameBuffer(), renderer.getBufferSize()); file.write(renderer.getFrameBuffer(), renderer.getBufferSize());
file.close(); file.close();
} }
static bool loadSleepFrameBuffer() { static bool loadSleepFrameBuffer() {
FsFile file; HalFile file;
if (!Storage.openFileForRead("SLP", SLEEP_FRAME_FILE, file)) return false; if (!Storage.openFileForRead("SLP", SLEEP_FRAME_FILE, file)) return false;
const size_t bufferSize = display.getBufferSize(); const size_t bufferSize = display.getBufferSize();
const size_t bytesRead = file.read(display.getFrameBuffer(), bufferSize); const size_t bytesRead = file.read(display.getFrameBuffer(), bufferSize);
+16 -12
View File
@@ -35,7 +35,7 @@ constexpr uint16_t LOCAL_UDP_PORT = 8134;
CrossPointWebServer* wsInstance = nullptr; CrossPointWebServer* wsInstance = nullptr;
// WebSocket upload state // WebSocket upload state
FsFile wsUploadFile; HalFile wsUploadFile;
String wsUploadFileName; String wsUploadFileName;
String wsUploadPath; String wsUploadPath;
size_t wsUploadSize = 0; size_t wsUploadSize = 0;
@@ -374,7 +374,7 @@ void CrossPointWebServer::handleStatus() const {
} }
void CrossPointWebServer::scanFiles(const char* path, const std::function<void(FileInfo)>& callback) const { void CrossPointWebServer::scanFiles(const char* path, const std::function<void(FileInfo)>& callback) const {
FsFile root = Storage.open(path); HalFile root = Storage.open(path);
if (!root) { if (!root) {
LOG_DBG("WEB", "Failed to open directory: %s", path); LOG_DBG("WEB", "Failed to open directory: %s", path);
return; return;
@@ -388,7 +388,7 @@ void CrossPointWebServer::scanFiles(const char* path, const std::function<void(F
LOG_DBG("WEB", "Scanning files in: %s", path); LOG_DBG("WEB", "Scanning files in: %s", path);
FsFile file = root.openNextFile(); HalFile file = root.openNextFile();
char name[500]; char name[500];
while (file) { while (file) {
file.getName(name, sizeof(name)); file.getName(name, sizeof(name));
@@ -519,7 +519,7 @@ void CrossPointWebServer::handleDownload() const {
return; return;
} }
FsFile file = Storage.open(itemPath.c_str()); HalFile file = Storage.open(itemPath.c_str());
if (!file) { if (!file) {
server->send(500, "text/plain", "Failed to open file"); server->send(500, "text/plain", "Failed to open file");
return; return;
@@ -842,7 +842,7 @@ void CrossPointWebServer::handleRename() const {
return; return;
} }
FsFile file = Storage.open(itemPath.c_str()); HalFile file = Storage.open(itemPath.c_str());
if (!file) { if (!file) {
server->send(500, "text/plain", "Failed to open file"); server->send(500, "text/plain", "Failed to open file");
return; return;
@@ -918,7 +918,7 @@ void CrossPointWebServer::handleMove() const {
return; return;
} }
FsFile file = Storage.open(itemPath.c_str()); HalFile file = Storage.open(itemPath.c_str());
if (!file) { if (!file) {
server->send(500, "text/plain", "Failed to open file"); server->send(500, "text/plain", "Failed to open file");
return; return;
@@ -934,7 +934,7 @@ void CrossPointWebServer::handleMove() const {
server->send(404, "text/plain", "Destination not found"); server->send(404, "text/plain", "Destination not found");
return; return;
} }
FsFile destDir = Storage.open(destPath.c_str()); HalFile destDir = Storage.open(destPath.c_str());
if (!destDir || !destDir.isDirectory()) { if (!destDir || !destDir.isDirectory()) {
if (destDir) { if (destDir) {
destDir.close(); destDir.close();
@@ -1064,10 +1064,10 @@ void CrossPointWebServer::handleDelete() const {
// Decide whether it's a directory or file by opening it // Decide whether it's a directory or file by opening it
bool success = false; bool success = false;
FsFile f = Storage.open(itemPath.c_str()); HalFile f = Storage.open(itemPath.c_str());
if (f && f.isDirectory()) { if (f && f.isDirectory()) {
// For folders, ensure empty before removing // For folders, ensure empty before removing
FsFile entry = f.openNextFile(); HalFile entry = f.openNextFile();
if (entry) { if (entry) {
entry.close(); entry.close();
f.close(); f.close();
@@ -1741,7 +1741,7 @@ void CrossPointWebServer::handleFontList() const {
fileObj["name"] = name ? name + 1 : file.path.c_str(); fileObj["name"] = name ? name + 1 : file.path.c_str();
// Stat the file for size // Stat the file for size
FsFile f; HalFile f;
if (Storage.openFileForRead("WEB", file.path.c_str(), f)) { if (Storage.openFileForRead("WEB", file.path.c_str(), f)) {
fileObj["size"] = static_cast<unsigned long>(f.size()); fileObj["size"] = static_cast<unsigned long>(f.size());
f.close(); f.close();
@@ -1848,7 +1848,9 @@ void CrossPointWebServer::handleFontUploadData() {
fontUpload.bytesWritten += fontUpload.bufferPos; fontUpload.bytesWritten += fontUpload.bufferPos;
fontUpload.bufferPos = 0; fontUpload.bufferPos = 0;
} }
fontUpload.file.close(); if (fontUpload.file) {
fontUpload.file.close();
}
if (!fontUpload.valid && !fontUpload.filePath.empty()) { if (!fontUpload.valid && !fontUpload.filePath.empty()) {
Storage.remove(fontUpload.filePath.c_str()); Storage.remove(fontUpload.filePath.c_str());
@@ -1859,7 +1861,9 @@ void CrossPointWebServer::handleFontUploadData() {
} }
case UPLOAD_FILE_ABORTED: { case UPLOAD_FILE_ABORTED: {
fontUpload.file.close(); if (fontUpload.file) {
fontUpload.file.close();
}
if (!fontUpload.filePath.empty()) { if (!fontUpload.filePath.empty()) {
Storage.remove(fontUpload.filePath.c_str()); Storage.remove(fontUpload.filePath.c_str());
} }
+2 -2
View File
@@ -31,7 +31,7 @@ class CrossPointWebServer {
// Used by POST upload handler // Used by POST upload handler
struct UploadState { struct UploadState {
FsFile file; HalFile file;
String fileName; String fileName;
String path = "/"; String path = "/";
size_t size = 0; size_t size = 0;
@@ -117,7 +117,7 @@ class CrossPointWebServer {
// Font upload state // Font upload state
struct FontUploadState { struct FontUploadState {
FsFile file; HalFile file;
std::string familyName; std::string familyName;
std::string filePath; std::string filePath;
bool valid = false; bool valid = false;
+1 -1
View File
@@ -179,7 +179,7 @@ HttpDownloader::DownloadError HttpDownloader::downloadToFile(const std::string&
if (Storage.exists(destPath.c_str())) { if (Storage.exists(destPath.c_str())) {
Storage.remove(destPath.c_str()); Storage.remove(destPath.c_str());
} }
FsFile file; HalFile file;
if (!Storage.openFileForWrite("HTTP", destPath.c_str(), file)) { if (!Storage.openFileForWrite("HTTP", destPath.c_str(), file)) {
LOG_ERR("HTTP", "Failed to open file for writing"); LOG_ERR("HTTP", "Failed to open file for writing");
return FILE_ERROR; return FILE_ERROR;
+11 -11
View File
@@ -67,7 +67,7 @@ void WebDAVHandler::raw(WebServer& server, const String& uri, HTTPRaw& raw) {
_putExisted = Storage.exists(_putPath.c_str()); _putExisted = Storage.exists(_putPath.c_str());
if (_putExisted) { if (_putExisted) {
FsFile existing = Storage.open(_putPath.c_str()); HalFile existing = Storage.open(_putPath.c_str());
if (existing && existing.isDirectory()) { if (existing && existing.isDirectory()) {
existing.close(); existing.close();
_putOk = false; _putOk = false;
@@ -96,7 +96,7 @@ void WebDAVHandler::raw(WebServer& server, const String& uri, HTTPRaw& raw) {
if (_putOk) { if (_putOk) {
String tempPath = _putPath + ".davtmp"; String tempPath = _putPath + ".davtmp";
if (_putExisted) Storage.remove(_putPath.c_str()); if (_putExisted) Storage.remove(_putPath.c_str());
FsFile tmp = Storage.open(tempPath.c_str()); HalFile tmp = Storage.open(tempPath.c_str());
if (tmp) { if (tmp) {
_putOk = tmp.rename(_putPath.c_str()); _putOk = tmp.rename(_putPath.c_str());
tmp.close(); tmp.close();
@@ -182,7 +182,7 @@ void WebDAVHandler::handlePropfind(WebServer& s) {
return; return;
} }
FsFile root = Storage.open(path.c_str()); HalFile root = Storage.open(path.c_str());
if (!root) { if (!root) {
if (path == "/") { if (path == "/") {
// Root should always work — send minimal response // Root should always work — send minimal response
@@ -221,7 +221,7 @@ void WebDAVHandler::handlePropfind(WebServer& s) {
// If depth > 0 and it's a directory, list children // If depth > 0 and it's a directory, list children
if (depth > 0) { if (depth > 0) {
FsFile file = root.openNextFile(); HalFile file = root.openNextFile();
char name[500]; char name[500];
while (file) { while (file) {
file.getName(name, sizeof(name)); file.getName(name, sizeof(name));
@@ -311,7 +311,7 @@ void WebDAVHandler::handleGet(WebServer& s) {
return; return;
} }
FsFile file = Storage.open(path.c_str()); HalFile file = Storage.open(path.c_str());
if (!file) { if (!file) {
s.send(500, "text/plain", "Failed to open file"); s.send(500, "text/plain", "Failed to open file");
return; return;
@@ -348,7 +348,7 @@ void WebDAVHandler::handleHead(WebServer& s) {
return; return;
} }
FsFile file = Storage.open(path.c_str()); HalFile file = Storage.open(path.c_str());
if (!file) { if (!file) {
s.send(500, "text/plain", ""); s.send(500, "text/plain", "");
return; return;
@@ -411,7 +411,7 @@ void WebDAVHandler::handleDelete(WebServer& s) {
return; return;
} }
FsFile file = Storage.open(path.c_str()); HalFile file = Storage.open(path.c_str());
if (!file) { if (!file) {
s.send(500, "text/plain", "Failed to open"); s.send(500, "text/plain", "Failed to open");
return; return;
@@ -419,7 +419,7 @@ void WebDAVHandler::handleDelete(WebServer& s) {
if (file.isDirectory()) { if (file.isDirectory()) {
// Check if directory is empty // Check if directory is empty
FsFile entry = file.openNextFile(); HalFile entry = file.openNextFile();
if (entry) { if (entry) {
entry.close(); entry.close();
file.close(); file.close();
@@ -537,7 +537,7 @@ void WebDAVHandler::handleMove(WebServer& s) {
Storage.remove(dstPath.c_str()); Storage.remove(dstPath.c_str());
} }
FsFile file = Storage.open(srcPath.c_str()); HalFile file = Storage.open(srcPath.c_str());
if (!file) { if (!file) {
s.send(500, "text/plain", "Failed to open source"); s.send(500, "text/plain", "Failed to open source");
return; return;
@@ -583,7 +583,7 @@ void WebDAVHandler::handleCopy(WebServer& s) {
return; return;
} }
FsFile srcFile = Storage.open(srcPath.c_str()); HalFile srcFile = Storage.open(srcPath.c_str());
if (!srcFile) { if (!srcFile) {
s.send(500, "text/plain", "Failed to open source"); s.send(500, "text/plain", "Failed to open source");
return; return;
@@ -617,7 +617,7 @@ void WebDAVHandler::handleCopy(WebServer& s) {
Storage.remove(dstPath.c_str()); Storage.remove(dstPath.c_str());
} }
FsFile dstFile; HalFile dstFile;
if (!Storage.openFileForWrite("DAV", dstPath, dstFile)) { if (!Storage.openFileForWrite("DAV", dstPath, dstFile)) {
srcFile.close(); srcFile.close();
s.send(500, "text/plain", "Failed to create destination"); s.send(500, "text/plain", "Failed to create destination");
+1 -1
View File
@@ -13,7 +13,7 @@ class WebDAVHandler : public RequestHandler {
private: private:
// PUT streaming state (raw() is called in chunks) // PUT streaming state (raw() is called in chunks)
FsFile _putFile; HalFile _putFile;
String _putPath; String _putPath;
bool _putOk = false; bool _putOk = false;
bool _putExisted = false; bool _putExisted = false;
+1 -1
View File
@@ -121,7 +121,7 @@ bool ScreenshotUtil::saveFramebufferAsBmp(const char* filename, const uint8_t* f
} }
} }
FsFile file; HalFile file;
if (!Storage.openFileForWrite("SCR", filename, file)) { if (!Storage.openFileForWrite("SCR", filename, file)) {
LOG_ERR("SCR", "Failed to save screenshot"); LOG_ERR("SCR", "Failed to save screenshot");
return false; return false;