Example #1
0
  @Override
  public boolean evaluate(Tuple tuple, ImmutableBytesWritable ptr) {
    // TODO: multi-byte characters
    Expression offsetExpression = getOffsetExpression();
    if (!offsetExpression.evaluate(tuple, ptr)) {
      return false;
    }
    LongNative longNative = (LongNative) offsetExpression.getDataType().getNative();
    int offset = (int) longNative.toLong(ptr);

    int length = -1;
    if (hasLengthExpression) {
      Expression lengthExpression = getLengthExpression();
      if (!lengthExpression.evaluate(tuple, ptr)) {
        return false;
      }
      longNative = (LongNative) lengthExpression.getDataType().getNative();
      length = (int) longNative.toLong(ptr);
      if (length <= 0) {
        return false;
      }
    }

    if (!getStrExpression().evaluate(tuple, ptr)) {
      return false;
    }

    try {
      boolean isCharType = getStrExpression().getDataType() == PDataType.CHAR;
      int strlen =
          isCharType
              ? ptr.getLength()
              : StringUtil.calculateUTF8Length(ptr.get(), ptr.getOffset(), ptr.getLength());

      // Account for 1 versus 0-based offset
      offset = offset - (offset <= 0 ? 0 : 1);
      if (offset < 0) { // Offset < 0 means get from end
        offset = strlen + offset;
      }
      if (offset < 0 || offset >= strlen) {
        return false;
      }
      int maxLength = strlen - offset;
      length = length == -1 ? maxLength : Math.min(length, maxLength);

      int byteOffset =
          isCharType
              ? offset
              : StringUtil.getByteLengthForUtf8SubStr(ptr.get(), ptr.getOffset(), offset);
      int byteLength =
          isCharType
              ? length
              : StringUtil.getByteLengthForUtf8SubStr(
                  ptr.get(), ptr.getOffset() + byteOffset, length);
      ptr.set(ptr.get(), ptr.getOffset() + byteOffset, byteLength);
      return true;
    } catch (UnsupportedEncodingException e) {
      return false;
    }
  }