private boolean readPrimitive()

in serde/src/java/org/apache/hadoop/hive/serde2/binarysortable/fast/BinarySortableDeserializeRead.java [238:495]


  private boolean readPrimitive(Field field) throws IOException {
    final int fieldIndex = root.index;
    field.start = inputByteBuffer.tell();

    /*
     * We have a field and are positioned to it.  Read it.
     */
    switch (field.primitiveCategory) {
    case BOOLEAN:
      currentBoolean = (inputByteBuffer.read(columnSortOrderIsDesc[fieldIndex]) == 2);
      return true;
    case BYTE:
      currentByte = (byte) (inputByteBuffer.read(columnSortOrderIsDesc[fieldIndex]) ^ 0x80);
      return true;
    case SHORT:
      {
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        int v = inputByteBuffer.read(invert) ^ 0x80;
        v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
        currentShort = (short) v;
      }
      return true;
    case INT:
      {
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        int v = inputByteBuffer.read(invert) ^ 0x80;
        for (int i = 0; i < 3; i++) {
          v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
        }
        currentInt = v;
      }
      return true;
    case LONG:
      {
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        long v = inputByteBuffer.read(invert) ^ 0x80;
        for (int i = 0; i < 7; i++) {
          v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
        }
        currentLong = v;
      }
      return true;
    case DATE:
      {
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        int v = inputByteBuffer.read(invert) ^ 0x80;
        for (int i = 0; i < 3; i++) {
          v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
        }
        currentDateWritable.set(v);
      }
      return true;
    case TIMESTAMP:
      {
        if (tempTimestampBytes == null) {
          tempTimestampBytes = new byte[TimestampWritableV2.BINARY_SORTABLE_LENGTH];
        }
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        for (int i = 0; i < tempTimestampBytes.length; i++) {
          tempTimestampBytes[i] = inputByteBuffer.read(invert);
        }
        currentTimestampWritable.setBinarySortable(tempTimestampBytes, 0);
      }
      return true;
    case FLOAT:
      {
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        int v = 0;
        for (int i = 0; i < 4; i++) {
          v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
        }
        if ((v & (1 << 31)) == 0) {
          // negative number, flip all bits
          v = ~v;
        } else {
          // positive number, flip the first bit
          v = v ^ (1 << 31);
        }
        currentFloat = Float.intBitsToFloat(v);
      }
      return true;
    case DOUBLE:
      {
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        long v = 0;
        for (int i = 0; i < 8; i++) {
          v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
        }
        if ((v & (1L << 63)) == 0) {
          // negative number, flip all bits
          v = ~v;
        } else {
          // positive number, flip the first bit
          v = v ^ (1L << 63);
        }
        currentDouble = Double.longBitsToDouble(v);
      }
      return true;
    case BINARY:
    case STRING:
    case CHAR:
    case VARCHAR:
      {
        /*
         * This code is a modified version of BinarySortableSerDe.deserializeText that lets us
         * detect if we can return a reference to the bytes directly.
         */

        // Get the actual length first
        bytesStart = inputByteBuffer.tell();
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        int length = 0;
        do {
          byte b = inputByteBuffer.read(invert);
          if (b == 0) {
            // end of string
            break;
          }
          if (b == 1) {
            // the last char is an escape char. read the actual char
            inputByteBuffer.read(invert);
          }
          length++;
        } while (true);

        if (length == 0 ||
            (!invert && length == inputByteBuffer.tell() - bytesStart - 1)) {
          // No inversion or escaping happened, so we are can reference directly.
          currentExternalBufferNeeded = false;
          currentBytes = inputByteBuffer.getData();
          currentBytesStart = bytesStart;
          currentBytesLength = length;
        } else {
          // We are now positioned at the end of this field's bytes.
          if (useExternalBuffer) {
            // If we decided not to reposition and re-read the buffer to copy it with
            // copyToExternalBuffer, we we will still be correctly positioned for the next field.
            currentExternalBufferNeeded = true;
            currentExternalBufferNeededLen = length;
          } else {
            // The copyToBuffer will reposition and re-read the input buffer.
            currentExternalBufferNeeded = false;
            if (internalBufferLen < length) {
              internalBufferLen = length;
              internalBuffer = new byte[internalBufferLen];
            }
            copyToBuffer(internalBuffer, 0, length);
            currentBytes = internalBuffer;
            currentBytesStart = 0;
            currentBytesLength = length;
          }
        }
      }
      return true;
    case INTERVAL_YEAR_MONTH:
      {
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        int v = inputByteBuffer.read(invert) ^ 0x80;
        for (int i = 0; i < 3; i++) {
          v = (v << 8) + (inputByteBuffer.read(invert) & 0xff);
        }
        currentHiveIntervalYearMonthWritable.set(v);
      }
      return true;
    case INTERVAL_DAY_TIME:
      {
        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        long totalSecs = inputByteBuffer.read(invert) ^ 0x80;
        for (int i = 0; i < 7; i++) {
          totalSecs = (totalSecs << 8) + (inputByteBuffer.read(invert) & 0xff);
        }
        int nanos = inputByteBuffer.read(invert) ^ 0x80;
        for (int i = 0; i < 3; i++) {
          nanos = (nanos << 8) + (inputByteBuffer.read(invert) & 0xff);
        }
        currentHiveIntervalDayTimeWritable.set(totalSecs, nanos);
      }
      return true;
    case DECIMAL:
      {
        // Since enforcing precision and scale can cause a HiveDecimal to become NULL,
        // we must read it, enforce it here, and either return NULL or buffer the result.

        final boolean invert = columnSortOrderIsDesc[fieldIndex];
        int b = inputByteBuffer.read(invert) - 1;
        if (!(b == 1 || b == -1 || b == 0)) {
          throw new IOException("Unexpected byte value " + (int)b + " in binary sortable format data (invert " + invert + ")");
        }
        final boolean positive = b != -1;

        int factor = inputByteBuffer.read(invert) ^ 0x80;
        for (int i = 0; i < 3; i++) {
          factor = (factor << 8) + (inputByteBuffer.read(invert) & 0xff);
        }

        if (!positive) {
          factor = -factor;
        }

        final int decimalStart = inputByteBuffer.tell();
        int length = 0;

        do {
          b = inputByteBuffer.read(positive ? invert : !invert);
          if (b == 1) {
            throw new IOException("Expected -1 and found byte value " + (int)b + " in binary sortable format data (invert " + invert + ")");
          }


          if (b == 0) {
            // end of digits
            break;
          }

          length++;
        } while (true);

        // CONSIDER: Allocate a larger initial size.
        if(tempDecimalBuffer == null || tempDecimalBuffer.length < length) {
          tempDecimalBuffer = new byte[length];
        }

        inputByteBuffer.seek(decimalStart);
        for (int i = 0; i < length; ++i) {
          tempDecimalBuffer[i] = inputByteBuffer.read(positive ? invert : !invert);
        }

        // read the null byte again
        inputByteBuffer.read(positive ? invert : !invert);

        // Set the value of the writable from the decimal digits that were written with no dot.
        final int scale = length - factor;
        currentHiveDecimalWritable.setFromDigitsOnlyBytesWithScale(
            !positive, tempDecimalBuffer, 0, length, scale);
        boolean decimalIsNull = !currentHiveDecimalWritable.isSet();
        if (!decimalIsNull) {

          // We have a decimal.  After we enforce precision and scale, will it become a NULL?

          final DecimalTypeInfo decimalTypeInfo = (DecimalTypeInfo) field.typeInfo;

          final int enforcePrecision = decimalTypeInfo.getPrecision();
          final int enforceScale = decimalTypeInfo.getScale();

          decimalIsNull =
              !currentHiveDecimalWritable.mutateEnforcePrecisionScale(
                  enforcePrecision, enforceScale);

        }
        if (decimalIsNull) {
          return false;
        }
      }
      return true;
    default:
      throw new RuntimeException("Unexpected primitive type category " + field.primitiveCategory);
    }
  }