public static boolean fastSerializationUtilsRead()

in kyuubi-hive-jdbc/src/main/java/org/apache/kyuubi/jdbc/hive/common/FastHiveDecimalImpl.java [1863:1984]


  public static boolean fastSerializationUtilsRead(
      InputStream inputStream, int scale, byte[] scratchBytes, FastHiveDecimal fastResult)
      throws IOException {

    // Following a suggestion from Gopal, quickly read in the bytes from the stream.
    // CONSIDER: Have ORC read the whole input stream into a big byte array with one call to
    // the read(byte[] b, int off, int len) method and then let this method read from the big
    // byte array.
    int readCount = 0;
    int input;
    do {
      input = inputStream.read();
      if (input == -1) {
        throw new EOFException("Reading BigInteger past EOF from " + inputStream);
      }
      scratchBytes[readCount++] = (byte) input;
    } while (input >= 0x80);

    /*
     * Determine the 3 binary words like what SerializationUtils.readBigInteger does.
     */

    long lowerWord63 = 0;
    long middleWord63 = 0;
    long highWord63 = 0;

    long work = 0;
    int offset = 0;
    int readIndex = 0;
    long b;
    do {
      b = scratchBytes[readIndex++];
      work |= (0x7f & b) << (offset % 63);
      offset += 7;
      // if we've read 63 bits, roll them into the result
      if (offset == 63) {
        lowerWord63 = work;
        work = 0;
      } else if (offset % 63 == 0) {
        if (offset == 126) {
          middleWord63 = work;
        } else if (offset == 189) {
          highWord63 = work;
        } else {
          throw new EOFException("Reading more than 3 words of BigInteger");
        }
        work = 0;
      }
    } while (readIndex < readCount);

    if (work != 0) {
      if (offset < 63) {
        lowerWord63 = work;
      } else if (offset < 126) {
        middleWord63 = work;
      } else if (offset < 189) {
        highWord63 = work;
      } else {
        throw new EOFException("Reading more than 3 words of BigInteger");
      }
    }

    // Grab sign bit and shift it away.
    boolean isNegative = ((lowerWord63 & 0x1) != 0);
    lowerWord63 >>= 1;

    /*
     * Use common binary to decimal conversion method we share with fastSetFromBigIntegerBytes.
     */
    if (!doBinaryToDecimalConversion(
        lowerWord63,
        middleWord63,
        highWord63,
        FAST_HIVE_DECIMAL_TWO_POWER_62,
        FAST_HIVE_DECIMAL_TWO_POWER_125, // 2^(62 + 63)
        fastResult)) {
      return false;
    }

    if (isNegative) {

      // Adjust negative result, again doing what SerializationUtils.readBigInteger does.
      if (!doAddSameScaleSameSign(
          /* resultSignum */ 1,
          fastResult.fast0,
          fastResult.fast1,
          fastResult.fast2,
          1,
          0,
          0,
          fastResult)) {
        return false;
      }
    }

    if (fastResult.fast0 == 0 && fastResult.fast1 == 0 && fastResult.fast2 == 0) {
      fastResult.fastSignum = 0;
    } else {
      fastResult.fastSignum = (isNegative ? -1 : 1);
      final int rawPrecision = fastRawPrecision(fastResult);
      fastResult.fastIntegerDigitCount = Math.max(0, rawPrecision - scale);
      fastResult.fastScale = scale;

      /*
       * Just in case we deserialize a decimal with trailing zeroes...
       */
      final int resultTrailingZeroCount =
          fastTrailingDecimalZeroCount(
              fastResult.fast0,
              fastResult.fast1,
              fastResult.fast2,
              fastResult.fastIntegerDigitCount,
              fastResult.fastScale);
      if (resultTrailingZeroCount > 0) {
        doFastScaleDown(fastResult, resultTrailingZeroCount, fastResult);

        fastResult.fastScale -= resultTrailingZeroCount;
      }
    }

    return true;
  }