/** * Overridable factory method that actually instantiates parser * using given {@link Reader} object for reading content. *<p> * This method is specifically designed to remain * compatible between minor versions so that sub-classes can count * on it being called as expected. That is, it is part of official * interface from sub-class perspective, although not a public * method available to users of factory implementations. */ protected JsonParser _createJsonParser(Reader r, IOContext ctxt) throws IOException, JsonParseException { return new ReaderBasedParser(ctxt, _parserFeatures, r, _objectCodec, _rootCharSymbols.makeChild(isEnabled(JsonParser.Feature.CANONICALIZE_FIELD_NAMES), isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES))); }
private final int _skipWS() throws IOException, JsonParseException { while (_inputPtr < _inputEnd || loadMore()) { int i = (int) _inputBuffer[_inputPtr++]; if (i > INT_SPACE) { if (i != INT_SLASH) { return i; } _skipComment(); } else if (i != INT_SPACE) { if (i == INT_LF) { _skipLF(); } else if (i == INT_CR) { _skipCR(); } else if (i != INT_TAB) { _throwInvalidSpace(i); } } } throw _constructError("Unexpected end-of-input within/between "+_parsingContext.getTypeDesc()+" entries"); }
if (inputPtr >= inputLen) { _inputPtr = inputPtr; if (!loadMore()) { _reportInvalidEOF(": was expecting closing quote for a string value"); c = _decodeEscaped(); inputPtr = _inputPtr; inputLen = _inputEnd; _throwUnquotedSpace(i, "string value");
protected char getNextChar(String eofMsg) throws IOException, JsonParseException { if (_inputPtr >= _inputEnd) { if (!loadMore()) { _reportInvalidEOF(eofMsg); } } return _inputBuffer[_inputPtr++]; }
private final void _skipComment() throws IOException, JsonParseException { if (!isEnabled(Feature.ALLOW_COMMENTS)) { _reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)"); } // First: check which comment (if either) it is: if (_inputPtr >= _inputEnd && !loadMore()) { _reportInvalidEOF(" in a comment"); } char c = _inputBuffer[_inputPtr++]; if (c == '/') { _skipCppComment(); } else if (c == '*') { _skipCComment(); } else { _reportUnexpectedChar(c, "was expecting either '*' or '/' for a comment"); } }
private final int _skipWSOrEnd() throws IOException, JsonParseException { while ((_inputPtr < _inputEnd) || loadMore()) { int i = (int) _inputBuffer[_inputPtr++]; if (i > INT_SPACE) { if (i == INT_SLASH) { _skipComment(); continue; } return i; } if (i != INT_SPACE) { if (i == INT_LF) { _skipLF(); } else if (i == INT_CR) { _skipCR(); } else if (i != INT_TAB) { _throwInvalidSpace(i); } } } // We ran out of input... _handleEOF(); return -1; }
return _nextAfterName(); _skipString(); // only strings can be partial int i = _skipWSOrEnd(); if (i < 0) { // end-of-input close(); return (_currToken = null); _reportMismatchedEndMarker(i, '}'); _reportMismatchedEndMarker(i, ']'); _reportUnexpectedChar(i, "was expecting comma to separate "+_parsingContext.getTypeDesc()+" entries"); i = _skipWS(); String name = _parseFieldName(i); _parsingContext.setCurrentName(name); _currToken = JsonToken.FIELD_NAME; i = _skipWS(); if (i != INT_COLON) { _reportUnexpectedChar(i, "was expecting a colon to separate field name and value"); i = _skipWS(); _reportUnexpectedChar(i, "expected a value"); case INT_t:
if (isEnabled(Feature.ALLOW_SINGLE_QUOTES)) { return _handleApostropheValue(); _matchToken("NaN", 1); if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { return resetAsNaN("NaN", Double.NaN); _reportError("Non-standard token 'NaN': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow"); break; case '+': // note: '-' is taken as number if (_inputPtr >= _inputEnd) { if (!loadMore()) { _reportInvalidEOFInValue(); return _handleInvalidNumberStart(_inputBuffer[_inputPtr++], false); _reportUnexpectedChar(i, "expected a valid value (number, String, array, object, 'true', 'false' or 'null')"); return null;
while ((_inputPtr < _inputEnd) || loadMore()) { int i = (int) _inputBuffer[_inputPtr++]; if (i <= INT_ASTERISK) { if (i == INT_ASTERISK) { // end? if ((_inputPtr >= _inputEnd) && !loadMore()) { break main_loop; _skipLF(); } else if (i == INT_CR) { _skipCR(); } else if (i != INT_TAB) { _throwInvalidSpace(i); _reportInvalidEOF(" in a comment");
if (!loadMore()) { _reportInvalidEOFInValue(); if (ch == 'N') { String match = negative ? "-INF" :"+INF"; _matchToken(match, 3); if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { return resetAsNaN(match, negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY); _reportError("Non-standard token '"+match+"': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow"); } else if (ch == 'n') { String match = negative ? "-Infinity" :"+Infinity"; _matchToken(match, 3); if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { return resetAsNaN(match, negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY); _reportError("Non-standard token '"+match+"': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow"); reportUnexpectedNumberChar(ch, "expected digit (0-9) to follow minus sign, for valid numeric value"); return null;
return _nextAfterName(); _skipString(); // only strings can be partial int i = _skipWSOrEnd(); if (i < 0) { // end-of-input return (_currToken = null); _reportMismatchedEndMarker(i, ']'); _reportMismatchedEndMarker(i, '}'); _reportUnexpectedChar(i, "was expecting comma to separate "+_parsingContext.getTypeDesc()+" entries"); i = _skipWS(); _handleFieldName(i); _currToken = JsonToken.FIELD_NAME; i = _skipWS(); if (i != INT_COLON) { _reportUnexpectedChar(i, "was expecting a colon to separate field name and value"); i = _skipWS(); _reportUnexpectedChar(i, "expected a value"); case INT_t: _matchToken(JsonToken.VALUE_TRUE); t = JsonToken.VALUE_TRUE; break;
if (!loadMore()) { _reportInvalidEOF(" in character escape sequence"); return _handleUnrecognizedCharacterEscape(c); for (int i = 0; i < 4; ++i) { if (_inputPtr >= _inputEnd) { if (!loadMore()) { _reportInvalidEOF(" in character escape sequence"); int digit = CharTypes.charToHex(ch); if (digit < 0) { _reportUnexpectedChar(ch, "expected a hex-digit for character escape sequence");
private final void _skipComment() throws IOException, JsonParseException { if (!isFeatureEnabled(Feature.ALLOW_COMMENTS)) { _reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)"); } // First: check which comment (if either) it is: if (_inputPtr >= _inputEnd && !loadMore()) { _reportInvalidEOF(" in a comment"); } char c = _inputBuffer[_inputPtr++]; if (c == '/') { _skipCppComment(); } else if (c == '*') { _skipCComment(); } else { _reportUnexpectedChar(c, "was expecting either '*' or '/' for a comment"); } }
if (!loadMore()) { _reportInvalidEOF(" in character escape sequence"); _reportError("Unrecognized character escape "+_getCharDesc(c)); for (int i = 0; i < 4; ++i) { if (_inputPtr >= _inputEnd) { if (!loadMore()) { _reportInvalidEOF(" in character escape sequence"); int digit = CharTypes.charToHex(ch); if (digit < 0) { _reportUnexpectedChar(ch, "expected a hex-digit for character escape sequence");
_reportError("Current token ("+_currToken+") not VALUE_STRING or VALUE_EMBEDDED_OBJECT, can not access as binary"); _binaryValue = _decodeBase64(b64variant); } catch (IllegalArgumentException iae) { throw _constructError("Failed to decode VALUE_STRING as base64 ("+b64variant+"): "+iae.getMessage()); } else { // may actually require conversion... if (_binaryValue == null) { ByteArrayBuilder builder = _getByteArrayBuilder(); _decodeBase64(getText(), builder, b64variant); _binaryValue = builder.toByteArray();
if (!loadMore()) { _reportInvalidEOFInValue(); _reportInvalidToken(matchStr.substring(0, i), "'null', 'true', 'false' or NaN"); if (!loadMore()) { return; _reportInvalidToken(matchStr.substring(0, i), "'null', 'true', 'false' or NaN");
/** * Method called to much one of literal tokens we may expect */ protected void _matchToken(JsonToken token) throws IOException, JsonParseException { // First char is already matched, need to check the rest String matchStr = token.asString(); int i = 1; for (int len = matchStr.length(); i < len; ++i) { if (_inputPtr >= _inputEnd) { if (!loadMore()) { _reportInvalidEOF(" in a value"); } } char c = _inputBuffer[_inputPtr]; if (c != matchStr.charAt(i)) { _reportInvalidToken(matchStr.substring(0, i)); } ++_inputPtr; } /* Ok, fine; let's not bother checking anything beyond keyword. * If there's something wrong there, it'll cause a parsing * error later on. */ return; }
protected void _reportInvalidToken(String matchedPart, String msg) throws IOException, JsonParseException { StringBuilder sb = new StringBuilder(matchedPart); /* Let's just try to find what appears to be the token, using * regular Java identifier character rules. It's just a heuristic, * nothing fancy here. */ while (true) { if (_inputPtr >= _inputEnd) { if (!loadMore()) { break; } } char c = _inputBuffer[_inputPtr]; if (!Character.isJavaIdentifierPart(c)) { break; } ++_inputPtr; sb.append(c); } _reportError("Unrecognized token '"+sb.toString()+"': was expecting "); } }
@Override public byte[] getBinaryValue(Base64Variant b64variant) throws IOException, JsonParseException { if (_currToken != JsonToken.VALUE_STRING && (_currToken != JsonToken.VALUE_EMBEDDED_OBJECT || _binaryValue == null)) { _reportError("Current token ("+_currToken+") not VALUE_STRING or VALUE_EMBEDDED_OBJECT, can not access as binary"); } /* To ensure that we won't see inconsistent data, better clear up * state... */ if (_tokenIncomplete) { try { _binaryValue = _decodeBase64(b64variant); } catch (IllegalArgumentException iae) { throw _constructError("Failed to decode VALUE_STRING as base64 ("+b64variant+"): "+iae.getMessage()); } /* let's clear incomplete only now; allows for accessing other * textual content in error cases */ _tokenIncomplete = false; } return _binaryValue; }
private final int _decodeBase64Escape(Base64Variant b64variant, char ch, int index) throws IOException, JsonParseException { // 17-May-2011, tatu: As per [JACKSON-xxx], need to handle escaped chars if (ch != '\\') { throw reportInvalidChar(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) { throw reportInvalidChar(b64variant, unescaped, index); } return bits; }