diff -r b381da3a9b19 -r 54df904472b0 src/json.c --- a/src/json.c Thu Jan 09 21:19:52 2025 +0100 +++ b/src/json.c Thu Jan 09 22:37:10 2025 +0100 @@ -988,7 +988,7 @@ static const CxJsonWriter cx_json_writer_default = { false, true, - 255, + 6, false, 4 }; @@ -1001,7 +1001,7 @@ return (CxJsonWriter) { true, true, - 255, + 6, use_spaces, 4 }; @@ -1050,7 +1050,7 @@ size_t actual = 0, expected = 0; // small buffer for number to string conversions - char numbuf[32]; + char numbuf[40]; // recursively write the values switch (value->type) { @@ -1160,12 +1160,71 @@ break; } case CX_JSON_NUMBER: { - // TODO: locale bullshit - // TODO: formatting settings - snprintf(numbuf, 32, "%g", value->value.number); - size_t len = strlen(numbuf); - actual += wfunc(numbuf, 1, len, target); - expected += len; + int precision = settings->frac_max_digits; + // because of the way how %g is defined, we need to + // double the precision and truncate ourselves + precision = 1 + (precision > 15 ? 30 : 2 * precision); + snprintf(numbuf, 40, "%.*g", precision, value->value.number); + char *dot, *exp; + unsigned char max_digits; + // find the decimal separator and hope that it's one of . or , + dot = strchr(numbuf, '.'); + if (dot == NULL) { + dot = strchr(numbuf, ','); + } + if (dot == NULL) { + // no decimal separator found + // output everything until a possible exponent + max_digits = 30; + dot = numbuf; + } else { + // found a decimal separator + // output everything until the separator + // and set max digits to what the settings say + size_t len = dot - numbuf; + actual += wfunc(numbuf, 1, len, target); + expected += len; + max_digits = settings->frac_max_digits; + if (max_digits > 15) { + max_digits = 15; + } + // locale independent separator + if (max_digits > 0) { + actual += wfunc(".", 1, 1, target); + expected++; + } + dot++; + } + // find the exponent + exp = strchr(dot, 'e'); + if (exp == NULL) { + // no exponent - output the rest + if (max_digits > 0) { + size_t len = strlen(dot); + if (len > max_digits) { + len = max_digits; + } + actual += wfunc(dot, 1, len, target); + expected += len; + } + } else { + // exponent found - truncate the frac digits + // and then output the rest + if (max_digits > 0) { + size_t len = exp - dot - 1; + if (len > max_digits) { + len = max_digits; + } + actual += wfunc(dot, 1, len, target); + expected += len; + } + actual += wfunc("e", 1, 1, target); + expected++; + exp++; + size_t len = strlen(exp); + actual += wfunc(exp, 1, len, target); + expected += len; + } break; } case CX_JSON_INTEGER: {