Categories:
Audio (13)
Biotech (29)
Bytecode (36)
Database (77)
Framework (7)
Game (7)
General (507)
Graphics (53)
I/O (35)
IDE (2)
JAR Tools (101)
JavaBeans (21)
JDBC (121)
JDK (426)
JSP (20)
Logging (108)
Mail (58)
Messaging (8)
Network (84)
PDF (97)
Report (7)
Scripting (84)
Security (32)
Server (121)
Servlet (26)
SOAP (24)
Testing (54)
Web (15)
XML (309)
Collections:
Other Resources:
Jackson Core Source Code
Jackson is "the Java JSON library" or "the best JSON parser for Java". Or simply as "JSON for Java".
Jackson Core Source Code files are provided in the source packge (jackson-core-2.14.0-sources.jar). You can download it at Jackson Maven Website.
You can also browse Jackson Core Source Code below:
✍: FYIcenter.com
⏎ com/fasterxml/jackson/core/base/ParserBase.java
package com.fasterxml.jackson.core.base; import java.io.*; import java.math.BigDecimal; import java.math.BigInteger; import java.util.Arrays; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.io.ContentReference; import com.fasterxml.jackson.core.io.NumberInput; import com.fasterxml.jackson.core.json.DupDetector; import com.fasterxml.jackson.core.json.JsonReadContext; import com.fasterxml.jackson.core.json.PackageVersion; import com.fasterxml.jackson.core.util.ByteArrayBuilder; import com.fasterxml.jackson.core.util.JacksonFeatureSet; import com.fasterxml.jackson.core.util.TextBuffer; /** * Intermediate base class used by all Jackson {@link JsonParser} * implementations. Contains most common things that are independent * of actual underlying input source. */ public abstract class ParserBase extends ParserMinimalBase { // JSON capabilities are the same as defaults // @since 2.12 protected final static JacksonFeatureSet<StreamReadCapability> JSON_READ_CAPABILITIES = DEFAULT_READ_CAPABILITIES; /* /********************************************************** /* Generic I/O state /********************************************************** */ /** * I/O context for this reader. It handles buffer allocation * for the reader. */ final protected IOContext _ioContext; /** * Flag that indicates whether parser is closed or not. Gets * set when parser is either closed by explicit call * ({@link #close}) or when end-of-input is reached. */ protected boolean _closed; /* /********************************************************** /* Current input data /********************************************************** */ // Note: type of actual buffer depends on sub-class, can't include /** * Pointer to next available character in buffer */ protected int _inputPtr; /** * Index of character after last available one in the buffer. */ protected int _inputEnd; /* /********************************************************** /* Current input location information /********************************************************** */ /** * Number of characters/bytes that were contained in previous blocks * (blocks that were already processed prior to the current buffer). */ protected long _currInputProcessed; /** * Current row location of current point in input buffer, starting * from 1, if available. */ protected int _currInputRow = 1; /** * Current index of the first character of the current row in input * buffer. Needed to calculate column position, if necessary; benefit * of not having column itself is that this only has to be updated * once per line. */ protected int _currInputRowStart; /* /********************************************************** /* Information about starting location of event /* Reader is pointing to; updated on-demand /********************************************************** */ // // // Location info at point when current token was started /** * Total number of bytes/characters read before start of current token. * For big (gigabyte-sized) sizes are possible, needs to be long, * unlike pointers and sizes related to in-memory buffers. */ protected long _tokenInputTotal; /** * Input row on which current token starts, 1-based */ protected int _tokenInputRow = 1; /** * Column on input row that current token starts; 0-based (although * in the end it'll be converted to 1-based) */ protected int _tokenInputCol; /* /********************************************************** /* Parsing state /********************************************************** */ /** * Information about parser context, context in which * the next token is to be parsed (root, array, object). */ protected JsonReadContext _parsingContext; /** * Secondary token related to the next token after current one; * used if its type is known. This may be value token that * follows FIELD_NAME, for example. */ protected JsonToken _nextToken; /* /********************************************************** /* Buffer(s) for local name(s) and text content /********************************************************** */ /** * Buffer that contains contents of String values, including * field names if necessary (name split across boundary, * contains escape sequence, or access needed to char array) */ protected final TextBuffer _textBuffer; /** * Temporary buffer that is needed if field name is accessed * using {@link #getTextCharacters} method (instead of String * returning alternatives) */ protected char[] _nameCopyBuffer; /** * Flag set to indicate whether the field name is available * from the name copy buffer or not (in addition to its String * representation being available via read context) */ protected boolean _nameCopied; /** * ByteArrayBuilder is needed if 'getBinaryValue' is called. If so, * we better reuse it for remainder of content. */ protected ByteArrayBuilder _byteArrayBuilder; /** * We will hold on to decoded binary data, for duration of * current event, so that multiple calls to * {@link #getBinaryValue} will not need to decode data more * than once. */ protected byte[] _binaryValue; // Numeric value holders: multiple fields used for // for efficiency /** * Bitfield that indicates which numeric representations * have been calculated for the current type */ protected int _numTypesValid = NR_UNKNOWN; // First primitives protected int _numberInt; protected long _numberLong; protected float _numberFloat; protected double _numberDouble; // And then object types protected BigInteger _numberBigInt; protected BigDecimal _numberBigDecimal; /** * Textual number representation captured from input in cases lazy-parsing * is desired. *<p> * As of 2.14, this only applies to {@link BigInteger} and {@link BigDecimal}. * * @since 2.14 */ protected String _numberString; // And then other information about value itself /** * Flag that indicates whether numeric value has a negative * value. That is, whether its textual representation starts * with minus character. */ protected boolean _numberNegative; /** * Length of integer part of the number, in characters */ protected int _intLength; /** * Length of the fractional part (not including decimal * point or exponent), in characters. * Not used for pure integer values. */ protected int _fractLength; /** * Length of the exponent part of the number, if any, not * including 'e' marker or sign, just digits. * Not used for pure integer values. */ protected int _expLength; /* /********************************************************** /* Life-cycle /********************************************************** */ protected ParserBase(IOContext ctxt, int features) { super(features); _ioContext = ctxt; _textBuffer = ctxt.constructTextBuffer(); DupDetector dups = Feature.STRICT_DUPLICATE_DETECTION.enabledIn(features) ? DupDetector.rootDetector(this) : null; _parsingContext = JsonReadContext.createRootContext(dups); } @Override public Version version() { return PackageVersion.VERSION; } @Override public Object getCurrentValue() { return _parsingContext.getCurrentValue(); } @Override public void setCurrentValue(Object v) { _parsingContext.setCurrentValue(v); } /* /********************************************************** /* Overrides for Feature handling /********************************************************** */ @Override public JsonParser enable(Feature f) { _features |= f.getMask(); if (f == Feature.STRICT_DUPLICATE_DETECTION) { // enabling dup detection? if (_parsingContext.getDupDetector() == null) { // but only if disabled currently _parsingContext = _parsingContext.withDupDetector(DupDetector.rootDetector(this)); } } return this; } @Override public JsonParser disable(Feature f) { _features &= ~f.getMask(); if (f == Feature.STRICT_DUPLICATE_DETECTION) { _parsingContext = _parsingContext.withDupDetector(null); } return this; } @Override @Deprecated public JsonParser setFeatureMask(int newMask) { int changes = (_features ^ newMask); if (changes != 0) { _features = newMask; _checkStdFeatureChanges(newMask, changes); } return this; } @Override // since 2.7 public JsonParser overrideStdFeatures(int values, int mask) { int oldState = _features; int newState = (oldState & ~mask) | (values & mask); int changed = oldState ^ newState; if (changed != 0) { _features = newState; _checkStdFeatureChanges(newState, changed); } return this; } /** * Helper method called to verify changes to standard features. * * @param newFeatureFlags Bitflag of standard features after they were changed * @param changedFeatures Bitflag of standard features for which setting * did change * * @since 2.7 */ protected void _checkStdFeatureChanges(int newFeatureFlags, int changedFeatures) { int f = Feature.STRICT_DUPLICATE_DETECTION.getMask(); if ((changedFeatures & f) != 0) { if ((newFeatureFlags & f) != 0) { if (_parsingContext.getDupDetector() == null) { _parsingContext = _parsingContext.withDupDetector(DupDetector.rootDetector(this)); } else { // disabling _parsingContext = _parsingContext.withDupDetector(null); } } } } /* /********************************************************** /* JsonParser impl /********************************************************** */ /** * Method that can be called to get the name associated with * the current event. */ @Override public String getCurrentName() throws IOException { // [JACKSON-395]: start markers require information from parent if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { JsonReadContext parent = _parsingContext.getParent(); if (parent != null) { return parent.getCurrentName(); } } return _parsingContext.getCurrentName(); } @Override public void overrideCurrentName(String name) { // Simple, but need to look for START_OBJECT/ARRAY's "off-by-one" thing: JsonReadContext ctxt = _parsingContext; if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { ctxt = ctxt.getParent(); } // 24-Sep-2013, tatu: Unfortunate, but since we did not expose exceptions, // need to wrap this here try { ctxt.setCurrentName(name); } catch (IOException e) { throw new IllegalStateException(e); } } @Override public void close() throws IOException { if (!_closed) { // 19-Jan-2018, tatu: as per [core#440] need to ensure no more data assumed available _inputPtr = Math.max(_inputPtr, _inputEnd); _closed = true; try { _closeInput(); } finally { // as per [JACKSON-324], do in finally block // Also, internal buffer(s) can now be released as well _releaseBuffers(); } } } @Override public boolean isClosed() { return _closed; } @Override public JsonReadContext getParsingContext() { return _parsingContext; } /** * Method that return the <b>starting</b> location of the current * token; that is, position of the first character from input * that starts the current token. */ @Override public JsonLocation getTokenLocation() { return new JsonLocation(_contentReference(), -1L, getTokenCharacterOffset(), // bytes, chars getTokenLineNr(), getTokenColumnNr()); } /** * Method that returns location of the last processed character; * usually for error reporting purposes */ @Override public JsonLocation getCurrentLocation() { int col = _inputPtr - _currInputRowStart + 1; // 1-based return new JsonLocation(_contentReference(), -1L, _currInputProcessed + _inputPtr, // bytes, chars _currInputRow, col); } /* /********************************************************** /* Public API, access to token information, text and similar /********************************************************** */ @Override public boolean hasTextCharacters() { if (_currToken == JsonToken.VALUE_STRING) { return true; } // usually true if (_currToken == JsonToken.FIELD_NAME) { return _nameCopied; } return false; } @SuppressWarnings("resource") @Override // since 2.7 public byte[] getBinaryValue(Base64Variant variant) throws IOException { if (_binaryValue == null) { if (_currToken != JsonToken.VALUE_STRING) { _reportError("Current token ("+_currToken+") not VALUE_STRING, can not access as binary"); } ByteArrayBuilder builder = _getByteArrayBuilder(); _decodeBase64(getText(), builder, variant); _binaryValue = builder.toByteArray(); } return _binaryValue; } /* /********************************************************** /* Public low-level accessors /********************************************************** */ public long getTokenCharacterOffset() { return _tokenInputTotal; } public int getTokenLineNr() { return _tokenInputRow; } public int getTokenColumnNr() { // note: value of -1 means "not available"; otherwise convert from 0-based to 1-based int col = _tokenInputCol; return (col < 0) ? col : (col + 1); } /* /********************************************************** /* Abstract methods for sub-classes to implement /********************************************************** */ protected abstract void _closeInput() throws IOException; /* /********************************************************** /* Low-level reading, other /********************************************************** */ /** * 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). * * @throws IOException Not thrown by base implementation but could be thrown * by sub-classes */ protected void _releaseBuffers() throws IOException { _textBuffer.releaseBuffers(); char[] buf = _nameCopyBuffer; if (buf != null) { _nameCopyBuffer = null; _ioContext.releaseNameCopyBuffer(buf); } } /** * Method called when an EOF is encountered between tokens. * If so, it may be a legitimate EOF, but only iff there * is no open non-root context. */ @Override protected void _handleEOF() throws JsonParseException { if (!_parsingContext.inRoot()) { String marker = _parsingContext.inArray() ? "Array" : "Object"; _reportInvalidEOF(String.format( ": expected close marker for %s (start marker at %s)", marker, _parsingContext.startLocation(_contentReference())), null); } } /** * @return If no exception is thrown, {@code -1} which is used as marked for "end-of-input" * * @throws JsonParseException If check on {@code _handleEOF()} fails; usually because * the current context is not root context (missing end markers in content) * * @since 2.4 */ protected final int _eofAsNextChar() throws JsonParseException { _handleEOF(); return -1; } /* /********************************************************** /* Internal/package methods: shared/reusable builders /********************************************************** */ public ByteArrayBuilder _getByteArrayBuilder() { if (_byteArrayBuilder == null) { _byteArrayBuilder = new ByteArrayBuilder(); } else { _byteArrayBuilder.reset(); } return _byteArrayBuilder; } /* /********************************************************** /* Methods from former JsonNumericParserBase /********************************************************** */ // // // Life-cycle of number-parsing protected final JsonToken reset(boolean negative, int intLen, int fractLen, int expLen) { if (fractLen < 1 && expLen < 1) { // integer return resetInt(negative, intLen); } return resetFloat(negative, intLen, fractLen, expLen); } protected final JsonToken resetInt(boolean negative, int intLen) { _numberNegative = negative; _intLength = intLen; _fractLength = 0; _expLength = 0; _numTypesValid = NR_UNKNOWN; // to force parsing return JsonToken.VALUE_NUMBER_INT; } protected final JsonToken resetFloat(boolean negative, int intLen, int fractLen, int expLen) { _numberNegative = negative; _intLength = intLen; _fractLength = fractLen; _expLength = expLen; _numTypesValid = NR_UNKNOWN; // to force parsing return JsonToken.VALUE_NUMBER_FLOAT; } protected final JsonToken resetAsNaN(String valueStr, double value) { _textBuffer.resetWithString(valueStr); _numberDouble = value; _numTypesValid = NR_DOUBLE; return JsonToken.VALUE_NUMBER_FLOAT; } @Override public boolean isNaN() { if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) { if ((_numTypesValid & NR_DOUBLE) != 0) { // 10-Mar-2017, tatu: Alas, `Double.isFinite(d)` only added in JDK 8 double d = _numberDouble; return Double.isNaN(d) || Double.isInfinite(d); } } return false; } /* /********************************************************** /* Numeric accessors of public API /********************************************************** */ @Override public Number getNumberValue() throws IOException { if (_numTypesValid == NR_UNKNOWN) { _parseNumericValue(NR_UNKNOWN); // will also check event type } // Separate types for int types if (_currToken == JsonToken.VALUE_NUMBER_INT) { if ((_numTypesValid & NR_INT) != 0) { return _numberInt; } if ((_numTypesValid & NR_LONG) != 0) { return _numberLong; } if ((_numTypesValid & NR_BIGINT) != 0) { return _getBigInteger(); } _throwInternal(); } // And then floating point types. But here optimal type // needs to be big decimal, to avoid losing any data? if ((_numTypesValid & NR_BIGDECIMAL) != 0) { return _getBigDecimal(); } if ((_numTypesValid & NR_FLOAT) != 0) { return _numberFloat; } if ((_numTypesValid & NR_DOUBLE) == 0) { // sanity check _throwInternal(); } return _numberDouble; } // NOTE: mostly copied from above @Override public Number getNumberValueExact() throws IOException { if (_currToken == JsonToken.VALUE_NUMBER_INT) { if (_numTypesValid == NR_UNKNOWN) { _parseNumericValue(NR_UNKNOWN); } if ((_numTypesValid & NR_INT) != 0) { return _numberInt; } if ((_numTypesValid & NR_LONG) != 0) { return _numberLong; } if ((_numTypesValid & NR_BIGINT) != 0) { return _getBigInteger(); } _throwInternal(); } // 09-Jul-2020, tatu: [databind#2644] requires we will retain accuracy, so: if (_numTypesValid == NR_UNKNOWN) { _parseNumericValue(NR_BIGDECIMAL); } if ((_numTypesValid & NR_BIGDECIMAL) != 0) { return _getBigDecimal(); } if ((_numTypesValid & NR_FLOAT) != 0) { return _numberFloat; } if ((_numTypesValid & NR_DOUBLE) == 0) { // sanity check _throwInternal(); } return _numberDouble; } @Override public NumberType getNumberType() throws IOException { if (_numTypesValid == NR_UNKNOWN) { _parseNumericValue(NR_UNKNOWN); // will also check event type } if (_currToken == JsonToken.VALUE_NUMBER_INT) { if ((_numTypesValid & NR_INT) != 0) { return NumberType.INT; } if ((_numTypesValid & NR_LONG) != 0) { return NumberType.LONG; } return NumberType.BIG_INTEGER; } /* And then floating point types. Here optimal type * needs to be big decimal, to avoid losing any data? * However... using BD is slow, so let's allow returning * double as type if no explicit call has been made to access * data as BD? */ if ((_numTypesValid & NR_BIGDECIMAL) != 0) { return NumberType.BIG_DECIMAL; } if ((_numTypesValid & NR_FLOAT) != 0) { return NumberType.FLOAT; } return NumberType.DOUBLE; } @Override public int getIntValue() throws IOException { if ((_numTypesValid & NR_INT) == 0) { if (_numTypesValid == NR_UNKNOWN) { // not parsed at all return _parseIntValue(); } if ((_numTypesValid & NR_INT) == 0) { // wasn't an int natively? convertNumberToInt(); // let's make it so, if possible } } return _numberInt; } @Override public long getLongValue() throws IOException { if ((_numTypesValid & NR_LONG) == 0) { if (_numTypesValid == NR_UNKNOWN) { _parseNumericValue(NR_LONG); } if ((_numTypesValid & NR_LONG) == 0) { convertNumberToLong(); } } return _numberLong; } @Override public BigInteger getBigIntegerValue() throws IOException { if ((_numTypesValid & NR_BIGINT) == 0) { if (_numTypesValid == NR_UNKNOWN) { _parseNumericValue(NR_BIGINT); } if ((_numTypesValid & NR_BIGINT) == 0) { convertNumberToBigInteger(); } } return _getBigInteger(); } @Override public float getFloatValue() throws IOException { /* 22-Jan-2009, tatu: Bounds/range checks would be tricky * here, so let's not bother even trying... */ /* if (value < -Float.MAX_VALUE || value > MAX_FLOAT_D) { _reportError("Numeric value ("+getText()+") out of range of Java float"); } */ if ((_numTypesValid & NR_FLOAT) == 0) { if (_numTypesValid == NR_UNKNOWN) { _parseNumericValue(NR_FLOAT); } if ((_numTypesValid & NR_FLOAT) == 0) { convertNumberToFloat(); } } return _numberFloat; } @Override public double getDoubleValue() throws IOException { if ((_numTypesValid & NR_DOUBLE) == 0) { if (_numTypesValid == NR_UNKNOWN) { _parseNumericValue(NR_DOUBLE); } if ((_numTypesValid & NR_DOUBLE) == 0) { convertNumberToDouble(); } } return _numberDouble; } @Override public BigDecimal getDecimalValue() throws IOException { if ((_numTypesValid & NR_BIGDECIMAL) == 0) { if (_numTypesValid == NR_UNKNOWN) { _parseNumericValue(NR_BIGDECIMAL); } if ((_numTypesValid & NR_BIGDECIMAL) == 0) { convertNumberToBigDecimal(); } } return _getBigDecimal(); } /* /********************************************************** /* Conversion from textual to numeric representation /********************************************************** */ /** * 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 * * @throws IOException If there are problems reading content * @throws JsonParseException If there are problems decoding number value */ protected void _parseNumericValue(int expType) throws IOException { // 12-Jun-2020, tatu: Sanity check to prevent more cryptic error for this case. // (note: could alternatively see if TextBuffer has aggregated contents, avoid // exception -- but that might be more confusing) if (_closed) { _reportError("Internal error: _parseNumericValue called when parser instance closed"); } // Int or float? if (_currToken == JsonToken.VALUE_NUMBER_INT) { final int len = _intLength; // First: optimization for simple int if (len <= 9) { int i = _textBuffer.contentsAsInt(_numberNegative); _numberInt = i; _numTypesValid = NR_INT; return; } if (len <= 18) { // definitely fits AND is easy to parse using 2 int parse calls long l = _textBuffer.contentsAsLong(_numberNegative); // Might 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; } _parseSlowInt(expType); return; } if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) { _parseSlowFloat(expType); return; } _reportError("Current token (%s) not numeric, can not use numeric value accessors", _currToken); } // @since 2.6 protected int _parseIntValue() throws IOException { // 12-Jun-2020, tatu: Sanity check to prevent more cryptic error for this case. // (note: could alternatively see if TextBuffer has aggregated contents, avoid // exception -- but that might be more confusing) if (_closed) { _reportError("Internal error: _parseNumericValue called when parser instance closed"); } // Inlined variant of: _parseNumericValue(NR_INT) if (_currToken == JsonToken.VALUE_NUMBER_INT) { if (_intLength <= 9) { int i = _textBuffer.contentsAsInt(_numberNegative); _numberInt = i; _numTypesValid = NR_INT; return i; } } // if not optimizable, use more generic _parseNumericValue(NR_INT); if ((_numTypesValid & NR_INT) == 0) { convertNumberToInt(); } return _numberInt; } private void _parseSlowFloat(int expType) throws IOException { /* 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 = null; _numberString = _textBuffer.contentsAsString(); _numTypesValid = NR_BIGDECIMAL; } else if (expType == NR_FLOAT) { _numberFloat = _textBuffer.contentsAsFloat(isEnabled(Feature.USE_FAST_DOUBLE_PARSER)); _numTypesValid = NR_FLOAT; } else { // Otherwise double has to do _numberDouble = _textBuffer.contentsAsDouble(isEnabled(Feature.USE_FAST_DOUBLE_PARSER)); _numTypesValid = NR_DOUBLE; } } catch (NumberFormatException nex) { // Can this ever occur? Due to overflow, maybe? _wrapError("Malformed numeric value ("+_longNumberDesc(_textBuffer.contentsAsString())+")", nex); } } private void _parseSlowInt(int expType) throws IOException { String numStr = _textBuffer.contentsAsString(); try { int len = _intLength; char[] buf = _textBuffer.getTextBuffer(); int offset = _textBuffer.getTextOffset(); if (_numberNegative) { ++offset; } // 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 { // 16-Oct-2018, tatu: Need to catch "too big" early due to [jackson-core#488] if ((expType == NR_INT) || (expType == NR_LONG)) { _reportTooLongIntegral(expType, numStr); } if ((expType == NR_DOUBLE) || (expType == NR_FLOAT)) { _numberDouble = NumberInput.parseDouble(numStr, isEnabled(Feature.USE_FAST_DOUBLE_PARSER)); _numTypesValid = NR_DOUBLE; } else { // nope, need the heavy guns... (rare case) - since Jackson v2.14, BigInteger parsing is lazy _numberBigInt = null; _numberString = numStr; _numTypesValid = NR_BIGINT; } } } catch (NumberFormatException nex) { // Can this ever occur? Due to overflow, maybe? _wrapError("Malformed numeric value ("+_longNumberDesc(numStr)+")", nex); } } // @since 2.9.8 protected void _reportTooLongIntegral(int expType, String rawNum) throws IOException { if (expType == NR_INT) { reportOverflowInt(rawNum); } else { reportOverflowLong(rawNum); } } /* /********************************************************** /* Numeric conversions /********************************************************** */ protected void convertNumberToInt() throws IOException { // First, converting from long ought to be easy if ((_numTypesValid & NR_LONG) != 0) { // Let's verify it's lossless conversion by simple roundtrip int result = (int) _numberLong; if (((long) result) != _numberLong) { reportOverflowInt(getText(), currentToken()); } _numberInt = result; } else if ((_numTypesValid & NR_BIGINT) != 0) { final BigInteger bigInteger = _getBigInteger(); if (BI_MIN_INT.compareTo(bigInteger) > 0 || BI_MAX_INT.compareTo(bigInteger) < 0) { reportOverflowInt(); } _numberInt = bigInteger.intValue(); } else if ((_numTypesValid & NR_DOUBLE) != 0) { // Need to check boundaries if (_numberDouble < MIN_INT_D || _numberDouble > MAX_INT_D) { reportOverflowInt(); } _numberInt = (int) _numberDouble; } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) { final BigDecimal bigDecimal = _getBigDecimal(); if (BD_MIN_INT.compareTo(bigDecimal) > 0 || BD_MAX_INT.compareTo(bigDecimal) < 0) { reportOverflowInt(); } _numberInt = bigDecimal.intValue(); } else { _throwInternal(); } _numTypesValid |= NR_INT; } protected void convertNumberToLong() throws IOException { if ((_numTypesValid & NR_INT) != 0) { _numberLong = (long) _numberInt; } else if ((_numTypesValid & NR_BIGINT) != 0) { final BigInteger bigInteger = _getBigInteger(); if (BI_MIN_LONG.compareTo(bigInteger) > 0 || BI_MAX_LONG.compareTo(bigInteger) < 0) { reportOverflowLong(); } _numberLong = bigInteger.longValue(); } else if ((_numTypesValid & NR_DOUBLE) != 0) { // Need to check boundaries if (_numberDouble < MIN_LONG_D || _numberDouble > MAX_LONG_D) { reportOverflowLong(); } _numberLong = (long) _numberDouble; } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) { final BigDecimal bigDecimal = _getBigDecimal(); if (BD_MIN_LONG.compareTo(bigDecimal) > 0 || BD_MAX_LONG.compareTo(bigDecimal) < 0) { reportOverflowLong(); } _numberLong = bigDecimal.longValue(); } else { _throwInternal(); } _numTypesValid |= NR_LONG; } protected void convertNumberToBigInteger() throws IOException { if ((_numTypesValid & NR_BIGDECIMAL) != 0) { // here it'll just get truncated, no exceptions thrown _numberBigInt = _getBigDecimal().toBigInteger(); } else if ((_numTypesValid & NR_LONG) != 0) { _numberBigInt = BigInteger.valueOf(_numberLong); } else if ((_numTypesValid & NR_INT) != 0) { _numberBigInt = BigInteger.valueOf(_numberInt); } else if ((_numTypesValid & NR_DOUBLE) != 0) { _numberBigInt = BigDecimal.valueOf(_numberDouble).toBigInteger(); } else { _throwInternal(); } _numTypesValid |= NR_BIGINT; } protected void convertNumberToDouble() throws IOException { /* 05-Aug-2008, tatus: Important note: this MUST start with * more accurate representations, since we don't know which * value is the original one (others get generated when * requested) */ if ((_numTypesValid & NR_BIGDECIMAL) != 0) { _numberDouble = _getBigDecimal().doubleValue(); } else if ((_numTypesValid & NR_BIGINT) != 0) { _numberDouble = _getBigInteger().doubleValue(); } else if ((_numTypesValid & NR_LONG) != 0) { _numberDouble = (double) _numberLong; } else if ((_numTypesValid & NR_INT) != 0) { _numberDouble = (double) _numberInt; } else if ((_numTypesValid & NR_FLOAT) != 0) { _numberDouble = (double) _numberFloat; } else { _throwInternal(); } _numTypesValid |= NR_DOUBLE; } protected void convertNumberToFloat() throws IOException { /* 05-Aug-2008, tatus: Important note: this MUST start with * more accurate representations, since we don't know which * value is the original one (others get generated when * requested) */ if ((_numTypesValid & NR_BIGDECIMAL) != 0) { _numberFloat = _getBigDecimal().floatValue(); } else if ((_numTypesValid & NR_BIGINT) != 0) { _numberFloat = _getBigInteger().floatValue(); } else if ((_numTypesValid & NR_LONG) != 0) { _numberFloat = (float) _numberLong; } else if ((_numTypesValid & NR_INT) != 0) { _numberFloat = (float) _numberInt; } else if ((_numTypesValid & NR_DOUBLE) != 0) { _numberFloat = (float) _numberDouble; } else { _throwInternal(); } _numTypesValid |= NR_FLOAT; } protected void convertNumberToBigDecimal() throws IOException { /* 05-Aug-2008, tatus: Important note: this MUST start with * more accurate representations, since we don't know which * value is the original one (others get generated when * requested) */ if ((_numTypesValid & NR_DOUBLE) != 0) { // Let's actually parse from String representation, to avoid // rounding errors that non-decimal floating operations could incur _numberBigDecimal = NumberInput.parseBigDecimal(getText()); } else if ((_numTypesValid & NR_BIGINT) != 0) { _numberBigDecimal = new BigDecimal(_getBigInteger()); } else if ((_numTypesValid & NR_LONG) != 0) { _numberBigDecimal = BigDecimal.valueOf(_numberLong); } else if ((_numTypesValid & NR_INT) != 0) { _numberBigDecimal = BigDecimal.valueOf(_numberInt); } else { _throwInternal(); } _numTypesValid |= NR_BIGDECIMAL; } /** * Internal accessor that needs to be used for accessing number value of type * {@link BigInteger} which -- as of 2.14 -- is typically lazily parsed. * * @since 2.14 */ protected BigInteger _getBigInteger() { if (_numberBigInt != null) { return _numberBigInt; } else if (_numberString == null) { throw new IllegalStateException("cannot get BigInteger from current parser state"); } _numberBigInt = NumberInput.parseBigInteger(_numberString); _numberString = null; return _numberBigInt; } /** * Internal accessor that needs to be used for accessing number value of type * {@link BigDecimal} which -- as of 2.14 -- is typically lazily parsed. * * @since 2.14 */ protected BigDecimal _getBigDecimal() { if (_numberBigDecimal != null) { return _numberBigDecimal; } else if (_numberString == null) { throw new IllegalStateException("cannot get BigDecimal from current parser state"); } _numberBigDecimal = NumberInput.parseBigDecimal(_numberString); _numberString = null; return _numberBigDecimal; } /* /********************************************************** /* Internal/package methods: Error reporting /********************************************************** */ protected void _reportMismatchedEndMarker(int actCh, char expCh) throws JsonParseException { JsonReadContext ctxt = getParsingContext(); _reportError(String.format( "Unexpected close marker '%s': expected '%c' (for %s starting at %s)", (char) actCh, expCh, ctxt.typeDesc(), ctxt.startLocation(_contentReference()))); } @SuppressWarnings("deprecation") protected char _handleUnrecognizedCharacterEscape(char ch) throws JsonProcessingException { // as per [JACKSON-300] if (isEnabled(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)) { return ch; } // and [JACKSON-548] if (ch == '\'' && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) { return ch; } _reportError("Unrecognized character escape "+_getCharDesc(ch)); return ch; } /** * Method called to report a problem with unquoted control character. * Note: it is possible to suppress some instances of * exception by enabling * {@link com.fasterxml.jackson.core.json.JsonReadFeature#ALLOW_UNESCAPED_CONTROL_CHARS}. * * @param i Invalid control character * @param ctxtDesc Addition description of context to use in exception message * * @throws JsonParseException explaining the problem */ @SuppressWarnings("deprecation") protected void _throwUnquotedSpace(int i, String ctxtDesc) throws JsonParseException { // JACKSON-208; possible to allow unquoted control chars: if (!isEnabled(Feature.ALLOW_UNQUOTED_CONTROL_CHARS) || i > INT_SPACE) { char c = (char) i; String msg = "Illegal unquoted character ("+_getCharDesc(c)+"): has to be escaped using backslash to be included in "+ctxtDesc; _reportError(msg); } } /** * @return Description to use as "valid tokens" in an exception message about * invalid (unrecognized) JSON token: called when parser finds something that * looks like unquoted textual token * * @throws IOException Not thrown by base implementation but allowed by sub-classes * * @since 2.10 */ protected String _validJsonTokenList() throws IOException { return _validJsonValueList(); } /** * @return Description to use as "valid JSON values" in an exception message about * invalid (unrecognized) JSON value: called when parser finds something that * does not look like a value or separator. * * @throws IOException Not thrown by base implementation but allowed by sub-classes * * @since 2.10 */ @SuppressWarnings("deprecation") protected String _validJsonValueList() throws IOException { if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { return "(JSON String, Number (or 'NaN'/'INF'/'+INF'), Array, Object or token 'null', 'true' or 'false')"; } return "(JSON String, Number, Array, Object or token 'null', 'true' or 'false')"; } /* /********************************************************** /* Base64 handling support /********************************************************** */ /** * Method that sub-classes must implement to support escaped sequences * in base64-encoded sections. * Sub-classes that do not need base64 support can leave this as is * * @return Character decoded, if any * * @throws IOException If escape decoding fails */ protected char _decodeEscaped() throws IOException { throw new UnsupportedOperationException(); } protected final int _decodeBase64Escape(Base64Variant b64variant, int ch, int index) throws IOException { // 17-May-2011, tatu: As per [JACKSON-xxx], need to handle escaped chars if (ch != '\\') { throw reportInvalidBase64Char(b64variant, ch, index); } int unescaped = _decodeEscaped(); // if white space, skip if first triplet; otherwise errors if (unescaped <= INT_SPACE) { if (index == 0) { // whitespace only allowed to be skipped between triplets return -1; } } // otherwise try to find actual triplet value int bits = b64variant.decodeBase64Char(unescaped); if (bits < 0) { if (bits != Base64Variant.BASE64_VALUE_PADDING) { throw reportInvalidBase64Char(b64variant, unescaped, index); } } return bits; } protected final int _decodeBase64Escape(Base64Variant b64variant, char ch, int index) throws IOException { if (ch != '\\') { throw reportInvalidBase64Char(b64variant, ch, index); } char unescaped = _decodeEscaped(); // if white space, skip if first triplet; otherwise errors if (unescaped <= INT_SPACE) { if (index == 0) { // whitespace only allowed to be skipped between triplets return -1; } } // otherwise try to find actual triplet value int bits = b64variant.decodeBase64Char(unescaped); if (bits < 0) { // second check since padding can only be 3rd or 4th byte (index #2 or #3) if ((bits != Base64Variant.BASE64_VALUE_PADDING) || (index < 2)) { throw reportInvalidBase64Char(b64variant, unescaped, index); } } return bits; } protected IllegalArgumentException reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex) throws IllegalArgumentException { return reportInvalidBase64Char(b64variant, ch, bindex, null); } /* * @param bindex Relative index within base64 character unit; between 0 * and 3 (as unit has exactly 4 characters) */ protected IllegalArgumentException reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex, String msg) throws IllegalArgumentException { String base; if (ch <= INT_SPACE) { base = String.format("Illegal white space character (code 0x%s) as character #%d of 4-char base64 unit: can only used between units", Integer.toHexString(ch), (bindex+1)); } else if (b64variant.usesPaddingChar(ch)) { base = "Unexpected padding character ('"+b64variant.getPaddingChar()+"') as character #"+(bindex+1)+" of 4-char base64 unit: padding only legal as 3rd or 4th character"; } else if (!Character.isDefined(ch) || Character.isISOControl(ch)) { // Not sure if we can really get here... ? (most illegal xml chars are caught at lower level) base = "Illegal character (code 0x"+Integer.toHexString(ch)+") in base64 content"; } else { base = "Illegal character '"+((char)ch)+"' (code 0x"+Integer.toHexString(ch)+") in base64 content"; } if (msg != null) { base = base + ": " + msg; } return new IllegalArgumentException(base); } // since 2.9.8 protected void _handleBase64MissingPadding(Base64Variant b64variant) throws IOException { _reportError(b64variant.missingPaddingMessage()); } /* /********************************************************** /* Internal/package methods: other /********************************************************** */ /** * @return Source reference * @since 2.9 * @deprecated Since 2.13, use {@link #_contentReference()} instead. */ @Deprecated protected Object _getSourceReference() { if (JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION.enabledIn(_features)) { return _ioContext.contentReference().getRawContent(); } return null; } /** * Helper method used to encapsulate logic of including (or not) of * "content reference" when constructing {@link JsonLocation} instances. * * @return Source reference object, if any; {@code null} if none * * @since 2.13 */ protected ContentReference _contentReference() { if (JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION.enabledIn(_features)) { return _ioContext.contentReference(); } return ContentReference.unknown(); } protected static int[] growArrayBy(int[] arr, int more) { if (arr == null) { return new int[more]; } return Arrays.copyOf(arr, arr.length + more); } /* /********************************************************** /* Stuff that was abstract and required before 2.8, but that /* is not mandatory in 2.8 or above. /********************************************************** */ @Deprecated // since 2.8 protected void loadMoreGuaranteed() throws IOException { if (!loadMore()) { _reportInvalidEOF(); } } @Deprecated // since 2.8 protected boolean loadMore() throws IOException { return false; } // Can't declare as deprecated, for now, but shouldn't be needed protected void _finishString() throws IOException { } }
⏎ com/fasterxml/jackson/core/base/ParserBase.java
Or download all of them as a single archive file:
File name: jackson-core-2.14.0-sources.jar File size: 497693 bytes Release date: 2022-11-05 Download
⇒ Download and Install Jackson Binary Package
2016-02-03, 39010👍, 1💬
Popular Posts:
This package is the backport of java.util.concurrent API, introduced in Java 5.0 and further refined...
Java Cryptography Extension 1.6 JAR File Size and Download Location: File name: jce.jar, jce-1.6.jar...
What Is mail.jar of JavaMail 1.3? I got the JAR file from javamail-1_3.zip. mail.jar in javamail-1_3...
Java Servlet 3.0 Specification API. JAR File Size and Download Location: File name: servlet-api.jar,...
What Is mail.jar of JavaMail 1.4? I got the JAR file from javamail-1_4.zip. mail.jar in javamail-1_4...