/** * Method that will parse actual numeric value out of a syntactically valid number value. Type it * will parse into depends on whether it is a floating point number, as well as its magnitude: * smallest legal type (of ones available) is used for efficiency. * * @param expType Numeric type that we will immediately need, if any; mostly necessary to optimize * handling of floating point numbers */ protected void _parseNumericValue(int expType) throws IOException, JsonParseException { // Int or float? if (_currToken == JsonToken.VALUE_NUMBER_INT) { char[] buf = _textBuffer.getTextBuffer(); int offset = _textBuffer.getTextOffset(); int len = _intLength; if (_numberNegative) { ++offset; } if (len <= 9) { // definitely fits in int int i = NumberInput.parseInt(buf, offset, len); _numberInt = _numberNegative ? -i : i; _numTypesValid = NR_INT; return; } if (len <= 18) { // definitely fits AND is easy to parse using 2 int parse calls long l = NumberInput.parseLong(buf, offset, len); if (_numberNegative) { l = -l; } // [JACKSON-230] Could still fit in int, need to check if (len == 10) { if (_numberNegative) { if (l >= MIN_INT_L) { _numberInt = (int) l; _numTypesValid = NR_INT; return; } } else { if (l <= MAX_INT_L) { _numberInt = (int) l; _numTypesValid = NR_INT; return; } } } _numberLong = l; _numTypesValid = NR_LONG; return; } _parseSlowIntValue(expType, buf, offset, len); return; } if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) { _parseSlowFloatValue(expType); return; } _reportError( "Current token (" + _currToken + ") not numeric, can not use numeric value accessors"); }
/** * Method called to release internal buffers owned by the base reader. This may be called along * with {@link #_closeInput} (for example, when explicitly closing this reader instance), or * separately (if need be). */ protected void _releaseBuffers() throws IOException { _textBuffer.releaseBuffers(); char[] buf = _nameCopyBuffer; if (buf != null) { _nameCopyBuffer = null; _ioContext.releaseNameCopyBuffer(buf); } }
private final void _parseSlowFloatValue(int expType) throws IOException, JsonParseException { /* Nope: floating point. Here we need to be careful to get * optimal parsing strategy: choice is between accurate but * slow (BigDecimal) and lossy but fast (Double). For now * let's only use BD when explicitly requested -- it can * still be constructed correctly at any point since we do * retain textual representation */ try { if (expType == NR_BIGDECIMAL) { _numberBigDecimal = _textBuffer.contentsAsDecimal(); _numTypesValid = NR_BIGDECIMAL; } else { // Otherwise double has to do _numberDouble = _textBuffer.contentsAsDouble(); _numTypesValid = NR_DOUBLE; } } catch (NumberFormatException nex) { // Can this ever occur? Due to overflow, maybe? _wrapError("Malformed numeric value '" + _textBuffer.contentsAsString() + "'", nex); } }
private final void _parseSlowIntValue(int expType, char[] buf, int offset, int len) throws IOException, JsonParseException { String numStr = _textBuffer.contentsAsString(); try { // [JACKSON-230] Some long cases still... if (NumberInput.inLongRange(buf, offset, len, _numberNegative)) { // Probably faster to construct a String, call parse, than to use BigInteger _numberLong = Long.parseLong(numStr); _numTypesValid = NR_LONG; } else { // nope, need the heavy guns... (rare case) _numberBigInt = new BigInteger(numStr); _numTypesValid = NR_BIGINT; } } catch (NumberFormatException nex) { // Can this ever occur? Due to overflow, maybe? _wrapError("Malformed numeric value '" + numStr + "'", nex); } }
protected final JsonToken resetAsNaN(String valueStr, double value) { _textBuffer.resetWithString(valueStr); _numberDouble = value; _numTypesValid = NR_DOUBLE; return JsonToken.VALUE_NUMBER_FLOAT; }