From 50e6ef9bd865290e7b17f255f78d75df00945a7c Mon Sep 17 00:00:00 2001 From: jpirnay Date: Mon, 16 Feb 2026 12:11:26 +0100 Subject: [PATCH] fix: Auto calculate the settings size on serialization (#832) ## Summary * The constant SETTINGS_CONST was hardcoded and needed to be updated whenever an additional setting was added * This is no longer necessary as the settings size will be determined automatically on settings persistence ## Additional Context * New settings need to be added (as previously) in saveToFile - that's it --- ### 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? YES --------- Co-authored-by: Xuan Son Nguyen --- src/CrossPointSettings.cpp | 106 +++++++++++++++++++++++++------------ src/CrossPointSettings.h | 6 +++ 2 files changed, 78 insertions(+), 34 deletions(-) diff --git a/src/CrossPointSettings.cpp b/src/CrossPointSettings.cpp index 05cdeffe..1404709d 100644 --- a/src/CrossPointSettings.cpp +++ b/src/CrossPointSettings.cpp @@ -5,6 +5,7 @@ #include #include +#include #include "fontIds.h" @@ -21,8 +22,7 @@ void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) { namespace { constexpr uint8_t SETTINGS_FILE_VERSION = 1; -// Increment this when adding new persisted settings fields -constexpr uint8_t SETTINGS_COUNT = 30; +// SETTINGS_COUNT is now calculated automatically in saveToFile constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin"; // Validate front button mapping to ensure each hardware button is unique. @@ -77,6 +77,68 @@ void applyLegacyFrontButtonLayout(CrossPointSettings& settings) { } } // namespace +class SettingsWriter { + public: + bool is_counting = false; + uint8_t item_count = 0; + template + + void writeItem(FsFile& file, const T& value) { + if (is_counting) { + item_count++; + } else { + serialization::writePod(file, value); + } + } + + void writeItemString(FsFile& file, const char* value) { + if (is_counting) { + item_count++; + } else { + serialization::writeString(file, std::string(value)); + } + } +}; + +uint8_t CrossPointSettings::writeSettings(FsFile& file, bool count_only) const { + SettingsWriter writer; + writer.is_counting = count_only; + + writer.writeItem(file, sleepScreen); + writer.writeItem(file, extraParagraphSpacing); + writer.writeItem(file, shortPwrBtn); + writer.writeItem(file, statusBar); + writer.writeItem(file, orientation); + writer.writeItem(file, frontButtonLayout); // legacy + writer.writeItem(file, sideButtonLayout); + writer.writeItem(file, fontFamily); + writer.writeItem(file, fontSize); + writer.writeItem(file, lineSpacing); + writer.writeItem(file, paragraphAlignment); + writer.writeItem(file, sleepTimeout); + writer.writeItem(file, refreshFrequency); + writer.writeItem(file, screenMargin); + writer.writeItem(file, sleepScreenCoverMode); + writer.writeItemString(file, opdsServerUrl); + writer.writeItem(file, textAntiAliasing); + writer.writeItem(file, hideBatteryPercentage); + writer.writeItem(file, longPressChapterSkip); + writer.writeItem(file, hyphenationEnabled); + writer.writeItemString(file, opdsUsername); + writer.writeItemString(file, opdsPassword); + writer.writeItem(file, sleepScreenCoverFilter); + writer.writeItem(file, uiTheme); + writer.writeItem(file, frontButtonBack); + writer.writeItem(file, frontButtonConfirm); + writer.writeItem(file, frontButtonLeft); + writer.writeItem(file, frontButtonRight); + writer.writeItem(file, fadingFix); + writer.writeItem(file, embeddedStyle); + // New fields need to be added at end for backward compatibility + + return writer.item_count; +} + bool CrossPointSettings::saveToFile() const { // Make sure the directory exists Storage.mkdir("/.crosspoint"); @@ -86,39 +148,15 @@ bool CrossPointSettings::saveToFile() const { return false; } + // First pass: count the items + uint8_t item_count = writeSettings(outputFile, true); // This will just count, not write + + // Write header serialization::writePod(outputFile, SETTINGS_FILE_VERSION); - serialization::writePod(outputFile, SETTINGS_COUNT); - serialization::writePod(outputFile, sleepScreen); - serialization::writePod(outputFile, extraParagraphSpacing); - serialization::writePod(outputFile, shortPwrBtn); - serialization::writePod(outputFile, statusBar); - serialization::writePod(outputFile, orientation); - serialization::writePod(outputFile, frontButtonLayout); // legacy - serialization::writePod(outputFile, sideButtonLayout); - serialization::writePod(outputFile, fontFamily); - serialization::writePod(outputFile, fontSize); - serialization::writePod(outputFile, lineSpacing); - serialization::writePod(outputFile, paragraphAlignment); - serialization::writePod(outputFile, sleepTimeout); - serialization::writePod(outputFile, refreshFrequency); - serialization::writePod(outputFile, screenMargin); - serialization::writePod(outputFile, sleepScreenCoverMode); - serialization::writeString(outputFile, std::string(opdsServerUrl)); - serialization::writePod(outputFile, textAntiAliasing); - serialization::writePod(outputFile, hideBatteryPercentage); - serialization::writePod(outputFile, longPressChapterSkip); - serialization::writePod(outputFile, hyphenationEnabled); - serialization::writeString(outputFile, std::string(opdsUsername)); - serialization::writeString(outputFile, std::string(opdsPassword)); - serialization::writePod(outputFile, sleepScreenCoverFilter); - serialization::writePod(outputFile, uiTheme); - serialization::writePod(outputFile, frontButtonBack); - serialization::writePod(outputFile, frontButtonConfirm); - serialization::writePod(outputFile, frontButtonLeft); - serialization::writePod(outputFile, frontButtonRight); - serialization::writePod(outputFile, fadingFix); - serialization::writePod(outputFile, embeddedStyle); - // New fields added at end for backward compatibility + serialization::writePod(outputFile, static_cast(item_count)); + // Second pass: actually write the settings + writeSettings(outputFile); // This will write the actual data + outputFile.close(); LOG_DBG("CPS", "Settings saved to file"); diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index 1348519f..a2814eb8 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -2,6 +2,9 @@ #include #include +// Forward declarations +class FsFile; + class CrossPointSettings { private: // Private constructor for singleton @@ -182,6 +185,9 @@ class CrossPointSettings { } int getReaderFontId() const; + // 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; + bool saveToFile() const; bool loadFromFile();