size_t stream_putdouble(stream_s *stream, long double value, int precision, int flags) { char *string = __format_double(value, flags, precision); size_t len = strlen(string); stream_putstring(stream, string); free(string); return len; }
static char *__format_double(long double value, int flags, int precision) { char *int_part; char *dec_part; char *string; long double i; if (isnan(value)) { if (flags & FLAG_UPPER) { return strdup("NAN"); } else { return strdup("nan"); } } if (isinf(value)) { if (flags & FLAG_UPPER) { if (value < 0) { return strdup("-INF"); } else { if (flags & FLAG_SIGN) { return strdup("+INF"); } else { return strdup("INF"); } } } else { if (value < 0) { return strdup("-inf"); } else { if (flags & FLAG_SIGN) { return strdup("+inf"); } else { return strdup("inf"); } } } } if (flags & FLAG_EXP || (flags & FLAG_MEXP && value > 1000000000)) { i = log10l(value); value /= powl(10, floorl(i)); int_part = __format_double(value, flags & ~(FLAG_EXP), precision); dec_part = __format_int(i, flags | FLAG_SIGN); string = strvcat(int_part, (flags & FLAG_UPPER) ? "E" : "e", dec_part, NULL); free(int_part); free(dec_part); } else { value = modfl(value, &i); if (value > 2000000000) { int_part = __format_double_int(i, flags); } else { int_part = __format_int(i, flags); } dec_part = __format_double_frac(value, flags, precision); if (i == 0.0 && value < 0) { if (value != 0.0 || flags & FLAG_ALT) { string = strvcat("-", int_part, ".", dec_part, NULL); } else { string = strvcat("-", int_part, NULL); } } else { if (value != 0.0 || flags & FLAG_ALT) { string = strvcat(int_part, ".", dec_part, NULL); } else { string = strdup(int_part); } } free(int_part); free(dec_part); } return string; }