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.TextBuffer;
17
18 /**
19  * Intermediate base class used by all Jackson {@link JsonParser}
20  * implementations. Contains most common things that are independent
21  * of actual underlying input source.
22  */

23 public abstract class ParserBase extends ParserMinimalBase
24 {
25     /*
26     /**********************************************************
27     /* Generic I/O state
28     /**********************************************************
29      */

30
31     /**
32      * I/O context for this reader. It handles buffer allocation
33      * for the reader.
34      */

35     final protected IOContext _ioContext;
36
37     /**
38      * Flag that indicates whether parser is closed or not. Gets
39      * set when parser is either closed by explicit call
40      * ({@link #close}) or when end-of-input is reached.
41      */

42     protected boolean _closed;
43
44     /*
45     /**********************************************************
46     /* Current input data
47     /**********************************************************
48      */

49
50     // Note: type of actual buffer depends on sub-class, can't include
51
52     /**
53      * Pointer to next available character in buffer
54      */

55     protected int _inputPtr;
56
57     /**
58      * Index of character after last available one in the buffer.
59      */

60     protected int _inputEnd;
61
62     /*
63     /**********************************************************
64     /* Current input location information
65     /**********************************************************
66      */

67
68     /**
69      * Number of characters/bytes that were contained in previous blocks
70      * (blocks that were already processed prior to the current buffer).
71      */

72     protected long _currInputProcessed;
73
74     /**
75      * Current row location of current point in input buffer, starting
76      * from 1, if available.
77      */

78     protected int _currInputRow = 1;
79
80     /**
81      * Current index of the first character of the current row in input
82      * buffer. Needed to calculate column position, if necessary; benefit
83      * of not having column itself is that this only has to be updated
84      * once per line.
85      */

86     protected int _currInputRowStart;
87
88     /*
89     /**********************************************************
90     /* Information about starting location of event
91     /* Reader is pointing to; updated on-demand
92     /**********************************************************
93      */

94
95     // // // Location info at point when current token was started
96
97     /**
98      * Total number of bytes/characters read before start of current token.
99      * For big (gigabyte-sized) sizes are possible, needs to be long,
100      * unlike pointers and sizes related to in-memory buffers.
101      */

102     protected long _tokenInputTotal;
103
104     /**
105      * Input row on which current token starts, 1-based
106      */

107     protected int _tokenInputRow = 1;
108
109     /**
110      * Column on input row that current token starts; 0-based (although
111      * in the end it'll be converted to 1-based)
112      */

113     protected int _tokenInputCol;
114
115     /*
116     /**********************************************************
117     /* Parsing state
118     /**********************************************************
119      */

120
121     /**
122      * Information about parser context, context in which
123      * the next token is to be parsed (root, array, object).
124      */

125     protected JsonReadContext _parsingContext;
126     
127     /**
128      * Secondary token related to the next token after current one;
129      * used if its type is known. This may be value token that
130      * follows FIELD_NAME, for example.
131      */

132     protected JsonToken _nextToken;
133
134     /*
135     /**********************************************************
136     /* Buffer(s) for local name(s) and text content
137     /**********************************************************
138      */

139
140     /**
141      * Buffer that contains contents of String values, including
142      * field names if necessary (name split across boundary,
143      * contains escape sequence, or access needed to char array)
144      */

145     protected final TextBuffer _textBuffer;
146
147     /**
148      * Temporary buffer that is needed if field name is accessed
149      * using {@link #getTextCharacters} method (instead of String
150      * returning alternatives)
151      */

152     protected char[] _nameCopyBuffer;
153
154     /**
155      * Flag set to indicate whether the field name is available
156      * from the name copy buffer or not (in addition to its String
157      * representation  being available via read context)
158      */

159     protected boolean _nameCopied;
160
161     /**
162      * ByteArrayBuilder is needed if 'getBinaryValue' is called. If so,
163      * we better reuse it for remainder of content.
164      */

165     protected ByteArrayBuilder _byteArrayBuilder;
166
167     /**
168      * We will hold on to decoded binary data, for duration of
169      * current event, so that multiple calls to
170      * {@link #getBinaryValue} will not need to decode data more
171      * than once.
172      */

173     protected byte[] _binaryValue;
174
175     // Numeric value holders: multiple fields used for
176     // for efficiency
177
178     /**
179      * Bitfield that indicates which numeric representations
180      * have been calculated for the current type
181      */

182     protected int _numTypesValid = NR_UNKNOWN;
183
184     // First primitives
185
186     protected int _numberInt;
187
188     protected long _numberLong;
189
190     protected double _numberDouble;
191
192     // And then object types
193
194     protected BigInteger _numberBigInt;
195
196     protected BigDecimal _numberBigDecimal;
197
198     // And then other information about value itself
199
200     /**
201      * Flag that indicates whether numeric value has a negative
202      * value. That is, whether its textual representation starts
203      * with minus character.
204      */

205     protected boolean _numberNegative;
206
207     /**
208      * Length of integer part of the number, in characters
209      */

210     protected int _intLength;
211
212     /**
213      * Length of the fractional part (not including decimal
214      * point or exponent), in characters.
215      * Not used for  pure integer values.
216      */

217     protected int _fractLength;
218
219     /**
220      * Length of the exponent part of the number, if any, not
221      * including 'e' marker or sign, just digits. 
222      * Not used for  pure integer values.
223      */

224     protected int _expLength;
225
226     /*
227     /**********************************************************
228     /* Life-cycle
229     /**********************************************************
230      */

231
232     protected ParserBase(IOContext ctxt, int features) {
233         super(features);
234         _ioContext = ctxt;
235         _textBuffer = ctxt.constructTextBuffer();
236         DupDetector dups = Feature.STRICT_DUPLICATE_DETECTION.enabledIn(features)
237                 ? DupDetector.rootDetector(this) : null;
238         _parsingContext = JsonReadContext.createRootContext(dups);
239     }
240
241     @Override public Version version() { return PackageVersion.VERSION; }
242
243     @Override
244     public Object getCurrentValue() {
245         return _parsingContext.getCurrentValue();
246     }
247
248     @Override
249     public void setCurrentValue(Object v) {
250         _parsingContext.setCurrentValue(v);
251     }
252     
253     /*
254     /**********************************************************
255     /* Overrides for Feature handling
256     /**********************************************************
257      */

258
259     @Override
260     public JsonParser enable(Feature f) {
261         _features |= f.getMask();
262         if (f == Feature.STRICT_DUPLICATE_DETECTION) { // enabling dup detection?
263             if (_parsingContext.getDupDetector() == null) { // but only if disabled currently
264                 _parsingContext = _parsingContext.withDupDetector(DupDetector.rootDetector(this));
265             }
266         }
267         return this;
268     }
269
270     @Override
271     public JsonParser disable(Feature f) {
272         _features &= ~f.getMask();
273         if (f == Feature.STRICT_DUPLICATE_DETECTION) {
274             _parsingContext = _parsingContext.withDupDetector(null);
275         }
276         return this;
277     }
278
279     @Override
280     @Deprecated
281     public JsonParser setFeatureMask(int newMask) {
282         int changes = (_features ^ newMask);
283         if (changes != 0) {
284             _features = newMask;
285             _checkStdFeatureChanges(newMask, changes);
286         }
287         return this;
288     }
289
290     @Override // since 2.7
291     public JsonParser overrideStdFeatures(int values, int mask) {
292         int oldState = _features;
293         int newState = (oldState & ~mask) | (values & mask);
294         int changed = oldState ^ newState;
295         if (changed != 0) {
296             _features = newState;
297             _checkStdFeatureChanges(newState, changed);
298         }
299         return this;
300     }
301
302     /**
303      * Helper method called to verify changes to standard features.
304      *
305      * @param newFeatureFlags Bitflag of standard features after they were changed
306      * @param changedFeatures Bitflag of standard features for which setting
307      *    did change
308      *
309      * @since 2.7
310      */

311     protected void _checkStdFeatureChanges(int newFeatureFlags, int changedFeatures)
312     {
313         int f = Feature.STRICT_DUPLICATE_DETECTION.getMask();
314         
315         if ((changedFeatures & f) != 0) {
316             if ((newFeatureFlags & f) != 0) {
317                 if (_parsingContext.getDupDetector() == null) {
318                     _parsingContext = _parsingContext.withDupDetector(DupDetector.rootDetector(this));
319                 } else { // disabling
320                     _parsingContext = _parsingContext.withDupDetector(null);
321                 }
322             }
323         }
324     }
325
326     /*
327     /**********************************************************
328     /* JsonParser impl
329     /**********************************************************
330      */

331     
332     /**
333      * Method that can be called to get the name associated with
334      * the current event.
335      */

336     @Override public String getCurrentName() throws IOException {
337         // [JACKSON-395]: start markers require information from parent
338         if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) {
339             JsonReadContext parent = _parsingContext.getParent();
340             if (parent != null) {
341                 return parent.getCurrentName();
342             }
343         }
344         return _parsingContext.getCurrentName();
345     }
346
347     @Override public void overrideCurrentName(String name) {
348         // Simple, but need to look for START_OBJECT/ARRAY's "off-by-one" thing:
349         JsonReadContext ctxt = _parsingContext;
350         if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) {
351             ctxt = ctxt.getParent();
352         }
353         /* 24-Sep-2013, tatu: Unfortunate, but since we did not expose exceptions,
354          *   need to wrap this here
355          */

