perf: Avoid creating strings for file extension checks (#1303)

## Summary

**What is the goal of this PR?**

This change avoids the pattern of creating a `std::string` using
`.substr` in order to compare against a file extension literal.
```c++
std::string path;
if (path.length() >= 4 && path.substr(path.length() - 4) == ".ext")
```

The `checkFileExtension` utility has moved from StringUtils to
FsHelpers, to be available to code in lib/. The signature now accepts a
`std::string_view` instead of `std::string`, which makes the single
implementation reusable for Arduino `String`.

Added utility functions for commonly repeated extensions.

These changes **save about 2 KB of flash (5,999,427 to 5,997,343)**.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**NO**_
This commit is contained in:
Zach Nelson
2026-03-05 10:12:22 -06:00
committed by GitHub
parent ea88797c8e
commit c3f1dbfa09
19 changed files with 160 additions and 151 deletions

View File

@@ -103,14 +103,11 @@ bool Epub::parseContentOpf(BookMetadataCache::BookMetadata& bookMetadata) {
pos += strlen(pattern);
const auto endPos = coverPageHtml.find('"', pos);
if (endPos != std::string::npos) {
const auto ref = coverPageHtml.substr(pos, endPos - pos);
const auto ref = std::string_view{coverPageHtml}.substr(pos, endPos - pos);
// Check if it's an image file
if (ref.length() >= 4) {
const auto ext = ref.substr(ref.length() - 4);
if (ext == ".png" || ext == ".jpg" || ext == "jpeg" || ext == ".gif") {
imageRef = ref;
break;
}
if (FsHelpers::hasPngExtension(ref) || FsHelpers::hasJpgExtension(ref) || FsHelpers::hasGifExtension(ref)) {
imageRef = ref;
break;
}
}
pos = coverPageHtml.find(pattern, pos);
@@ -541,8 +538,7 @@ bool Epub::generateCoverBmp(bool cropped) const {
return false;
}
if (coverImageHref.substr(coverImageHref.length() - 4) == ".jpg" ||
coverImageHref.substr(coverImageHref.length() - 5) == ".jpeg") {
if (FsHelpers::hasJpgExtension(coverImageHref)) {
LOG_DBG("EBP", "Generating BMP from JPG cover image (%s mode)", cropped ? "cropped" : "fit");
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
@@ -575,7 +571,7 @@ bool Epub::generateCoverBmp(bool cropped) const {
return success;
}
if (coverImageHref.substr(coverImageHref.length() - 4) == ".png") {
if (FsHelpers::hasPngExtension(coverImageHref)) {
LOG_DBG("EBP", "Generating BMP from PNG cover image (%s mode)", cropped ? "cropped" : "fit");
const auto coverPngTempPath = getCachePath() + "/.cover.png";
@@ -629,8 +625,7 @@ bool Epub::generateThumbBmp(int height) const {
const auto coverImageHref = bookMetadataCache->coreMetadata.coverItemHref;
if (coverImageHref.empty()) {
LOG_DBG("EBP", "No known cover image for thumbnail");
} else if (coverImageHref.substr(coverImageHref.length() - 4) == ".jpg" ||
coverImageHref.substr(coverImageHref.length() - 5) == ".jpeg") {
} else if (FsHelpers::hasJpgExtension(coverImageHref)) {
LOG_DBG("EBP", "Generating thumb BMP from JPG cover image");
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
@@ -666,7 +661,7 @@ bool Epub::generateThumbBmp(int height) const {
}
LOG_DBG("EBP", "Generated thumb BMP from JPG cover image, success: %s", success ? "yes" : "no");
return success;
} else if (coverImageHref.substr(coverImageHref.length() - 4) == ".png") {
} else if (FsHelpers::hasPngExtension(coverImageHref)) {
LOG_DBG("EBP", "Generating thumb BMP from PNG cover image");
const auto coverPngTempPath = getCachePath() + "/.cover.png";

View File

@@ -1,5 +1,6 @@
#include "JpegToFramebufferConverter.h"
#include <FsHelpers.h>
#include <GfxRenderer.h>
#include <HalStorage.h>
#include <JPEGDEC.h>
@@ -486,9 +487,5 @@ bool JpegToFramebufferConverter::decodeToFramebuffer(const std::string& imagePat
}
bool JpegToFramebufferConverter::supportsFormat(const std::string& extension) {
std::string ext = extension;
for (auto& c : ext) {
c = tolower(c);
}
return (ext == ".jpg" || ext == ".jpeg");
return FsHelpers::hasJpgExtension(extension);
}

View File

@@ -1,5 +1,6 @@
#include "PngToFramebufferConverter.h"
#include <FsHelpers.h>
#include <GfxRenderer.h>
#include <HalStorage.h>
#include <Logging.h>
@@ -391,9 +392,5 @@ bool PngToFramebufferConverter::decodeToFramebuffer(const std::string& imagePath
}
bool PngToFramebufferConverter::supportsFormat(const std::string& extension) {
std::string ext = extension;
for (auto& c : ext) {
c = tolower(c);
}
return (ext == ".png");
return FsHelpers::hasPngExtension(extension);
}