public Decimal128 update(char[] str, int offset, int length, short scale) {
    final int end = offset + length;
    assert (end <= str.length);
    int cursor = offset;

    // sign mark
    boolean negative = false;
    if (str[cursor] == '+') {
      ++cursor;
    } else if (str[cursor] == '-') {
      negative = true;
      ++cursor;
    }

    // Skip leading zeros and compute number of digits in magnitude
    while (cursor < end && str[cursor] == '0') {
      ++cursor;
    }

    this.scale = scale;
    zeroClear();
    if (cursor == end) {
      return this;
    }

    // "1234567" => unscaledValue=1234567, negative=false,
    // fractionalDigits=0
    // "-1234567.89" => unscaledValue=123456789, negative=true,
    // fractionalDigits=2
    // "12.3E7" => unscaledValue=123, negative=false, fractionalDigits=1,
    // exponent=7
    // ".123E-7" => unscaledValue=123, negative=false, fractionalDigits=3,
    // exponent=-7
    int accumulated = 0;
    int accumulatedCount = 0;
    boolean fractional = false; // after "."?
    int fractionalDigits = 0;
    int exponent = 0;
    while (cursor < end) {
      if (str[cursor] == '.') {
        if (fractional) {

          // two dots??
          throw new NumberFormatException("Invalid string:"
              + new String(str, offset, length));
        }
        fractional = true;
      } else if (str[cursor] >= '0' && str[cursor] <= '9') {
        if (accumulatedCount == 9) {
          this.unscaledValue.scaleUpTenDestructive((short) accumulatedCount);
          this.unscaledValue.addDestructive(accumulated);
          accumulated = 0;
          accumulatedCount = 0;
        }
        int digit = str[cursor] - '0';
        accumulated = accumulated * 10 + digit;
        ++accumulatedCount;
        if (fractional) {
          ++fractionalDigits;
        }
      } else if (str[cursor] == 'e' || str[cursor] == 'E') {
        // exponent part
        ++cursor;
        boolean exponentNegative = false;
        if (str[cursor] == '+') {
          ++cursor;
        } else if (str[cursor] == '-') {
          exponentNegative = true;
          ++cursor;
        }
        while (cursor < end) {
          if (str[cursor] >= '0' && str[cursor] <= '9') {
            int exponentDigit = str[cursor] - '0';
            exponent *= 10;
            exponent += exponentDigit;
          }
          ++cursor;
        }
        if (exponentNegative) {
          exponent = -exponent;
        }
      } else {
        throw new NumberFormatException("Invalid string:"
            + new String(str, offset, length));
      }

      ++cursor;
    }

    if (accumulatedCount > 0) {
      this.unscaledValue.scaleUpTenDestructive((short) accumulatedCount);
      this.unscaledValue.addDestructive(accumulated);
    }

    int scaleAdjust = scale - fractionalDigits + exponent;
    if (scaleAdjust > 0) {
      this.unscaledValue.scaleUpTenDestructive((short) scaleAdjust);
    } else if (scaleAdjust < 0) {
      this.unscaledValue.scaleDownTenDestructive((short) -scaleAdjust);
    }
    this.signum = (byte) (this.unscaledValue.isZero() ? 0 : (negative ? -1 : 1));
    return this;
  }
Updates the value of this object from the given string with given offset
and length.

@param str
         string
@param offset
         offset
@param length
         length
@param scale
         scale of the {@code Decimal128}.
common/src/java/org/apache/hadoop/hive/common/type/Decimal128.java