C_MODE_END inline int my_decimal_get_binary_size(uint precision, uint scale) { return decimal_bin_size((int)precision, (int)scale); }
int bin2dec(const char *from, decimal_t *to, int precision, int scale) { int error=E_DEC_OK, intg=precision-scale, intg0=intg/DIG_PER_DEC1, frac0=scale/DIG_PER_DEC1, intg0x=intg-intg0*DIG_PER_DEC1, frac0x=scale-frac0*DIG_PER_DEC1, intg1=intg0+(intg0x>0), frac1=frac0+(frac0x>0); dec1 *buf=to->buf, mask=(*from & 0x80) ? 0 : -1; const char *stop; char *d_copy; int bin_size= decimal_bin_size(precision, scale); //sanity(to); d_copy= (char*) my_alloca(bin_size); memcpy(d_copy, from, bin_size); d_copy[0]^= 0x80; from= d_copy; FIX_INTG_FRAC_ERROR(to->len, intg1, frac1, error); if (unlikely(error)) { if (intg1 < intg0+(intg0x>0)) { from+=dig2bytes[intg0x]+sizeof(dec1)*(intg0-intg1); frac0=frac0x=intg0x=0; intg0=intg1; } else { frac0x=0; frac0=frac1; } } to->sign=(mask != 0); to->intg=intg0*DIG_PER_DEC1+intg0x; to->frac=frac0*DIG_PER_DEC1+frac0x; if (intg0x) { int i=dig2bytes[intg0x]; dec1 UNINIT_VAR(x); switch (i) { case 1: x=mi_sint1korr(from); break; case 2: x=mi_sint2korr(from); break; case 3: x=mi_sint3korr(from); break; case 4: x=mi_sint4korr(from); break; default: DBUG_ASSERT(0); } from+=i; *buf=x ^ mask; if (((ulonglong)*buf) >= (ulonglong) powers10[intg0x+1]) goto err; if (buf > to->buf || *buf != 0) buf++; else to->intg-=intg0x; } for (stop=from+intg0*sizeof(dec1); from < stop; from+=sizeof(dec1)) { DBUG_ASSERT(sizeof(dec1) == 4); *buf=mi_sint4korr(from) ^ mask; if (((uint32)*buf) > DIG_MAX) goto err; if (buf > to->buf || *buf != 0) buf++; else to->intg-=DIG_PER_DEC1; } DBUG_ASSERT(to->intg >=0); for (stop=from+frac0*sizeof(dec1); from < stop; from+=sizeof(dec1)) { DBUG_ASSERT(sizeof(dec1) == 4); *buf=mi_sint4korr(from) ^ mask; if (((uint32)*buf) > DIG_MAX) goto err; buf++; } if (frac0x) { int i=dig2bytes[frac0x]; dec1 UNINIT_VAR(x); switch (i) { case 1: x=mi_sint1korr(from); break; case 2: x=mi_sint2korr(from); break; case 3: x=mi_sint3korr(from); break; case 4: x=mi_sint4korr(from); break; default: DBUG_ASSERT(0); } *buf=(x ^ mask) * powers10[DIG_PER_DEC1 - frac0x]; if (((uint32)*buf) > DIG_MAX) goto err; buf++; } my_afree(d_copy); if (to->intg == 0 && to->frac == 0) decimal_make_zero(to); return error; err: my_afree(d_copy); decimal_make_zero(to); return(E_DEC_BAD_NUM); }