aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/fpconv
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2019-05-19 10:35:34 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2019-05-19 10:35:34 +0100
commit2dc49d136538276625a38d0944d221a1f0580d54 (patch)
tree4bb9a903ae4cdf86ff7c7244d58ae0f0ab97dafa /contrib/fpconv
parent31a1224de44218d8252f25aa42e2544b7ef74119 (diff)
downloadrspamd-2dc49d136538276625a38d0944d221a1f0580d54.tar.gz
rspamd-2dc49d136538276625a38d0944d221a1f0580d54.zip
[Fix] Fix some more corner cases for fpconv
Diffstat (limited to 'contrib/fpconv')
-rw-r--r--contrib/fpconv/fpconv.c46
1 files changed, 30 insertions, 16 deletions
diff --git a/contrib/fpconv/fpconv.c b/contrib/fpconv/fpconv.c
index 4ec2e3560..3b96af270 100644
--- a/contrib/fpconv/fpconv.c
+++ b/contrib/fpconv/fpconv.c
@@ -236,26 +236,24 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg,
return ndigits + 2 + offset;
}
else {
- /* Overflow */
- dest[2] = '0';
- return 3;
+ goto scientific_fallback;
}
/* fp > 1.0 */
} else {
- memcpy(dest, digits, offset);
-
/* Overflow check */
if (ndigits <= 23) {
+ memcpy(dest, digits, offset);
dest[offset] = '.';
memcpy(dest + offset + 1, digits + offset, ndigits - offset);
return ndigits + 1;
}
- return offset;
+ goto scientific_fallback;
}
}
+scientific_fallback:
/* write decimal w/ scientific notation */
ndigits = minv(ndigits, 18 - neg);
@@ -296,9 +294,18 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg,
static int filter_special(double fp, char* dest)
{
+ int nchars = 3;
+
if(fp == 0.0) {
- dest[0] = '0';
- return 1;
+ if(get_dbits(fp) & signmask) {
+ dest[0] = '-';
+ dest[1] = '0';
+ return 2;
+ }
+ else {
+ dest[0] = '0';
+ return 1;
+ }
}
uint64_t bits = get_dbits(fp);
@@ -311,12 +318,18 @@ static int filter_special(double fp, char* dest)
if(bits & fracmask) {
dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n';
-
} else {
- dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+ if(get_dbits(fp) & signmask) {
+ dest[0] = '-';
+ dest[1] = 'i'; dest[2] = 'n'; dest[3] = 'f';
+ nchars = 4;
+ }
+ else {
+ dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+ }
}
- return 3;
+ return nchars;
}
int fpconv_dtoa(double d, char dest[24], bool scientific)
@@ -326,11 +339,6 @@ int fpconv_dtoa(double d, char dest[24], bool scientific)
int str_len = 0;
bool neg = false;
- if(get_dbits(d) & signmask) {
- dest[0] = '-';
- str_len++;
- neg = true;
- }
int spec = filter_special(d, dest + str_len);
@@ -338,6 +346,12 @@ int fpconv_dtoa(double d, char dest[24], bool scientific)
return str_len + spec;
}
+ if(get_dbits(d) & signmask) {
+ dest[0] = '-';
+ str_len++;
+ neg = true;
+ }
+
int K = 0;
int ndigits = grisu2(d, digits, &K);