aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil/printf.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2019-04-06 12:24:53 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2019-04-06 12:24:53 +0100
commite0f9152733fda5ffd356ab453a242377c3fbea2e (patch)
tree5e242ddf5bb85faa4458ce01490029b49b0a264a /src/libutil/printf.c
parent4f9f85c6d1b7ca4bfab4599cb76e885c71ad07f6 (diff)
downloadrspamd-e0f9152733fda5ffd356ab453a242377c3fbea2e.tar.gz
rspamd-e0f9152733fda5ffd356ab453a242377c3fbea2e.zip
[Feature] Use fpconv girsu2 implementation for printing floats
Diffstat (limited to 'src/libutil/printf.c')
-rw-r--r--src/libutil/printf.c54
1 files changed, 42 insertions, 12 deletions
diff --git a/src/libutil/printf.c b/src/libutil/printf.c
index 3c4acef47..403fa8877 100644
--- a/src/libutil/printf.c
+++ b/src/libutil/printf.c
@@ -40,6 +40,7 @@
#include "printf.h"
#include "str_util.h"
+#include "contrib/fpconv/fpconv.h"
/**
* From FreeBSD libutil code
@@ -590,7 +591,7 @@ rspamd_vprintf_common (rspamd_printf_append_func func,
const gchar *fmt,
va_list args)
{
- gchar zero, numbuf[G_ASCII_DTOSTR_BUF_SIZE], dtoabuf[8], *p, *last, c;
+ gchar zero, numbuf[G_ASCII_DTOSTR_BUF_SIZE], dtoabuf[24], *p, *last, c;
const gchar *buf_start = fmt, *fmt_start = NULL;
gint d;
gdouble f;
@@ -948,23 +949,52 @@ rspamd_vprintf_common (rspamd_printf_append_func func,
case 'f':
case 'g':
f = (gdouble) va_arg (args, double);
- rspamd_strlcpy (dtoabuf, fmt_start, MIN (sizeof (dtoabuf),
- (fmt - fmt_start + 2)));
- g_ascii_formatd (numbuf, sizeof (numbuf), dtoabuf, (double)f);
- slen = strlen (numbuf);
- RSPAMD_PRINTF_APPEND (numbuf, slen);
+ slen = fpconv_dtoa (f, dtoabuf);
+
+ if (frac_width != 0) {
+ const gchar *dot_pos = memchr (dtoabuf, '.', slen);
+
+ if (dot_pos) {
+ if (frac_width < (slen - ((dot_pos - dtoabuf) + 1))) {
+ /* Truncate */
+ slen = (dot_pos - dtoabuf) + 1 + /* xxx. */
+ frac_width; /* .yyy */
+ }
+ else if (frac_width + dot_pos + 1 < dtoabuf + sizeof (dtoabuf)) {
+ /* Expand */
+ frac_width -= slen - ((dot_pos - dtoabuf) + 1);
+ memset (dtoabuf + slen, '0', frac_width);
+ slen += frac_width;
+ }
+ }
+ else {
+ /* Expand */
+ frac_width = MIN (frac_width, sizeof (dtoabuf) - slen - 1);
+ dtoabuf[slen ++] = '.';
+ memset (dtoabuf + slen, '0', frac_width);
+ slen += frac_width;
+ }
+ }
+
+ RSPAMD_PRINTF_APPEND (dtoabuf, slen);
continue;
case 'F':
case 'G':
f = (gdouble) va_arg (args, long double);
- slen = rspamd_strlcpy (dtoabuf, fmt_start, MIN (sizeof (dtoabuf),
- (fmt - fmt_start + 2)));
- dtoabuf[slen - 1] = g_ascii_tolower (dtoabuf[slen - 1]);
- g_ascii_formatd (numbuf, sizeof (numbuf), dtoabuf, (double)f);
- slen = strlen (numbuf);
- RSPAMD_PRINTF_APPEND (numbuf, slen);
+ slen = fpconv_dtoa (f, dtoabuf);
+
+ if (frac_width != 0) {
+ const gchar *dot_pos = memchr (dtoabuf, '.', slen);
+
+ if (dot_pos && frac_width < (slen - ((dot_pos - dtoabuf) + 1))) {
+ slen = (dot_pos - dtoabuf) + 1 + /* xxx. */
+ frac_width; /* .yyy */
+ }
+ }
+
+ RSPAMD_PRINTF_APPEND (dtoabuf, slen);
continue;