From b596f21e61bf3b872d3181f58e122d2a2e9f9825 Mon Sep 17 00:00:00 2001 From: hooligan333 <59103913+hooligan333@users.noreply.github.com> Date: Sat, 11 Jul 2026 19:57:48 -0700 Subject: [PATCH] perf: stream NCX/NAV TOC into parser, drop temp-file round-trip (#2440) Co-authored-by: Erica Jensen --- lib/Epub/Epub.cpp | 73 +++++++++-------------------------------------- 1 file changed, 14 insertions(+), 59 deletions(-) diff --git a/lib/Epub/Epub.cpp b/lib/Epub/Epub.cpp index 5f5dcc8a..0f38f566 100644 --- a/lib/Epub/Epub.cpp +++ b/lib/Epub/Epub.cpp @@ -153,18 +153,11 @@ bool Epub::parseTocNcxFile() const { LOG_DBG("EBP", "Parsing toc ncx file: %s", tocNcxItem.c_str()); - const auto tmpNcxPath = getCachePath() + "/toc.ncx"; - HalFile tempNcxFile; - if (!Storage.openFileForWrite("EBP", tmpNcxPath, tempNcxFile)) { + size_t ncxSize; + if (!getItemSize(tocNcxItem, &ncxSize)) { + LOG_ERR("EBP", "Could not get size of toc ncx file"); return false; } - readItemContentsToStream(tocNcxItem, tempNcxFile, 1024); - // Explicitly close() file before reopening for reading - tempNcxFile.close(); - if (!Storage.openFileForRead("EBP", tmpNcxPath, tempNcxFile)) { - return false; - } - const auto ncxSize = tempNcxFile.size(); TocNcxParser ncxParser(contentBasePath, ncxSize, bookMetadataCache.get()); @@ -173,29 +166,13 @@ bool Epub::parseTocNcxFile() const { return false; } - const auto ncxBuffer = static_cast(malloc(1024)); - if (!ncxBuffer) { - LOG_ERR("EBP", "Could not allocate memory for toc ncx parser"); + // Stream the decompressed NCX straight into the parser instead of round-tripping + // through a temp file on the SD card (decompress -> write -> reopen -> reread -> delete). + if (!readItemContentsToStream(tocNcxItem, ncxParser, 1024)) { + LOG_ERR("EBP", "Could not read toc ncx file"); return false; } - while (tempNcxFile.available()) { - const auto readSize = tempNcxFile.read(ncxBuffer, 1024); - if (readSize == 0) break; - const auto processedSize = ncxParser.write(ncxBuffer, readSize); - - if (processedSize != readSize) { - LOG_ERR("EBP", "Could not process all toc ncx data"); - free(ncxBuffer); - return false; - } - } - - free(ncxBuffer); - // Explicitly close() file before calling Storage.remove() - tempNcxFile.close(); - Storage.remove(tmpNcxPath.c_str()); - LOG_DBG("EBP", "Parsed TOC items"); return true; } @@ -209,18 +186,11 @@ bool Epub::parseTocNavFile() const { LOG_DBG("EBP", "Parsing toc nav file: %s", tocNavItem.c_str()); - const auto tmpNavPath = getCachePath() + "/toc.nav"; - HalFile tempNavFile; - if (!Storage.openFileForWrite("EBP", tmpNavPath, tempNavFile)) { + size_t navSize; + if (!getItemSize(tocNavItem, &navSize)) { + LOG_ERR("EBP", "Could not get size of toc nav file"); return false; } - readItemContentsToStream(tocNavItem, tempNavFile, 1024); - // Explicitly close() file before reopening for reading - tempNavFile.close(); - if (!Storage.openFileForRead("EBP", tmpNavPath, tempNavFile)) { - return false; - } - const auto navSize = tempNavFile.size(); // Note: We can't use `contentBasePath` here as the nav file may be in a different folder to the content.opf // and the HTMLX nav file will have hrefs relative to itself @@ -232,28 +202,13 @@ bool Epub::parseTocNavFile() const { return false; } - const auto navBuffer = static_cast(malloc(1024)); - if (!navBuffer) { - LOG_ERR("EBP", "Could not allocate memory for toc nav parser"); + // Stream the decompressed nav document straight into the parser instead of round-tripping + // through a temp file on the SD card (decompress -> write -> reopen -> reread -> delete). + if (!readItemContentsToStream(tocNavItem, navParser, 1024)) { + LOG_ERR("EBP", "Could not read toc nav file"); return false; } - while (tempNavFile.available()) { - const auto readSize = tempNavFile.read(navBuffer, 1024); - const auto processedSize = navParser.write(navBuffer, readSize); - - if (processedSize != readSize) { - LOG_ERR("EBP", "Could not process all toc nav data"); - free(navBuffer); - return false; - } - } - - free(navBuffer); - // Explicitly close() file before calling Storage.remove() - tempNavFile.close(); - Storage.remove(tmpNavPath.c_str()); - LOG_DBG("EBP", "Parsed TOC nav items"); return true; }