Skip to content

Commit a7eecf6

Browse files
committed
FFstrbuf: improves double formatting precision handling
1 parent 8e282a3 commit a7eecf6

File tree

3 files changed

+41
-10
lines changed

3 files changed

+41
-10
lines changed

src/util/FFstrbuf.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value)
570570
strbuf->length += (uint32_t)(end - start);
571571
}
572572

573-
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, uint8_t precision)
573+
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision)
574574
{
575575
assert(precision <= 15); // yyjson_write_number supports up to 15 digits after the decimal point
576576

@@ -579,12 +579,12 @@ void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, uint8_t precision)
579579

580580
yyjson_val val = {};
581581
unsafe_yyjson_set_double(&val, value);
582-
if (precision > 0) unsafe_yyjson_set_fp_to_fixed(&val, (int) precision);
582+
if (precision >= 0) unsafe_yyjson_set_fp_to_fixed(&val, precision == 0 ? 1 : precision); // yyjson ignores precision == 0
583583

584584
// Write at most <precision> digits after the decimal point; doesn't append trailing zeros
585585
char* end = yyjson_write_number(&val, start);
586586

587-
assert(end != NULL);
587+
assert(end > start);
588588

589589
strbuf->length += (uint32_t)(end - start);
590590

@@ -599,12 +599,11 @@ void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, uint8_t precision)
599599
for (char* p = end - 1; *p != '.' && p > start; --p)
600600
--precision;
601601
if (precision > 0)
602-
ffStrbufAppendNC(strbuf, precision, '0');
602+
ffStrbufAppendNC(strbuf, (uint32_t) precision, '0');
603603
}
604-
else if (precision == 0 && end[-1] == '0' && end[-2] == '.')
604+
else if (precision == 0 || (precision < 0 && end[-1] == '0'))
605605
{
606-
// yyjson always appends a decimal point if value is an integer
607-
// Remove trailing zeros and the decimal point if precision is 0
606+
// yyjson always appends ".0", so we need to remove it
608607
strbuf->length -= 2;
609608
strbuf->chars[strbuf->length] = '\0';
610609
}

src/util/FFstrbuf.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,9 @@ int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint);
105105

106106
void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value);
107107
void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value);
108-
// Appends a double value to the string buffer with the specified precision.
109-
// if `precision == 0`, let yyjson decide the precision
110-
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, uint8_t precision);
108+
// Appends a double value to the string buffer with the specified precision (0~15).
109+
// if `precision < 0`, let yyjson decide the precision
110+
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, int8_t precision);
111111

112112
FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
113113
{

tests/strbuf.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,10 @@ int main(void)
747747
ffStrbufAppendDouble(&strbuf, 120.0, 0);
748748
VERIFY(ffStrbufEqualS(&strbuf, "120"));
749749

750+
ffStrbufClear(&strbuf);
751+
ffStrbufAppendDouble(&strbuf, 120.0, 1);
752+
VERIFY(ffStrbufEqualS(&strbuf, "120.0"));
753+
750754
ffStrbufClear(&strbuf);
751755
ffStrbufAppendDouble(&strbuf, 120.0, 5);
752756
VERIFY(ffStrbufEqualS(&strbuf, "120.00000"));
@@ -757,6 +761,10 @@ int main(void)
757761

758762
ffStrbufClear(&strbuf);
759763
ffStrbufAppendDouble(&strbuf, 120.123456789, 0);
764+
VERIFY(ffStrbufEqualS(&strbuf, "120"));
765+
766+
ffStrbufClear(&strbuf);
767+
ffStrbufAppendDouble(&strbuf, 120.123456789, -1);
760768
VERIFY(ffStrbufEqualS(&strbuf, "120.123456789"));
761769

762770
ffStrbufClear(&strbuf);
@@ -767,6 +775,10 @@ int main(void)
767775
ffStrbufAppendDouble(&strbuf, -120.0, 0);
768776
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
769777

778+
ffStrbufClear(&strbuf);
779+
ffStrbufAppendDouble(&strbuf, -120.0, 1);
780+
VERIFY(ffStrbufEqualS(&strbuf, "-120.0"));
781+
770782
ffStrbufClear(&strbuf);
771783
ffStrbufAppendDouble(&strbuf, -120.0, 5);
772784
VERIFY(ffStrbufEqualS(&strbuf, "-120.00000"));
@@ -777,6 +789,10 @@ int main(void)
777789

778790
ffStrbufClear(&strbuf);
779791
ffStrbufAppendDouble(&strbuf, -120.123456789, 0);
792+
VERIFY(ffStrbufEqualS(&strbuf, "-120"));
793+
794+
ffStrbufClear(&strbuf);
795+
ffStrbufAppendDouble(&strbuf, -120.123456789, -1);
780796
VERIFY(ffStrbufEqualS(&strbuf, "-120.123456789"));
781797

782798
ffStrbufClear(&strbuf);
@@ -791,6 +807,22 @@ int main(void)
791807
ffStrbufAppendDouble(&strbuf, -1.2345e50, 1);
792808
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
793809

810+
ffStrbufClear(&strbuf);
811+
ffStrbufAppendDouble(&strbuf, 1.2345e50, 0);
812+
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
813+
814+
ffStrbufClear(&strbuf);
815+
ffStrbufAppendDouble(&strbuf, -1.2345e50, 0);
816+
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
817+
818+
ffStrbufClear(&strbuf);
819+
ffStrbufAppendDouble(&strbuf, 1.2345e50, -1);
820+
VERIFY(ffStrbufEqualS(&strbuf, "1.2345e50"));
821+
822+
ffStrbufClear(&strbuf);
823+
ffStrbufAppendDouble(&strbuf, -1.2345e50, -1);
824+
VERIFY(ffStrbufEqualS(&strbuf, "-1.2345e50"));
825+
794826
ffStrbufClear(&strbuf);
795827
ffStrbufAppendDouble(&strbuf, 1.2345e20, 1);
796828
VERIFY(ffStrbufEqualS(&strbuf, "123450000000000000000.0"));

0 commit comments

Comments
 (0)