diff --git a/lib/Epub/Epub/htmlEntities.cpp b/lib/Epub/Epub/htmlEntities.cpp
index 6fdcb71c..2fd35b8a 100644
--- a/lib/Epub/Epub/htmlEntities.cpp
+++ b/lib/Epub/Epub/htmlEntities.cpp
@@ -4,6 +4,7 @@
#include "htmlEntities.h"
#include
+#include
struct EntityPair {
const char* key;
@@ -62,8 +63,6 @@ static constexpr EntityPair ENTITY_LOOKUP[] = {
{"¥", "¥"}, {"ÿ", "ÿ"}, {"ζ", "ζ"}, {"", "\u200D"}, {"", "\u200C"},
};
-static const size_t ENTITY_LOOKUP_COUNT = sizeof(ENTITY_LOOKUP) / sizeof(ENTITY_LOOKUP[0]);
-
// Verify the table is sorted at compile time.
static constexpr int constexprStrcmp(const char* a, const char* b) {
for (size_t i = 0;; i++) {
@@ -73,7 +72,7 @@ static constexpr int constexprStrcmp(const char* a, const char* b) {
}
static constexpr bool isTableSorted() {
- for (size_t i = 1; i < ENTITY_LOOKUP_COUNT; i++) {
+ for (size_t i = 1; i < std::size(ENTITY_LOOKUP); i++) {
if (constexprStrcmp(ENTITY_LOOKUP[i - 1].key, ENTITY_LOOKUP[i].key) >= 0) return false;
}
return true;
@@ -85,7 +84,7 @@ const char* lookupHtmlEntity(const char* entity, size_t len) {
if (entity == nullptr || len == 0) return nullptr;
size_t lo = 0;
- size_t hi = ENTITY_LOOKUP_COUNT;
+ size_t hi = std::size(ENTITY_LOOKUP);
while (lo < hi) {
const size_t mid = lo + (hi - lo) / 2;
diff --git a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp
index 3c8694af..92f0280a 100644
--- a/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp
+++ b/lib/Epub/Epub/parsers/ChapterHtmlSlimParser.cpp
@@ -8,42 +8,30 @@
#include
#include
+#include
+
#include "../../Epub.h"
#include "../Page.h"
#include "../converters/ImageDecoderFactory.h"
#include "../converters/ImageToFramebufferDecoder.h"
#include "../htmlEntities.h"
-const char* HEADER_TAGS[] = {"h1", "h2", "h3", "h4", "h5", "h6"};
-constexpr int NUM_HEADER_TAGS = sizeof(HEADER_TAGS) / sizeof(HEADER_TAGS[0]);
-
// Minimum file size (in bytes) to show indexing popup - smaller chapters don't benefit from it
constexpr size_t MIN_SIZE_FOR_POPUP = 10 * 1024; // 10KB
constexpr size_t PARSE_BUFFER_SIZE = 1024;
-const char* BLOCK_TAGS[] = {"p", "li", "div", "br", "blockquote"};
-constexpr int NUM_BLOCK_TAGS = sizeof(BLOCK_TAGS) / sizeof(BLOCK_TAGS[0]);
-
-const char* BOLD_TAGS[] = {"b", "strong"};
-constexpr int NUM_BOLD_TAGS = sizeof(BOLD_TAGS) / sizeof(BOLD_TAGS[0]);
-
-const char* ITALIC_TAGS[] = {"i", "em"};
-constexpr int NUM_ITALIC_TAGS = sizeof(ITALIC_TAGS) / sizeof(ITALIC_TAGS[0]);
-
-const char* UNDERLINE_TAGS[] = {"u", "ins"};
-constexpr int NUM_UNDERLINE_TAGS = sizeof(UNDERLINE_TAGS) / sizeof(UNDERLINE_TAGS[0]);
-
-const char* IMAGE_TAGS[] = {"img"};
-constexpr int NUM_IMAGE_TAGS = sizeof(IMAGE_TAGS) / sizeof(IMAGE_TAGS[0]);
-
-const char* SKIP_TAGS[] = {"head"};
-constexpr int NUM_SKIP_TAGS = sizeof(SKIP_TAGS) / sizeof(SKIP_TAGS[0]);
+constexpr const char* HEADER_TAGS[] = {"h1", "h2", "h3", "h4", "h5", "h6"};
+constexpr const char* BLOCK_TAGS[] = {"p", "li", "div", "br", "blockquote"};
+constexpr const char* BOLD_TAGS[] = {"b", "strong"};
+constexpr const char* ITALIC_TAGS[] = {"i", "em"};
+constexpr const char* UNDERLINE_TAGS[] = {"u", "ins"};
+constexpr const char* IMAGE_TAGS[] = {"img"};
+constexpr const char* SKIP_TAGS[] = {"head"};
bool isWhitespace(const char c) { return c == ' ' || c == '\r' || c == '\n' || c == '\t'; }
-// given the start and end of a tag, check to see if it matches a known tag
-bool matches(const char* tag_name, const char* possible_tags[], const int possible_tag_count) {
- for (int i = 0; i < possible_tag_count; i++) {
+bool matches(const char* tag_name, const char* const* possible_tags, size_t count) {
+ for (size_t i = 0; i < count; i++) {
if (strcmp(tag_name, possible_tags[i]) == 0) {
return true;
}
@@ -70,7 +58,7 @@ bool isInternalEpubLink(const char* href) {
}
bool isHeaderOrBlock(const char* name) {
- return matches(name, HEADER_TAGS, NUM_HEADER_TAGS) || matches(name, BLOCK_TAGS, NUM_BLOCK_TAGS);
+ return matches(name, HEADER_TAGS, std::size(HEADER_TAGS)) || matches(name, BLOCK_TAGS, std::size(BLOCK_TAGS));
}
bool isTableStructuralTag(const char* name) {
@@ -271,7 +259,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
return;
}
- if (matches(name, IMAGE_TAGS, NUM_IMAGE_TAGS)) {
+ if (matches(name, IMAGE_TAGS, std::size(IMAGE_TAGS))) {
std::string src;
std::string alt;
if (atts != nullptr) {
@@ -541,7 +529,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
}
}
- if (matches(name, SKIP_TAGS, NUM_SKIP_TAGS)) {
+ if (matches(name, SKIP_TAGS, std::size(SKIP_TAGS))) {
// start skip
self->skipUntilDepth = self->depth;
self->depth += 1;
@@ -608,7 +596,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
const auto userAlignmentBlockStyle = BlockStyle::fromCssStyle(
cssStyle, emSize, static_cast(self->paragraphAlignment), self->viewportWidth);
- if (matches(name, HEADER_TAGS, NUM_HEADER_TAGS)) {
+ if (matches(name, HEADER_TAGS, std::size(HEADER_TAGS))) {
self->currentCssStyle = cssStyle;
auto headerBlockStyle = BlockStyle::fromCssStyle(cssStyle, emSize, CssTextAlign::Center, self->viewportWidth);
headerBlockStyle.textAlignDefined = true;
@@ -621,7 +609,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
self->startNewTextBlock(accumulated.withoutBottom());
self->boldUntilDepth = std::min(self->boldUntilDepth, self->depth);
self->updateEffectiveInlineStyle();
- } else if (matches(name, BLOCK_TAGS, NUM_BLOCK_TAGS)) {
+ } else if (matches(name, BLOCK_TAGS, std::size(BLOCK_TAGS))) {
if (strcmp(name, "br") == 0) {
if (self->partWordBufferIndex > 0) {
// flush word preceding
to currentTextBlock before calling startNewTextBlock
@@ -640,7 +628,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
self->currentTextBlock->addWord("\xe2\x80\xa2", EpdFontFamily::REGULAR);
}
}
- } else if (matches(name, UNDERLINE_TAGS, NUM_UNDERLINE_TAGS)) {
+ } else if (matches(name, UNDERLINE_TAGS, std::size(UNDERLINE_TAGS))) {
// Flush buffer before style change so preceding text gets current style
if (self->partWordBufferIndex > 0) {
self->flushPartWordBuffer();
@@ -662,7 +650,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
}
self->inlineStyleStack.push_back(entry);
self->updateEffectiveInlineStyle();
- } else if (matches(name, BOLD_TAGS, NUM_BOLD_TAGS)) {
+ } else if (matches(name, BOLD_TAGS, std::size(BOLD_TAGS))) {
// Flush buffer before style change so preceding text gets current style
if (self->partWordBufferIndex > 0) {
self->flushPartWordBuffer();
@@ -684,7 +672,7 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
}
self->inlineStyleStack.push_back(entry);
self->updateEffectiveInlineStyle();
- } else if (matches(name, ITALIC_TAGS, NUM_ITALIC_TAGS)) {
+ } else if (matches(name, ITALIC_TAGS, std::size(ITALIC_TAGS))) {
// Flush buffer before style change so preceding text gets current style
if (self->partWordBufferIndex > 0) {
self->flushPartWordBuffer();
@@ -946,12 +934,12 @@ void XMLCALL ChapterHtmlSlimParser::endElement(void* userData, const XML_Char* n
// Flush buffer with current style BEFORE any style changes
if (self->partWordBufferIndex > 0) {
// Flush if style will change OR if we're closing a block/structural element
- const bool isInlineTag =
- !headerOrBlockTag && !tableStructuralTag && !matches(name, IMAGE_TAGS, NUM_IMAGE_TAGS) && self->depth != 1;
- const bool shouldFlush = styleWillChange || headerOrBlockTag || matches(name, BOLD_TAGS, NUM_BOLD_TAGS) ||
- matches(name, ITALIC_TAGS, NUM_ITALIC_TAGS) ||
- matches(name, UNDERLINE_TAGS, NUM_UNDERLINE_TAGS) || tableStructuralTag ||
- matches(name, IMAGE_TAGS, NUM_IMAGE_TAGS) || self->depth == 1;
+ const bool isInlineTag = !headerOrBlockTag && !tableStructuralTag &&
+ !matches(name, IMAGE_TAGS, std::size(IMAGE_TAGS)) && self->depth != 1;
+ const bool shouldFlush = styleWillChange || headerOrBlockTag || matches(name, BOLD_TAGS, std::size(BOLD_TAGS)) ||
+ matches(name, ITALIC_TAGS, std::size(ITALIC_TAGS)) ||
+ matches(name, UNDERLINE_TAGS, std::size(UNDERLINE_TAGS)) || tableStructuralTag ||
+ matches(name, IMAGE_TAGS, std::size(IMAGE_TAGS)) || self->depth == 1;
if (shouldFlush) {
self->flushPartWordBuffer();
diff --git a/src/network/CrossPointWebServer.cpp b/src/network/CrossPointWebServer.cpp
index 0ad2f1ab..2346f221 100644
--- a/src/network/CrossPointWebServer.cpp
+++ b/src/network/CrossPointWebServer.cpp
@@ -22,8 +22,7 @@
namespace {
// Folders/files to hide from the web interface file browser
// Note: Items starting with "." are automatically hidden
-const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
-constexpr size_t HIDDEN_ITEMS_COUNT = sizeof(HIDDEN_ITEMS) / sizeof(HIDDEN_ITEMS[0]);
+constexpr const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
constexpr uint16_t UDP_PORTS[] = {54982, 48123, 39001, 44044, 59678};
constexpr uint16_t LOCAL_UDP_PORT = 8134;
@@ -75,8 +74,8 @@ bool isProtectedItemName(const String& name) {
if (name.startsWith(".")) {
return true;
}
- for (size_t i = 0; i < HIDDEN_ITEMS_COUNT; i++) {
- if (name.equals(HIDDEN_ITEMS[i])) {
+ for (const auto* item : HIDDEN_ITEMS) {
+ if (name.equals(item)) {
return true;
}
}
@@ -389,8 +388,8 @@ void CrossPointWebServer::scanFiles(const char* path, const std::functionsend(403, "text/plain", "Cannot access system files");
return;
}
- for (size_t i = 0; i < HIDDEN_ITEMS_COUNT; i++) {
- if (itemName.equals(HIDDEN_ITEMS[i])) {
+ for (const auto* item : HIDDEN_ITEMS) {
+ if (itemName.equals(item)) {
server->send(403, "text/plain", "Cannot access protected items");
return;
}
@@ -1033,8 +1032,8 @@ void CrossPointWebServer::handleDelete() const {
// Check against explicitly protected items
bool isProtected = false;
- for (size_t i = 0; i < HIDDEN_ITEMS_COUNT; i++) {
- if (itemName.equals(HIDDEN_ITEMS[i])) {
+ for (const auto* item : HIDDEN_ITEMS) {
+ if (itemName.equals(item)) {
isProtected = true;
break;
}
diff --git a/src/network/WebDAVHandler.cpp b/src/network/WebDAVHandler.cpp
index b6c8a5e1..f20e8261 100644
--- a/src/network/WebDAVHandler.cpp
+++ b/src/network/WebDAVHandler.cpp
@@ -7,8 +7,7 @@
#include
namespace {
-const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
-constexpr size_t HIDDEN_ITEMS_COUNT = sizeof(HIDDEN_ITEMS) / sizeof(HIDDEN_ITEMS[0]);
+constexpr const char* HIDDEN_ITEMS[] = {"System Volume Information", "XTCache"};
// RFC 1123 date format helper: "Sun, 06 Nov 1994 08:49:37 GMT"
// ESP32 doesn't have real-time clock set by default, so we use a fixed epoch date
@@ -230,8 +229,8 @@ void WebDAVHandler::handlePropfind(WebServer& s) {
// Skip hidden/protected items
bool shouldHide = fileName.startsWith(".");
if (!shouldHide) {
- for (size_t i = 0; i < HIDDEN_ITEMS_COUNT; i++) {
- if (fileName.equals(HIDDEN_ITEMS[i])) {
+ for (const auto* item : HIDDEN_ITEMS) {
+ if (fileName.equals(item)) {
shouldHide = true;
break;
}
@@ -774,8 +773,8 @@ bool WebDAVHandler::isProtectedPath(const String& path) const {
if (segment.startsWith(".")) return true;
- for (size_t i = 0; i < HIDDEN_ITEMS_COUNT; i++) {
- if (segment.equals(HIDDEN_ITEMS[i])) return true;
+ for (const auto* item : HIDDEN_ITEMS) {
+ if (segment.equals(item)) return true;
}
start = end + 1;