mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-06 23:57:39 +03:00
Compare commits
2 Commits
35a3bd7995
...
250b32f20e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
250b32f20e | ||
|
|
5ae10a7eb6 |
@ -49,4 +49,12 @@ static void readString(FsFile& file, std::string& s) {
|
|||||||
s.resize(len);
|
s.resize(len);
|
||||||
file.read(&s[0], len);
|
file.read(&s[0], len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void readString(FsFile& file, char* buffer, size_t maxLen) {
|
||||||
|
uint32_t len;
|
||||||
|
readPod(file, len);
|
||||||
|
const uint32_t bytesToRead = (len < maxLen - 1) ? len : (maxLen - 1);
|
||||||
|
file.read(reinterpret_cast<uint8_t*>(buffer), bytesToRead);
|
||||||
|
buffer[bytesToRead] = '\0';
|
||||||
|
}
|
||||||
} // namespace serialization
|
} // namespace serialization
|
||||||
|
|||||||
@ -29,20 +29,16 @@ void SettingDescriptor::setValue(CrossPointSettings& settings, uint8_t value) co
|
|||||||
|
|
||||||
void SettingDescriptor::resetToDefault(CrossPointSettings& settings) const {
|
void SettingDescriptor::resetToDefault(CrossPointSettings& settings) const {
|
||||||
if (type == SettingType::STRING) {
|
if (type == SettingType::STRING) {
|
||||||
char* str = getStringPtr(settings);
|
strncpy(stringPtr, stringData.defaultString, stringData.maxSize - 1);
|
||||||
if (str && stringData.defaultString) {
|
stringPtr[stringData.maxSize - 1] = '\0';
|
||||||
strncpy(str, stringData.defaultString, stringData.maxSize - 1);
|
|
||||||
str[stringData.maxSize - 1] = '\0';
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
settings.*(memberPtr) = defaultValue;
|
setValue(settings, defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SettingDescriptor::save(FsFile& file, const CrossPointSettings& settings) const {
|
void SettingDescriptor::save(FsFile& file, const CrossPointSettings& settings) const {
|
||||||
if (type == SettingType::STRING) {
|
if (type == SettingType::STRING) {
|
||||||
const char* str = getStringPtr(settings);
|
serialization::writeString(file, std::string(stringPtr));
|
||||||
serialization::writeString(file, std::string(str ? str : ""));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
serialization::writePod(file, settings.*(memberPtr));
|
serialization::writePod(file, settings.*(memberPtr));
|
||||||
@ -50,13 +46,7 @@ void SettingDescriptor::save(FsFile& file, const CrossPointSettings& settings) c
|
|||||||
|
|
||||||
void SettingDescriptor::load(FsFile& file, CrossPointSettings& settings) const {
|
void SettingDescriptor::load(FsFile& file, CrossPointSettings& settings) const {
|
||||||
if (type == SettingType::STRING) {
|
if (type == SettingType::STRING) {
|
||||||
char* str = getStringPtr(settings);
|
serialization::readString(file, stringPtr, stringData.maxSize);
|
||||||
if (str) {
|
|
||||||
std::string tempStr;
|
|
||||||
serialization::readString(file, tempStr);
|
|
||||||
strncpy(str, tempStr.c_str(), stringData.maxSize - 1);
|
|
||||||
str[stringData.maxSize - 1] = '\0';
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
@ -96,8 +86,8 @@ constexpr SettingDescriptor makeEnumDescriptor(const char* name, uint8_t CrossPo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Helper macro to create STRING descriptors without repetition
|
// Helper macro to create STRING descriptors without repetition
|
||||||
#define makeStringDescriptor(name, member, defStr) \
|
#define makeStringDescriptor(name, member, defStr) \
|
||||||
SettingDescriptor(name, SettingType::STRING, offsetof(CrossPointSettings, member), defStr, \
|
SettingDescriptor(name, SettingType::STRING, CrossPointSettings::instance.member, defStr, \
|
||||||
sizeof(CrossPointSettings::member))
|
sizeof(CrossPointSettings::member))
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -157,10 +147,9 @@ bool CrossPointSettings::saveToFile() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
serialization::writePod(outputFile, SETTINGS_FILE_VERSION);
|
serialization::writePod(outputFile, SETTINGS_FILE_VERSION);
|
||||||
serialization::writePod(outputFile, CrossPointSettings::DESCRIPTOR_COUNT);
|
serialization::writePod(outputFile, static_cast<uint8_t>(CrossPointSettings::DESCRIPTOR_COUNT));
|
||||||
|
|
||||||
// Use descriptors to automatically serialize all uint8_t settings
|
// Use descriptors to automatically serialize all uint8_t settings
|
||||||
// opdsServerUrl string is written at position 15 (between descriptors 14 and 15)
|
|
||||||
uint8_t descriptorIndex = 0;
|
uint8_t descriptorIndex = 0;
|
||||||
for (const auto& desc : descriptors) {
|
for (const auto& desc : descriptors) {
|
||||||
desc.save(outputFile, *this);
|
desc.save(outputFile, *this);
|
||||||
@ -193,7 +182,6 @@ bool CrossPointSettings::loadFromFile() {
|
|||||||
serialization::readPod(inputFile, fileSettingsCount);
|
serialization::readPod(inputFile, fileSettingsCount);
|
||||||
|
|
||||||
// Use descriptors to automatically deserialize all uint8_t settings
|
// Use descriptors to automatically deserialize all uint8_t settings
|
||||||
// opdsServerUrl string is at position 15 (between descriptors 14 and 15)
|
|
||||||
uint8_t descriptorIndex = 0;
|
uint8_t descriptorIndex = 0;
|
||||||
uint8_t filePosition = 0;
|
uint8_t filePosition = 0;
|
||||||
|
|
||||||
@ -203,20 +191,15 @@ bool CrossPointSettings::loadFromFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
desc.load(inputFile, *this);
|
desc.load(inputFile, *this);
|
||||||
descriptorIndex++;
|
|
||||||
filePosition++;
|
|
||||||
}
|
|
||||||
|
|
||||||
inputFile.close();
|
|
||||||
|
|
||||||
// Validate each setting and reset invalid values to defaults
|
|
||||||
for (const auto& desc : descriptors) {
|
|
||||||
if (!desc.validate(*this)) {
|
if (!desc.validate(*this)) {
|
||||||
Serial.printf("[%lu] [CPS] Invalid value (0x%X) for %s, resetting to default\n", millis(), desc.getValue(*this),
|
Serial.printf("[%lu] [CPS] Invalid value (0x%X) for %s, resetting to default\n", millis(), desc.getValue(*this),
|
||||||
desc.name);
|
desc.name);
|
||||||
desc.resetToDefault(*this);
|
desc.resetToDefault(*this);
|
||||||
}
|
}
|
||||||
|
descriptorIndex++;
|
||||||
|
filePosition++;
|
||||||
}
|
}
|
||||||
|
inputFile.close();
|
||||||
|
|
||||||
Serial.printf("[%lu] [CPS] Settings loaded from file\n", millis());
|
Serial.printf("[%lu] [CPS] Settings loaded from file\n", millis());
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -30,7 +30,10 @@ struct ValueRange {
|
|||||||
|
|
||||||
// Concrete descriptor for uint8_t settings (constexpr-compatible)
|
// Concrete descriptor for uint8_t settings (constexpr-compatible)
|
||||||
struct SettingDescriptor : public SettingDescriptorBase {
|
struct SettingDescriptor : public SettingDescriptorBase {
|
||||||
uint8_t CrossPointSettings::* memberPtr; // Member pointer (unused for STRING type)
|
union {
|
||||||
|
uint8_t CrossPointSettings::* memberPtr; // For TOGGLE/ENUM/VALUE types
|
||||||
|
char* stringPtr; // For STRING type
|
||||||
|
};
|
||||||
uint8_t defaultValue;
|
uint8_t defaultValue;
|
||||||
SettingValidator validator; // Optional validator function
|
SettingValidator validator; // Optional validator function
|
||||||
|
|
||||||
@ -46,7 +49,6 @@ struct SettingDescriptor : public SettingDescriptorBase {
|
|||||||
|
|
||||||
// For STRING types
|
// For STRING types
|
||||||
struct {
|
struct {
|
||||||
size_t offset; // Offset of the string member in CrossPointSettings
|
|
||||||
const char* defaultString; // Default string value
|
const char* defaultString; // Default string value
|
||||||
size_t maxSize; // Max size of the string buffer
|
size_t maxSize; // Max size of the string buffer
|
||||||
} stringData;
|
} stringData;
|
||||||
@ -72,12 +74,12 @@ struct SettingDescriptor : public SettingDescriptorBase {
|
|||||||
valueRange(valRange) {}
|
valueRange(valRange) {}
|
||||||
|
|
||||||
// STRING constructor
|
// STRING constructor
|
||||||
constexpr SettingDescriptor(const char* name_, SettingType type_, size_t offset, const char* defStr, size_t maxSz)
|
constexpr SettingDescriptor(const char* name_, SettingType type_, char* strPtr, const char* defStr, size_t maxSz)
|
||||||
: SettingDescriptorBase{name_, type_},
|
: SettingDescriptorBase{name_, type_},
|
||||||
memberPtr(nullptr), // Not used for strings
|
stringPtr(strPtr),
|
||||||
defaultValue(0),
|
defaultValue(0),
|
||||||
validator(nullptr),
|
validator(nullptr),
|
||||||
stringData{offset, defStr, maxSz} {}
|
stringData{defStr, maxSz} {}
|
||||||
|
|
||||||
bool validate(const CrossPointSettings& settings) const;
|
bool validate(const CrossPointSettings& settings) const;
|
||||||
uint8_t getValue(const CrossPointSettings& settings) const;
|
uint8_t getValue(const CrossPointSettings& settings) const;
|
||||||
@ -93,17 +95,6 @@ struct SettingDescriptor : public SettingDescriptorBase {
|
|||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helpers for STRING type - get pointer to string member using offset
|
|
||||||
char* getStringPtr(CrossPointSettings& settings) const {
|
|
||||||
if (type != SettingType::STRING) return nullptr;
|
|
||||||
return reinterpret_cast<char*>(reinterpret_cast<uint8_t*>(&settings) + stringData.offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* getStringPtr(const CrossPointSettings& settings) const {
|
|
||||||
if (type != SettingType::STRING) return nullptr;
|
|
||||||
return reinterpret_cast<const char*>(reinterpret_cast<const uint8_t*>(&settings) + stringData.offset);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Validator functions (constexpr for compile-time optimization)
|
// Validator functions (constexpr for compile-time optimization)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user