src/melon/modules/string/format.c
static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
	char buf[PRINTF_FTOA_BUFFER_SIZE];
	size_t len = 0U;
	double diff = 0.0;

	// powers of 10
	static const double pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};

	// test for special values
	if (value != value)
		return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
	if (value < -DBL_MAX)
		return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
	if (value > DBL_MAX)
		return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);

	// test for very large values
	// standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
	if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT))
	{
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
		return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
#else
		return 0U;
#endif
	}

	// test for negative
	bool negative = false;
	if (value < 0)
	{
		negative = true;
		value = 0 - value;
	}

	// set default precision, if not set explicitly
	if (!(flags & FLAGS_PRECISION))
	{
		prec = PRINTF_DEFAULT_FLOAT_PRECISION;
	}
	// limit precision to 9, cause a prec >= 10 can lead to overflow errors
	while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U))
	{
		buf[len++] = '0';
		prec--;
	}

	int whole = (int)value;
	double tmp = (value - whole) * pow10[prec];
	unsigned long frac = (unsigned long)tmp;
	diff = tmp - frac;

	if (diff > 0.5)
	{
		++frac;
		// handle rollover, e.g. case 0.99 with prec 1 is 1.0
		if (frac >= pow10[prec])
		{
			frac = 0;
			++whole;
		}
	}
	else if (diff < 0.5)
	{
	}
	else if ((frac == 0U) || (frac & 1U))
	{
		// if halfway, round up if odd OR if last digit is 0
		++frac;
	}

	if (prec == 0U)
	{
		diff = value - (double)whole;
		if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1))
		{
			// exactly 0.5 and ODD, then round up
			// 1.5 -> 2, but 2.5 -> 2
			++whole;
		}
	}
	else
	{
		unsigned int count = prec;
		// now do fractional part, as an unsigned number
		while (len < PRINTF_FTOA_BUFFER_SIZE)
		{
			--count;
			buf[len++] = (char)(48U + (frac % 10U));
			if (!(frac /= 10U))
			{
				break;
			}
		}
		// add extra 0s
		while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U))
		{
			buf[len++] = '0';
		}
		if (len < PRINTF_FTOA_BUFFER_SIZE)
		{
			// add decimal
			buf[len++] = '.';
		}
	}

	// do whole part, number is reversed
	while (len < PRINTF_FTOA_BUFFER_SIZE)
	{
		buf[len++] = (char)(48 + (whole % 10));
		if (!(whole /= 10))
		{
			break;
		}
	}

	// pad leading zeros
	if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD))
	{
		if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE))))
		{
			width--;
		}
		while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE))
		{
			buf[len++] = '0';
		}
	}

	if (len < PRINTF_FTOA_BUFFER_SIZE)
	{
		if (negative)
		{
			buf[len++] = '-';
		}
		else if (flags & FLAGS_PLUS)
		{
			buf[len++] = '+'; // ignore the space if the '+' exists
		}
		else if (flags & FLAGS_SPACE)
		{
			buf[len++] = ' ';
		}
	}

	return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
// internal ftoa for fixed decimal floating point

