in kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/common/FastHiveDecimalImpl.java [701:826]
public static boolean fastSetFromDigitsOnlyBytesAndScale(
boolean isNegative,
byte[] bytes,
int offset,
int length,
int scale,
FastHiveDecimal fastResult) {
final int bytesLength = bytes.length;
if (offset < 0 || offset >= bytesLength) {
return false;
}
final int end = offset + length;
if (end <= offset || end > bytesLength) {
return false;
}
// We start here with at least one byte.
int index = offset;
// A stripped down version of fastSetFromBytes.
int precision = 0;
// We fill starting with highest digit in highest longword (HIGHWORD_DECIMAL_DIGITS) and
// move down. At end will will shift everything down if necessary.
int longWordIndex = 0; // Where 0 is the highest longword; 1 is middle longword, etc.
int digitNum = HIGHWORD_DECIMAL_DIGITS;
long multiplier = powerOfTenTable[HIGHWORD_DECIMAL_DIGITS - 1];
int digitValue;
long longWord = 0;
long fast0 = 0;
long fast1 = 0;
long fast2 = 0;
byte work;
// Parse digits.
boolean haveInteger = false;
while (true) {
work = bytes[index];
if (work < BYTE_DIGIT_ZERO || work > BYTE_DIGIT_NINE) {
if (!haveInteger) {
return false;
}
break;
}
haveInteger = true;
if (precision == 0 && work == BYTE_DIGIT_ZERO) {
// Ignore leading zeroes.
if (++index >= end) {
break;
}
continue;
}
digitValue = work - BYTE_DIGIT_ZERO;
if (digitNum == 0) {
// Integer parsing move to next lower longword.
// Save previous longword.
if (longWordIndex == 0) {
fast2 = longWord;
} else if (longWordIndex == 1) {
fast1 = longWord;
} else if (longWordIndex == 2) {
// We have filled HiveDecimal.MAX_PRECISION digits and have no more room in our limit
// precision
// fast decimal.
return false;
}
longWordIndex++;
// The middle and lowest longwords highest digit number is LONGWORD_DECIMAL_DIGITS.
digitNum = LONGWORD_DECIMAL_DIGITS;
multiplier = powerOfTenTable[LONGWORD_DECIMAL_DIGITS - 1];
longWord = 0;
}
longWord += digitValue * multiplier;
multiplier /= 10;
digitNum--;
precision++;
if (++index >= end) {
break;
}
}
// Just an digits?
if (index < end) {
return false;
}
if (precision == 0) {
// We just had leading zeroes.
// Value is 0.
return true;
}
// Save last longword.
if (longWordIndex == 0) {
fast2 = longWord;
} else if (longWordIndex == 1) {
fast1 = longWord;
} else {
fast0 = longWord;
}
fastResult.fastSignum = (isNegative ? -1 : 1);
fastResult.fastIntegerDigitCount = Math.max(0, precision - scale);
fastResult.fastScale = scale;
final int scaleDown = HiveDecimal.MAX_PRECISION - precision;
if (scaleDown > 0) {
doFastScaleDown(fast0, fast1, fast2, scaleDown, fastResult);
} else {
fastResult.fast0 = fast0;
fastResult.fast1 = fast1;
fastResult.fast2 = fast2;
}
return true;
}