Global: adds configurable trailing zeros for double formatting

This commit is contained in:
李通洲
2025-09-02 14:12:58 +08:00
parent 48fc72e95c
commit 54d8b0a95d
8 changed files with 196 additions and 43 deletions
+2 -2
View File
@@ -32,10 +32,10 @@ void ffFormatAppendFormatArg(FFstrbuf* buffer, const FFformatarg* formatarg)
ffStrbufAppend(buffer, (const FFstrbuf*)formatarg->value);
break;
case FF_FORMAT_ARG_TYPE_FLOAT:
ffStrbufAppendDouble(buffer, *(float*)formatarg->value, instance.config.display.fractionNdigits);
ffStrbufAppendDouble(buffer, *(float*)formatarg->value, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_HIDE);
break;
case FF_FORMAT_ARG_TYPE_DOUBLE:
ffStrbufAppendDouble(buffer, *(double*)formatarg->value, instance.config.display.fractionNdigits);
ffStrbufAppendDouble(buffer, *(double*)formatarg->value, instance.config.display.fractionNdigits, instance.config.display.fractionTrailingZeros != FF_FRACTION_TRAILING_ZEROS_TYPE_HIDE);
break;
case FF_FORMAT_ARG_TYPE_BOOL:
ffStrbufAppendS(buffer, *(bool*)formatarg->value ? "true" : "false");
+1 -1
View File
@@ -11,7 +11,7 @@ bool ffFreqAppendNum(uint32_t mhz, FFstrbuf* result)
if (ndigits >= 0)
{
ffStrbufAppendDouble(result, mhz / 1000., ndigits);
ffStrbufAppendDouble(result, mhz / 1000., ndigits, true);
if (spaceBeforeUnit) ffStrbufAppendC(result, ' ');
ffStrbufAppendS(result, "GHz");
}
+1 -1
View File
@@ -17,7 +17,7 @@ static void appendNum(FFstrbuf* result, uint64_t bytes, uint32_t base, const cha
if (counter == 0)
ffStrbufAppendUInt(result, bytes);
else
ffStrbufAppendDouble(result, size, (int8_t) options->sizeNdigits);
ffStrbufAppendDouble(result, size, (int8_t) options->sizeNdigits, true);
if (options->sizeSpaceBeforeUnit != FF_SPACE_BEFORE_UNIT_NEVER)
ffStrbufAppendC(result, ' ');
ffStrbufAppendS(result, prefixes[counter]);
+19
View File
@@ -380,6 +380,24 @@ const char* ffOptionsParseDisplayJsonConfig(FFOptionsDisplay* options, yyjson_va
return "display.fraction.ndigits must be an integer";
options->fractionNdigits = (int8_t) yyjson_get_int(ndigits);
}
yyjson_val* trailingZeros = yyjson_obj_get(val, "trailingZeros");
if (trailingZeros)
{
if (yyjson_is_null(trailingZeros))
options->fractionTrailingZeros = FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT;
else
{
int value;
const char* error = ffJsonConfigParseEnum(trailingZeros, &value, (FFKeyValuePair[]) {
{ "default", FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT },
{ "show", FF_FRACTION_TRAILING_ZEROS_TYPE_SHOW },
{ "hide", FF_FRACTION_TRAILING_ZEROS_TYPE_HIDE },
{},
});
if (error) return error;
options->fractionTrailingZeros = (FFFractionTrailingZerosType) value;
}
}
}
else
return "display.fraction must be an object";
@@ -810,6 +828,7 @@ void ffOptionsInitDisplay(FFOptionsDisplay* options)
options->freqNdigits = 2;
options->freqSpaceBeforeUnit = FF_SPACE_BEFORE_UNIT_DEFAULT;
options->fractionNdigits = -1;
options->fractionTrailingZeros = FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT;
ffListInit(&options->constants, sizeof(FFstrbuf));
}
+8
View File
@@ -25,6 +25,13 @@ typedef enum __attribute__((__packed__)) FFSpaceBeforeUnitType
FF_SPACE_BEFORE_UNIT_NEVER,
} FFSpaceBeforeUnitType;
typedef enum __attribute__((__packed__)) FFFractionTrailingZerosType
{
FF_FRACTION_TRAILING_ZEROS_TYPE_DEFAULT,
FF_FRACTION_TRAILING_ZEROS_TYPE_SHOW,
FF_FRACTION_TRAILING_ZEROS_TYPE_HIDE,
} FFFractionTrailingZerosType;
typedef struct FFOptionsDisplay
{
//If one of those is empty, ffLogoPrint will set them
@@ -81,6 +88,7 @@ typedef struct FFOptionsDisplay
int8_t freqNdigits;
FFSpaceBeforeUnitType freqSpaceBeforeUnit;
int8_t fractionNdigits;
FFFractionTrailingZerosType fractionTrailingZeros;
FFlist constants; // list of FFstrbuf
} FFOptionsDisplay;
+21 -10
View File
@@ -571,7 +571,7 @@ void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value)
strbuf->length += (uint32_t)(end - start);
}
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision)
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision, bool trailingZeros)
{
assert(precision <= 15); // yyjson_write_number supports up to 15 digits after the decimal point
@@ -598,18 +598,29 @@ void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision)
return;
}
if (precision > 1)
if (trailingZeros)
{
for (char* p = end - 1; *p != '.' && p > start; --p)
--precision;
if (precision > 0)
ffStrbufAppendNC(strbuf, (uint32_t) precision, '0');
if (precision > 1)
{
for (char* p = end - 1; *p != '.' && p > start; --p)
--precision;
if (precision > 0)
ffStrbufAppendNC(strbuf, (uint32_t) precision, '0');
}
else if (precision == 0 || (precision < 0 && end[-1] == '0'))
{
goto removeDecimalPoint;
}
}
else if (precision == 0 || (precision < 0 && end[-1] == '0'))
else
{
// yyjson always appends ".0", so we need to remove it
strbuf->length -= 2;
strbuf->chars[strbuf->length] = '\0';
if (end[-1] == '0')
{
removeDecimalPoint:
// yyjson always appends ".0" to make it a float point number. We need to remove it
strbuf->length -= 2;
strbuf->chars[strbuf->length] = '\0';
}
}
}
+1 -1
View File
@@ -107,7 +107,7 @@ void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value);
void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value);
// Appends a double value to the string buffer with the specified precision (0~15).
// if `precision < 0`, let yyjson decide the precision
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision);
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision, bool trailingZeros);
FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
{
+143 -28
View File
@@ -744,115 +744,230 @@ int main(void)
}
{
ffStrbufAppendDouble(&strbuf, 120.0, 0);
ffStrbufAppendDouble(&strbuf, 120.0, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.0, 1);
ffStrbufAppendDouble(&strbuf, 120.0, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.0, 5);
ffStrbufAppendDouble(&strbuf, 120.0, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.00000"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, 5);
ffStrbufAppendDouble(&strbuf, 120.123456789, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.12346"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.888888, 0);
ffStrbufAppendDouble(&strbuf, 120.888888, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.999999, 2);
ffStrbufAppendDouble(&strbuf, 120.999999, 2, true);
VERIFY(ffStrbufEqualS(&strbuf, "121.00"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, 0);
ffStrbufAppendDouble(&strbuf, 120.123456789, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, -1);
ffStrbufAppendDouble(&strbuf, 120.123456789, -1, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.123456789"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123, 5);
ffStrbufAppendDouble(&strbuf, 120.123, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "120.12300"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 0);
ffStrbufAppendDouble(&strbuf, -120.0, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 1);
ffStrbufAppendDouble(&strbuf, -120.0, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 5);
ffStrbufAppendDouble(&strbuf, -120.0, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.00000"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, 5);
ffStrbufAppendDouble(&strbuf, -120.123456789, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.12346"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, 0);
ffStrbufAppendDouble(&strbuf, -120.123456789, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, -1);
ffStrbufAppendDouble(&strbuf, -120.123456789, -1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.123456789"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123, 5);
ffStrbufAppendDouble(&strbuf, -120.123, 5, true);
VERIFY(ffStrbufEqualS(&strbuf, "-120.12300"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.888888, 0);
ffStrbufAppendDouble(&strbuf, -120.888888, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.999999, 2);
ffStrbufAppendDouble(&strbuf, -120.999999, 2, true);
VERIFY(ffStrbufEqualS(&strbuf, "-121.00"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 1);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 1);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 0);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 0);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, -1);
ffStrbufAppendDouble(&strbuf, 1.2345e50, -1, true);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, -1);
ffStrbufAppendDouble(&strbuf, -1.2345e50, -1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e20, 1);
ffStrbufAppendDouble(&strbuf, 1.2345e20, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "123450000000000000000.0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e20, 1);
ffStrbufAppendDouble(&strbuf, -1.2345e20, 1, true);
VERIFY(ffStrbufEqualS(&strbuf, "-123450000000000000000.0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, +0.0, 0);
ffStrbufAppendDouble(&strbuf, +0.0, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -0.0, 0);
ffStrbufAppendDouble(&strbuf, -0.0, 0, true);
VERIFY(ffStrbufEqualS(&strbuf, "-0"));
ffStrbufDestroy(&strbuf);
}
{
ffStrbufAppendDouble(&strbuf, 120.0, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.0, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.0, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "120.12346"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.888888, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.999999, 2, false);
VERIFY(ffStrbufEqualS(&strbuf, "121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123456789, -1, false);
VERIFY(ffStrbufEqualS(&strbuf, "120.123456789"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 120.123, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "120.123"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.0, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120.12346"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123456789, -1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120.123456789"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.123, 5, false);
VERIFY(ffStrbufEqualS(&strbuf, "-120.123"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.888888, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -120.999999, 2, false);
VERIFY(ffStrbufEqualS(&strbuf, "-121"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e50, -1, false);
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e50, -1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, 1.2345e20, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "123450000000000000000"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -1.2345e20, 1, false);
VERIFY(ffStrbufEqualS(&strbuf, "-123450000000000000000"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, +0.0, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "0"));
ffStrbufClear(&strbuf);
ffStrbufAppendDouble(&strbuf, -0.0, 0, false);
VERIFY(ffStrbufEqualS(&strbuf, "-0"));
ffStrbufDestroy(&strbuf);