internal ftoa for fixed decimal floating point
internal ftoa for fixed decimal floating point
static size_t _ftoa(out_fct_type out, char *buffer, size_t idx, size_t maxlen, double value, unsigned int prec, unsigned int width, unsigned int flags)
{
	char buf[PRINTF_FTOA_BUFFER_SIZE];
	size_t len = 0U;
	double diff = 0.0;
	static const double pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};
	if (value != value)
		return _out_rev(out, buffer, idx, maxlen, "nan", 3, width, flags);
	if (value < -DBL_MAX)
		return _out_rev(out, buffer, idx, maxlen, "fni-", 4, width, flags);
	if (value > DBL_MAX)
		return _out_rev(out, buffer, idx, maxlen, (flags & FLAGS_PLUS) ? "fni+" : "fni", (flags & FLAGS_PLUS) ? 4U : 3U, width, flags);
	if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT))
	{
#if defined(PRINTF_SUPPORT_EXPONENTIAL)
		return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
#else
		return 0U;
#endif
	}
	bool negative = false;
	if (value < 0)
	{
		negative = true;
		value = 0 - value;
	}
	if (!(flags & FLAGS_PRECISION))
	{
		prec = PRINTF_DEFAULT_FLOAT_PRECISION;
	}
	while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U))
	{
		buf[len++] = '0';
		prec--;
	}
	int whole = (int)value;
	double tmp = (value - whole) * pow10[prec];
	unsigned long frac = (unsigned long)tmp;
	diff = tmp - frac;
	if (diff > 0.5)
	{
		++frac;
		if (frac >= pow10[prec])
		{
			frac = 0;
			++whole;
		}
	}
	else if (diff < 0.5)
	{
	}
	else if ((frac == 0U) || (frac & 1U))
	{
		++frac;
	}
	if (prec == 0U)
	{
		diff = value - (double)whole;
		if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1))
		{
			++whole;
		}
	}
	else
	{
		unsigned int count = prec;
		while (len < PRINTF_FTOA_BUFFER_SIZE)
		{
			--count;
			buf[len++] = (char)(48U + (frac % 10U));
			if (!(frac /= 10U))
			{
				break;
			}
		}
		while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U))
		{
			buf[len++] = '0';
		}
		if (len < PRINTF_FTOA_BUFFER_SIZE)
		{
			buf[len++] = '.';
		}
	}
	while (len < PRINTF_FTOA_BUFFER_SIZE)
	{
		buf[len++] = (char)(48 + (whole % 10));
		if (!(whole /= 10))
		{
			break;
		}
	}
	if (!(flags & FLAGS_LEFT) && (flags & FLAGS_ZEROPAD))
	{
		if (width && (negative || (flags & (FLAGS_PLUS | FLAGS_SPACE))))
		{
			width--;
		}
		while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE))
		{
			buf[len++] = '0';
		}
	}
	if (len < PRINTF_FTOA_BUFFER_SIZE)
	{
		if (negative)
		{
			buf[len++] = '-';
		}
		else if (flags & FLAGS_PLUS)
		{
			buf[len++] = '+'; 
		}
		else if (flags & FLAGS_SPACE)
		{
			buf[len++] = ' ';
		}
	}
	return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
}
static size_t _ftoa ( out_fct_type out , char * buffer , size_t idx , size_t maxlen , double value , unsigned int prec , unsigned int width , unsigned int flags ) { char buf [ PRINTF_FTOA_BUFFER_SIZE ] ; size_t len = 0U ; double diff = 0.0 ; static const double pow10 [ ] = { 1 , 10 , 100 , 1000 , 10000 , 100000 , 1000000 , 10000000 , 100000000 , 1000000000 } ; if ( value != value ) return _out_rev ( out , buffer , idx , maxlen , " " , 3 , width , flags ) ; if ( value < - DBL_MAX ) return _out_rev ( out , buffer , idx , maxlen , " " , 4 , width , flags ) ; if ( value > DBL_MAX ) return _out_rev ( out , buffer , idx , maxlen , ( flags & FLAGS_PLUS ) ? " " : " " , ( flags & FLAGS_PLUS ) ? 4U : 3U , width , flags ) ; if ( ( value > PRINTF_MAX_FLOAT ) || ( value < - PRINTF_MAX_FLOAT ) ) { #if defined ( PRINTF_SUPPORT_EXPONENTIAL ) return _etoa ( out , buffer , idx , maxlen , value , prec , width , flags ) ; #else return 0U ; #endif } bool negative = false ; if ( value < 0 ) { negative = true ; value = 0 - value ; } if ( ! ( flags & FLAGS_PRECISION ) ) { prec = PRINTF_DEFAULT_FLOAT_PRECISION ; } while ( ( len < PRINTF_FTOA_BUFFER_SIZE ) && ( prec > 9U ) ) { buf [ len ++ ] = ' ' ; prec -- ; } int whole = ( int ) value ; double tmp = ( value - whole ) * pow10 [ prec ] ; unsigned long frac = ( unsigned long ) tmp ; diff = tmp - frac ; if ( diff > 0.5 ) { ++ frac ; if ( frac >= pow10 [ prec ] ) { frac = 0 ; ++ whole ; } } else if ( diff < 0.5 ) { } else if ( ( frac == 0U ) || ( frac & 1U ) ) { ++ frac ; } if ( prec == 0U ) { diff = value - ( double ) whole ; if ( ( ! ( diff < 0.5 ) || ( diff > 0.5 ) ) && ( whole & 1 ) ) { ++ whole ; } } else { unsigned int count = prec ; while ( len < PRINTF_FTOA_BUFFER_SIZE ) { -- count ; buf [ len ++ ] = ( char ) ( 48U + ( frac % 10U ) ) ; if ( ! ( frac /= 10U ) ) { break ; } } while ( ( len < PRINTF_FTOA_BUFFER_SIZE ) && ( count -- > 0U ) ) { buf [ len ++ ] = ' ' ; } if ( len < PRINTF_FTOA_BUFFER_SIZE ) { buf [ len ++ ] = ' ' ; } } while ( len < PRINTF_FTOA_BUFFER_SIZE ) { buf [ len ++ ] = ( char ) ( 48 + ( whole % 10 ) ) ; if ( ! ( whole /= 10 ) ) { break ; } } if ( ! ( flags & FLAGS_LEFT ) && ( flags & FLAGS_ZEROPAD ) ) { if ( width && ( negative || ( flags & ( FLAGS_PLUS | FLAGS_SPACE ) ) ) ) { width -- ; } while ( ( len < width ) && ( len < PRINTF_FTOA_BUFFER_SIZE ) ) { buf [ len ++ ] = ' ' ; } } if ( len < PRINTF_FTOA_BUFFER_SIZE ) { if ( negative ) { buf [ len ++ ] = ' ' ; } else if ( flags & FLAGS_PLUS ) { buf [ len ++ ] = ' ' ; } else if ( flags & FLAGS_SPACE ) { buf [ len ++ ] = ' ' ; } } return _out_rev ( out , buffer , idx , maxlen , buf , len , width , flags ) ; }
internal ftoa for fixed decimal floating point
internal ftoa for fixed decimal floating point
// powers of 10
 // test for special values
 // test for very large values
 // standard printf behavior is to print EVERY whole number digit -- which could be 100s of characters overflowing your buffers == bad
 // test for negative
 // set default precision, if not set explicitly
 // limit precision to 9, cause a prec >= 10 can lead to overflow errors
 // handle rollover, e.g. case 0.99 with prec 1 is 1.0
 // if halfway, round up if odd OR if last digit is 0
 // exactly 0.5 and ODD, then round up
 // 1.5 -> 2, but 2.5 -> 2
 // now do fractional part, as an unsigned number
 // add extra 0s
 // add decimal
 // do whole part, number is reversed
 // pad leading zeros
 // ignore the space if the '+' exists