356         try {
357             ctxt.setCurrentName(name);
358         } catch (IOException e) {
359             throw new IllegalStateException(e);
360         }
361     }
362
363     @Override public void close() throws IOException {
364         if (!_closed) {
365             // 19-Jan-2018, tatu: as per [core#440] need to ensure no more data assumed available
366             _inputPtr = Math.max(_inputPtr, _inputEnd);
367             _closed = true;
368             try {
369                 _closeInput();
370             } finally {
371                 // as per [JACKSON-324], do in finally block
372                 // Also, internal buffer(s) can now be released as well
373                 _releaseBuffers();
374             }
375         }
376     }
377
378     @Override public boolean isClosed() { return _closed; }
379     @Override public JsonReadContext getParsingContext() { return _parsingContext; }
380
381     /**
382      * Method that return the <b>starting</b> location of the current
383      * token; that is, position of the first character from input
384      * that starts the current token.
385      */

386     @Override
387     public JsonLocation getTokenLocation() {
388         return new JsonLocation(_getSourceReference(),
389                 -1L, getTokenCharacterOffset(), // bytes, chars
390                 getTokenLineNr(),
391                 getTokenColumnNr());
392     }
393
394     /**
395      * Method that returns location of the last processed character;
396      * usually for error reporting purposes
397      */

