in kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/common/FastHiveDecimalImpl.java [262:681]
public static boolean fastSetFromBytes(
byte[] bytes, int offset, int length, boolean trimBlanks, 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;
if (trimBlanks) {
while (bytes[index] == BYTE_BLANK) {
if (++index >= end) {
return false;
}
}
}
// Started with a few ideas from BigDecimal(char[] in, int offset, int len) constructor...
// But soon became very fast decimal specific.
boolean isNegative = false;
if (bytes[index] == BYTE_MINUS) {
isNegative = true;
if (++index >= end) {
return false;
}
} else if (bytes[index] == BYTE_PLUS) {
if (++index >= end) {
return false;
}
}
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 = 0;
long longWord = 0;
long fast0 = 0;
long fast1 = 0;
long fast2 = 0;
byte work;
// Parse integer portion.
boolean haveInteger = false;
while (true) {
work = bytes[index];
if (work < BYTE_DIGIT_ZERO || work > BYTE_DIGIT_NINE) {
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;
}
}
// At this point we may have parsed an integer.
// Try to eat a dot now since it could be the end. We remember if we saw a dot so we can
// do error checking later and detect just a dot.
boolean sawDot = false;
if (index < end && bytes[index] == BYTE_DOT) {
sawDot = true;
index++;
}
// Try to eat trailing blank padding.
if (trimBlanks && index < end && bytes[index] == BYTE_BLANK) {
index++;
while (index < end && bytes[index] == BYTE_BLANK) {
index++;
}
if (index < end) {
// Junk after trailing blank padding.
return false;
}
// Otherwise, fall through and process the what we saw before possible trailing blanks.
}
// Any more input?
if (index >= end) {
// We hit the end after getting optional integer and optional dot and optional blank padding.
if (!haveInteger) {
return false;
}
if (precision == 0) {
// We just had leading zeroes (and possibly a dot and trailing blanks).
// 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 = precision;
fastResult.fastScale = 0;
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;
}
// We have more input but did we start with something valid?
if (!haveInteger && !sawDot) {
// Must have one of those at this point.
return false;
}
int integerDigitCount = precision;
int nonTrailingZeroScale = 0;
boolean roundingNecessary = false;
if (sawDot) {
// Parse fraction portion.
while (true) {
work = bytes[index];
if (work < BYTE_DIGIT_ZERO || work > BYTE_DIGIT_NINE) {
if (!haveInteger) {
// Naked dot.
return false;
}
break;
}
digitValue = work - BYTE_DIGIT_ZERO;
if (digitNum == 0) {
// Fraction digit 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. However, since we are processing fractional digits, we do rounding.
// away.
if (digitValue >= 5) {
roundingNecessary = true;
}
// Scan through any remaining digits...
while (++index < end) {
work = bytes[index];
if (work < BYTE_DIGIT_ZERO || work > BYTE_DIGIT_NINE) {
break;
}
}
break;
}
longWordIndex++;
digitNum = LONGWORD_DECIMAL_DIGITS;
multiplier = powerOfTenTable[digitNum - 1];
longWord = 0;
}
longWord += digitValue * multiplier;
multiplier /= 10;
digitNum--;
precision++;
if (digitValue != 0) {
nonTrailingZeroScale = precision - integerDigitCount;
}
if (++index >= end) {
break;
}
}
}
boolean haveExponent = false;
if (index < end
&& (bytes[index] == BYTE_EXPONENT_UPPER || bytes[index] == BYTE_EXPONENT_LOWER)) {
haveExponent = true;
index++;
if (index >= end) {
// More required.
return false;
}
}
// At this point we have a number. Save it in fastResult. Round it. If we have an exponent,
// we will do a power 10 operation on fastResult.
// Save last longword.
if (longWordIndex == 0) {
fast2 = longWord;
} else if (longWordIndex == 1) {
fast1 = longWord;
} else {
fast0 = longWord;
}
int trailingZeroesScale = precision - integerDigitCount;
if (integerDigitCount == 0 && nonTrailingZeroScale == 0) {
// Zero(es).
} else {
fastResult.fastSignum = (isNegative ? -1 : 1);
fastResult.fastIntegerDigitCount = integerDigitCount;
fastResult.fastScale = nonTrailingZeroScale;
final int trailingZeroCount = trailingZeroesScale - fastResult.fastScale;
final int scaleDown = HiveDecimal.MAX_PRECISION - precision + trailingZeroCount;
if (scaleDown > 0) {
doFastScaleDown(fast0, fast1, fast2, scaleDown, fastResult);
} else {
fastResult.fast0 = fast0;
fastResult.fast1 = fast1;
fastResult.fast2 = fast2;
}
}
if (roundingNecessary) {
if (fastResult.fastSignum == 0) {
fastResult.fastSignum = (isNegative ? -1 : 1);
fastResult.fast0 = 1;
fastResult.fastIntegerDigitCount = 0;
fastResult.fastScale = HiveDecimal.MAX_SCALE;
} else {
if (!fastAdd(
fastResult.fastSignum,
fastResult.fast0,
fastResult.fast1,
fastResult.fast2,
fastResult.fastIntegerDigitCount,
fastResult.fastScale,
fastResult.fastSignum,
1,
0,
0,
0,
trailingZeroesScale,
fastResult)) {
return false;
}
}
}
if (!haveExponent) {
// Try to eat trailing blank padding.
if (trimBlanks && index < end && bytes[index] == BYTE_BLANK) {
index++;
while (index < end && bytes[index] == BYTE_BLANK) {
index++;
}
}
if (index < end) {
// Junk after trailing blank padding.
return false;
}
return true;
}
// At this point, we have seen the exponent letter E or e and have decimal information as:
// isNegative, precision, integerDigitCount, nonTrailingZeroScale, and
// fast0, fast1, fast2.
//
// After we determine the exponent, we will do appropriate scaling and fill in fastResult.
boolean isExponentNegative = false;
if (bytes[index] == BYTE_MINUS) {
isExponentNegative = true;
if (++index >= end) {
return false;
}
} else if (bytes[index] == BYTE_PLUS) {
if (++index >= end) {
return false;
}
}
long exponent = 0;
multiplier = 1;
while (true) {
work = bytes[index];
if (work < BYTE_DIGIT_ZERO || work > BYTE_DIGIT_NINE) {
break;
}
if (multiplier > 10) {
// Power of ten way beyond our precision/scale...
return false;
}
digitValue = work - BYTE_DIGIT_ZERO;
if (digitValue != 0 || exponent != 0) {
exponent = exponent * 10 + digitValue;
multiplier *= 10;
}
if (++index >= end) {
break;
}
}
if (isExponentNegative) {
exponent = -exponent;
}
// Try to eat trailing blank padding.
if (trimBlanks && index < end && bytes[index] == BYTE_BLANK) {
index++;
while (index < end && bytes[index] == BYTE_BLANK) {
index++;
}
}
if (index < end) {
// Junk after exponent.
return false;
}
if (integerDigitCount == 0 && nonTrailingZeroScale == 0) {
// Zero(es).
return true;
}
if (exponent == 0) {
// No effect since 10^0 = 1.
} else {
// We for these input with exponents, we have at this point an intermediate decimal,
// an exponent power, and a result:
//
// intermediate
// input decimal exponent result
// 701E+1 701 scale 0 +1 7010 scale 0
// 3E+4 3 scale 0 +4 3 scale 0
// 3.223E+9 3.223 scale 3 +9 3223000000 scale 0
// 0.009E+10 0.009 scale 4 +10 90000000 scale 0
// 0.3221E-2 0.3221 scale 4 -2 0.003221 scale 6
// 0.00223E-20 0.00223 scale 5 -20 0.0000000000000000000000223 scale 25
//
if (!fastScaleByPowerOfTen(fastResult, (int) exponent, fastResult)) {
return false;
}
}
final int trailingZeroCount =
fastTrailingDecimalZeroCount(
fastResult.fast0,
fastResult.fast1,
fastResult.fast2,
fastResult.fastIntegerDigitCount,
fastResult.fastScale);
if (trailingZeroCount > 0) {
doFastScaleDown(fastResult, trailingZeroCount, fastResult);
fastResult.fastScale -= trailingZeroCount;
}
return true;
}