Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 27 additions & 15 deletions src/JsonSettings.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#include "JsonSettings.h"

#include <ArduinoJson.h>
#include <sstream>
#include <stdexcept>
#include <stdlib.h>

String JsonSettings::getString(const char *key) {
preferences.begin(name, true);
Expand Down Expand Up @@ -29,18 +30,29 @@ std::vector<int> JsonSettings::getIntVector(const char *key) {
String value = preferences.getString(key, this->find(key).strDefault);
preferences.end();

// Parsed by hand rather than with std::istringstream: pulling in <sstream>
// drags the whole C++ iostreams and locale machinery into the image, and
// with it the wide-character and floating point printf/scanf families -
// tens of KB of flash for a comma separated list of small integers.
std::vector<int> intVector;
std::istringstream stream(value.c_str());
std::string token;
while (std::getline(stream, token, ',')) {
try {
intVector.push_back(std::stoi(token));
} catch (const std::invalid_argument &) {
throw std::runtime_error("Invalid CSV: Non-integer value found");
} catch (const std::out_of_range &) {
throw std::runtime_error("Invalid CSV: Integer value out of range");
const char *cursor = value.c_str();

while (*cursor != '\0') {
char *end = nullptr;
long parsed = strtol(cursor, &end, 10);

if (end == cursor) {
break; // no digits here, stop rather than spin
}

intVector.push_back((int) parsed);
cursor = end;

while (*cursor == ',' || *cursor == ' ') {
cursor++;
}
}

return intVector;
}

Expand All @@ -63,14 +75,14 @@ void JsonSettings::putFloat(const char *key, float value) {
}

void JsonSettings::putIntVector(const char *key, std::vector<int> value) {
std::ostringstream stream;
String joined;
for (size_t i = 0; i < value.size(); ++i) {
stream << value[i];
if (i < value.size() - 1) {
stream << ",";
if (i > 0) {
joined += ',';
}
joined += value[i];
}
putString(key, stream.str().c_str());
putString(key, joined);
}

JsonDocument JsonSettings::toJson() {
Expand Down
9 changes: 7 additions & 2 deletions src/SplitFlapDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,19 @@ void SplitFlapDisplay::init() {
maxVel = settings.getFloat("maxVel");
charSetSize = settings.getInt("charset");

// moduleCount is what sizes these loops, but the address and offset lists
// are free-form strings: a short or malformed one used to read straight
// past the end of the vector. Fall back to sane per-module values instead.
numModules = constrain(numModules, 1, MAX_MODULES);

std::vector<int> settingAddresses = settings.getIntVector("moduleAddresses");
for (int i = 0; i < numModules; i++) {
moduleAddresses[i] = (uint8_t) settingAddresses[i];
moduleAddresses[i] = (uint8_t) (i < (int) settingAddresses.size() ? settingAddresses[i] : 0x20 + i);
}

std::vector<int> settingOffsets = settings.getIntVector("moduleOffsets");
for (int i = 0; i < numModules; i++) {
moduleOffsets[i] = settingOffsets[i];
moduleOffsets[i] = i < (int) settingOffsets.size() ? settingOffsets[i] : 0;
}

Serial.print("Module Offsets: ");
Expand Down