398     @Override
399     public JsonLocation getCurrentLocation() {
400         int col = _inputPtr - _currInputRowStart + 1; // 1-based
401         return new JsonLocation(_getSourceReference(),
402                 -1L, _currInputProcessed + _inputPtr, // bytes, chars
403                 _currInputRow, col);
404     }
405
406     /*
407     /**********************************************************
408     /* Public API, access to token information, text and similar
409     /**********************************************************
410      */

411
412     @Override
413     public boolean hasTextCharacters() {
414         if (_currToken == JsonToken.VALUE_STRING) { return true; } // usually true        
415         if (_currToken == JsonToken.FIELD_NAME) { return _nameCopied; }
416         return false;
417     }
418
419     @SuppressWarnings("resource")
420     @Override // since 2.7
421     public byte[] getBinaryValue(Base64Variant variant) throws IOException
422     {
423         if (_binaryValue == null) {
424             if (_currToken != JsonToken.VALUE_STRING) {
425                 _reportError("Current token ("+_currToken+") not VALUE_STRING, can not access as binary");
426             }
427             ByteArrayBuilder builder = _getByteArrayBuilder();
428             _decodeBase64(getText(), builder, variant);
429             _binaryValue = builder.toByteArray();
430         }
431         return _binaryValue;
432     }
433
434     /*
435     /**********************************************************
436     /* Public low-level accessors
437     /**********************************************************
438      */

439
440     public long getTokenCharacterOffset() { return _tokenInputTotal; }
441     public int getTokenLineNr() { return _tokenInputRow; }
442     public int getTokenColumnNr() {
443         // note: value of -1 means "not available"; otherwise convert from 0-based to 1-based
444         int col = _tokenInputCol;
445         return (col < 0) ? col : (col + 1);
446     }
447
448     /*
449     /**********************************************************
450     /* Abstract methods for sub-classes to implement
451     /**********************************************************
452      */

453
454     protected abstract void _closeInput() throws IOException;
455     
456     /*
457     /**********************************************************
458     /* Low-level reading, other
459     /**********************************************************
460      */

461
462     /**
463      * Method called to release internal buffers owned by the base
464      * reader. This may be called along with {@link #_closeInput} (for
465      * example, when explicitly closing this reader instance), or
466      * separately (if need be).
467      */

468     protected void _releaseBuffers() throws IOException {
469         _textBuffer.releaseBuffers();
470         char[] buf = _nameCopyBuffer;
471         if (buf != null) {
472             _nameCopyBuffer = null;
473             _ioContext.releaseNameCopyBuffer(buf);
474         }
475     }
476     
477     /**
478      * Method called when an EOF is encountered between tokens.
479      * If so, it may be a legitimate EOF, but only iff there
480      * is no open non-root context.
481      */

482     @Override
483     protected void _handleEOF() throws JsonParseException {
484         if (!_parsingContext.inRoot()) {
485             String marker = _parsingContext.inArray() ? "Array" : "Object";
486             _reportInvalidEOF(String.format(
487                     ": expected close marker for %s (start marker at %s)",
488                     marker,
489                     _parsingContext.getStartLocation(_getSourceReference())),
490                     null);
491         }
492     }
493
494     /**
495      * @since 2.4
496      */

497     protected final int _eofAsNextChar() throws JsonParseException {
498         _handleEOF();
499         return -1;
500     }
501
502     /*
503     /**********************************************************
504     /* Internal/package methods: shared/reusable builders
505     /**********************************************************
506      */

507     
508     public ByteArrayBuilder _getByteArrayBuilder()
509     {
510         if (_byteArrayBuilder == null) {
511             _byteArrayBuilder = new ByteArrayBuilder();
512         } else {
513             _byteArrayBuilder.reset();
514         }
515         return _byteArrayBuilder;
516     }
517
518     /*
519     /**********************************************************
520     /* Methods from former JsonNumericParserBase
521     /**********************************************************
522      */

