private void decodeBigInteger(final BigIntegerStruct bis) {
final int start = _index;
final int signum = (_bytes[_index++] & 0xFF) - 0x40;
if (signum < -1 || signum > 1) {
throw new ConversionException("Invalid BigInteger signum at offset " + (start));
}
if (signum == 0) {
bis._bigInteger = BigInteger.ZERO;
bis._scale = 0;
return;
}
final boolean neg = signum < 0;
//
// Decode the exponent
//
int exp = decodeIntInternal();
if (neg)
exp = -exp;
//
// Reset the fields of the BigIntegerStruct
//
bis._bigInteger = null;
bis._scale = 0;
bis._zeroCount = 0;
boolean done = false;
int lastDigit = 0;
boolean leftOverDigit = false;
boolean lastDigitZero = false;
int zeroCount = 0;
while (!done) {
long lowBits = leftOverDigit ? lastDigit : 0;
//
// Number of digits that will be accumulated in lowBits before
// adding to the accumulator.
//
int chunk = 0;
if (exp > 0) {
chunk = exp % 16;
if (chunk == 0)
chunk = 16;
} else {
chunk = 16;
}
exp -= chunk;
if (leftOverDigit)
chunk--;
boolean dontAccumulate = false;
while (chunk > 0 && !done) {
int b = _bytes[_index++] & 0xFF;
if (b == 0) {
done = true;
_index--;
if (chunk >= 15 && exp == -16 && lowBits == 0) {
exp += 16;
dontAccumulate = true;
} else {
if (leftOverDigit)
lastDigitZero = (lastDigit == 0);
if (lastDigitZero)
zeroCount++;
for (; --chunk >= 0;) {
zeroCount++;
lowBits *= 10;
}
}
} else if (b != 0xFF) {
if (neg)
b = 0xAA - b;
else
b = b - 0x11;
if (((b >>> 4) & 0x0F) > 9 || (b & 0x0F) > 9) {
throw new ConversionException("Invalid BigInteger encoding at index " + (_index - 1));
}
if (chunk == 1) {
final int digit = (b >>> 4) & 0x0F;
lowBits = lowBits * 10 + digit;
lastDigit = b & 0x0F;