-
-
Notifications
You must be signed in to change notification settings - Fork 767
add global.ndigits fallback for all ndigits settings #2270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -30,10 +30,10 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg) { | |
| ffStrbufAppend(buffer, (const FFstrbuf*) formatarg->value); | ||
| break; | ||
| case FF_ARG_TYPE_FLOAT: | ||
| ffStrbufAppendDouble(buffer, *(float*) formatarg->value, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER); | ||
| ffStrbufAppendDouble(buffer, *(float*) formatarg->value, ffNdigitsResolveInt8(instance.config.display.fractionNdigits, instance.config.display.globalNdigits, 2), instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER); | ||
| break; | ||
| case FF_ARG_TYPE_DOUBLE: | ||
| ffStrbufAppendDouble(buffer, *(double*) formatarg->value, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER); | ||
| ffStrbufAppendDouble(buffer, *(double*) formatarg->value, ffNdigitsResolveInt8(instance.config.display.fractionNdigits, instance.config.display.globalNdigits, 2), instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_NEVER); | ||
|
Comment on lines
+33
to
+36
|
||
| break; | ||
| case FF_ARG_TYPE_BOOL: | ||
| ffStrbufAppendS(buffer, *(bool*) formatarg->value ? "true" : "false"); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -511,6 +511,26 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va | |||||
| } | ||||||
| options->freqSpaceBeforeUnit = (FFSpaceBeforeUnitType) value; | ||||||
| } | ||||||
| } else if (unsafe_yyjson_equals_str(key, "global")) { | ||||||
| if (!yyjson_is_obj(val)) { | ||||||
| return "display.global must be an object"; | ||||||
| } | ||||||
|
|
||||||
|
Comment on lines
+514
to
+518
|
||||||
| yyjson_val* ndigits = yyjson_obj_get(val, "ndigits"); | ||||||
| if (ndigits) { | ||||||
| if (yyjson_is_null(ndigits)) { | ||||||
| options->globalNdigits = -1; | ||||||
| } else { | ||||||
| if (!yyjson_is_uint(ndigits)) { | ||||||
| return "display.global.ndigits must be an unsigned integer"; | ||||||
| } | ||||||
| uint64_t val = yyjson_get_uint(ndigits); | ||||||
| if (val > 9) { | ||||||
| return "display.global.ndigits must be between 0 and 9"; | ||||||
| } | ||||||
| options->globalNdigits = (int8_t) val; | ||||||
| } | ||||||
| } | ||||||
| } else { | ||||||
| return "Unknown display property"; | ||||||
| } | ||||||
|
|
@@ -619,7 +639,12 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key | |||||
| if (ffStrEqualsIgnCase(subkey, "binary-prefix")) { | ||||||
| options->sizeBinaryPrefix = (FFSizeBinaryPrefixType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { { "iec", FF_SIZE_BINARY_PREFIX_TYPE_IEC }, { "si", FF_SIZE_BINARY_PREFIX_TYPE_SI }, { "jedec", FF_SIZE_BINARY_PREFIX_TYPE_JEDEC }, {} }); | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "ndigits")) { | ||||||
| options->sizeNdigits = (uint8_t) ffOptionParseUInt32(key, value); | ||||||
| uint32_t ndigits = ffOptionParseUInt32(key, value); | ||||||
| if (ndigits > 9) { | ||||||
| fprintf(stderr, "Error: %s must be between 0 and 9\n", key); | ||||||
| exit(477); | ||||||
| } | ||||||
| options->sizeNdigits = (uint8_t) ndigits; | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "max-prefix")) { | ||||||
| options->sizeMaxPrefix = (uint8_t) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { { "B", 0 }, { "kB", 1 }, { "MB", 2 }, { "GB", 3 }, { "TB", 4 }, { "PB", 5 }, { "EB", 6 }, { "ZB", 7 }, { "YB", 8 }, {} }); | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "space-before-unit")) { | ||||||
|
|
@@ -647,7 +672,12 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key | |||||
| {}, | ||||||
| }); | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "ndigits")) { | ||||||
| options->tempNdigits = (uint8_t) ffOptionParseUInt32(key, value); | ||||||
| uint32_t ndigits = ffOptionParseUInt32(key, value); | ||||||
| if (ndigits > 9) { | ||||||
| fprintf(stderr, "Error: %s must be between 0 and 9\n", key); | ||||||
| exit(477); | ||||||
| } | ||||||
| options->tempNdigits = (uint8_t) ndigits; | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "color-green")) { | ||||||
| ffOptionParseColor(value, &options->tempColorGreen); | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "color-yellow")) { | ||||||
|
|
@@ -669,7 +699,12 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key | |||||
| if (ffStrEqualsIgnCase(subkey, "type")) { | ||||||
| options->percentType = (uint8_t) ffOptionParseUInt32(key, value); | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "ndigits")) { | ||||||
| options->percentNdigits = (uint8_t) ffOptionParseUInt32(key, value); | ||||||
| uint32_t ndigits = ffOptionParseUInt32(key, value); | ||||||
| if (ndigits > 9) { | ||||||
| fprintf(stderr, "Error: %s must be between 0 and 9\n", key); | ||||||
| exit(477); | ||||||
| } | ||||||
| options->percentNdigits = (uint8_t) ndigits; | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "color-green")) { | ||||||
| ffOptionParseColor(value, &options->percentColorGreen); | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "color-yellow")) { | ||||||
|
|
@@ -689,7 +724,19 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key | |||||
| return false; | ||||||
| } | ||||||
| } else if (ffStrEqualsIgnCase(key, "--fraction-ndigits")) { | ||||||
| options->fractionNdigits = (int8_t) ffOptionParseInt32(key, value); | ||||||
| int32_t ndigits = ffOptionParseInt32(key, value); | ||||||
| if (ndigits < -1 || ndigits > 9) { | ||||||
| fprintf(stderr, "Error: %s must be between -1 and 9\n", key); | ||||||
| exit(477); | ||||||
| } | ||||||
| options->fractionNdigits = (int8_t) ndigits; | ||||||
| } else if (ffStrEqualsIgnCase(key, "--ndigits")) { | ||||||
| uint32_t ndigits = ffOptionParseUInt32(key, value); | ||||||
| if (ndigits > 9) { | ||||||
| fprintf(stderr, "Error: %s must be between 0 and 9\n", key); | ||||||
| exit(477); | ||||||
| } | ||||||
| options->globalNdigits = (int8_t) ndigits; | ||||||
| } else if (ffStrEqualsIgnCase(key, "--fraction-trailing-zeros")) { | ||||||
| options->fractionTrailingZeros = (FFFractionTrailingZerosType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { | ||||||
| { "default", FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT }, | ||||||
|
|
@@ -733,7 +780,12 @@ bool ffOptionsParseDisplayCommandLine(FFOptionsDisplay* options, const char* key | |||||
| } else if (ffStrStartsWithIgnCase(key, "--freq-")) { | ||||||
| const char* subkey = key + strlen("--freq-"); | ||||||
| if (ffStrEqualsIgnCase(subkey, "ndigits")) { | ||||||
| options->freqNdigits = (int8_t) ffOptionParseInt32(key, value); | ||||||
| int32_t ndigits = ffOptionParseInt32(key, value); | ||||||
| if (ndigits < -1 || ndigits > 9) { | ||||||
| fprintf(stderr, "Error: %s must be between -1 and 9\n", key); | ||||||
| exit(477); | ||||||
| } | ||||||
| options->freqNdigits = (int8_t) ndigits; | ||||||
| } else if (ffStrEqualsIgnCase(subkey, "space-before-unit")) { | ||||||
| options->freqSpaceBeforeUnit = (FFSpaceBeforeUnitType) ffOptionParseEnum(key, value, (FFKeyValuePair[]) { | ||||||
| { "default", FF_SPACE_BEFORE_UNIT_DEFAULT }, | ||||||
|
|
@@ -771,7 +823,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) { | |||||
| options->durationSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; | ||||||
| options->hideCursor = false; | ||||||
| options->sizeBinaryPrefix = FF_SIZE_BINARY_PREFIX_TYPE_IEC; | ||||||
| options->sizeNdigits = 2; | ||||||
| options->sizeNdigits = UINT8_MAX; | ||||||
| options->sizeMaxPrefix = 8; // YB | ||||||
|
Comment on lines
825
to
827
|
||||||
| options->sizeSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT; | ||||||
|
Comment on lines
825
to
828
|
||||||
|
|
||||||
|
|
@@ -782,7 +834,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options) { | |||||
| options->keyType = FF_MODULE_KEY_TYPE_STRING; | ||||||
|
|
||||||
| options->tempUnit = FF_TEMPERATURE_UNIT_DEFAULT; | ||||||
| options->tempNdigits = 1; | ||||||
| options->tempNdigits = UINT8_MAX; | ||||||
|
||||||
| options->tempNdigits = UINT8_MAX; | |
| options->tempNdigits = 2; |
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ffOptionsInitDisplay now initializes percentNdigits to UINT8_MAX as an “unset” sentinel, but ffOptionsGenerateDisplayJsonConfig still unconditionally serializes display.percent.ndigits. With the new default this will cause --gen-config to emit ndigits=255, which is outside the accepted 0–9 range and will not round-trip through the JSON parser. Update config generation to omit percent.ndigits (or emit null) when the sentinel is set, and ensure emitted values stay within the documented bounds.
| options->percentNdigits = UINT8_MAX; | |
| options->percentNdigits = 0; |
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
percentNdigits now uses UINT8_MAX as an "unset" sentinel, but --percent-ndigits accepts any value and casts to uint8_t, allowing wraparound and collisions with the sentinel (255). Add 0–9 validation for --percent-ndigits to keep CLI behavior consistent with JSON parsing and with the new sentinel logic.
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fractionNdigits now defaults to INT8_MIN (unset sentinel). There are still call sites that pass instance.config.display.fractionNdigits directly into ffStrbufAppendDouble (e.g. src/modules/display/display.c and src/modules/localip/localip.c), which will now see precision=-128 when unset and ignore the intended default/global fallback. Either keep the runtime default at 2 instead of INT8_MIN, or update remaining call sites to use ffNdigitsResolveInt8(..., globalNdigits, 2) before calling ffStrbufAppendDouble.
| options->globalNdigits = -1; | |
| options->globalNdigits = 2; |
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
freqNdigits / fractionNdigits now use INT8_MIN as an "unset" sentinel, but --freq-ndigits / --fraction-ndigits accept arbitrary int32 values and cast to int8_t. This can wrap and/or collide with the sentinel (-128), causing inputs to be misinterpreted as "unset". Add range validation on the CLI path (matching the JSON constraints: freq -1..9; fraction -1..9) before casting.
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In generated display JSON config, the temperature unit is written to the root display object (obj) for C/F/K cases, instead of to the temp object (temperature). This will produce an invalid/incorrect display.temp.unit in --gen-config output (only the default case uses the correct object). Write the unit key into temperature for all cases.
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In config generation for display.temp, the unit field is being added to obj (the top-level display object) instead of the temperature object. This makes generated JSON incorrect and inconsistent with the DEFAULT case (and with parsing expectations). Add the unit key to temperature for all unit cases (C/F/K).
Copilot
AI
Apr 13, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ffOptionsGenerateDisplayJsonConfig writes display.freq.spaceBeforeUnit based on options->percentSpaceBeforeUnit. This will generate incorrect config output for the freq block; it should use options->freqSpaceBeforeUnit.
| switch (options->percentSpaceBeforeUnit) { | |
| switch (options->freqSpaceBeforeUnit) { |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,18 @@ | |
| #include "common/FFstrbuf.h" | ||
| #include "common/FFlist.h" | ||
|
|
||
| static inline uint8_t ffNdigitsResolve(uint8_t specific, int8_t global, uint8_t hardcoded) { | ||
| if (specific != UINT8_MAX) return specific; | ||
| if (global >= 0) return (uint8_t) global; | ||
| return hardcoded; | ||
| } | ||
|
|
||
| static inline int8_t ffNdigitsResolveInt8(int8_t specific, int8_t global, int8_t hardcoded) { | ||
| if (specific != INT8_MIN) return specific; | ||
| if (global >= 0) return global; | ||
| return hardcoded; | ||
|
Comment on lines
+14
to
+17
|
||
| } | ||
|
|
||
| typedef enum FF_A_PACKED FFSizeBinaryPrefixType { | ||
| FF_SIZE_BINARY_PREFIX_TYPE_IEC, // 1024 Bytes = 1 KiB, 1024 KiB = 1 MiB, ... (standard) | ||
| FF_SIZE_BINARY_PREFIX_TYPE_SI, // 1000 Bytes = 1 kB, 1000 kB = 1 MB, ... | ||
|
|
@@ -86,6 +98,7 @@ typedef struct FFOptionsDisplay { | |
| FFSpaceBeforeUnitType freqSpaceBeforeUnit; | ||
| int8_t fractionNdigits; | ||
| FFFractionTrailingZerosType fractionTrailingZeros; | ||
| int8_t globalNdigits; | ||
|
|
||
| FFlist constants; // list of FFstrbuf | ||
| } FFOptionsDisplay; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.