in dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/LogBuffer.java [1404:1555]
private final BigDecimal getDecimal0(final int begin, final int intg, final int frac, final int intg0,
final int frac0, final int intg0x, final int frac0x) {
final int mask = ((buffer[begin] & 0x80) == 0x80) ? 0 : -1;
int from = begin;
/* max string length */
final int len = ((mask != 0) ? 1 : 0) + ((intg != 0) ? intg : 1) // NL
+ ((frac != 0) ? 1 : 0) + frac;
char[] buf = new char[len];
int pos = 0;
if (mask != 0) /* decimal sign */
buf[pos++] = ('-');
final byte[] d_copy = buffer;
d_copy[begin] ^= 0x80; /* clear sign */
int mark = pos;
if (intg0x != 0) {
final int i = dig2bytes[intg0x];
int x = 0;
switch (i) {
case 1:
x = d_copy[from] /* one byte */;
break;
case 2:
x = getInt16BE(d_copy, from);
break;
case 3:
x = getInt24BE(d_copy, from);
break;
case 4:
x = getInt32BE(d_copy, from);
break;
}
from += i;
x ^= mask;
if (x < 0 || x >= powers10[intg0x + 1]) {
throw new IllegalArgumentException("bad format, x exceed: " + x + ", " + powers10[intg0x + 1]);
}
if (x != 0 /* !digit || x != 0 */) {
for (int j = intg0x; j > 0; j--) {
final int divisor = powers10[j - 1];
final int y = x / divisor;
if (mark < pos || y != 0) {
buf[pos++] = ((char) ('0' + y));
}
x -= y * divisor;
}
}
}
for (final int stop = from + intg0 * SIZE_OF_INT32; from < stop; from += SIZE_OF_INT32) {
int x = getInt32BE(d_copy, from);
x ^= mask;
if (x < 0 || x > DIG_MAX) {
throw new IllegalArgumentException("bad format, x exceed: " + x + ", " + DIG_MAX);
}
if (x != 0) {
if (mark < pos) {
for (int i = DIG_PER_DEC1; i > 0; i--) {
final int divisor = powers10[i - 1];
final int y = x / divisor;
buf[pos++] = ((char) ('0' + y));
x -= y * divisor;
}
} else {
for (int i = DIG_PER_DEC1; i > 0; i--) {
final int divisor = powers10[i - 1];
final int y = x / divisor;
if (mark < pos || y != 0) {
buf[pos++] = ((char) ('0' + y));
}
x -= y * divisor;
}
}
} else if (mark < pos) {
for (int i = DIG_PER_DEC1; i > 0; i--)
buf[pos++] = ('0');
}
}
if (mark == pos)
/* fix 0.0 problem, only '.' may cause BigDecimal parsing exception. */
buf[pos++] = ('0');
if (frac > 0) {
buf[pos++] = ('.');
mark = pos;
for (final int stop = from + frac0 * SIZE_OF_INT32; from < stop; from += SIZE_OF_INT32) {
int x = getInt32BE(d_copy, from);
x ^= mask;
if (x < 0 || x > DIG_MAX) {
throw new IllegalArgumentException("bad format, x exceed: " + x + ", " + DIG_MAX);
}
if (x != 0) {
for (int i = DIG_PER_DEC1; i > 0; i--) {
final int divisor = powers10[i - 1];
final int y = x / divisor;
buf[pos++] = ((char) ('0' + y));
x -= y * divisor;
}
} else {
for (int i = DIG_PER_DEC1; i > 0; i--)
buf[pos++] = ('0');
}
}
if (frac0x != 0) {
final int i = dig2bytes[frac0x];
int x = 0;
switch (i) {
case 1:
x = d_copy[from] /* one byte */;
break;
case 2:
x = getInt16BE(d_copy, from);
break;
case 3:
x = getInt24BE(d_copy, from);
break;
case 4:
x = getInt32BE(d_copy, from);
break;
}
x ^= mask;
if (x != 0) {
final int dig = DIG_PER_DEC1 - frac0x;
x *= powers10[dig];
if (x < 0 || x > DIG_MAX) {
throw new IllegalArgumentException("bad format, x exceed: " + x + ", " + DIG_MAX);
}
for (int j = DIG_PER_DEC1; j > dig; j--) {
final int divisor = powers10[j - 1];
final int y = x / divisor;
buf[pos++] = ((char) ('0' + y));
x -= y * divisor;
}
}
}
if (mark == pos)
/* make number more friendly */
buf[pos++] = ('0');
}
d_copy[begin] ^= 0x80; /* restore sign */
// String decimal = String.valueOf(buf, 0, pos);
// return new BigDecimal(decimal);
return new BigDecimal(buf, 0, pos);
}