523
524     // // // Life-cycle of number-parsing
525     
526     protected final JsonToken reset(boolean negative, int intLen, int fractLen, int expLen)
527     {
528         if (fractLen < 1 && expLen < 1) { // integer
529             return resetInt(negative, intLen);
530         }
531         return resetFloat(negative, intLen, fractLen, expLen);
532     }
533         
534     protected final JsonToken resetInt(boolean negative, int intLen)
535     {
536         _numberNegative = negative;
537         _intLength = intLen;
538         _fractLength = 0;
539         _expLength = 0;
540         _numTypesValid = NR_UNKNOWN; // to force parsing
541         return JsonToken.VALUE_NUMBER_INT;
542     }
543     
544     protected final JsonToken resetFloat(boolean negative, int intLen, int fractLen, int expLen)
545     {
546         _numberNegative = negative;
547         _intLength = intLen;
548         _fractLength = fractLen;
549         _expLength = expLen;
550         _numTypesValid = NR_UNKNOWN; // to force parsing
551         return JsonToken.VALUE_NUMBER_FLOAT;
552     }
553     
554     protected final JsonToken resetAsNaN(String valueStr, double value)
555     {
556         _textBuffer.resetWithString(valueStr);
557         _numberDouble = value;
558         _numTypesValid = NR_DOUBLE;
559         return JsonToken.VALUE_NUMBER_FLOAT;
560     }
561
562     @Override
563     public boolean isNaN() {
564         if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) {
565             if ((_numTypesValid & NR_DOUBLE) != 0) {
566                 // 10-Mar-2017, tatu: Alas, `Double.isFinite(d)` only added in JDK 8
567                 double d = _numberDouble;
568                 return Double.isNaN(d) || Double.isInfinite(d);              
569             }
570         }
571         return false;
572     }
573
574     /*
575     /**********************************************************
576     /* Numeric accessors of public API
577     /**********************************************************
578      */

579     
580     @Override
581     public Number getNumberValue() throws IOException
582     {
583         if (_numTypesValid == NR_UNKNOWN) {
584             _parseNumericValue(NR_UNKNOWN); // will also check event type
585         }
586         // Separate types for int types
587         if (_currToken == JsonToken.VALUE_NUMBER_INT) {
588             if ((_numTypesValid & NR_INT) != 0) {
589                 return _numberInt;
590             }
591             if ((_numTypesValid & NR_LONG) != 0) {
592                 return _numberLong;
593             }
594             if ((_numTypesValid & NR_BIGINT) != 0) {
595                 return _numberBigInt;
596             }
597             // Shouldn't get this far but if we do
598             return _numberBigDecimal;
599         }
600     
601         /* And then floating point types. But here optimal type
602          * needs to be big decimal, to avoid losing any data?
603          */

604         if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
605             return _numberBigDecimal;
606         }
607         if ((_numTypesValid & NR_DOUBLE) == 0) { // sanity check
608             _throwInternal();
609         }
610         return _numberDouble;
611     }
612     
613     @Override
614     public NumberType getNumberType() throws IOException
615     {
616         if (_numTypesValid == NR_UNKNOWN) {
617             _parseNumericValue(NR_UNKNOWN); // will also check event type
618         }
619         if (_currToken == JsonToken.VALUE_NUMBER_INT) {
620             if ((_numTypesValid & NR_INT) != 0) {
621                 return NumberType.INT;
622             }
623             if ((_numTypesValid & NR_LONG) != 0) {
624                 return NumberType.LONG;
625             }
626             return NumberType.BIG_INTEGER;
627         }
628     
629         /* And then floating point types. Here optimal type
630          * needs to be big decimal, to avoid losing any data?
631          * However... using BD is slow, so let's allow returning
632          * double as type if no explicit call has been made to access
633          * data as BD?
634          */

635         if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
636             return NumberType.BIG_DECIMAL;
637         }
638         return NumberType.DOUBLE;
639     }
640     
641     @Override
642     public int getIntValue() throws IOException
643     {
644         if ((_numTypesValid & NR_INT) == 0) {
645             if (_numTypesValid == NR_UNKNOWN) { // not parsed at all
646                 return _parseIntValue();
647             }
648             if ((_numTypesValid & NR_INT) == 0) { // wasn't an int natively?
649                 convertNumberToInt(); // let's make it so, if possible
650             }
651         }
652         return _numberInt;
653     }
654     
655     @Override
656     public long getLongValue() throws IOException
657     {
658         if ((_numTypesValid & NR_LONG) == 0) {
659             if (_numTypesValid == NR_UNKNOWN) {
660                 _parseNumericValue(NR_LONG);
661             }
662             if ((_numTypesValid & NR_LONG) == 0) {
663                 convertNumberToLong();
664             }
665         }
666         return _numberLong;
667     }
668     
669     @Override
670     public BigInteger getBigIntegerValue() throws IOException
671     {
672         if ((_numTypesValid & NR_BIGINT) == 0) {
673             if (_numTypesValid == NR_UNKNOWN) {
674                 _parseNumericValue(NR_BIGINT);
675             }
676             if ((_numTypesValid & NR_BIGINT) == 0) {
677                 convertNumberToBigInteger();
678             }
679         }
680         return _numberBigInt;
681     }
682     
683     @Override
684     public float getFloatValue() throws IOException
685     {
686         double value = getDoubleValue();
687         /* 22-Jan-2009, tatu: Bounds/range checks would be tricky
688          *   here, so let's not bother even trying...
689          */

690         /*
691         if (value < -Float.MAX_VALUE || value > MAX_FLOAT_D) {
692             _reportError("Numeric value ("+getText()+") out of range of Java float");
693         }
694         */

695         return (float) value;
696     }
697     
698     @Override
699     public double getDoubleValue() throws IOException
700     {
701         if ((_numTypesValid & NR_DOUBLE) == 0) {
702             if (_numTypesValid == NR_UNKNOWN) {
703                 _parseNumericValue(NR_DOUBLE);
704             }
705             if ((_numTypesValid & NR_DOUBLE) == 0) {
706                 convertNumberToDouble();
707             }
708         }
709         return _numberDouble;
710     }
711     
712     @Override
713     public BigDecimal getDecimalValue() throws IOException
714     {
715         if ((_numTypesValid & NR_BIGDECIMAL) == 0) {
716             if (_numTypesValid == NR_UNKNOWN) {
717                 _parseNumericValue(NR_BIGDECIMAL);
718             }
719             if ((_numTypesValid & NR_BIGDECIMAL) == 0) {
720                 convertNumberToBigDecimal();
721             }
722         }
723         return _numberBigDecimal;
724     }
725
726     /*
727     /**********************************************************
728     /* Conversion from textual to numeric representation
729     /**********************************************************
730      */

