Skip to content

Commit

Permalink
Printf formatters (String and Int types) (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
nullstalgia authored Mar 29, 2020
1 parent 31daf19 commit df1f026
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 5 deletions.
39 changes: 39 additions & 0 deletions lib/Variables/PrintfFormatterNumeric.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <VariableFormatters.h>
#include <ArduinoJson.h>

static const char FORMAT_ARG_NAME[] = "format";

PrintfFormatterNumeric::PrintfFormatterNumeric(const String& formatSchema)
: formatSchema(formatSchema)
{ }

std::shared_ptr<const PrintfFormatterNumeric> PrintfFormatterNumeric::build(JsonObject args) {
String formatSchema;

if (args.containsKey(FORMAT_ARG_NAME)) {
formatSchema = args[FORMAT_ARG_NAME].as<const char*>();
// In case someone does a schema that can crash the ESP
formatSchema.replace("%s", "ERR");
// Replacing the double percent in case the user needs a percent sign in the output
// Replacing it with a (hopefully) impossible character should make sure that it doesn't get un-replaced by anything that is needed.
// \a is the bell/ding that can flash your console/cause it to make a sound.
formatSchema.replace("%%", "\a");
// This makes sure that if they add more than one formatter, it will only use the first and only argument.
formatSchema.replace("%", "%1$");
// Undoing the first replace so the escaped percent can be printed
formatSchema.replace("\a", "%%");
} else {
formatSchema = "%1$d";
}

return std::shared_ptr<const PrintfFormatterNumeric>(new PrintfFormatterNumeric(formatSchema));
}

String PrintfFormatterNumeric::format(const String &value) const {
int numericValue = value.toInt();

char buffer[120];
snprintf(buffer, sizeof(buffer), formatSchema.c_str(), numericValue);

return buffer;
}
34 changes: 34 additions & 0 deletions lib/Variables/PrintfFormatterString.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <VariableFormatters.h>
#include <ArduinoJson.h>

static const char FORMAT_ARG_NAME[] = "format";

PrintfFormatterString::PrintfFormatterString(const String& formatSchema)
: formatSchema(formatSchema)
{ }

std::shared_ptr<const PrintfFormatterString> PrintfFormatterString::build(JsonObject args) {
String formatSchema;

if (args.containsKey(FORMAT_ARG_NAME)) {
formatSchema = args[FORMAT_ARG_NAME].as<const char*>();
// Replacing the double percent in case the user needs a percent sign in the output
// Replacing it with a (hopefully) impossible character should make sure that it doesn't get un-replaced by anything that is needed.
formatSchema.replace("%%", "\a");
// This makes sure that if they add more than one formatter, it will only use the first and only argument.
formatSchema.replace("%", "%1$");
// Undoing the first replace so the escaped percent can be printed
formatSchema.replace("\a", "%%");
} else {
formatSchema = "%1$s";
}

return std::shared_ptr<const PrintfFormatterString>(new PrintfFormatterString(formatSchema));
}

String PrintfFormatterString::format(const String &value) const {
char buffer[120];
snprintf(buffer, sizeof(buffer), formatSchema.c_str(), value.c_str());

return buffer;
}
4 changes: 4 additions & 0 deletions lib/Variables/VariableFormatterFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ VariableFormatterFactory::_createInternal(
}

return std::make_shared<RatioVariableFormatter>(base);
} else if (formatterDef.equalsIgnoreCase("pfstring")) {
return PrintfFormatterString::build(formatterArgs);
} else if (formatterDef.equalsIgnoreCase("pfnumeric")) {
return PrintfFormatterNumeric::build(formatterArgs);
} else {
return defaultFormatter;
}
Expand Down
22 changes: 22 additions & 0 deletions lib/Variables/VariableFormatters.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,28 @@ class TimeVariableFormatter : public VariableFormatter {
Timezone& timezone;
};

class PrintfFormatterNumeric : public VariableFormatter {
public:
PrintfFormatterNumeric(const String& formatSchema);

virtual String format(const String& value) const;
static std::shared_ptr<const PrintfFormatterNumeric> build(JsonObject args);

protected:
String formatSchema;
};

class PrintfFormatterString : public VariableFormatter {
public:
PrintfFormatterString(const String& formatSchema);

virtual String format(const String& value) const;
static std::shared_ptr<const PrintfFormatterString> build(JsonObject args);

protected:
String formatSchema;
};

class CasesVariableFormatter : public VariableFormatter {
public:
CasesVariableFormatter(JsonObject args);
Expand Down
46 changes: 43 additions & 3 deletions template.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,19 @@
"time",
"round",
"cases",
"ratio"
"ratio",
"pfstring",
"pfnumeric"
],
"enumNames": [
"Pre-Defined Formatter",
"Identity (No-Op)",
"Time (strftime)",
"Round",
"Cases",
"Ratio"
"Ratio",
"Printf (String)",
"Printf (int)"
]
},
"args": {
Expand Down Expand Up @@ -271,7 +275,43 @@
}
}
}
}
},
{
"properties": {
"type": {
"enum": [
"pfstring"
]
},
"args": {
"type": "object",
"properties": {
"format": {
"title": "Printf (String)",
"type": "string"
}
}
}
}
},
{
"properties": {
"type": {
"enum": [
"pfnumeric"
]
},
"args": {
"type": "object",
"properties": {
"format": {
"title": "Printf (int)",
"type": "string"
}
}
}
}
}
]
}
}
Expand Down
38 changes: 36 additions & 2 deletions web/src/templates/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,16 @@ const Definitions = {
type: {
title: "Type",
type: "string",
enum: ["ref", "identity", "time", "round", "cases", "ratio"],
enum: ["ref", "identity", "time", "round", "cases", "ratio", "pfstring", "pfnumeric"],
enumNames: [
"Pre-Defined Formatter",
"Identity (No-Op)",
"Time (strftime)",
"Round",
"Cases",
"Ratio"
"Ratio",
"Printf (String)",
"Printf (int)"
]
},
args: {
Expand Down Expand Up @@ -337,6 +339,38 @@ const Definitions = {
}
}
}
},
{
properties: {
type: {
enum: ["pfstring"]
},
args: {
type: "object",
properties: {
format: {
title: "Printf (String)",
type: "string"
}
}
}
}
},
{
properties: {
type: {
enum: ["pfnumeric"]
},
args: {
type: "object",
properties: {
format: {
title: "Printf (int)",
type: "string"
}
}
}
}
}
]
}
Expand Down

0 comments on commit df1f026

Please sign in to comment.