summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--strings/decimal.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/strings/decimal.c b/strings/decimal.c
index 821fc1414ad..c34f570eec3 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -579,18 +579,44 @@ int decimal2bin(decimal *from, char *to, int precision, int frac)
{
dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
int error=E_DEC_OK, intg=precision-frac,
+ isize1, intg1, intg1x=from->intg,
intg0=intg/DIG_PER_DEC1,
frac0=frac/DIG_PER_DEC1,
intg0x=intg-intg0*DIG_PER_DEC1,
frac0x=frac-frac0*DIG_PER_DEC1,
- intg1=from->intg/DIG_PER_DEC1,
frac1=from->frac/DIG_PER_DEC1,
- intg1x=from->intg-intg1*DIG_PER_DEC1,
frac1x=from->frac-frac1*DIG_PER_DEC1,
isize0=intg0*sizeof(dec1)+dig2bytes[intg0x],
fsize0=frac0*sizeof(dec1)+dig2bytes[frac0x],
- isize1=intg1*sizeof(dec1)+dig2bytes[intg1x],
fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
+
+ /* removing leading zeroes */
+ intg1=((intg1x-1) % DIG_PER_DEC1)+1;
+ while (intg1x > 0 && *buf1 == 0)
+ {
+ intg1x-=intg1;
+ intg1=DIG_PER_DEC1;
+ buf1++;
+ }
+ if (intg1x > 0)
+ {
+ for (intg1=(intg1x-1) % DIG_PER_DEC1; *buf1 < powers10[intg1--]; intg1x--) ;
+ DBUG_ASSERT(intg1x > 0);
+ }
+ else
+ intg1x=0;
+
+ if (unlikely(intg1x+fsize1==0))
+ {
+ mask=0; /* just in case */
+ intg=1;
+ buf1=&mask;
+ }
+
+ intg1=intg1x/DIG_PER_DEC1;
+ intg1x=intg1x-intg1*DIG_PER_DEC1;
+ isize1=intg1*sizeof(dec1)+dig2bytes[intg1x];
+
if (isize0 < isize1)
{
buf1+=intg1-intg0+(intg1x>0)-(intg0x>0);