731     
732     /**
733      * Method that will parse actual numeric value out of a syntactically
734      * valid number value. Type it will parse into depends on whether
735      * it is a floating point number, as well as its magnitude: smallest
736      * legal type (of ones available) is used for efficiency.
737      *
738      * @param expType Numeric type that we will immediately need, if any;
739      *   mostly necessary to optimize handling of floating point numbers
740      */

741     protected void _parseNumericValue(int expType) throws IOException
742     {
743         // Int or float?
744         if (_currToken == JsonToken.VALUE_NUMBER_INT) {
745             int len = _intLength;
746             // First: optimization for simple int
747             if (len <= 9) { 
748                 int i = _textBuffer.contentsAsInt(_numberNegative);
749                 _numberInt = i;
750                 _numTypesValid = NR_INT;
751                 return;
752             }
753             if (len <= 18) { // definitely fits AND is easy to parse using 2 int parse calls
754                 long l = _textBuffer.contentsAsLong(_numberNegative);
755                 // Might still fit in int, need to check
756                 if (len == 10) {
757                     if (_numberNegative) {
758                         if (l >= MIN_INT_L) {
759                             _numberInt = (int) l;
760                             _numTypesValid = NR_INT;
761                             return;
762                         }
763                     } else {
764                         if (l <= MAX_INT_L) {
765                             _numberInt = (int) l;
766                             _numTypesValid = NR_INT;
767                             return;
768                         }
769                     }
770                 }
771                 _numberLong = l;
772                 _numTypesValid = NR_LONG;
773                 return;
774             }
775             _parseSlowInt(expType);
776             return;
777         }
778         if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) {
779             _parseSlowFloat(expType);
780             return;
781         }
782         _reportError("Current token (%s) not numeric, can not use numeric value accessors", _currToken);
783     }
784
785     /**
786      * @since 2.6
787      */

788     protected int _parseIntValue() throws IOException
789     {
790         // Inlined variant of: _parseNumericValue(NR_INT)
791         if (_currToken == JsonToken.VALUE_NUMBER_INT) {
792             if (_intLength <= 9) {
793                 int i = _textBuffer.contentsAsInt(_numberNegative);
794                 _numberInt = i;
795                 _numTypesValid = NR_INT;
796                 return i;
797             }
798         }
799         // if not optimizable, use more generic
800         _parseNumericValue(NR_INT);
801         if ((_numTypesValid & NR_INT) == 0) {
802             convertNumberToInt();
803         }
804         return _numberInt;
805     }
806
807     private void _parseSlowFloat(int expType) throws IOException
808     {
809         /* Nope: floating point. Here we need to be careful to get
810          * optimal parsing strategy: choice is between accurate but
811          * slow (BigDecimal) and lossy but fast (Double). For now
812          * let's only use BD when explicitly requested -- it can
813          * still be constructed correctly at any point since we do
814          * retain textual representation
815          */

816         try {
817             if (expType == NR_BIGDECIMAL) {
818                 _numberBigDecimal = _textBuffer.contentsAsDecimal();
819                 _numTypesValid = NR_BIGDECIMAL;
820             } else {
821                 // Otherwise double has to do
822                 _numberDouble = _textBuffer.contentsAsDouble();
823                 _numTypesValid = NR_DOUBLE;
824             }
825         } catch (NumberFormatException nex) {
826             // Can this ever occur? Due to overflow, maybe?
827             _wrapError("Malformed numeric value ("+_longNumberDesc(_textBuffer.contentsAsString())+")", nex);
828         }
829     }
830
831     private void _parseSlowInt(int expType) throws IOException
832     {
833         String numStr = _textBuffer.contentsAsString();
834         try {
835             int len = _intLength;
836             char[] buf = _textBuffer.getTextBuffer();
837             int offset = _textBuffer.getTextOffset();
838             if (_numberNegative) {
839                 ++offset;
840             }
841             // Some long cases still...
842             if (NumberInput.inLongRange(buf, offset, len, _numberNegative)) {
843                 // Probably faster to construct a String, call parse, than to use BigInteger
844                 _numberLong = Long.parseLong(numStr);
845                 _numTypesValid = NR_LONG;
846             } else {
847                 // 16-Oct-2018, tatu: Need to catch "too big" early due to [jackson-core#488]
848                 if ((expType == NR_INT) || (expType == NR_LONG)) {
849                     _reportTooLongIntegral(expType, numStr);
850                 }
851                 if ((expType == NR_DOUBLE) || (expType == NR_FLOAT)) {
852                     _numberDouble = NumberInput.parseDouble(numStr);
853                     _numTypesValid = NR_DOUBLE;
854                 } else {
855                     // nope, need the heavy guns... (rare case)
856                     _numberBigInt = new BigInteger(numStr);
857                     _numTypesValid = NR_BIGINT;
858                 }
859             }
860         } catch (NumberFormatException nex) {
861             // Can this ever occur? Due to overflow, maybe?
862             _wrapError("Malformed numeric value ("+_longNumberDesc(numStr)+")", nex);
863         }
864     }
865
866     // @since 2.9.8
867     protected void _reportTooLongIntegral(int expType, String rawNum) throws IOException
868     {
869         if (expType == NR_INT) {
870             reportOverflowInt(rawNum);
871         } else {
872             reportOverflowLong(rawNum);
873         }
874     }
875
876     /*
877     /**********************************************************
878     /* Numeric conversions
879     /**********************************************************
880      */
    
