protected IonType load_number()

in src/com/amazon/ion/impl/IonReaderTextRawTokensX.java [1529:1637]


    protected IonType load_number(StringBuilder sb) throws IOException
    {
        boolean has_sign = false;
        int     t, c;

        // this reads int, float, decimal and timestamp strings
        // anything staring with a +, a - or a digit
        //case '0': case '1': case '2': case '3': case '4':
        //case '5': case '6': case '7': case '8': case '9':
        //case '-': case '+':

        //start_pos = _stream.getPosition();
        c = read_char();
        has_sign = ((c == '-') || (c == '+'));
        if (has_sign) {
            // if there is a sign character, we just consume it
            // here and get whatever is next in line
            sb.append((char)c);
            c = read_char();
        }

        // first leading digit - to look for hex and
        // to make sure that there is at least 1 digit (or
        // this isn't really a number
        if (!IonTokenConstsX.isDigit(c)) {
            // if it's not a digit, this isn't a number
            // the only non-digit it could have been was a
            // sign character, and we'll have read past that
            // by now
            // TODO this will be a confusing error message,
            // but I can't figure out when it will be reached.
            bad_token(c);
        }

        // the first digit is a special case
        boolean starts_with_zero = (c == '0');
        if (starts_with_zero) {
            // if it's a leading 0 check for a hex value
            int c2 = read_char();
            if (Radix.HEX.isPrefix(c2)) {
                sb.append((char)c);
                c = loadRadixValue(sb, has_sign, c2, Radix.HEX);
                return load_finish_number(sb, c, IonTokenConstsX.TOKEN_HEX);
            } else if (Radix.BINARY.isPrefix(c2)) {
                sb.append((char) c);
                c = loadRadixValue(sb, has_sign, c2, Radix.BINARY);
                return load_finish_number(sb, c, IonTokenConstsX.TOKEN_BINARY);
            }
            // not a next value, back up and try again
            unread_char(c2);
        }

        // remaining (after the first, c is the first) leading digits
        c = load_digits(sb, c);

        if (c == '-' || c == 'T') {
            // this better be a timestamp and it starts with a 4 digit
            // year followed by a dash and no leading sign
            if (has_sign) {
                error("Numeric value followed by invalid character: "
                      + sb + (char)c);
            }
            int len = sb.length();
            if (len != 4) {
                error("Numeric value followed by invalid character: "
                      + sb + (char)c);
            }
            IonType tt = load_timestamp(sb, c);
            return tt;
        }

        if (starts_with_zero) {
            // Ion doesn't allow leading zeros, so make sure our buffer only
            // has one character.
            int len = sb.length();
            if (has_sign) {
                len--; // we don't count the sign
            }
            if (len != 1) {
                error("Invalid leading zero in number: " + sb);
            }
        }

        if (c == '.') {
            // so if it's a float of some sort
            // mark it as at least a DECIMAL
            // and read the "fraction" digits
            sb.append((char)c);
            c = read_char();
            c = load_digits(sb, c);
            t = IonTokenConstsX.TOKEN_DECIMAL;
        }
        else {
            t = IonTokenConstsX.TOKEN_INT;
        }

        // see if we have an exponential as in 2d+3
        if (c == 'e' || c == 'E') {
            t = IonTokenConstsX.TOKEN_FLOAT;
            sb.append((char)c);
            c = load_exponent(sb);  // the unused lookahead char
        }
        else if (c == 'd' || c == 'D') {
            t = IonTokenConstsX.TOKEN_DECIMAL;
            sb.append((char)c);
            c = load_exponent(sb);
        }
        return load_finish_number(sb, c, t);
    }