func()

in lib/go/thrift/simple_json_protocol.go [1183:1305]


func (p *TSimpleJSONProtocol) readNumeric() (Numeric, error) {
	isNull, err := p.readIfNull()
	if isNull || err != nil {
		return NUMERIC_NULL, err
	}
	hasDecimalPoint := false
	nextCanBeSign := true
	hasE := false
	MAX_LEN := 40
	buf := bytes.NewBuffer(make([]byte, 0, MAX_LEN))
	continueFor := true
	inQuotes := false
	for continueFor {
		c, err := p.reader.ReadByte()
		if err != nil {
			if errors.Is(err, io.EOF) {
				break
			}
			return NUMERIC_NULL, NewTProtocolException(err)
		}
		switch c {
		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
			buf.WriteByte(c)
			nextCanBeSign = false
		case '.':
			if hasDecimalPoint {
				e := fmt.Errorf("Unable to parse number with multiple decimal points '%s.'", buf.String())
				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
			}
			if hasE {
				e := fmt.Errorf("Unable to parse number with decimal points in the exponent '%s.'", buf.String())
				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
			}
			buf.WriteByte(c)
			hasDecimalPoint, nextCanBeSign = true, false
		case 'e', 'E':
			if hasE {
				e := fmt.Errorf("Unable to parse number with multiple exponents '%s%c'", buf.String(), c)
				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
			}
			buf.WriteByte(c)
			hasE, nextCanBeSign = true, true
		case '-', '+':
			if !nextCanBeSign {
				e := fmt.Errorf("Negative sign within number")
				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
			}
			buf.WriteByte(c)
			nextCanBeSign = false
		case ' ', 0, '\t', '\n', '\r', JSON_RBRACE[0], JSON_RBRACKET[0], JSON_COMMA[0], JSON_COLON[0]:
			p.reader.UnreadByte()
			continueFor = false
		case JSON_NAN[0]:
			if buf.Len() == 0 {
				buffer := make([]byte, len(JSON_NAN))
				buffer[0] = c
				_, e := p.reader.Read(buffer[1:])
				if e != nil {
					return NUMERIC_NULL, NewTProtocolException(e)
				}
				if JSON_NAN != string(buffer) {
					e := mismatch(JSON_NAN, string(buffer))
					return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
				}
				if inQuotes {
					p.readQuoteIfNext()
				}
				return NAN, nil
			} else {
				e := fmt.Errorf("Unable to parse number starting with character '%c'", c)
				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
			}
		case JSON_INFINITY[0]:
			if buf.Len() == 0 || (buf.Len() == 1 && buf.Bytes()[0] == '+') {
				buffer := make([]byte, len(JSON_INFINITY))
				buffer[0] = c
				_, e := p.reader.Read(buffer[1:])
				if e != nil {
					return NUMERIC_NULL, NewTProtocolException(e)
				}
				if JSON_INFINITY != string(buffer) {
					e := mismatch(JSON_INFINITY, string(buffer))
					return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
				}
				if inQuotes {
					p.readQuoteIfNext()
				}
				return INFINITY, nil
			} else if buf.Len() == 1 && buf.Bytes()[0] == JSON_NEGATIVE_INFINITY[0] {
				buffer := make([]byte, len(JSON_NEGATIVE_INFINITY))
				buffer[0] = JSON_NEGATIVE_INFINITY[0]
				buffer[1] = c
				_, e := p.reader.Read(buffer[2:])
				if e != nil {
					return NUMERIC_NULL, NewTProtocolException(e)
				}
				if JSON_NEGATIVE_INFINITY != string(buffer) {
					e := mismatch(JSON_NEGATIVE_INFINITY, string(buffer))
					return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
				}
				if inQuotes {
					p.readQuoteIfNext()
				}
				return NEGATIVE_INFINITY, nil
			} else {
				e := fmt.Errorf("Unable to parse number starting with character '%c' due to existing buffer %s", c, buf.String())
				return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
			}
		case JSON_QUOTE:
			if !inQuotes {
				inQuotes = true
			}
		default:
			e := fmt.Errorf("Unable to parse number starting with character '%c'", c)
			return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
		}
	}
	if buf.Len() == 0 {
		e := fmt.Errorf("Unable to parse number from empty string ''")
		return NUMERIC_NULL, NewTProtocolExceptionWithType(INVALID_DATA, e)
	}
	return NewNumericFromJSONString(buf.String(), false), nil
}