881     
882     protected void convertNumberToInt() throws IOException
883     {
884         // First, converting from long ought to be easy
885         if ((_numTypesValid & NR_LONG) != 0) {
886             // Let's verify it's lossless conversion by simple roundtrip
887             int result = (int) _numberLong;
888             if (((long) result) != _numberLong) {
889                 reportOverflowInt(getText(), currentToken());
890             }
891             _numberInt = result;
892         } else if ((_numTypesValid & NR_BIGINT) != 0) {
893             if (BI_MIN_INT.compareTo(_numberBigInt) > 0 
894                     || BI_MAX_INT.compareTo(_numberBigInt) < 0) {
895                 reportOverflowInt();
896             }
897             _numberInt = _numberBigInt.intValue();
898         } else if ((_numTypesValid & NR_DOUBLE) != 0) {
899             // Need to check boundaries
900             if (_numberDouble < MIN_INT_D || _numberDouble > MAX_INT_D) {
901                 reportOverflowInt();
902             }
903             _numberInt = (int) _numberDouble;
904         } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
905             if (BD_MIN_INT.compareTo(_numberBigDecimal) > 0 
906                 || BD_MAX_INT.compareTo(_numberBigDecimal) < 0) {
907                 reportOverflowInt();
908             }
909             _numberInt = _numberBigDecimal.intValue();
910         } else {
911             _throwInternal();
912         }
913         _numTypesValid |= NR_INT;
914     }
915     
916     protected void convertNumberToLong() throws IOException
917     {
918         if ((_numTypesValid & NR_INT) != 0) {
919             _numberLong = (long) _numberInt;
920         } else if ((_numTypesValid & NR_BIGINT) != 0) {
921             if (BI_MIN_LONG.compareTo(_numberBigInt) > 0 
922                     || BI_MAX_LONG.compareTo(_numberBigInt) < 0) {
923                 reportOverflowLong();
924             }
925             _numberLong = _numberBigInt.longValue();
926         } else if ((_numTypesValid & NR_DOUBLE) != 0) {
927             // Need to check boundaries
928             if (_numberDouble < MIN_LONG_D || _numberDouble > MAX_LONG_D) {
929                 reportOverflowLong();
930             }
931             _numberLong = (long) _numberDouble;
932         } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
933             if (BD_MIN_LONG.compareTo(_numberBigDecimal) > 0 
934                 || BD_MAX_LONG.compareTo(_numberBigDecimal) < 0) {
935                 reportOverflowLong();
936             }
937             _numberLong = _numberBigDecimal.longValue();
938         } else {
939             _throwInternal();
940         }
941         _numTypesValid |= NR_LONG;
942     }
943     
944     protected void convertNumberToBigInteger() throws IOException
945     {
946         if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
947             // here it'll just get truncated, no exceptions thrown
948             _numberBigInt = _numberBigDecimal.toBigInteger();
949         } else if ((_numTypesValid & NR_LONG) != 0) {
950             _numberBigInt = BigInteger.valueOf(_numberLong);
951         } else if ((_numTypesValid & NR_INT) != 0) {
952             _numberBigInt = BigInteger.valueOf(_numberInt);
953         } else if ((_numTypesValid & NR_DOUBLE) != 0) {
954             _numberBigInt = BigDecimal.valueOf(_numberDouble).toBigInteger();
955         } else {
956             _throwInternal();
957         }
958         _numTypesValid |= NR_BIGINT;
959     }
960     
961     protected void convertNumberToDouble() throws IOException
962     {
963         /* 05-Aug-2008, tatus: Important note: this MUST start with
964          *   more accurate representations, since we don't know which
965          *   value is the original one (others get generated when
966          *   requested)
967          */

968     
969         if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
970             _numberDouble = _numberBigDecimal.doubleValue();
971         } else if ((_numTypesValid & NR_BIGINT) != 0) {
972             _numberDouble = _numberBigInt.doubleValue();
973         } else if ((_numTypesValid & NR_LONG) != 0) {
974             _numberDouble = (double) _numberLong;
975         } else if ((_numTypesValid & NR_INT) != 0) {
976             _numberDouble = (double) _numberInt;
977         } else {
978             _throwInternal();
979         }
980         _numTypesValid |= NR_DOUBLE;
981     }
982     
983     protected void convertNumberToBigDecimal() throws IOException
984     {
985         /* 05-Aug-2008, tatus: Important note: this MUST start with
986          *   more accurate representations, since we don't know which
987          *   value is the original one (others get generated when
988          *   requested)
989          */

990     
991         if ((_numTypesValid & NR_DOUBLE) != 0) {
992             /* Let's actually parse from String representation, to avoid
993              * rounding errors that non-decimal floating operations could incur
994              */

995             _numberBigDecimal = NumberInput.parseBigDecimal(getText());
996         } else if ((_numTypesValid & NR_BIGINT) != 0) {
997             _numberBigDecimal = new BigDecimal(_numberBigInt);
998         } else if ((_numTypesValid & NR_LONG) != 0) {
999             _numberBigDecimal = BigDecimal.valueOf(_numberLong);
1000         } else if ((_numTypesValid & NR_INT) != 0) {
1001             _numberBigDecimal = BigDecimal.valueOf(_numberInt);
1002         } else {
1003             _throwInternal();
1004         }
1005         _numTypesValid |= NR_BIGDECIMAL;
1006     }
1007
1008     /*
1009     /**********************************************************
1010     /* Internal/package methods: Error reporting
1011     /**********************************************************
1012      */

