1 package com.fasterxml.jackson.core.base; 2 3 import java.io.*; 4 import java.math.BigDecimal; 5 import java.math.BigInteger; 6 import java.util.Arrays; 7 8 import com.fasterxml.jackson.core.*; 9 import com.fasterxml.jackson.core.JsonParser.Feature; 10 import com.fasterxml.jackson.core.io.IOContext; 11 import com.fasterxml.jackson.core.io.NumberInput; 12 import com.fasterxml.jackson.core.json.DupDetector; 13 import com.fasterxml.jackson.core.json.JsonReadContext; 14 import com.fasterxml.jackson.core.json.PackageVersion; 15 import com.fasterxml.jackson.core.util.ByteArrayBuilder; 16 import com.fasterxml.jackson.core.util.JacksonFeatureSet; 17 import com.fasterxml.jackson.core.util.TextBuffer; 18 19 /** 20 * Intermediate base class used by all Jackson {@link JsonParser} 21 * implementations. Contains most common things that are independent 22 * of actual underlying input source. 23 */ 24 public abstract class ParserBase extends ParserMinimalBase 25 { 26 // JSON capabilities are the same as defaults 27 // @since 2.12 28 protected final static JacksonFeatureSet<StreamReadCapability> JSON_READ_CAPABILITIES 29 = DEFAULT_READ_CAPABILITIES; 30 31 /* 32 /********************************************************** 33 /* Generic I/O state 34 /********************************************************** 35 */ 36 37 /** 38 * I/O context for this reader. It handles buffer allocation 39 * for the reader. 40 */ 41 final protected IOContext _ioContext; 42 43 /** 44 * Flag that indicates whether parser is closed or not. Gets 45 * set when parser is either closed by explicit call 46 * ({@link #close}) or when end-of-input is reached. 47 */ 48 protected boolean _closed; 49 50 /* 51 /********************************************************** 52 /* Current input data 53 /********************************************************** 54 */ 55 56 // Note: type of actual buffer depends on sub-class, can't include 57 58 /** 59 * Pointer to next available character in buffer 60 */ 61 protected int _inputPtr; 62 63 /** 64 * Index of character after last available one in the buffer. 65 */ 66 protected int _inputEnd; 67 68 /* 69 /********************************************************** 70 /* Current input location information 71 /********************************************************** 72 */ 73 74 /** 75 * Number of characters/bytes that were contained in previous blocks 76 * (blocks that were already processed prior to the current buffer). 77 */ 78 protected long _currInputProcessed; 79 80 /** 81 * Current row location of current point in input buffer, starting 82 * from 1, if available. 83 */ 84 protected int _currInputRow = 1; 85 86 /** 87 * Current index of the first character of the current row in input 88 * buffer. Needed to calculate column position, if necessary; benefit 89 * of not having column itself is that this only has to be updated 90 * once per line. 91 */ 92 protected int _currInputRowStart; 93 94 /* 95 /********************************************************** 96 /* Information about starting location of event 97 /* Reader is pointing to; updated on-demand 98 /********************************************************** 99 */ 100 101 // // // Location info at point when current token was started 102 103 /** 104 * Total number of bytes/characters read before start of current token. 105 * For big (gigabyte-sized) sizes are possible, needs to be long, 106 * unlike pointers and sizes related to in-memory buffers. 107 */ 108 protected long _tokenInputTotal; 109 110 /** 111 * Input row on which current token starts, 1-based 112 */ 113 protected int _tokenInputRow = 1; 114 115 /** 116 * Column on input row that current token starts; 0-based (although 117 * in the end it'll be converted to 1-based) 118 */ 119 protected int _tokenInputCol; 120 121 /* 122 /********************************************************** 123 /* Parsing state 124 /********************************************************** 125 */ 126 127 /** 128 * Information about parser context, context in which 129 * the next token is to be parsed (root, array, object). 130 */ 131 protected JsonReadContext _parsingContext; 132 133 /** 134 * Secondary token related to the next token after current one; 135 * used if its type is known. This may be value token that 136 * follows FIELD_NAME, for example. 137 */ 138 protected JsonToken _nextToken; 139 140 /* 141 /********************************************************** 142 /* Buffer(s) for local name(s) and text content 143 /********************************************************** 144 */ 145 146 /** 147 * Buffer that contains contents of String values, including 148 * field names if necessary (name split across boundary, 149 * contains escape sequence, or access needed to char array) 150 */ 151 protected final TextBuffer _textBuffer; 152 153 /** 154 * Temporary buffer that is needed if field name is accessed 155 * using {@link #getTextCharacters} method (instead of String 156 * returning alternatives) 157 */ 158 protected char[] _nameCopyBuffer; 159 160 /** 161 * Flag set to indicate whether the field name is available 162 * from the name copy buffer or not (in addition to its String 163 * representation being available via read context) 164 */ 165 protected boolean _nameCopied; 166 167 /** 168 * ByteArrayBuilder is needed if 'getBinaryValue' is called. If so, 169 * we better reuse it for remainder of content. 170 */ 171 protected ByteArrayBuilder _byteArrayBuilder; 172 173 /** 174 * We will hold on to decoded binary data, for duration of 175 * current event, so that multiple calls to 176 * {@link #getBinaryValue} will not need to decode data more 177 * than once. 178 */ 179 protected byte[] _binaryValue; 180 181 // Numeric value holders: multiple fields used for 182 // for efficiency 183 184 /** 185 * Bitfield that indicates which numeric representations 186 * have been calculated for the current type 187 */ 188 protected int _numTypesValid = NR_UNKNOWN; 189 190 // First primitives 191 192 protected int _numberInt; 193 194 protected long _numberLong; 195 196 protected double _numberDouble; 197 198 // And then object types 199 200 protected BigInteger _numberBigInt; 201 202 protected BigDecimal _numberBigDecimal; 203 204 // And then other information about value itself 205 206 /** 207 * Flag that indicates whether numeric value has a negative 208 * value. That is, whether its textual representation starts 209 * with minus character. 210 */ 211 protected boolean _numberNegative; 212 213 /** 214 * Length of integer part of the number, in characters 215 */ 216 protected int _intLength; 217 218 /** 219 * Length of the fractional part (not including decimal 220 * point or exponent), in characters. 221 * Not used for pure integer values. 222 */ 223 protected int _fractLength; 224 225 /** 226 * Length of the exponent part of the number, if any, not 227 * including 'e' marker or sign, just digits. 228 * Not used for pure integer values. 229 */ 230 protected int _expLength; 231 232 /* 233 /********************************************************** 234 /* Life-cycle 235 /********************************************************** 236 */ 237 ParserBase(IOContext ctxt, int features)238 protected ParserBase(IOContext ctxt, int features) { 239 super(features); 240 _ioContext = ctxt; 241 _textBuffer = ctxt.constructTextBuffer(); 242 DupDetector dups = Feature.STRICT_DUPLICATE_DETECTION.enabledIn(features) 243 ? DupDetector.rootDetector(this) : null; 244 _parsingContext = JsonReadContext.createRootContext(dups); 245 } 246 version()247 @Override public Version version() { return PackageVersion.VERSION; } 248 249 @Override getCurrentValue()250 public Object getCurrentValue() { 251 return _parsingContext.getCurrentValue(); 252 } 253 254 @Override setCurrentValue(Object v)255 public void setCurrentValue(Object v) { 256 _parsingContext.setCurrentValue(v); 257 } 258 259 /* 260 /********************************************************** 261 /* Overrides for Feature handling 262 /********************************************************** 263 */ 264 265 @Override enable(Feature f)266 public JsonParser enable(Feature f) { 267 _features |= f.getMask(); 268 if (f == Feature.STRICT_DUPLICATE_DETECTION) { // enabling dup detection? 269 if (_parsingContext.getDupDetector() == null) { // but only if disabled currently 270 _parsingContext = _parsingContext.withDupDetector(DupDetector.rootDetector(this)); 271 } 272 } 273 return this; 274 } 275 276 @Override disable(Feature f)277 public JsonParser disable(Feature f) { 278 _features &= ~f.getMask(); 279 if (f == Feature.STRICT_DUPLICATE_DETECTION) { 280 _parsingContext = _parsingContext.withDupDetector(null); 281 } 282 return this; 283 } 284 285 @Override 286 @Deprecated setFeatureMask(int newMask)287 public JsonParser setFeatureMask(int newMask) { 288 int changes = (_features ^ newMask); 289 if (changes != 0) { 290 _features = newMask; 291 _checkStdFeatureChanges(newMask, changes); 292 } 293 return this; 294 } 295 296 @Override // since 2.7 overrideStdFeatures(int values, int mask)297 public JsonParser overrideStdFeatures(int values, int mask) { 298 int oldState = _features; 299 int newState = (oldState & ~mask) | (values & mask); 300 int changed = oldState ^ newState; 301 if (changed != 0) { 302 _features = newState; 303 _checkStdFeatureChanges(newState, changed); 304 } 305 return this; 306 } 307 308 /** 309 * Helper method called to verify changes to standard features. 310 * 311 * @param newFeatureFlags Bitflag of standard features after they were changed 312 * @param changedFeatures Bitflag of standard features for which setting 313 * did change 314 * 315 * @since 2.7 316 */ _checkStdFeatureChanges(int newFeatureFlags, int changedFeatures)317 protected void _checkStdFeatureChanges(int newFeatureFlags, int changedFeatures) 318 { 319 int f = Feature.STRICT_DUPLICATE_DETECTION.getMask(); 320 321 if ((changedFeatures & f) != 0) { 322 if ((newFeatureFlags & f) != 0) { 323 if (_parsingContext.getDupDetector() == null) { 324 _parsingContext = _parsingContext.withDupDetector(DupDetector.rootDetector(this)); 325 } else { // disabling 326 _parsingContext = _parsingContext.withDupDetector(null); 327 } 328 } 329 } 330 } 331 332 /* 333 /********************************************************** 334 /* JsonParser impl 335 /********************************************************** 336 */ 337 338 /** 339 * Method that can be called to get the name associated with 340 * the current event. 341 */ getCurrentName()342 @Override public String getCurrentName() throws IOException { 343 // [JACKSON-395]: start markers require information from parent 344 if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { 345 JsonReadContext parent = _parsingContext.getParent(); 346 if (parent != null) { 347 return parent.getCurrentName(); 348 } 349 } 350 return _parsingContext.getCurrentName(); 351 } 352 overrideCurrentName(String name)353 @Override public void overrideCurrentName(String name) { 354 // Simple, but need to look for START_OBJECT/ARRAY's "off-by-one" thing: 355 JsonReadContext ctxt = _parsingContext; 356 if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { 357 ctxt = ctxt.getParent(); 358 } 359 // 24-Sep-2013, tatu: Unfortunate, but since we did not expose exceptions, 360 // need to wrap this here 361 try { 362 ctxt.setCurrentName(name); 363 } catch (IOException e) { 364 throw new IllegalStateException(e); 365 } 366 } 367 close()368 @Override public void close() throws IOException { 369 if (!_closed) { 370 // 19-Jan-2018, tatu: as per [core#440] need to ensure no more data assumed available 371 _inputPtr = Math.max(_inputPtr, _inputEnd); 372 _closed = true; 373 try { 374 _closeInput(); 375 } finally { 376 // as per [JACKSON-324], do in finally block 377 // Also, internal buffer(s) can now be released as well 378 _releaseBuffers(); 379 } 380 } 381 } 382 isClosed()383 @Override public boolean isClosed() { return _closed; } getParsingContext()384 @Override public JsonReadContext getParsingContext() { return _parsingContext; } 385 386 /** 387 * Method that return the <b>starting</b> location of the current 388 * token; that is, position of the first character from input 389 * that starts the current token. 390 */ 391 @Override getTokenLocation()392 public JsonLocation getTokenLocation() { 393 return new JsonLocation(_getSourceReference(), 394 -1L, getTokenCharacterOffset(), // bytes, chars 395 getTokenLineNr(), 396 getTokenColumnNr()); 397 } 398 399 /** 400 * Method that returns location of the last processed character; 401 * usually for error reporting purposes 402 */ 403 @Override getCurrentLocation()404 public JsonLocation getCurrentLocation() { 405 int col = _inputPtr - _currInputRowStart + 1; // 1-based 406 return new JsonLocation(_getSourceReference(), 407 -1L, _currInputProcessed + _inputPtr, // bytes, chars 408 _currInputRow, col); 409 } 410 411 /* 412 /********************************************************** 413 /* Public API, access to token information, text and similar 414 /********************************************************** 415 */ 416 417 @Override hasTextCharacters()418 public boolean hasTextCharacters() { 419 if (_currToken == JsonToken.VALUE_STRING) { return true; } // usually true 420 if (_currToken == JsonToken.FIELD_NAME) { return _nameCopied; } 421 return false; 422 } 423 424 @SuppressWarnings("resource") 425 @Override // since 2.7 getBinaryValue(Base64Variant variant)426 public byte[] getBinaryValue(Base64Variant variant) throws IOException 427 { 428 if (_binaryValue == null) { 429 if (_currToken != JsonToken.VALUE_STRING) { 430 _reportError("Current token ("+_currToken+") not VALUE_STRING, can not access as binary"); 431 } 432 ByteArrayBuilder builder = _getByteArrayBuilder(); 433 _decodeBase64(getText(), builder, variant); 434 _binaryValue = builder.toByteArray(); 435 } 436 return _binaryValue; 437 } 438 439 /* 440 /********************************************************** 441 /* Public low-level accessors 442 /********************************************************** 443 */ 444 getTokenCharacterOffset()445 public long getTokenCharacterOffset() { return _tokenInputTotal; } getTokenLineNr()446 public int getTokenLineNr() { return _tokenInputRow; } getTokenColumnNr()447 public int getTokenColumnNr() { 448 // note: value of -1 means "not available"; otherwise convert from 0-based to 1-based 449 int col = _tokenInputCol; 450 return (col < 0) ? col : (col + 1); 451 } 452 453 /* 454 /********************************************************** 455 /* Abstract methods for sub-classes to implement 456 /********************************************************** 457 */ 458 _closeInput()459 protected abstract void _closeInput() throws IOException; 460 461 /* 462 /********************************************************** 463 /* Low-level reading, other 464 /********************************************************** 465 */ 466 467 /** 468 * Method called to release internal buffers owned by the base 469 * reader. This may be called along with {@link #_closeInput} (for 470 * example, when explicitly closing this reader instance), or 471 * separately (if need be). 472 */ _releaseBuffers()473 protected void _releaseBuffers() throws IOException { 474 _textBuffer.releaseBuffers(); 475 char[] buf = _nameCopyBuffer; 476 if (buf != null) { 477 _nameCopyBuffer = null; 478 _ioContext.releaseNameCopyBuffer(buf); 479 } 480 } 481 482 /** 483 * Method called when an EOF is encountered between tokens. 484 * If so, it may be a legitimate EOF, but only iff there 485 * is no open non-root context. 486 */ 487 @Override _handleEOF()488 protected void _handleEOF() throws JsonParseException { 489 if (!_parsingContext.inRoot()) { 490 String marker = _parsingContext.inArray() ? "Array" : "Object"; 491 _reportInvalidEOF(String.format( 492 ": expected close marker for %s (start marker at %s)", 493 marker, 494 _parsingContext.getStartLocation(_getSourceReference())), 495 null); 496 } 497 } 498 499 /** 500 * @since 2.4 501 */ _eofAsNextChar()502 protected final int _eofAsNextChar() throws JsonParseException { 503 _handleEOF(); 504 return -1; 505 } 506 507 /* 508 /********************************************************** 509 /* Internal/package methods: shared/reusable builders 510 /********************************************************** 511 */ 512 _getByteArrayBuilder()513 public ByteArrayBuilder _getByteArrayBuilder() 514 { 515 if (_byteArrayBuilder == null) { 516 _byteArrayBuilder = new ByteArrayBuilder(); 517 } else { 518 _byteArrayBuilder.reset(); 519 } 520 return _byteArrayBuilder; 521 } 522 523 /* 524 /********************************************************** 525 /* Methods from former JsonNumericParserBase 526 /********************************************************** 527 */ 528 529 // // // Life-cycle of number-parsing 530 reset(boolean negative, int intLen, int fractLen, int expLen)531 protected final JsonToken reset(boolean negative, int intLen, int fractLen, int expLen) 532 { 533 if (fractLen < 1 && expLen < 1) { // integer 534 return resetInt(negative, intLen); 535 } 536 return resetFloat(negative, intLen, fractLen, expLen); 537 } 538 resetInt(boolean negative, int intLen)539 protected final JsonToken resetInt(boolean negative, int intLen) 540 { 541 _numberNegative = negative; 542 _intLength = intLen; 543 _fractLength = 0; 544 _expLength = 0; 545 _numTypesValid = NR_UNKNOWN; // to force parsing 546 return JsonToken.VALUE_NUMBER_INT; 547 } 548 resetFloat(boolean negative, int intLen, int fractLen, int expLen)549 protected final JsonToken resetFloat(boolean negative, int intLen, int fractLen, int expLen) 550 { 551 _numberNegative = negative; 552 _intLength = intLen; 553 _fractLength = fractLen; 554 _expLength = expLen; 555 _numTypesValid = NR_UNKNOWN; // to force parsing 556 return JsonToken.VALUE_NUMBER_FLOAT; 557 } 558 resetAsNaN(String valueStr, double value)559 protected final JsonToken resetAsNaN(String valueStr, double value) 560 { 561 _textBuffer.resetWithString(valueStr); 562 _numberDouble = value; 563 _numTypesValid = NR_DOUBLE; 564 return JsonToken.VALUE_NUMBER_FLOAT; 565 } 566 567 @Override isNaN()568 public boolean isNaN() { 569 if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) { 570 if ((_numTypesValid & NR_DOUBLE) != 0) { 571 // 10-Mar-2017, tatu: Alas, `Double.isFinite(d)` only added in JDK 8 572 double d = _numberDouble; 573 return Double.isNaN(d) || Double.isInfinite(d); 574 } 575 } 576 return false; 577 } 578 579 /* 580 /********************************************************** 581 /* Numeric accessors of public API 582 /********************************************************** 583 */ 584 585 @Override getNumberValue()586 public Number getNumberValue() throws IOException 587 { 588 if (_numTypesValid == NR_UNKNOWN) { 589 _parseNumericValue(NR_UNKNOWN); // will also check event type 590 } 591 // Separate types for int types 592 if (_currToken == JsonToken.VALUE_NUMBER_INT) { 593 if ((_numTypesValid & NR_INT) != 0) { 594 return _numberInt; 595 } 596 if ((_numTypesValid & NR_LONG) != 0) { 597 return _numberLong; 598 } 599 if ((_numTypesValid & NR_BIGINT) != 0) { 600 return _numberBigInt; 601 } 602 _throwInternal(); 603 } 604 605 // And then floating point types. But here optimal type 606 // needs to be big decimal, to avoid losing any data? 607 if ((_numTypesValid & NR_BIGDECIMAL) != 0) { 608 return _numberBigDecimal; 609 } 610 if ((_numTypesValid & NR_DOUBLE) == 0) { // sanity check 611 _throwInternal(); 612 } 613 return _numberDouble; 614 } 615 616 // NOTE: mostly copied from above 617 @Override getNumberValueExact()618 public Number getNumberValueExact() throws IOException 619 { 620 if (_currToken == JsonToken.VALUE_NUMBER_INT) { 621 if (_numTypesValid == NR_UNKNOWN) { 622 _parseNumericValue(NR_UNKNOWN); 623 } 624 if ((_numTypesValid & NR_INT) != 0) { 625 return _numberInt; 626 } 627 if ((_numTypesValid & NR_LONG) != 0) { 628 return _numberLong; 629 } 630 if ((_numTypesValid & NR_BIGINT) != 0) { 631 return _numberBigInt; 632 } 633 _throwInternal(); 634 } 635 // 09-Jul-2020, tatu: [databind#2644] requires we will retain accuracy, so: 636 if (_numTypesValid == NR_UNKNOWN) { 637 _parseNumericValue(NR_BIGDECIMAL); 638 } 639 if ((_numTypesValid & NR_BIGDECIMAL) != 0) { 640 return _numberBigDecimal; 641 } 642 if ((_numTypesValid & NR_DOUBLE) == 0) { // sanity check 643 _throwInternal(); 644 } 645 return _numberDouble; 646 } 647 648 @Override getNumberType()649 public NumberType getNumberType() throws IOException 650 { 651 if (_numTypesValid == NR_UNKNOWN) { 652 _parseNumericValue(NR_UNKNOWN); // will also check event type 653 } 654 if (_currToken == JsonToken.VALUE_NUMBER_INT) { 655 if ((_numTypesValid & NR_INT) != 0) { 656 return NumberType.INT; 657 } 658 if ((_numTypesValid & NR_LONG) != 0) { 659 return NumberType.LONG; 660 } 661 return NumberType.BIG_INTEGER; 662 } 663 664 /* And then floating point types. Here optimal type 665 * needs to be big decimal, to avoid losing any data? 666 * However... using BD is slow, so let's allow returning 667 * double as type if no explicit call has been made to access 668 * data as BD? 669 */ 670 if ((_numTypesValid & NR_BIGDECIMAL) != 0) { 671 return NumberType.BIG_DECIMAL; 672 } 673 return NumberType.DOUBLE; 674 } 675 676 @Override getIntValue()677 public int getIntValue() throws IOException 678 { 679 if ((_numTypesValid & NR_INT) == 0) { 680 if (_numTypesValid == NR_UNKNOWN) { // not parsed at all 681 return _parseIntValue(); 682 } 683 if ((_numTypesValid & NR_INT) == 0) { // wasn't an int natively? 684 convertNumberToInt(); // let's make it so, if possible 685 } 686 } 687 return _numberInt; 688 } 689 690 @Override getLongValue()691 public long getLongValue() throws IOException 692 { 693 if ((_numTypesValid & NR_LONG) == 0) { 694 if (_numTypesValid == NR_UNKNOWN) { 695 _parseNumericValue(NR_LONG); 696 } 697 if ((_numTypesValid & NR_LONG) == 0) { 698 convertNumberToLong(); 699 } 700 } 701 return _numberLong; 702 } 703 704 @Override getBigIntegerValue()705 public BigInteger getBigIntegerValue() throws IOException 706 { 707 if ((_numTypesValid & NR_BIGINT) == 0) { 708 if (_numTypesValid == NR_UNKNOWN) { 709 _parseNumericValue(NR_BIGINT); 710 } 711 if ((_numTypesValid & NR_BIGINT) == 0) { 712 convertNumberToBigInteger(); 713 } 714 } 715 return _numberBigInt; 716 } 717 718 @Override getFloatValue()719 public float getFloatValue() throws IOException 720 { 721 double value = getDoubleValue(); 722 /* 22-Jan-2009, tatu: Bounds/range checks would be tricky 723 * here, so let's not bother even trying... 724 */ 725 /* 726 if (value < -Float.MAX_VALUE || value > MAX_FLOAT_D) { 727 _reportError("Numeric value ("+getText()+") out of range of Java float"); 728 } 729 */ 730 return (float) value; 731 } 732 733 @Override getDoubleValue()734 public double getDoubleValue() throws IOException 735 { 736 if ((_numTypesValid & NR_DOUBLE) == 0) { 737 if (_numTypesValid == NR_UNKNOWN) { 738 _parseNumericValue(NR_DOUBLE); 739 } 740 if ((_numTypesValid & NR_DOUBLE) == 0) { 741 convertNumberToDouble(); 742 } 743 } 744 return _numberDouble; 745 } 746 747 @Override getDecimalValue()748 public BigDecimal getDecimalValue() throws IOException 749 { 750 if ((_numTypesValid & NR_BIGDECIMAL) == 0) { 751 if (_numTypesValid == NR_UNKNOWN) { 752 _parseNumericValue(NR_BIGDECIMAL); 753 } 754 if ((_numTypesValid & NR_BIGDECIMAL) == 0) { 755 convertNumberToBigDecimal(); 756 } 757 } 758 return _numberBigDecimal; 759 } 760 761 /* 762 /********************************************************** 763 /* Conversion from textual to numeric representation 764 /********************************************************** 765 */ 766 767 /** 768 * Method that will parse actual numeric value out of a syntactically 769 * valid number value. Type it will parse into depends on whether 770 * it is a floating point number, as well as its magnitude: smallest 771 * legal type (of ones available) is used for efficiency. 772 * 773 * @param expType Numeric type that we will immediately need, if any; 774 * mostly necessary to optimize handling of floating point numbers 775 */ _parseNumericValue(int expType)776 protected void _parseNumericValue(int expType) throws IOException 777 { 778 // 12-Jun-2020, tatu: Sanity check to prevent more cryptic error for this case. 779 // (note: could alternatively see if TextBuffer has aggregated contents, avoid 780 // exception -- but that might be more confusing) 781 if (_closed) { 782 _reportError("Internal error: _parseNumericValue called when parser instance closed"); 783 } 784 785 // Int or float? 786 if (_currToken == JsonToken.VALUE_NUMBER_INT) { 787 final int len = _intLength; 788 // First: optimization for simple int 789 if (len <= 9) { 790 int i = _textBuffer.contentsAsInt(_numberNegative); 791 _numberInt = i; 792 _numTypesValid = NR_INT; 793 return; 794 } 795 if (len <= 18) { // definitely fits AND is easy to parse using 2 int parse calls 796 long l = _textBuffer.contentsAsLong(_numberNegative); 797 // Might still fit in int, need to check 798 if (len == 10) { 799 if (_numberNegative) { 800 if (l >= MIN_INT_L) { 801 _numberInt = (int) l; 802 _numTypesValid = NR_INT; 803 return; 804 } 805 } else { 806 if (l <= MAX_INT_L) { 807 _numberInt = (int) l; 808 _numTypesValid = NR_INT; 809 return; 810 } 811 } 812 } 813 _numberLong = l; 814 _numTypesValid = NR_LONG; 815 return; 816 } 817 _parseSlowInt(expType); 818 return; 819 } 820 if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) { 821 _parseSlowFloat(expType); 822 return; 823 } 824 _reportError("Current token (%s) not numeric, can not use numeric value accessors", _currToken); 825 } 826 827 /** 828 * @since 2.6 829 */ _parseIntValue()830 protected int _parseIntValue() throws IOException 831 { 832 // 12-Jun-2020, tatu: Sanity check to prevent more cryptic error for this case. 833 // (note: could alternatively see if TextBuffer has aggregated contents, avoid 834 // exception -- but that might be more confusing) 835 if (_closed) { 836 _reportError("Internal error: _parseNumericValue called when parser instance closed"); 837 } 838 // Inlined variant of: _parseNumericValue(NR_INT) 839 if (_currToken == JsonToken.VALUE_NUMBER_INT) { 840 if (_intLength <= 9) { 841 int i = _textBuffer.contentsAsInt(_numberNegative); 842 _numberInt = i; 843 _numTypesValid = NR_INT; 844 return i; 845 } 846 } 847 // if not optimizable, use more generic 848 _parseNumericValue(NR_INT); 849 if ((_numTypesValid & NR_INT) == 0) { 850 convertNumberToInt(); 851 } 852 return _numberInt; 853 } 854 _parseSlowFloat(int expType)855 private void _parseSlowFloat(int expType) throws IOException 856 { 857 /* Nope: floating point. Here we need to be careful to get 858 * optimal parsing strategy: choice is between accurate but 859 * slow (BigDecimal) and lossy but fast (Double). For now 860 * let's only use BD when explicitly requested -- it can 861 * still be constructed correctly at any point since we do 862 * retain textual representation 863 */ 864 try { 865 if (expType == NR_BIGDECIMAL) { 866 _numberBigDecimal = _textBuffer.contentsAsDecimal(); 867 _numTypesValid = NR_BIGDECIMAL; 868 } else { 869 // Otherwise double has to do 870 _numberDouble = _textBuffer.contentsAsDouble(); 871 _numTypesValid = NR_DOUBLE; 872 } 873 } catch (NumberFormatException nex) { 874 // Can this ever occur? Due to overflow, maybe? 875 _wrapError("Malformed numeric value ("+_longNumberDesc(_textBuffer.contentsAsString())+")", nex); 876 } 877 } 878 _parseSlowInt(int expType)879 private void _parseSlowInt(int expType) throws IOException 880 { 881 String numStr = _textBuffer.contentsAsString(); 882 try { 883 int len = _intLength; 884 char[] buf = _textBuffer.getTextBuffer(); 885 int offset = _textBuffer.getTextOffset(); 886 if (_numberNegative) { 887 ++offset; 888 } 889 // Some long cases still... 890 if (NumberInput.inLongRange(buf, offset, len, _numberNegative)) { 891 // Probably faster to construct a String, call parse, than to use BigInteger 892 _numberLong = Long.parseLong(numStr); 893 _numTypesValid = NR_LONG; 894 } else { 895 // 16-Oct-2018, tatu: Need to catch "too big" early due to [jackson-core#488] 896 if ((expType == NR_INT) || (expType == NR_LONG)) { 897 _reportTooLongIntegral(expType, numStr); 898 } 899 if ((expType == NR_DOUBLE) || (expType == NR_FLOAT)) { 900 _numberDouble = NumberInput.parseDouble(numStr); 901 _numTypesValid = NR_DOUBLE; 902 } else { 903 // nope, need the heavy guns... (rare case) 904 _numberBigInt = new BigInteger(numStr); 905 _numTypesValid = NR_BIGINT; 906 } 907 } 908 } catch (NumberFormatException nex) { 909 // Can this ever occur? Due to overflow, maybe? 910 _wrapError("Malformed numeric value ("+_longNumberDesc(numStr)+")", nex); 911 } 912 } 913 914 // @since 2.9.8 _reportTooLongIntegral(int expType, String rawNum)915 protected void _reportTooLongIntegral(int expType, String rawNum) throws IOException 916 { 917 if (expType == NR_INT) { 918 reportOverflowInt(rawNum); 919 } else { 920 reportOverflowLong(rawNum); 921 } 922 } 923 924 /* 925 /********************************************************** 926 /* Numeric conversions 927 /********************************************************** 928 */ 929 convertNumberToInt()930 protected void convertNumberToInt() throws IOException 931 { 932 // First, converting from long ought to be easy 933 if ((_numTypesValid & NR_LONG) != 0) { 934 // Let's verify it's lossless conversion by simple roundtrip 935 int result = (int) _numberLong; 936 if (((long) result) != _numberLong) { 937 reportOverflowInt(getText(), currentToken()); 938 } 939 _numberInt = result; 940 } else if ((_numTypesValid & NR_BIGINT) != 0) { 941 if (BI_MIN_INT.compareTo(_numberBigInt) > 0 942 || BI_MAX_INT.compareTo(_numberBigInt) < 0) { 943 reportOverflowInt(); 944 } 945 _numberInt = _numberBigInt.intValue(); 946 } else if ((_numTypesValid & NR_DOUBLE) != 0) { 947 // Need to check boundaries 948 if (_numberDouble < MIN_INT_D || _numberDouble > MAX_INT_D) { 949 reportOverflowInt(); 950 } 951 _numberInt = (int) _numberDouble; 952 } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) { 953 if (BD_MIN_INT.compareTo(_numberBigDecimal) > 0 954 || BD_MAX_INT.compareTo(_numberBigDecimal) < 0) { 955 reportOverflowInt(); 956 } 957 _numberInt = _numberBigDecimal.intValue(); 958 } else { 959 _throwInternal(); 960 } 961 _numTypesValid |= NR_INT; 962 } 963 convertNumberToLong()964 protected void convertNumberToLong() throws IOException 965 { 966 if ((_numTypesValid & NR_INT) != 0) { 967 _numberLong = (long) _numberInt; 968 } else if ((_numTypesValid & NR_BIGINT) != 0) { 969 if (BI_MIN_LONG.compareTo(_numberBigInt) > 0 970 || BI_MAX_LONG.compareTo(_numberBigInt) < 0) { 971 reportOverflowLong(); 972 } 973 _numberLong = _numberBigInt.longValue(); 974 } else if ((_numTypesValid & NR_DOUBLE) != 0) { 975 // Need to check boundaries 976 if (_numberDouble < MIN_LONG_D || _numberDouble > MAX_LONG_D) { 977 reportOverflowLong(); 978 } 979 _numberLong = (long) _numberDouble; 980 } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) { 981 if (BD_MIN_LONG.compareTo(_numberBigDecimal) > 0 982 || BD_MAX_LONG.compareTo(_numberBigDecimal) < 0) { 983 reportOverflowLong(); 984 } 985 _numberLong = _numberBigDecimal.longValue(); 986 } else { 987 _throwInternal(); 988 } 989 _numTypesValid |= NR_LONG; 990 } 991 convertNumberToBigInteger()992 protected void convertNumberToBigInteger() throws IOException 993 { 994 if ((_numTypesValid & NR_BIGDECIMAL) != 0) { 995 // here it'll just get truncated, no exceptions thrown 996 _numberBigInt = _numberBigDecimal.toBigInteger(); 997 } else if ((_numTypesValid & NR_LONG) != 0) { 998 _numberBigInt = BigInteger.valueOf(_numberLong); 999 } else if ((_numTypesValid & NR_INT) != 0) { 1000 _numberBigInt = BigInteger.valueOf(_numberInt); 1001 } else if ((_numTypesValid & NR_DOUBLE) != 0) { 1002 _numberBigInt = BigDecimal.valueOf(_numberDouble).toBigInteger(); 1003 } else { 1004 _throwInternal(); 1005 } 1006 _numTypesValid |= NR_BIGINT; 1007 } 1008 convertNumberToDouble()1009 protected void convertNumberToDouble() throws IOException 1010 { 1011 /* 05-Aug-2008, tatus: Important note: this MUST start with 1012 * more accurate representations, since we don't know which 1013 * value is the original one (others get generated when 1014 * requested) 1015 */ 1016 1017 if ((_numTypesValid & NR_BIGDECIMAL) != 0) { 1018 _numberDouble = _numberBigDecimal.doubleValue(); 1019 } else if ((_numTypesValid & NR_BIGINT) != 0) { 1020 _numberDouble = _numberBigInt.doubleValue(); 1021 } else if ((_numTypesValid & NR_LONG) != 0) { 1022 _numberDouble = (double) _numberLong; 1023 } else if ((_numTypesValid & NR_INT) != 0) { 1024 _numberDouble = (double) _numberInt; 1025 } else { 1026 _throwInternal(); 1027 } 1028 _numTypesValid |= NR_DOUBLE; 1029 } 1030 convertNumberToBigDecimal()1031 protected void convertNumberToBigDecimal() throws IOException 1032 { 1033 /* 05-Aug-2008, tatus: Important note: this MUST start with 1034 * more accurate representations, since we don't know which 1035 * value is the original one (others get generated when 1036 * requested) 1037 */ 1038 1039 if ((_numTypesValid & NR_DOUBLE) != 0) { 1040 /* Let's actually parse from String representation, to avoid 1041 * rounding errors that non-decimal floating operations could incur 1042 */ 1043 _numberBigDecimal = NumberInput.parseBigDecimal(getText()); 1044 } else if ((_numTypesValid & NR_BIGINT) != 0) { 1045 _numberBigDecimal = new BigDecimal(_numberBigInt); 1046 } else if ((_numTypesValid & NR_LONG) != 0) { 1047 _numberBigDecimal = BigDecimal.valueOf(_numberLong); 1048 } else if ((_numTypesValid & NR_INT) != 0) { 1049 _numberBigDecimal = BigDecimal.valueOf(_numberInt); 1050 } else { 1051 _throwInternal(); 1052 } 1053 _numTypesValid |= NR_BIGDECIMAL; 1054 } 1055 1056 /* 1057 /********************************************************** 1058 /* Internal/package methods: Error reporting 1059 /********************************************************** 1060 */ 1061 _reportMismatchedEndMarker(int actCh, char expCh)1062 protected void _reportMismatchedEndMarker(int actCh, char expCh) throws JsonParseException { 1063 JsonReadContext ctxt = getParsingContext(); 1064 _reportError(String.format( 1065 "Unexpected close marker '%s': expected '%c' (for %s starting at %s)", 1066 (char) actCh, expCh, ctxt.typeDesc(), ctxt.getStartLocation(_getSourceReference()))); 1067 } 1068 1069 @SuppressWarnings("deprecation") _handleUnrecognizedCharacterEscape(char ch)1070 protected char _handleUnrecognizedCharacterEscape(char ch) throws JsonProcessingException { 1071 // as per [JACKSON-300] 1072 if (isEnabled(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)) { 1073 return ch; 1074 } 1075 // and [JACKSON-548] 1076 if (ch == '\'' && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) { 1077 return ch; 1078 } 1079 _reportError("Unrecognized character escape "+_getCharDesc(ch)); 1080 return ch; 1081 } 1082 1083 /** 1084 * Method called to report a problem with unquoted control character. 1085 * Note: it is possible to suppress some instances of 1086 * exception by enabling {@link Feature#ALLOW_UNQUOTED_CONTROL_CHARS}. 1087 */ 1088 @SuppressWarnings("deprecation") _throwUnquotedSpace(int i, String ctxtDesc)1089 protected void _throwUnquotedSpace(int i, String ctxtDesc) throws JsonParseException { 1090 // JACKSON-208; possible to allow unquoted control chars: 1091 if (!isEnabled(Feature.ALLOW_UNQUOTED_CONTROL_CHARS) || i > INT_SPACE) { 1092 char c = (char) i; 1093 String msg = "Illegal unquoted character ("+_getCharDesc(c)+"): has to be escaped using backslash to be included in "+ctxtDesc; 1094 _reportError(msg); 1095 } 1096 } 1097 1098 /** 1099 * @return Description to use as "valid tokens" in an exception message about 1100 * invalid (unrecognized) JSON token: called when parser finds something that 1101 * looks like unquoted textual token 1102 * 1103 * @since 2.10 1104 */ _validJsonTokenList()1105 protected String _validJsonTokenList() throws IOException { 1106 return _validJsonValueList(); 1107 } 1108 1109 /** 1110 * @return Description to use as "valid JSON values" in an exception message about 1111 * invalid (unrecognized) JSON value: called when parser finds something that 1112 * does not look like a value or separator. 1113 * 1114 * @since 2.10 1115 */ 1116 @SuppressWarnings("deprecation") _validJsonValueList()1117 protected String _validJsonValueList() throws IOException { 1118 if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { 1119 return "(JSON String, Number (or 'NaN'/'INF'/'+INF'), Array, Object or token 'null', 'true' or 'false')"; 1120 } 1121 return "(JSON String, Number, Array, Object or token 'null', 'true' or 'false')"; 1122 } 1123 1124 /* 1125 /********************************************************** 1126 /* Base64 handling support 1127 /********************************************************** 1128 */ 1129 1130 /** 1131 * Method that sub-classes must implement to support escaped sequences 1132 * in base64-encoded sections. 1133 * Sub-classes that do not need base64 support can leave this as is 1134 */ _decodeEscaped()1135 protected char _decodeEscaped() throws IOException { 1136 throw new UnsupportedOperationException(); 1137 } 1138 _decodeBase64Escape(Base64Variant b64variant, int ch, int index)1139 protected final int _decodeBase64Escape(Base64Variant b64variant, int ch, int index) throws IOException 1140 { 1141 // 17-May-2011, tatu: As per [JACKSON-xxx], need to handle escaped chars 1142 if (ch != '\\') { 1143 throw reportInvalidBase64Char(b64variant, ch, index); 1144 } 1145 int unescaped = _decodeEscaped(); 1146 // if white space, skip if first triplet; otherwise errors 1147 if (unescaped <= INT_SPACE) { 1148 if (index == 0) { // whitespace only allowed to be skipped between triplets 1149 return -1; 1150 } 1151 } 1152 // otherwise try to find actual triplet value 1153 int bits = b64variant.decodeBase64Char(unescaped); 1154 if (bits < 0) { 1155 if (bits != Base64Variant.BASE64_VALUE_PADDING) { 1156 throw reportInvalidBase64Char(b64variant, unescaped, index); 1157 } 1158 } 1159 return bits; 1160 } 1161 _decodeBase64Escape(Base64Variant b64variant, char ch, int index)1162 protected final int _decodeBase64Escape(Base64Variant b64variant, char ch, int index) throws IOException 1163 { 1164 if (ch != '\\') { 1165 throw reportInvalidBase64Char(b64variant, ch, index); 1166 } 1167 char unescaped = _decodeEscaped(); 1168 // if white space, skip if first triplet; otherwise errors 1169 if (unescaped <= INT_SPACE) { 1170 if (index == 0) { // whitespace only allowed to be skipped between triplets 1171 return -1; 1172 } 1173 } 1174 // otherwise try to find actual triplet value 1175 int bits = b64variant.decodeBase64Char(unescaped); 1176 if (bits < 0) { 1177 // second check since padding can only be 3rd or 4th byte (index #2 or #3) 1178 if ((bits != Base64Variant.BASE64_VALUE_PADDING) || (index < 2)) { 1179 throw reportInvalidBase64Char(b64variant, unescaped, index); 1180 } 1181 } 1182 return bits; 1183 } 1184 reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex)1185 protected IllegalArgumentException reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex) throws IllegalArgumentException { 1186 return reportInvalidBase64Char(b64variant, ch, bindex, null); 1187 } 1188 1189 /** 1190 * @param bindex Relative index within base64 character unit; between 0 1191 * and 3 (as unit has exactly 4 characters) 1192 */ reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex, String msg)1193 protected IllegalArgumentException reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex, String msg) throws IllegalArgumentException { 1194 String base; 1195 if (ch <= INT_SPACE) { 1196 base = String.format("Illegal white space character (code 0x%s) as character #%d of 4-char base64 unit: can only used between units", 1197 Integer.toHexString(ch), (bindex+1)); 1198 } else if (b64variant.usesPaddingChar(ch)) { 1199 base = "Unexpected padding character ('"+b64variant.getPaddingChar()+"') as character #"+(bindex+1)+" of 4-char base64 unit: padding only legal as 3rd or 4th character"; 1200 } else if (!Character.isDefined(ch) || Character.isISOControl(ch)) { 1201 // Not sure if we can really get here... ? (most illegal xml chars are caught at lower level) 1202 base = "Illegal character (code 0x"+Integer.toHexString(ch)+") in base64 content"; 1203 } else { 1204 base = "Illegal character '"+((char)ch)+"' (code 0x"+Integer.toHexString(ch)+") in base64 content"; 1205 } 1206 if (msg != null) { 1207 base = base + ": " + msg; 1208 } 1209 return new IllegalArgumentException(base); 1210 } 1211 1212 // since 2.9.8 _handleBase64MissingPadding(Base64Variant b64variant)1213 protected void _handleBase64MissingPadding(Base64Variant b64variant) throws IOException 1214 { 1215 _reportError(b64variant.missingPaddingMessage()); 1216 } 1217 1218 /* 1219 /********************************************************** 1220 /* Internal/package methods: other 1221 /********************************************************** 1222 */ 1223 1224 /** 1225 * Helper method used to encapsulate logic of including (or not) of 1226 * "source reference" when constructing {@link JsonLocation} instances. 1227 * 1228 * @since 2.9 1229 */ _getSourceReference()1230 protected Object _getSourceReference() { 1231 if (JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION.enabledIn(_features)) { 1232 return _ioContext.getSourceReference(); 1233 } 1234 return null; 1235 } 1236 growArrayBy(int[] arr, int more)1237 protected static int[] growArrayBy(int[] arr, int more) 1238 { 1239 if (arr == null) { 1240 return new int[more]; 1241 } 1242 return Arrays.copyOf(arr, arr.length + more); 1243 } 1244 1245 /* 1246 /********************************************************** 1247 /* Stuff that was abstract and required before 2.8, but that 1248 /* is not mandatory in 2.8 or above. 1249 /********************************************************** 1250 */ 1251 1252 @Deprecated // since 2.8 loadMoreGuaranteed()1253 protected void loadMoreGuaranteed() throws IOException { 1254 if (!loadMore()) { _reportInvalidEOF(); } 1255 } 1256 1257 @Deprecated // since 2.8 loadMore()1258 protected boolean loadMore() throws IOException { return false; } 1259 1260 // Can't declare as deprecated, for now, but shouldn't be needed _finishString()1261 protected void _finishString() throws IOException { } 1262 } 1263