FFstrbuf: adds number appending functions

This commit is contained in:
李通洲
2025-08-19 15:00:30 +08:00
parent 70b11d953c
commit dcbf76b233
3 changed files with 164 additions and 0 deletions
+68
View File
@@ -542,6 +542,74 @@ int64_t ffStrbufToSInt(const FFstrbuf* strbuf, int64_t defaultValue)
return str_end == strbuf->chars ? defaultValue : (int64_t)result;
}
void ffStrbufAppendSInt(FFstrbuf* strbuf, int64_t value)
{
ffStrbufEnsureFree(strbuf, 21); // Required by yyjson_write_number
char* start = strbuf->chars + strbuf->length;
yyjson_val val = {};
unsafe_yyjson_set_sint(&val, value);
char* end = yyjson_write_number(&val, start);
assert(end != NULL);
strbuf->length += (uint32_t)(end - start);
}
void ffStrbufAppendUInt(FFstrbuf* strbuf, uint64_t value)
{
ffStrbufEnsureFree(strbuf, 21); // Required by yyjson_write_number
char* start = strbuf->chars + strbuf->length;
yyjson_val val = {};
unsafe_yyjson_set_uint(&val, value);
char* end = yyjson_write_number(&val, start);
assert(end != NULL);
strbuf->length += (uint32_t)(end - start);
}
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, uint8_t precision)
{
assert(precision <= 15); // yyjson_write_number supports up to 15 digits after the decimal point
ffStrbufEnsureFree(strbuf, 40); // Required by yyjson_write_number
char* start = strbuf->chars + strbuf->length;
yyjson_val val = {};
unsafe_yyjson_set_double(&val, value);
if (precision > 0) unsafe_yyjson_set_fp_to_fixed(&val, (int) precision);
// Write at most <precision> digits after the decimal point; doesn't append trailing zeros
char* end = yyjson_write_number(&val, start);
assert(end != NULL);
strbuf->length += (uint32_t)(end - start);
if (__builtin_expect(value > 1e21 || value < -1e21, false))
{
// If the value is too large, yyjson_write_number will write it in scientific notation
return;
}
if (precision > 1)
{
for (char* p = end - 1; *p != '.' && p > start; --p)
--precision;
if (precision > 0)
ffStrbufAppendNC(strbuf, precision, '0');
}
else if (precision == 0 && end[-1] == '0' && end[-2] == '.')
{
// yyjson always appends a decimal point if value is an integer
// Remove trailing zeros and the decimal point if precision is 0
strbuf->length -= 2;
strbuf->chars[strbuf->length] = '\0';
}
}
void ffStrbufUpperCase(FFstrbuf* strbuf)
{
for (uint32_t i = 0; i < strbuf->length; ++i)
+6
View File
@@ -103,6 +103,12 @@ bool ffStrbufMatchSeparatedNS(const FFstrbuf* strbuf, uint32_t compLength, const
int ffStrbufAppendUtf32CodePoint(FFstrbuf* strbuf, uint32_t codepoint);
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.
// if `precision == 0`, let yyjson decide the precision
void ffStrbufAppendDouble(FFstrbuf* strbuf, double value, uint8_t precision);
FF_C_NODISCARD static inline FFstrbuf ffStrbufCreateA(uint32_t allocate)
{
FFstrbuf strbuf;