1013
1014     protected void _reportMismatchedEndMarker(int actCh, char expCh) throws JsonParseException {
1015         JsonReadContext ctxt = getParsingContext();
1016         _reportError(String.format(
1017                 "Unexpected close marker '%s': expected '%c' (for %s starting at %s)",
1018                 (char) actCh, expCh, ctxt.typeDesc(), ctxt.getStartLocation(_getSourceReference())));
1019     }
1020
1021     @SuppressWarnings("deprecation")
1022     protected char _handleUnrecognizedCharacterEscape(char ch) throws JsonProcessingException {
1023         // as per [JACKSON-300]
1024         if (isEnabled(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)) {
1025             return ch;
1026         }
1027         // and [JACKSON-548]
1028         if (ch == '\'' && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) {
1029             return ch;
1030         }
1031         _reportError("Unrecognized character escape "+_getCharDesc(ch));
1032         return ch;
1033     }
1034
1035     /**
1036      * Method called to report a problem with unquoted control character.
1037      * Note: it is possible to suppress some instances of
1038      * exception by enabling {@link Feature#ALLOW_UNQUOTED_CONTROL_CHARS}.
1039      */

1040     @SuppressWarnings("deprecation")
1041     protected void _throwUnquotedSpace(int i, String ctxtDesc) throws JsonParseException {
1042         // JACKSON-208; possible to allow unquoted control chars:
1043         if (!isEnabled(Feature.ALLOW_UNQUOTED_CONTROL_CHARS) || i > INT_SPACE) {
1044             char c = (char) i;
1045             String msg = "Illegal unquoted character ("+_getCharDesc(c)+"): has to be escaped using backslash to be included in "+ctxtDesc;
1046             _reportError(msg);
1047         }
1048     }
1049
1050     /**
1051      * @return Description to use as "valid tokens" in an exception message about
1052      *    invalid (unrecognized) JSON token: called when parser finds something that
1053      *    looks like unquoted textual token
1054      *
1055      * @since 2.10
1056      */

1057     protected String _validJsonTokenList() throws IOException {
1058         return _validJsonValueList();
1059     }
1060
1061     /**
1062      * @return Description to use as "valid JSON values" in an exception message about
1063      *    invalid (unrecognized) JSON value: called when parser finds something that
1064      *    does not look like a value or separator.
1065      *
1066      * @since 2.10
1067      */

1068     @SuppressWarnings("deprecation")
1069     protected String _validJsonValueList() throws IOException {
1070         if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) {
1071             return "(JSON String, Number (or 'NaN'/'INF'/'+INF'), Array, Object or token 'null', 'true' or 'false')";
1072         }
1073         return "(JSON String, Number, Array, Object or token 'null', 'true' or 'false')";
1074     }
1075
1076     /*
1077     /**********************************************************
1078     /* Base64 handling support
1079     /**********************************************************
1080      */

1081
1082     /**
1083      * Method that sub-classes must implement to support escaped sequences
1084      * in base64-encoded sections.
1085      * Sub-classes that do not need base64 support can leave this as is
1086      */

1087     protected char _decodeEscaped() throws IOException {
1088         throw new UnsupportedOperationException();
1089     }
1090     
1091     protected final int _decodeBase64Escape(Base64Variant b64variant, int ch, int index) throws IOException
1092     {
1093         // 17-May-2011, tatu: As per [JACKSON-xxx], need to handle escaped chars
1094         if (ch != '\\') {
1095             throw reportInvalidBase64Char(b64variant, ch, index);
1096         }
1097         int unescaped = _decodeEscaped();
1098         // if white space, skip if first triplet; otherwise errors
1099         if (unescaped <= INT_SPACE) {
1100             if (index == 0) { // whitespace only allowed to be skipped between triplets
1101                 return -1;
1102             }
1103         }
1104         // otherwise try to find actual triplet value
1105         int bits = b64variant.decodeBase64Char(unescaped);
1106         if (bits < 0) {
1107             if (bits != Base64Variant.BASE64_VALUE_PADDING) {
1108                 throw reportInvalidBase64Char(b64variant, unescaped, index);
1109             }
1110         }
1111         return bits;
1112     }
1113     
1114     protected final int _decodeBase64Escape(Base64Variant b64variant, char ch, int index) throws IOException
1115     {
1116         if (ch != '\\') {
1117             throw reportInvalidBase64Char(b64variant, ch, index);
1118         }
1119         char unescaped = _decodeEscaped();
1120         // if white space, skip if first triplet; otherwise errors
1121         if (unescaped <= INT_SPACE) {
1122             if (index == 0) { // whitespace only allowed to be skipped between triplets
1123                 return -1;
1124             }
1125         }
1126         // otherwise try to find actual triplet value
1127         int bits = b64variant.decodeBase64Char(unescaped);
1128         if (bits < 0) {
1129             // second check since padding can only be 3rd or 4th byte (index #2 or #3)
1130             if ((bits != Base64Variant.BASE64_VALUE_PADDING) || (index < 2)) {
1131                 throw reportInvalidBase64Char(b64variant, unescaped, index);
1132             }
1133         }
1134         return bits;
1135     }
1136     
1137     protected IllegalArgumentException reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex) throws IllegalArgumentException {
1138         return reportInvalidBase64Char(b64variant, ch, bindex, null);
1139     }
1140
1141     /**
1142      * @param bindex Relative index within base64 character unit; between 0
1143      *   and 3 (as unit has exactly 4 characters)
1144      */

1145     protected IllegalArgumentException reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex, String msg) throws IllegalArgumentException {
1146         String base;
1147         if (ch <= INT_SPACE) {
1148             base = String.format("Illegal white space character (code 0x%s) as character #%d of 4-char base64 unit: can only used between units",
1149                     Integer.toHexString(ch), (bindex+1));
1150         } else if (b64variant.usesPaddingChar(ch)) {
1151             base = "Unexpected padding character ('"+b64variant.getPaddingChar()+"') as character #"+(bindex+1)+" of 4-char base64 unit: padding only legal as 3rd or 4th character";
1152         } else if (!Character.isDefined(ch) || Character.isISOControl(ch)) {
1153             // Not sure if we can really get here... ? (most illegal xml chars are caught at lower level)
1154             base = "Illegal character (code 0x"+Integer.toHexString(ch)+") in base64 content";
1155         } else {
1156             base = "Illegal character '"+((char)ch)+"' (code 0x"+Integer.toHexString(ch)+") in base64 content";
1157         }
1158         if (msg != null) {
1159             base = base + ": " + msg;
1160         }
1161         return new IllegalArgumentException(base);
1162     }
1163
1164     // since 2.9.8
1165     protected void _handleBase64MissingPadding(Base64Variant b64variant) throws IOException
1166     {
1167         _reportError(b64variant.missingPaddingMessage());
1168     }
1169
1170     /*
1171     /**********************************************************
1172     /* Internal/package methods: other
1173     /**********************************************************
1174      */

1175
1176     /**
1177      * Helper method used to encapsulate logic of including (or not) of
1178      * "source reference" when constructing {@link JsonLocation} instances.
1179      *
1180      * @since 2.9
1181      */

1182     protected Object _getSourceReference() {
1183         if (JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION.enabledIn(_features)) {
1184             return _ioContext.getSourceReference();
1185         }
1186         return null;
1187     }
1188
1189     protected static int[] growArrayBy(int[] arr, int more)
1190     {
1191         if (arr == null) {
1192             return new int[more];
1193         }
1194         return Arrays.copyOf(arr, arr.length + more);
1195     }
1196     
1197     /*
1198     /**********************************************************
1199     /* Stuff that was abstract and required before 2.8, but that
1200     /* is not mandatory in 2.8 or above.
1201     /**********************************************************
1202      */

1203
1204     @Deprecated // since 2.8
1205     protected void loadMoreGuaranteed() throws IOException {
1206         if (!loadMore()) { _reportInvalidEOF(); }
1207     }
1208
1209     @Deprecated // since 2.8
1210     protected boolean loadMore() throws IOException { return false; }
1211
1212     // Can't declare as deprecated, for now, but shouldn't be needed
1213     protected void _finishString() throws IOException { }
1214 }
1215