1 package com.fasterxml.jackson.dataformat.cbor;
2
3 import java.io.*;
4 import java.math.BigDecimal;
5 import java.math.BigInteger;
6 import java.nio.charset.Charset;
7 import java.util.Arrays;
8
9 import com.fasterxml.jackson.core.*;
10 import com.fasterxml.jackson.core.base.ParserMinimalBase;
11 import com.fasterxml.jackson.core.io.IOContext;
12 import com.fasterxml.jackson.core.io.NumberInput;
13 import com.fasterxml.jackson.core.json.DupDetector;
14 import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer;
15 import com.fasterxml.jackson.core.util.ByteArrayBuilder;
16 import com.fasterxml.jackson.core.util.TextBuffer;
17
18 import static com.fasterxml.jackson.dataformat.cbor.CBORConstants.*;
19
20 public class CBORParser extends ParserMinimalBase
21 {
22     /**
23      * Enumeration that defines all togglable features for CBOR generators.
24      */

25     public enum Feature implements FormatFeature
26     {
27 //        BOGUS(false)
28         ;
29
30         final boolean _defaultState;
31         final int _mask;
32         
33         /**
34          * Method that calculates bit set (flags) of all features that
35          * are enabled by default.
36          */

37         public static int collectDefaults()
38         {
39             int flags = 0;
40             for (Feature f : values()) {
41                 if (f.enabledByDefault()) {
42                     flags |= f.getMask();
43                 }
44             }
45             return flags;
46         }
47         
48         private Feature(boolean defaultState) {
49             _defaultState = defaultState;
50             _mask = (1 << ordinal());
51         }
52         
53         @Override public boolean enabledByDefault() { return _defaultState; }
54         @Override public int getMask() { return _mask; }
55         @Override public boolean enabledIn(int flags) { return (flags & _mask) != 0; }
56     }
57
58     private final static Charset UTF8 = Charset.forName("UTF-8");
59
60     private final static int[] UTF8_UNIT_CODES = CBORConstants.sUtf8UnitLengths;
61
62     // Constants for handling of 16-bit "mini-floats"
63     private final static double MATH_POW_2_10 = Math.pow(2, 10);
64     private final static double MATH_POW_2_NEG14 = Math.pow(2, -14);
65
66     /*
67     /**********************************************************
68     /* Configuration
69     /**********************************************************
70      */

71
72     /**
73      * Codec used for data binding when (if) requested.
74      */

75     protected ObjectCodec _objectCodec;
76
77     /*
78     /**********************************************************
79     /* Generic I/O state
80     /**********************************************************
81      */

82
83     /**
84      * I/O context for this reader. It handles buffer allocation
85      * for the reader.
86      */

87     final protected IOContext _ioContext;
88
89     /**
90      * Flag that indicates whether parser is closed or not. Gets
91      * set when parser is either closed by explicit call
92      * ({@link #close}) or when end-of-input is reached.
93      */

94     protected boolean _closed;
95
96     /*
97     /**********************************************************
98     /* Current input data
99     /**********************************************************
100      */

101
102     // Note: type of actual buffer depends on sub-class, can't include
103
104     /**
105      * Pointer to next available character in buffer
106      */

107     protected int _inputPtr = 0;
108
109     /**
110      * Index of character after last available one in the buffer.
111      */

112     protected int _inputEnd = 0;
113
114     /*
115     /**********************************************************
116     /* Current input location information
117     /**********************************************************
118      */

119
120     /**
121      * Number of characters/bytes that were contained in previous blocks
122      * (blocks that were already processed prior to the current buffer).
123      */

124     protected long _currInputProcessed = 0L;
125
126     /**
127      * Current row location of current point in input buffer, starting
128      * from 1, if available.
129      */

130     protected int _currInputRow = 1;
131
132     /**
133      * Current index of the first character of the current row in input
134      * buffer. Needed to calculate column position, if necessary; benefit
135      * of not having column itself is that this only has to be updated
136      * once per line.
137      */

138     protected int _currInputRowStart = 0;
139
140     /*
141     /**********************************************************
142     /* Information about starting location of event
143     /* Reader is pointing to; updated on-demand
144     /**********************************************************
145      */

146
147     // // // Location info at point when current token was started
148
149     /**
150      * Total number of bytes/characters read before start of current token.
151      * For big (gigabyte-sized) sizes are possible, needs to be long,
152      * unlike pointers and sizes related to in-memory buffers.
153      */

154     protected long _tokenInputTotal = 0; 
155
156     /**
157      * Input row on which current token starts, 1-based
158      */

159     protected int _tokenInputRow = 1;
160
161     /**
162      * Column on input row that current token starts; 0-based (although
163      * in the end it'll be converted to 1-based)
164      */

165     protected int _tokenInputCol = 0;
166
167     /*
168     /**********************************************************
169     /* Parsing state
170     /**********************************************************
171      */

172
173     /**
174      * Information about parser context, context in which
175      * the next token is to be parsed (root, array, object).
176      */

177     protected CBORReadContext _parsingContext;
178
179     /**
180      * Buffer that contains contents of String values, including
181      * field names if necessary (name split across boundary,
182      * contains escape sequence, or access needed to char array)
183      */

184     protected final TextBuffer _textBuffer;
185
186     /**
187      * Temporary buffer that is needed if field name is accessed
188      * using {@link #getTextCharacters} method (instead of String
189      * returning alternatives)
190      */

191     protected char[] _nameCopyBuffer = null;
192
193     /**
194      * Flag set to indicate whether the field name is available
195      * from the name copy buffer or not (in addition to its String
196      * representation  being available via read context)
197      */

198     protected boolean _nameCopied = false;
199
200     /**
201      * ByteArrayBuilder is needed if 'getBinaryValue' is called. If so,
202      * we better reuse it for remainder of content.
203      */

204     protected ByteArrayBuilder _byteArrayBuilder = null;
205
206     /**
207      * We will hold on to decoded binary data, for duration of
208      * current event, so that multiple calls to
209      * {@link #getBinaryValue} will not need to decode data more
210      * than once.
211      */

212     protected byte[] _binaryValue;
213
214     /**
215      * We will keep track of tag value for possible future use.
216      */

217     protected int _tagValue = -1;
218
219     /*
220     /**********************************************************
221     /* Input source config, state (from ex StreamBasedParserBase)
222     /**********************************************************
223      */

224
225     /**
226      * Input stream that can be used for reading more content, if one
227      * in use. May be nullif input comes just as a full buffer,
228      * or if the stream has been closed.
229      */

230     protected InputStream _inputStream;
231
232     /**
233      * Current buffer from which data is read; generally data is read into
234      * buffer from input source, but in some cases pre-loaded buffer
235      * is handed to the parser.
236      */

237     protected byte[] _inputBuffer;
238
239     /**
240      * Flag that indicates whether the input buffer is recycable (and
241      * needs to be returned to recycler once we are done) or not.
242      *<p>
243      * If it is not, it also means that parser can NOT modify underlying
244      * buffer.
245      */

246     protected boolean _bufferRecyclable;
247
248     /*
249     /**********************************************************
250     /* Additional parsing state
251     /**********************************************************
252      */

253
254     /**
255      * Flag that indicates that the current token has not yet
256      * been fully processed, and needs to be finished for
257      * some access (or skipped to obtain the next token)
258      */

259     protected boolean _tokenIncomplete = false;
260
261     /**
262      * Type byte of the current token
263      */

264     protected int _typeByte;
265
266     /**
267      * Helper variables used when dealing with chunked content.
268      */

269     private int _chunkLeft, _chunkEnd;
270
271     /*
272     /**********************************************************
273     /* Symbol handling, decoding
274     /**********************************************************
275      */

276
277     /**
278      * Symbol table that contains field names encountered so far
279      */

280     final protected ByteQuadsCanonicalizer _symbols;
281
282     /**
283      * Temporary buffer used for name parsing.
284      */

285     protected int[] _quadBuffer = NO_INTS;
286
287     /**
288      * Quads used for hash calculation
289      */

290     protected int _quad1, _quad2, _quad3;
291
292     /*
293     /**********************************************************
294     /* Constants and fields of former 'JsonNumericParserBase'
295     /**********************************************************
296      */

297
298     // Also, we need some numeric constants
299
300     @SuppressWarnings("hiding"// only since 2.9, remove in 3.0
301     final static BigInteger BI_MIN_INT = BigInteger.valueOf(Integer.MIN_VALUE);
302     @SuppressWarnings("hiding"// only since 2.9, remove in 3.0
303     final static BigInteger BI_MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE);
304
305     @SuppressWarnings("hiding"// only since 2.9, remove in 3.0
306     final static BigInteger BI_MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
307     @SuppressWarnings("hiding"// only since 2.9, remove in 3.0
308     final static BigInteger BI_MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
309     
310     @SuppressWarnings("hiding"// only since 2.9, remove in 3.0
311     final static BigDecimal BD_MIN_LONG = new BigDecimal(BI_MIN_LONG);
312     @SuppressWarnings("hiding"// only since 2.9, remove in 3.0
313     final static BigDecimal BD_MAX_LONG = new BigDecimal(BI_MAX_LONG);
314
315     @SuppressWarnings("hiding"// only since 2.9, remove in 3.0
316     final static BigDecimal BD_MIN_INT = new BigDecimal(BI_MIN_INT);
317     @SuppressWarnings("hiding"// only since 2.9, remove in 3.0
318     final static BigDecimal BD_MAX_INT = new BigDecimal(BI_MAX_INT);
319
320     // Numeric value holders: multiple fields used for
321     // for efficiency
322
323     /**
324      * Bitfield that indicates which numeric representations
325      * have been calculated for the current type
326      */

327     protected int _numTypesValid = NR_UNKNOWN;
328
329     // First primitives
330
331     protected int _numberInt;
332     protected long _numberLong;
333     protected float _numberFloat;
334     protected double _numberDouble;
335
336     // And then object types
337
338     protected BigInteger _numberBigInt;
339     protected BigDecimal _numberBigDecimal;
340
341     /*
342     /**********************************************************
343     /* Life-cycle
344     /**********************************************************
345      */

346
347     public CBORParser(IOContext ctxt, int parserFeatures, int cborFeatures,
348             ObjectCodec codec, ByteQuadsCanonicalizer sym,
349             InputStream in, byte[] inputBuffer, int start, int end,
350             boolean bufferRecyclable)
351     {
352         super(parserFeatures);
353         _ioContext = ctxt;
354         _objectCodec = codec;
355         _symbols = sym;
356
357         _inputStream = in;
358         _inputBuffer = inputBuffer;
359         _inputPtr = start;
360         _inputEnd = end;
361         _bufferRecyclable = bufferRecyclable;
362         _textBuffer = ctxt.constructTextBuffer();
363         DupDetector dups = JsonParser.Feature.STRICT_DUPLICATE_DETECTION.enabledIn(parserFeatures)
364                 ? DupDetector.rootDetector(this) : null;
365         _parsingContext = CBORReadContext.createRootContext(dups);
366
367         _tokenInputRow = -1;
368         _tokenInputCol = -1;
369     }
370
371     @Override
372     public ObjectCodec getCodec() {
373         return _objectCodec;
374     }
375
376     @Override
377     public void setCodec(ObjectCodec c) {
378         _objectCodec = c;
379     }
380
381     /*                                                                                       
382     /**********************************************************                              
383     /* Versioned                                                                             
384     /**********************************************************                              
385      */

386
387     @Override
388     public Version version() {
389         return PackageVersion.VERSION;
390     }
391
392     /*
393     /**********************************************************
394     /* Configuration
395     /**********************************************************
396      */

397
398 //    public JsonParser overrideStdFeatures(int values, int mask)
399
400     @Override
401     public int getFormatFeatures() {
402         // No parser features, yet
403         return 0;
404     }
405
406     //public JsonParser overrideFormatFeatures(int values, int mask) {
407
408     /*
409     /**********************************************************
410     /* Extended API
411     /**********************************************************
412      */

413
414     /**
415      * Method that can be used to access tag id associated with
416      * the most recently decoded value (whether completely, for
417      * scalar values, or partially, for Objects/Arrays), if any.
418      * If no tag was associated with it, -1 is returned.
419      * 
420      * @since 2.5
421      */

422     public int getCurrentTag() {
423         return _tagValue;
424     }
425
426     /*
427     /**********************************************************
428     /* Abstract impls
429     /**********************************************************
430      */

431
432     @Override
433     public int releaseBuffered(OutputStream out) throws IOException
434     {
435         int count = _inputEnd - _inputPtr;
436         if (count < 1) {
437             return 0;
438         }
439         // let's just advance ptr to end
440         int origPtr = _inputPtr;
441         out.write(_inputBuffer, origPtr, count);
442         return count;
443     }
444     
445     @Override
446     public Object getInputSource() {
447         return _inputStream;
448     }
449
450     /**
451      * Overridden since we do not really have character-based locations,
452      * but we do have byte offset to specify.
453      */

454     @Override
455     public JsonLocation getTokenLocation()
456     {
457         // token location is correctly managed...
458         return new JsonLocation(_ioContext.getSourceReference(),
459                 _tokenInputTotal, // bytes
460                 -1, -1, (int) _tokenInputTotal); // char offset, line, column
461     }   
462
463     /**
464      * Overridden since we do not really have character-based locations,
465      * but we do have byte offset to specify.
466      */

467     @Override
468     public JsonLocation getCurrentLocation()
469     {
470         final long offset = _currInputProcessed + _inputPtr;
471         return new JsonLocation(_ioContext.getSourceReference(),
472                 offset, // bytes
473                 -1, -1, (int) offset); // char offset, line, column
474     }
475
476     /**
477      * Method that can be called to get the name associated with
478      * the current event.
479      */

480     @Override
481     public String getCurrentName() throws IOException
482     {
483         if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) {
484             CBORReadContext parent = _parsingContext.getParent();
485             return parent.getCurrentName();
486         }
487         return _parsingContext.getCurrentName();
488     }
489
490     @Override
491     public void overrideCurrentName(String name)
492     {
493         // Simple, but need to look for START_OBJECT/ARRAY's "off-by-one" thing:
494         CBORReadContext ctxt = _parsingContext;
495         if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) {
496             ctxt = ctxt.getParent();
497         }
498         // Unfortunate, but since we did not expose exceptions, need to wrap
499         try {
500             ctxt.setCurrentName(name);
501         } catch (IOException e) {
502             throw new IllegalStateException(e);
503         }
504     }
505     
506     @Override
507     public void close() throws IOException {
508         if (!_closed) {
509             _closed = true;
510             _symbols.release();
511             try {
512                 _closeInput();
513             } finally {
514                 // as per [JACKSON-324], do in finally block
515                 // Also, internal buffer(s) can now be released as well
516                 _releaseBuffers();
517             }
518         }
519     }
520
521     @Override
522     public boolean isClosed() { return _closed; }
523
524     @Override
525     public CBORReadContext getParsingContext() {
526         return _parsingContext;
527     }
528
529     /*
530     /**********************************************************
531     /* Overridden methods
532     /**********************************************************
533      */

534
535     @Override
536     public boolean hasTextCharacters()
537     {
538         if (_currToken == JsonToken.VALUE_STRING) {
539             // yes; is or can be made available efficiently as char[]
540             return _textBuffer.hasTextAsCharacters();
541         }
542         if (_currToken == JsonToken.FIELD_NAME) {
543             // not necessarily; possible but:
544             return _nameCopied;
545         }
546         // other types, no benefit from accessing as char[]
547         return false;
548     }
549
550     /**
551      * Method called to release internal buffers owned by the base
552      * reader. This may be called along with {@link #_closeInput} (for
553      * example, when explicitly closing this reader instance), or
554      * separately (if need be).
555      */

556     protected void _releaseBuffers() throws IOException
557     {
558          if (_bufferRecyclable) {
559              byte[] buf = _inputBuffer;
560              if (buf != null) {
561                  _inputBuffer = null;
562                  _ioContext.releaseReadIOBuffer(buf);
563              }
564          }
565          _textBuffer.releaseBuffers();
566          char[] buf = _nameCopyBuffer;
567          if (buf != null) {
568              _nameCopyBuffer = null;
569              _ioContext.releaseNameCopyBuffer(buf);
570          }
571     }
572
573     /*
574     /**********************************************************
575     /* JsonParser impl
576     /**********************************************************
577      */

578
579     @Override
580     public JsonToken nextToken() throws IOException
581     {
582         _numTypesValid = NR_UNKNOWN;
583         // For longer tokens (text, binary), we'll only read when requested
584         if (_tokenIncomplete) {
585             _skipIncomplete();
586         }
587         _tokenInputTotal = _currInputProcessed + _inputPtr;
588         // also: clear any data retained so far
589         _binaryValue = null;
590
591         /* First: need to keep track of lengths of defined-length Arrays and
592          * Objects (to materialize END_ARRAY/END_OBJECT as necessary);
593          * as well as handle names for Object entries.
594          */

595         if (_parsingContext.inObject()) {
596             if (_currToken != JsonToken.FIELD_NAME) {
597                 _tagValue = -1;
598                 // completed the whole Object?
599                 if (!_parsingContext.expectMoreValues()) {
600                     _parsingContext = _parsingContext.getParent();
601                     return (_currToken = JsonToken.END_OBJECT);
602                 }
603                 return (_currToken = _decodeFieldName());
604             }
605         } else {
606             if (!_parsingContext.expectMoreValues()) {
607                 _tagValue = -1;
608                 _parsingContext = _parsingContext.getParent();
609                 return (_currToken = JsonToken.END_ARRAY);
610             }
611         }
612         if (_inputPtr >= _inputEnd) {
613             if (!loadMore()) {
614                 return _handleCBOREOF();
615             }
616         }
617         int ch = _inputBuffer[_inputPtr++];
618         int type = (ch >> 5) & 0x7;
619
620         // One special case: need to consider tag as prefix first:
621         if (type == 6) {
622             _tagValue = Integer.valueOf(_decodeTag(ch & 0x1F));
623             if (_inputPtr >= _inputEnd) {
624                 if (!loadMore()) {
625                     return _handleCBOREOF();
626                 }
627             }
628             ch = _inputBuffer[_inputPtr++];
629             type = (ch >> 5) & 0x7;
630         } else {
631             _tagValue = -1;
632         }
633         
634         final int lowBits = ch & 0x1F;
635         switch (type) {
636         case 0: // positive int
637             _numTypesValid = NR_INT;
638             if (lowBits <= 23) {
639                 _numberInt = lowBits;
640             } else {
641                 switch (lowBits - 24) {
642                 case 0:
643                     _numberInt = _decode8Bits();
644                     break;
645                 case 1:
646                     _numberInt = _decode16Bits();
647                     break;
648                 case 2:
649                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
650                     {
651                         int v = _decode32Bits();
652                         if (v >= 0) {
653                             _numberInt = v;
654                         } else {
655                             long l = (long) v;
656                             _numberLong = l & 0xFFFFFFFFL;
657                             _numTypesValid = NR_LONG;
658                         }
659                     }
660                     break;
661                 case 3:
662                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
663                     {
664                         long l = _decode64Bits();
665                         if (l >= 0L) {
666                             _numberLong = l;
667                             _numTypesValid = NR_LONG;
668                         } else {
669                             _numberBigInt = _bigPositive(l);
670                             _numTypesValid = NR_BIGINT;
671                         }
672                     }
673                     break;
674                 default:
675                     _invalidToken(ch);
676                 }
677             }
678             return (_currToken = JsonToken.VALUE_NUMBER_INT);
679         case 1: // negative int
680             _numTypesValid = NR_INT;
681             if (lowBits <= 23) {
682                 _numberInt = -lowBits - 1;
683             } else {
684                 switch (lowBits - 24) {
685                 case 0:
686                     _numberInt = -_decode8Bits() - 1;
687                     break;
688                 case 1:
689                     _numberInt = -_decode16Bits() - 1;
690                     break;
691                 case 2:
692                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
693                     {
694                         int v = _decode32Bits();
695                         if (v < 0) {
696                             long unsignedBase = (long) v & 0xFFFFFFFFL;
697                             _numberLong = -unsignedBase - 1L;
698                             _numTypesValid = NR_LONG;
699                         } else {
700                             _numberInt = -v - 1;
701                         }
702                     }
703                     break;
704                 case 3:
705                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
706                     {
707                         long l = _decode64Bits();
708                         if (l >= 0L) {
709                             _numberLong = -l - 1L;
710                             _numTypesValid = NR_LONG;
711                         } else {
712                             _numberBigInt = _bigNegative(l);
713                             _numTypesValid = NR_BIGINT;
714                         }
715                     }
716                     break;
717                 default:
718                     _invalidToken(ch);
719                 }
720             }
721             return (_currToken = JsonToken.VALUE_NUMBER_INT);
722
723         case 2: // byte[]
724             _typeByte = ch;
725             _tokenIncomplete = true;
726             if (_tagValue >= 0) {
727                 return _handleTaggedBinary(_tagValue);
728             }
729             return (_currToken = JsonToken.VALUE_EMBEDDED_OBJECT);
730
731         case 3: // String
732             _typeByte = ch;
733             _tokenIncomplete = true;
734             return (_currToken = JsonToken.VALUE_STRING);
735
736         case 4: // Array
737             {
738                 int len = _decodeExplicitLength(lowBits);
739                 if (_tagValue >= 0) {
740                     return _handleTaggedArray(_tagValue, len);
741                 }
742                 _parsingContext = _parsingContext.createChildArrayContext(len);
743             }
744             return (_currToken = JsonToken.START_ARRAY);
745
746         case 5: // Object
747             _currToken = JsonToken.START_OBJECT;
748             {
749                 int len = _decodeExplicitLength(lowBits);
750                 _parsingContext = _parsingContext.createChildObjectContext(len);
751             }
752             return _currToken;
753
754         case 6: // another tag; not allowed
755             _reportError("Multiple tags not allowed per value (first tag: "+_tagValue+")");
756             
757         default// misc: tokens, floats
758             switch (lowBits) {
759             case 20:
760                 return (_currToken = JsonToken.VALUE_FALSE);
761             case 21:
762                 return (_currToken = JsonToken.VALUE_TRUE);
763             case 22:
764                 return (_currToken = JsonToken.VALUE_NULL);
765             case 23:
766                 return (_currToken = _decodeUndefinedValue());
767                 
768             case 25: // 16-bit float... 
769                 // As per [http://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript]
770                 {
771                     _numberFloat = (float) _decodeHalfSizeFloat();
772                     _numTypesValid = NR_FLOAT;
773                 }
774                 return (_currToken = JsonToken.VALUE_NUMBER_FLOAT);
775             case 26: // Float32
776                 {
777                     _numberFloat = Float.intBitsToFloat(_decode32Bits());
778                     _numTypesValid = NR_FLOAT;
779                 }
780                 return (_currToken = JsonToken.VALUE_NUMBER_FLOAT);
781             case 27: // Float64
782                 _numberDouble = Double.longBitsToDouble(_decode64Bits());
783                 _numTypesValid = NR_DOUBLE;
784                 return (_currToken = JsonToken.VALUE_NUMBER_FLOAT);
785             case 31: // Break
786                 if (_parsingContext.inArray()) {
787                     if (!_parsingContext.hasExpectedLength()) {
788                         _parsingContext = _parsingContext.getParent();
789                         return (_currToken = JsonToken.END_ARRAY);
790                     }
791                 }
792                 // Object end-marker can't occur here
793                 _reportUnexpectedBreak();
794             }
795             _invalidToken(ch);
796         }
797         return null;
798     }
799
800     protected String _numberToName(int ch, boolean neg) throws IOException
801     {
802         final int lowBits = ch & 0x1F;
803         int i;
804         if (lowBits <= 23) {
805             i = lowBits;
806         } else {
807             switch (lowBits) {
808             case 24:
809                 i = _decode8Bits();
810                 break;
811             case 25:
812                 i = _decode16Bits();
813                 break;
814             case 26:
815                 i = _decode32Bits();
816                 break;
817             case 27:
818                 {
819                     long l = _decode64Bits();
820                     if (neg) {
821                         l = -l - 1L;
822                     }
823                     return String.valueOf(l);
824                 }
825             default:
826                 throw _constructError("Invalid length indicator for ints ("+lowBits+"), token 0x"+Integer.toHexString(ch));
827             }
828         }
829         if (neg) {
830             i = -i - 1;
831         }
832         return String.valueOf(i);
833     }
834
835     protected JsonToken _handleTaggedBinary(int tag) throws IOException
836     {
837         // For now all we should get is BigInteger
838         boolean neg;
839         if (tag == TAG_BIGNUM_POS) {
840             neg = false;
841         } else  if (tag == TAG_BIGNUM_NEG) {
842             neg = true;
843         } else {
844             // 12-May-2016, tatu: Since that's all we know, let's otherwise
845             //   just return default Binary data marker
846             return (_currToken = JsonToken.VALUE_EMBEDDED_OBJECT);
847         }
848
849         // First: get the data
850         _finishToken();
851
852         BigInteger nr = new BigInteger(_binaryValue);
853         if (neg) {
854             nr = nr.negate();
855         }
856         _numberBigInt = nr;
857         _numTypesValid = NR_BIGINT;
858         _tagValue = -1;
859         return (_currToken = JsonToken.VALUE_NUMBER_INT);
860     }
861
862     protected JsonToken _handleTaggedArray(int tag, int len) throws IOException
863     {
864         // For simplicity, let's create matching array context -- in perfect
865         // world that wouldn't be necessarily, but in this one there are
866         // some constraints that make it necessary
867         _parsingContext = _parsingContext.createChildArrayContext(len);
868
869         // BigDecimal is the only thing we know for sure
870         if (tag != CBORConstants.TAG_DECIMAL_FRACTION) {
871             return (_currToken = JsonToken.START_ARRAY);
872         }
873         _currToken = JsonToken.START_ARRAY;
874
875         // but has to have length of 2; otherwise we have a problem...
876         if (len != 2) {
877             _reportError("Unexpected array size ("+len+") for tagged 'bigfloat' value; should have exactly 2 number elements");
878         }
879         // and then use recursion to get values
880         // First: exponent, which MUST be a simple integer value
881         if (!_checkNextIsIntInArray("bigfloat")) {
882             _reportError("Unexpected token ("+currentToken()+") as the first part of 'bigfloat' value: should get VALUE_NUMBER_INT");
883         }
884         // 27-Nov-2019, tatu: As per [dataformats-binary#139] need to change sign here
885         int exp = -getIntValue();
886
887         // Should get an integer value; int/long/BigInteger
888         if (!_checkNextIsIntInArray("bigfloat")) {
889             _reportError("Unexpected token ("+currentToken()+") as the second part of 'bigfloat' value: should get VALUE_NUMBER_INT");
890         }
891
892         // important: check number type here
893         BigDecimal dec;
894         NumberType numberType = getNumberType();
895         if (numberType == NumberType.BIG_INTEGER) {
896             dec = new BigDecimal(getBigIntegerValue(), exp);
897         } else  {
898             dec = BigDecimal.valueOf(getLongValue(), exp);
899         }
900
901         // but verify closing END_ARRAY here, as this will now override current token
902         if (!_checkNextIsEndArray()) {
903             _reportError("Unexpected token ("+currentToken()+") after 2 elements of 'bigfloat' value");
904         }
905
906         // which needs to be reset here
907         _numberBigDecimal = dec;
908         _numTypesValid = NR_BIGDECIMAL;
909         return (_currToken = JsonToken.VALUE_NUMBER_FLOAT);
910     }
911
912     /**
913      * Heavily simplified method that does a subset of what {@code nextToken()} does to basically
914      * only (1) determine that we are getting {@code JsonToken.VALUE_NUMBER_INT} (if not,
915      * return with no processing) and (2) if so, prepare state so that number accessor
916      * method will work).
917      *<p>
918      * Note that in particular this method DOES NOT reset state that {@code nextToken()} would do,
919      * but will change current token type to allow access.
920      */

921     protected final boolean _checkNextIsIntInArray(final String typeDesc) throws IOException
922     {
923         // We know we are in array, with length prefix so:
924         if (!_parsingContext.expectMoreValues()) {
925             _tagValue = -1;
926             _parsingContext = _parsingContext.getParent();
927             _currToken = JsonToken.END_ARRAY;
928             return false;
929         }
930
931         if (_inputPtr >= _inputEnd) {
932             if (!loadMore()) {
933                 _handleCBOREOF();
934                 return false;
935             }
936         }
937         int ch = _inputBuffer[_inputPtr++];
938         int type = (ch >> 5) & 0x7;
939
940         // 01-Nov-2019, tatu: We may actually need tag so decode it, but do not assign
941         //   (that'd override tag we already have)
942         int tagValue = -1;
943         if (type == 6) {
944             tagValue = _decodeTag(ch & 0x1F);
945             if ((_inputPtr >= _inputEnd) && !loadMore()) {
946                 _handleCBOREOF();
947                 return false;
948             }
949             ch = _inputBuffer[_inputPtr++];
950             type = (ch >> 5) & 0x7;
951         }
952         
953         final int lowBits = ch & 0x1F;
954         switch (type) {
955         case 0: // positive int
956             _numTypesValid = NR_INT;
957             if (lowBits <= 23) {
958                 _numberInt = lowBits;
959             } else {
960                 switch (lowBits - 24) {
961                 case 0:
962                     _numberInt = _decode8Bits();
963                     break;
964                 case 1:
965                     _numberInt = _decode16Bits();
966                     break;
967                 case 2:
968                     {
969                         int v = _decode32Bits();
970                         if (v >= 0) {
971                             _numberInt = v;
972                         } else {
973                             long l = (long) v;
974                             _numberLong = l & 0xFFFFFFFFL;
975                             _numTypesValid = NR_LONG;
976                         }
977                     }
978                     break;
979                 case 3:
980                     {
981                         long l = _decode64Bits();
982                         if (l >= 0L) {
983                             _numberLong = l;
984                             _numTypesValid = NR_LONG;
985                         } else {
986                             _numberBigInt = _bigPositive(l);
987                             _numTypesValid = NR_BIGINT;
988                         }
989                     }
990                     break;
991                 default:
992                     _invalidToken(ch);
993                 }
994             }
995             _currToken = JsonToken.VALUE_NUMBER_INT;
996             return true;
997         case 1: // negative int
998             _numTypesValid = NR_INT;
999             if (lowBits <= 23) {
1000                 _numberInt = -lowBits - 1;
1001             } else {
1002                 switch (lowBits - 24) {
1003                 case 0:
1004                     _numberInt = -_decode8Bits() - 1;
1005                     break;
1006                 case 1:
1007                     _numberInt = -_decode16Bits() - 1;
1008                     break;
1009                 case 2:
1010                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
1011                     {
1012                         int v = _decode32Bits();
1013                         if (v < 0) {
1014                             long unsignedBase = (long) v & 0xFFFFFFFFL;
1015                             _numberLong = -unsignedBase - 1L;
1016                             _numTypesValid = NR_LONG;
1017                         } else {
1018                             _numberInt = -v - 1;
1019                         }
1020                     }
1021                     break;
1022                 case 3:
1023                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
1024                     {
1025                         long l = _decode64Bits();
1026                         if (l >= 0L) {
1027                             _numberLong = -l - 1L;
1028                             _numTypesValid = NR_LONG;
1029                         } else {
1030                             _numberBigInt = _bigNegative(l);
1031                             _numTypesValid = NR_BIGINT;
1032                         }
1033                     }
1034                     break;
1035                 default:
1036                     _invalidToken(ch);
1037                 }
1038             }
1039             _currToken = JsonToken.VALUE_NUMBER_INT;
1040             return true;
1041
1042         case 2: // byte[]
1043             // ... but we only really care about very specific case of `BigInteger`
1044             if (tagValue < 0) {
1045                 break;
1046             }
1047             _typeByte = ch;
1048             _tokenIncomplete = true;
1049             _currToken = _handleTaggedBinary(tagValue);
1050             return (_currToken == JsonToken.VALUE_NUMBER_INT);
1051
1052         case 6: // another tag; not allowed
1053             _reportError("Multiple tags not allowed per value (first tag: "+tagValue+")");
1054         }
1055
1056         // Important! Need to push back the last byte read (but not consumed)
1057         --_inputPtr;
1058         // and now it is safe to decode next token, too
1059         nextToken();
1060         return false;
1061     }
1062
1063     protected final boolean _checkNextIsEndArray() throws IOException
1064     {
1065         // We know we are in array, with length prefix, and this is where we should be:
1066         if (!_parsingContext.expectMoreValues()) {
1067             _tagValue = -1;
1068             _parsingContext = _parsingContext.getParent();
1069             _currToken = JsonToken.END_ARRAY;
1070             return true;
1071         }
1072
1073         // But while we otherwise could bail out we should check what follows for better
1074         // error reporting... yet we ALSO must avoid direct call to `nextToken()` to avoid
1075         // [dataformats-binary#185]
1076         int ch = _inputBuffer[_inputPtr++];
1077         int type = (ch >> 5) & 0x7;
1078
1079         // No use for tag but removing it is necessary
1080         int tagValue = -1;
1081         if (type == 6) {
1082             tagValue = _decodeTag(ch & 0x1F);
1083             if ((_inputPtr >= _inputEnd) && !loadMore()) {
1084                 _handleCBOREOF();
1085                 return false;
1086             }
1087             ch = _inputBuffer[_inputPtr++];
1088             type = (ch >> 5) & 0x7;
1089             // including but not limited to nested tags (which we do not allow)
1090             if (type == 6) {
1091                 _reportError("Multiple tags not allowed per value (first tag: "+tagValue+")");
1092             }
1093         }
1094         // and that's what we need to do for safety; now can drop to generic handling:
1095         
1096         // Important! Need to push back the last byte read (but not consumed)
1097         --_inputPtr;
1098         return nextToken() == JsonToken.END_ARRAY; // should never match
1099     }
1100
1101     // base impl is fine:
1102     //public String getCurrentName() throws IOException
1103
1104     /**
1105      * Method for forcing full read of current token, even if it might otherwise
1106      * only be read if data is accessed via {@link #getText} and similar methods.
1107      */

1108     @Override
1109     public void finishToken() throws IOException
1110     {
1111         if (_tokenIncomplete) {
1112             _finishToken();
1113         }
1114     }
1115
1116     /*
1117     /**********************************************************
1118     /* Public API, traversal, nextXxxValue/nextFieldName
1119     /**********************************************************
1120      */

1121
1122     @Override
1123     public boolean nextFieldName(SerializableString str) throws IOException
1124     {
1125         // Two parsing modes; can only succeed if expecting field name, so handle that first:
1126         if (_parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) {
1127             _numTypesValid = NR_UNKNOWN;
1128             if (_tokenIncomplete) {
1129                 _skipIncomplete();
1130             }
1131             _tokenInputTotal = _currInputProcessed + _inputPtr;
1132             _binaryValue = null;
1133             _tagValue = -1;
1134             // completed the whole Object?
1135             if (!_parsingContext.expectMoreValues()) {
1136                 _parsingContext = _parsingContext.getParent();
1137                 _currToken = JsonToken.END_OBJECT;
1138                 return false;
1139             }
1140             byte[] nameBytes = str.asQuotedUTF8();
1141             final int byteLen = nameBytes.length;
1142             // fine; require room for up to 2-byte marker, data itself
1143             int ptr = _inputPtr;
1144             if ((ptr + byteLen + 1) < _inputEnd) {
1145                 final int ch = _inputBuffer[ptr++];
1146                 // only handle usual textual type
1147                 if (((ch >> 5) & 0x7) == CBORConstants.MAJOR_TYPE_TEXT) { 
1148                     int lenMarker = ch & 0x1F;
1149                     if (lenMarker <= 24) {
1150                         if (lenMarker == 23) {
1151                             lenMarker = _inputBuffer[ptr++] & 0xFF;
1152                         }
1153                         if (lenMarker == byteLen) {
1154                             int i = 0;
1155                             while (true) {
1156                                 if (i == lenMarker) {
1157                                     _inputPtr = ptr+i;
1158                                     _parsingContext.setCurrentName(str.getValue());
1159                                     _currToken = JsonToken.FIELD_NAME;
1160                                     return true;
1161                                 }
1162                                 if (nameBytes[i] != _inputBuffer[ptr+i]) {
1163                                     break;
1164                                 }
1165                                 ++i;
1166                             }
1167                     }
1168                 }
1169             }
1170         }
1171
1172         }
1173         // otherwise just fall back to default handling; should occur rarely
1174         return (nextToken() == JsonToken.FIELD_NAME) && str.getValue().equals(getCurrentName());
1175     }
1176
1177     @Override
1178     public String nextFieldName() throws IOException
1179     {
1180         if (_parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) {
1181             _numTypesValid = NR_UNKNOWN;
1182             if (_tokenIncomplete) {
1183                 _skipIncomplete();
1184             }
1185             _tokenInputTotal = _currInputProcessed + _inputPtr;
1186             _binaryValue = null;
1187             _tagValue = -1;
1188             // completed the whole Object?
1189             if (!_parsingContext.expectMoreValues()) {
1190                 _parsingContext = _parsingContext.getParent();
1191                 _currToken = JsonToken.END_OBJECT;
1192                 return null;
1193             }
1194             // inlined "_decodeFieldName()"
1195
1196             if (_inputPtr >= _inputEnd) {
1197                 loadMoreGuaranteed();
1198             }
1199             final int ch = _inputBuffer[_inputPtr++];
1200             final int type = ((ch >> 5) & 0x7);
1201
1202             // offline non-String cases, as they are expected to be rare
1203             if (type != CBORConstants.MAJOR_TYPE_TEXT) {
1204                 if (ch == -1) { // end-of-object, common
1205                     if (!_parsingContext.hasExpectedLength()) {
1206                         _parsingContext = _parsingContext.getParent();
1207                         _currToken = JsonToken.END_OBJECT;
1208                         return null;
1209                     }
1210                     _reportUnexpectedBreak();
1211                 }
1212                 _decodeNonStringName(ch);
1213                 _currToken = JsonToken.FIELD_NAME;
1214                 return getText();
1215             }
1216             final int lenMarker = ch & 0x1F;
1217             String name;
1218             if (lenMarker <= 23) {
1219                 if (lenMarker == 0) {
1220                     name = "";
1221                 } else {
1222                     name = _findDecodedFromSymbols(lenMarker);
1223                     if (name != null) {
1224                         _inputPtr += lenMarker;
1225                     } else {
1226                         name = _decodeShortName(lenMarker);
1227                         name = _addDecodedToSymbols(lenMarker, name);
1228                     }
1229                 }
1230             } else {
1231                 final int actualLen = _decodeExplicitLength(lenMarker);
1232                 if (actualLen < 0) {
1233                     name = _decodeChunkedName();
1234                 } else {
1235                     name = _decodeLongerName(actualLen);
1236                 }
1237             }
1238             _parsingContext.setCurrentName(name);
1239             _currToken = JsonToken.FIELD_NAME;
1240             return name;
1241         }
1242         // otherwise just fall back to default handling; should occur rarely
1243         return (nextToken() == JsonToken.FIELD_NAME) ? getCurrentName() : null;
1244     }
1245
1246     @Override
1247     public String nextTextValue() throws IOException
1248     {
1249         _numTypesValid = NR_UNKNOWN;
1250         if (_tokenIncomplete) {
1251             _skipIncomplete();
1252         }
1253         _tokenInputTotal = _currInputProcessed + _inputPtr;
1254         _binaryValue = null;
1255         _tagValue = -1;
1256
1257         if (_parsingContext.inObject()) {
1258             if (_currToken != JsonToken.FIELD_NAME) {
1259                 _tagValue = -1;
1260                 // completed the whole Object?
1261                 if (!_parsingContext.expectMoreValues()) {
1262                     _parsingContext = _parsingContext.getParent();
1263                     _currToken = JsonToken.END_OBJECT;
1264                     return null;
1265                 }
1266                 _currToken = _decodeFieldName();
1267                 return null;
1268             }
1269         } else {
1270             if (!_parsingContext.expectMoreValues()) {
1271                 _tagValue = -1;
1272                 _parsingContext = _parsingContext.getParent();
1273                 _currToken = JsonToken.END_ARRAY;
1274                 return null;
1275             }
1276         }
1277         if (_inputPtr >= _inputEnd) {
1278             if (!loadMore()) {
1279                 _handleCBOREOF();
1280                 return null;
1281             }
1282         }
1283         int ch = _inputBuffer[_inputPtr++];
1284         int type = (ch >> 5) & 0x7;
1285
1286         // One special case: need to consider tag as prefix first:
1287         if (type == 6) {
1288             _tagValue = Integer.valueOf(_decodeTag(ch & 0x1F));
1289             if (_inputPtr >= _inputEnd) {
1290                 if (!loadMore()) {
1291                     _handleCBOREOF();
1292                     return null;
1293                 }
1294             }
1295             ch = _inputBuffer[_inputPtr++];
1296             type = (ch >> 5) & 0x7;
1297         } else {
1298             _tagValue = -1;
1299         }
1300         
1301         final int lowBits = ch & 0x1F;
1302         switch (type) {
1303         case 0: // positive int
1304             _numTypesValid = NR_INT;
1305             if (lowBits <= 23) {
1306                 _numberInt = lowBits;
1307             } else {
1308                 switch (lowBits - 24) {
1309                 case 0:
1310                     _numberInt = _decode8Bits();
1311                     break;
1312                 case 1:
1313                     _numberInt = _decode16Bits();
1314                     break;
1315                 case 2:
1316                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
1317                     {
1318                         int v = _decode32Bits();
1319                         if (v < 0) {
1320                             long l = (long) v;
1321                             _numberLong = l & 0xFFFFFFFFL;
1322                             _numTypesValid = NR_LONG;
1323                         } else{
1324                             _numberInt = v;
1325                         }
1326                     }
1327                     break;
1328                 case 3:
1329                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
1330                     {
1331                         long l = _decode64Bits();
1332                         if (l >= 0L) {
1333                             _numberLong = l;
1334                             _numTypesValid = NR_LONG;
1335                         } else {
1336                             _numberBigInt = _bigPositive(l);
1337                             _numTypesValid = NR_BIGINT;
1338                         }
1339                     }
1340                     break;
1341                 default:
1342                     _invalidToken(ch);
1343                 }
1344             }
1345             _currToken = JsonToken.VALUE_NUMBER_INT;
1346             return null;
1347         case 1: // negative int
1348             _numTypesValid = NR_INT;
1349             if (lowBits <= 23) {
1350                 _numberInt = -lowBits - 1;
1351             } else {
1352                 switch (lowBits - 24) {
1353                 case 0:
1354                     _numberInt = -_decode8Bits() - 1;
1355                     break;
1356                 case 1:
1357                     _numberInt = -_decode16Bits() - 1;
1358                     break;
1359                 case 2:
1360                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
1361                     {
1362                         int v = _decode32Bits();
1363                         if (v < 0) {
1364                             long unsignedBase = (long) v & 0xFFFFFFFFL;
1365                             _numberLong = -unsignedBase - 1L;
1366                             _numTypesValid = NR_LONG;
1367                         } else {
1368                             _numberInt = -v - 1;
1369                         }
1370                     }
1371                     break;
1372                 case 3:
1373                     // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
1374                 {
1375                     long l = _decode64Bits();
1376                     if (l >= 0L) {
1377                         _numberLong = l;
1378                         _numTypesValid = NR_LONG;
1379                     } else {
1380                         _numberBigInt = _bigNegative(l);
1381                         _numTypesValid = NR_BIGINT;
1382                     }
1383                 }
1384                     break;
1385                 default:
1386                     _invalidToken(ch);
1387                 }
1388             }
1389             _currToken = JsonToken.VALUE_NUMBER_INT;
1390             return null;
1391
1392         case 2: // byte[]
1393             _typeByte = ch;
1394             _tokenIncomplete = true;
1395             _currToken = JsonToken.VALUE_EMBEDDED_OBJECT;
1396             return null;
1397
1398         case 3: // String
1399             _typeByte = ch;
1400             _tokenIncomplete = true;
1401             _currToken = JsonToken.VALUE_STRING;
1402             return _finishTextToken(ch);
1403
1404         case 4: // Array
1405             _currToken = JsonToken.START_ARRAY;
1406             {
1407                 int len = _decodeExplicitLength(lowBits);
1408                 _parsingContext = _parsingContext.createChildArrayContext(len);
1409             }
1410             return null;
1411
1412         case 5: // Object
1413             _currToken = JsonToken.START_OBJECT;
1414             {
1415                 int len = _decodeExplicitLength(lowBits);
1416                 _parsingContext = _parsingContext.createChildObjectContext(len);
1417             }
1418             return null;
1419
1420         case 6: // another tag; not allowed
1421             _reportError("Multiple tags not allowed per value (first tag: "+_tagValue+")");
1422             
1423         default// misc: tokens, floats
1424             switch (lowBits) {
1425             case 20:
1426                 _currToken = JsonToken.VALUE_FALSE;
1427                 return null;
1428             case 21:
1429                 _currToken = JsonToken.VALUE_TRUE;
1430                 return null;
1431             case 22:
1432                 _currToken = JsonToken.VALUE_NULL;
1433                 return null;
1434             case 23:
1435                 _currToken = _decodeUndefinedValue();
1436                 return null;
1437
1438             case 25: // 16-bit float... 
1439                 // As per [http://stackoverflow.com/questions/5678432/decompressing-half-precision-floats-in-javascript]
1440                 {
1441                     _numberFloat = _decodeHalfSizeFloat();
1442                     _numTypesValid = NR_FLOAT;
1443                 }
1444                 _currToken = JsonToken.VALUE_NUMBER_FLOAT;
1445                 return null;
1446             case 26: // Float32
1447                 {
1448                     _numberFloat = Float.intBitsToFloat(_decode32Bits());
1449                     _numTypesValid = NR_FLOAT;
1450                 }
1451                 _currToken = JsonToken.VALUE_NUMBER_FLOAT;
1452                 return null;
1453             case 27: // Float64
1454                 _numberDouble = Double.longBitsToDouble(_decode64Bits());
1455                 _numTypesValid = NR_DOUBLE;
1456                 _currToken = JsonToken.VALUE_NUMBER_FLOAT;
1457                 return null;
1458             case 31: // Break
1459                 if (_parsingContext.inArray()) {
1460                     if (!_parsingContext.hasExpectedLength()) {
1461                         _parsingContext = _parsingContext.getParent();
1462                         _currToken = JsonToken.END_ARRAY;
1463                         return null;
1464                     }
1465                 }
1466                 // Object end-marker can't occur here
1467                 _reportUnexpectedBreak();
1468             }
1469             _invalidToken(ch);
1470         }
1471         // otherwise fall back to generic handling:
1472         return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null;
1473     }
1474
1475     @Override
1476     public int nextIntValue(int defaultValue) throws IOException
1477     {
1478         if (nextToken() == JsonToken.VALUE_NUMBER_INT) {
1479             return getIntValue();
1480         }
1481         return defaultValue;
1482     }
1483
1484     @Override
1485     public long nextLongValue(long defaultValue) throws IOException
1486     {
1487         if (nextToken() == JsonToken.VALUE_NUMBER_INT) {
1488             return getLongValue();
1489         }
1490         return defaultValue;
1491     }
1492
1493     @Override
1494     public Boolean nextBooleanValue() throws IOException
1495     {
1496         JsonToken t = nextToken();
1497         if (t == JsonToken.VALUE_TRUE) {
1498             return Boolean.TRUE;
1499         }
1500         if (t == JsonToken.VALUE_FALSE) {
1501             return Boolean.FALSE;
1502         }
1503         return null;
1504     }
1505
1506     /*
1507     /**********************************************************
1508     /* Public API, access to token information, text
1509     /**********************************************************
1510      */

1511
1512     /**
1513      * Method for accessing textual representation of the current event;
1514      * if no current event (before first call to {@link #nextToken}, or
1515      * after encountering end-of-input), returns null.
1516      * Method can be called for any event.
1517      */

1518     @Override    
1519     public String getText() throws IOException
1520     {
1521         JsonToken t = _currToken;
1522         if (_tokenIncomplete) {
1523             if (t == JsonToken.VALUE_STRING) {
1524                 return _finishTextToken(_typeByte);
1525             }
1526         }
1527         if (t == JsonToken.VALUE_STRING) {
1528             return _textBuffer.contentsAsString();
1529         }
1530         if (t == null) { // null only before/after document
1531             return null;
1532         }
1533         if (t == JsonToken.FIELD_NAME) {
1534             return _parsingContext.getCurrentName();
1535         }
1536         if (t.isNumeric()) {
1537             return getNumberValue().toString();
1538         }
1539         return _currToken.asString();
1540     }
1541
1542     @Override
1543     public char[] getTextCharacters() throws IOException
1544     {
1545         if (_currToken != null) { // null only before/after document
1546             if (_tokenIncomplete) {
1547                 _finishToken();
1548             }
1549             if (_currToken == JsonToken.VALUE_STRING) {
1550                 return _textBuffer.getTextBuffer();
1551             }
1552             if (_currToken == JsonToken.FIELD_NAME) {
1553                 return _parsingContext.getCurrentName().toCharArray();
1554             }
1555             if ((_currToken == JsonToken.VALUE_NUMBER_INT)
1556                     || (_currToken == JsonToken.VALUE_NUMBER_FLOAT)) {
1557                 return getNumberValue().toString().toCharArray();
1558             }
1559             return _currToken.asCharArray();
1560         }
1561         return null;
1562     }
1563
1564     @Override    
1565     public int getTextLength() throws IOException
1566     {
1567         if (_currToken != null) { // null only before/after document
1568             if (_tokenIncomplete) {
1569                 _finishToken();
1570             }
1571             if (_currToken == JsonToken.VALUE_STRING) {
1572                 return _textBuffer.size();                
1573             }
1574             if (_currToken == JsonToken.FIELD_NAME) {
1575                 return _parsingContext.getCurrentName().length();
1576             }
1577             if ((_currToken == JsonToken.VALUE_NUMBER_INT)
1578                     || (_currToken == JsonToken.VALUE_NUMBER_FLOAT)) {
1579                 return getNumberValue().toString().length();
1580             }
1581             return _currToken.asCharArray().length;
1582         }
1583         return 0;
1584     }
1585
1586     @Override
1587     public int getTextOffset() throws IOException {
1588         return 0;
1589     }
1590
1591     @Override
1592     public String getValueAsString() throws IOException
1593     {
1594         // inlined 'getText()' for common case of having String
1595         if (_tokenIncomplete) {
1596             if (_currToken == JsonToken.VALUE_STRING) {
1597                 return _finishTextToken(_typeByte);
1598             }
1599         }
1600         if (_currToken == JsonToken.VALUE_STRING) {
1601             return _textBuffer.contentsAsString();
1602         }
1603         if (_currToken == null || _currToken == JsonToken.VALUE_NULL || !_currToken.isScalarValue()) {
1604             return null;
1605         }
1606         return getText();
1607     }
1608
1609     @Override
1610     public String getValueAsString(String defaultValue) throws IOException
1611     {
1612         if (_currToken != JsonToken.VALUE_STRING) {
1613             if (_currToken == null || _currToken == JsonToken.VALUE_NULL || !_currToken.isScalarValue()) {
1614                 return defaultValue;
1615             }
1616         }
1617         return getText();
1618     }
1619
1620     @Override // since 2.8
1621     public int getText(Writer writer) throws IOException
1622     {
1623         if (_tokenIncomplete) {
1624             _finishToken();
1625         }
1626         JsonToken t = _currToken;
1627         if (t == JsonToken.VALUE_STRING) {
1628             return _textBuffer.contentsToWriter(writer);
1629         }
1630         if (t == JsonToken.FIELD_NAME) {
1631             String n = _parsingContext.getCurrentName();
1632             writer.write(n);
1633             return n.length();
1634         }
1635         if (t != null) {
1636             if (t.isNumeric()) {
1637                 return _textBuffer.contentsToWriter(writer);
1638             }
1639             char[] ch = t.asCharArray();
1640             writer.write(ch);
1641             return ch.length;
1642         }
1643         return 0;
1644     }
1645
1646     /*
1647     /**********************************************************
1648     /* Public API, access to token information, binary
1649     /**********************************************************
1650      */

1651
1652     @Override
1653     public byte[] getBinaryValue(Base64Variant b64variant) throws IOException
1654     {
1655         if (_tokenIncomplete) {
1656             _finishToken();
1657         }
1658         if (_currToken != JsonToken.VALUE_EMBEDDED_OBJECT ) {
1659             // TODO, maybe: support base64 for text?
1660             _reportError("Current token ("+currentToken()+") not VALUE_EMBEDDED_OBJECT, can not access as binary");
1661         }
1662         return _binaryValue;
1663     }
1664
1665     @Override
1666     public Object getEmbeddedObject() throws IOException
1667     {
1668         if (_tokenIncomplete) {
1669             _finishToken();
1670         }
1671         if (_currToken == JsonToken.VALUE_EMBEDDED_OBJECT ) {
1672             return _binaryValue;
1673         }
1674         return null;
1675     }
1676
1677     @Override
1678     public int readBinaryValue(Base64Variant b64variant, OutputStream out) throws IOException
1679     {
1680         if (_currToken != JsonToken.VALUE_EMBEDDED_OBJECT ) {
1681             // Todo, maybe: support base64 for text?
1682             _reportError("Current token ("+currentToken()+") not VALUE_EMBEDDED_OBJECT, can not access as binary");
1683         }
1684         if (!_tokenIncomplete) { // someone already decoded or read
1685             if (_binaryValue == null) { // if this method called twice in a row
1686                 return 0;
1687             }
1688             final int len = _binaryValue.length;
1689             out.write(_binaryValue, 0, len);
1690             return len;
1691         }
1692
1693         _tokenIncomplete = false;
1694         int len = _decodeExplicitLength(_typeByte & 0x1F);
1695         if (len >= 0) { // non-chunked
1696             return _readAndWriteBytes(out, len);
1697         }
1698         // Chunked...
1699         int total = 0;
1700         while (true) {
1701             len = _decodeChunkLength(CBORConstants.MAJOR_TYPE_BYTES);
1702             if (len < 0) {
1703                 return total;
1704             }
1705             total += _readAndWriteBytes(out, len);
1706         }
1707     }
1708
1709     private int _readAndWriteBytes(OutputStream out, int total) throws IOException
1710     {
1711         int left = total;
1712         while (left > 0) {
1713             int avail = _inputEnd - _inputPtr;
1714             if (_inputPtr >= _inputEnd) {
1715                 loadMoreGuaranteed();
1716                 avail = _inputEnd - _inputPtr;
1717             }
1718             int count = Math.min(avail, left);
1719             out.write(_inputBuffer, _inputPtr, count);
1720             _inputPtr += count;
1721             left -= count;
1722         }
1723         _tokenIncomplete = false;
1724         return total;
1725     }
1726
1727     /*
1728     /**********************************************************
1729     /* Numeric accessors of public API
1730     /**********************************************************
1731      */

1732
1733     @Override // since 2.9
1734     public boolean isNaN() {
1735         if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) {
1736             if ((_numTypesValid & NR_DOUBLE) != 0) {
1737                 // 10-Mar-2017, tatu: Alas, `Double.isFinite(d)` only added in JDK 8
1738                 double d = _numberDouble;
1739                 return Double.isNaN(d) || Double.isInfinite(d);
1740             }
1741             if ((_numTypesValid & NR_FLOAT) != 0) {
1742                 float f = _numberFloat;
1743                 return Float.isNaN(f) || Float.isInfinite(f);
1744             }
1745         }
1746         return false;
1747     }
1748
1749     @Override
1750     public Number getNumberValue() throws IOException
1751     {
1752         if (_numTypesValid == NR_UNKNOWN) {
1753             _checkNumericValue(NR_UNKNOWN); // will also check event type
1754         }
1755         // Separate types for int types
1756         if (_currToken == JsonToken.VALUE_NUMBER_INT) {
1757             if ((_numTypesValid & NR_INT) != 0) {
1758                 return _numberInt;
1759             }
1760             if ((_numTypesValid & NR_LONG) != 0) {
1761                 return _numberLong;
1762             }
1763             if ((_numTypesValid & NR_BIGINT) != 0) {
1764                 return _numberBigInt;
1765             }
1766             // Shouldn't get this far but if we do
1767             return _numberBigDecimal;
1768         }
1769     
1770         // And then floating point types. But here optimal type
1771         // needs to be big decimal, to avoid losing any data?
1772         if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
1773             return _numberBigDecimal;
1774         }
1775         if ((_numTypesValid & NR_DOUBLE) != 0) {
1776             return _numberDouble;
1777         }
1778         if ((_numTypesValid & NR_FLOAT) == 0) { // sanity check
1779             _throwInternal();
1780         }
1781         return _numberFloat;
1782     }
1783
1784     @Override
1785     public NumberType getNumberType() throws IOException
1786     {
1787         if (_numTypesValid == NR_UNKNOWN) {
1788             _checkNumericValue(NR_UNKNOWN); // will also check event type
1789         }
1790         if (_currToken == JsonToken.VALUE_NUMBER_INT) {
1791             if ((_numTypesValid & NR_INT) != 0) {
1792                 return NumberType.INT;
1793             }
1794             if ((_numTypesValid & NR_LONG) != 0) {
1795                 return NumberType.LONG;
1796             }
1797             return NumberType.BIG_INTEGER;
1798         }
1799     
1800         /* And then floating point types. Here optimal type
1801          * needs to be big decimal, to avoid losing any data?
1802          * However... using BD is slow, so let's allow returning
1803          * double as type if no explicit call has been made to access
1804          * data as BD?
1805          */

1806         if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
1807             return NumberType.BIG_DECIMAL;
1808         }
1809         if ((_numTypesValid & NR_DOUBLE) != 0) {
1810             return NumberType.DOUBLE;
1811         }
1812         return NumberType.FLOAT;
1813     }
1814     
1815     @Override
1816     public int getIntValue() throws IOException
1817     {
1818         if ((_numTypesValid & NR_INT) == 0) {
1819             if (_numTypesValid == NR_UNKNOWN) { // not parsed at all
1820                 _checkNumericValue(NR_INT); // will also check event type
1821             }
1822             if ((_numTypesValid & NR_INT) == 0) { // wasn't an int natively?
1823                 convertNumberToInt(); // let's make it so, if possible
1824             }
1825         }
1826         return _numberInt;
1827     }
1828     
1829     @Override
1830     public long getLongValue() throws IOException
1831     {
1832         if ((_numTypesValid & NR_LONG) == 0) {
1833             if (_numTypesValid == NR_UNKNOWN) {
1834                 _checkNumericValue(NR_LONG);
1835             }
1836             if ((_numTypesValid & NR_LONG) == 0) {
1837                 convertNumberToLong();
1838             }
1839         }
1840         return _numberLong;
1841     }
1842     
1843     @Override
1844     public BigInteger getBigIntegerValue() throws IOException
1845     {
1846         if ((_numTypesValid & NR_BIGINT) == 0) {
1847             if (_numTypesValid == NR_UNKNOWN) {
1848                 _checkNumericValue(NR_BIGINT);
1849             }
1850             if ((_numTypesValid & NR_BIGINT) == 0) {
1851                 convertNumberToBigInteger();
1852             }
1853         }
1854         return _numberBigInt;
1855     }
1856
1857     @Override
1858     public float getFloatValue() throws IOException
1859     {
1860         if ((_numTypesValid & NR_FLOAT) == 0) {
1861             if (_numTypesValid == NR_UNKNOWN) {
1862                 _checkNumericValue(NR_FLOAT);
1863             }
1864             if ((_numTypesValid & NR_FLOAT) == 0) {
1865                 convertNumberToFloat();
1866             }
1867         }
1868         // Bounds/range checks would be tricky here, so let's not bother even trying...
1869         /*
1870         if (value < -Float.MAX_VALUE || value > MAX_FLOAT_D) {
1871             _reportError("Numeric value ("+getText()+") out of range of Java float");
1872         }
1873         */

1874         return _numberFloat;
1875     }
1876
1877     @Override
1878     public double getDoubleValue() throws IOException
1879     {
1880         if ((_numTypesValid & NR_DOUBLE) == 0) {
1881             if (_numTypesValid == NR_UNKNOWN) {
1882                 _checkNumericValue(NR_DOUBLE);
1883             }
1884             if ((_numTypesValid & NR_DOUBLE) == 0) {
1885                 convertNumberToDouble();
1886             }
1887         }
1888         return _numberDouble;
1889     }
1890     
1891     @Override
1892     public BigDecimal getDecimalValue() throws IOException
1893     {
1894         if ((_numTypesValid & NR_BIGDECIMAL) == 0) {
1895             if (_numTypesValid == NR_UNKNOWN) {
1896                 _checkNumericValue(NR_BIGDECIMAL);
1897             }
1898             if ((_numTypesValid & NR_BIGDECIMAL) == 0) {
1899                 convertNumberToBigDecimal();
1900             }
1901         }
1902         return _numberBigDecimal;
1903     }
1904
1905     /*
1906     /**********************************************************
1907     /* Numeric conversions
1908     /**********************************************************
1909      */
    
1910
1911     protected void _checkNumericValue(int expType) throws IOException
1912     {
1913         // Int or float?
1914         if (_currToken == JsonToken.VALUE_NUMBER_INT || _currToken == JsonToken.VALUE_NUMBER_FLOAT) {
1915             return;
1916         }
1917         _reportError("Current token ("+currentToken()+") not numeric, can not use numeric value accessors");
1918     }
1919
1920     protected void convertNumberToInt() throws IOException
1921     {
1922         // First, converting from long ought to be easy
1923         if ((_numTypesValid & NR_LONG) != 0) {
1924             // Let's verify it's lossless conversion by simple roundtrip
1925             int result = (int) _numberLong;
1926             if (((long) result) != _numberLong) {
1927                 _reportError("Numeric value ("+getText()+") out of range of int");
1928             }
1929             _numberInt = result;
1930         } else if ((_numTypesValid & NR_BIGINT) != 0) {
1931             if (BI_MIN_INT.compareTo(_numberBigInt) > 0 
1932                     || BI_MAX_INT.compareTo(_numberBigInt) < 0) {
1933                 reportOverflowInt();
1934             }
1935             _numberInt = _numberBigInt.intValue();
1936         } else if ((_numTypesValid & NR_DOUBLE) != 0) {
1937             // Need to check boundaries
1938             if (_numberDouble < MIN_INT_D || _numberDouble > MAX_INT_D) {
1939                 reportOverflowInt();
1940             }
1941             _numberInt = (int) _numberDouble;
1942         } else if ((_numTypesValid & NR_FLOAT) != 0) {
1943             if (_numberFloat < MIN_INT_D || _numberFloat > MAX_INT_D) {
1944                 reportOverflowInt();
1945             }
1946             _numberInt = (int) _numberFloat;
1947         } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
1948             if (BD_MIN_INT.compareTo(_numberBigDecimal) > 0 
1949                 || BD_MAX_INT.compareTo(_numberBigDecimal) < 0) {
1950                 reportOverflowInt();
1951             }
1952             _numberInt = _numberBigDecimal.intValue();
1953         } else {
1954             _throwInternal();
1955         }
1956         _numTypesValid |= NR_INT;
1957     }
1958     
1959     protected void convertNumberToLong() throws IOException
1960     {
1961         if ((_numTypesValid & NR_INT) != 0) {
1962             _numberLong = (long) _numberInt;
1963         } else if ((_numTypesValid & NR_BIGINT) != 0) {
1964             if (BI_MIN_LONG.compareTo(_numberBigInt) > 0 
1965                     || BI_MAX_LONG.compareTo(_numberBigInt) < 0) {
1966                 reportOverflowLong();
1967             }
1968             _numberLong = _numberBigInt.longValue();
1969         } else if ((_numTypesValid & NR_DOUBLE) != 0) {
1970             if (_numberDouble < MIN_LONG_D || _numberDouble > MAX_LONG_D) {
1971                 reportOverflowLong();
1972             }
1973             _numberLong = (long) _numberDouble;
1974         } else if ((_numTypesValid & NR_FLOAT) != 0) {
1975             if (_numberFloat < MIN_LONG_D || _numberFloat > MAX_LONG_D) {
1976                 reportOverflowInt();
1977             }
1978             _numberLong = (long) _numberFloat;
1979         } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
1980             if (BD_MIN_LONG.compareTo(_numberBigDecimal) > 0 
1981                 || BD_MAX_LONG.compareTo(_numberBigDecimal) < 0) {
1982                 reportOverflowLong();
1983             }
1984             _numberLong = _numberBigDecimal.longValue();
1985         } else {
1986             _throwInternal();
1987         }
1988         _numTypesValid |= NR_LONG;
1989     }
1990     
1991     protected void convertNumberToBigInteger() throws IOException
1992     {
1993         if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
1994             // here it'll just get truncated, no exceptions thrown
1995             _numberBigInt = _numberBigDecimal.toBigInteger();
1996         } else if ((_numTypesValid & NR_LONG) != 0) {
1997             _numberBigInt = BigInteger.valueOf(_numberLong);
1998         } else if ((_numTypesValid & NR_INT) != 0) {
1999             _numberBigInt = BigInteger.valueOf(_numberInt);
2000         } else if ((_numTypesValid & NR_DOUBLE) != 0) {
2001             _numberBigInt = BigDecimal.valueOf(_numberDouble).toBigInteger();
2002         } else if ((_numTypesValid & NR_FLOAT) != 0) {
2003             _numberBigInt = BigDecimal.valueOf(_numberFloat).toBigInteger();
2004         } else {
2005             _throwInternal();
2006         }
2007         _numTypesValid |= NR_BIGINT;
2008     }
2009
2010     protected void convertNumberToFloat() throws IOException
2011     {
2012         // Note: this MUST start with more accurate representations, since we don't know which
2013         //  value is the original one (others get generated when requested)
2014         if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
2015             _numberFloat = _numberBigDecimal.floatValue();
2016         } else if ((_numTypesValid & NR_BIGINT) != 0) {
2017             _numberFloat = _numberBigInt.floatValue();
2018         } else if ((_numTypesValid & NR_DOUBLE) != 0) {
2019             _numberFloat = (float) _numberDouble;
2020         } else if ((_numTypesValid & NR_LONG) != 0) {
2021             _numberFloat = (float) _numberLong;
2022         } else if ((_numTypesValid & NR_INT) != 0) {
2023             _numberFloat = (float) _numberInt;
2024         } else {
2025             _throwInternal();
2026         }
2027         _numTypesValid |= NR_FLOAT;
2028     }
2029     
2030     protected void convertNumberToDouble() throws IOException
2031     {
2032         // Note: this MUST start with more accurate representations, since we don't know which
2033         //  value is the original one (others get generated when requested)
2034         if ((_numTypesValid & NR_BIGDECIMAL) != 0) {
2035             _numberDouble = _numberBigDecimal.doubleValue();
2036         } else if ((_numTypesValid & NR_FLOAT) != 0) {
2037             _numberDouble = (double) _numberFloat;
2038         } else if ((_numTypesValid & NR_BIGINT) != 0) {
2039             _numberDouble = _numberBigInt.doubleValue();
2040         } else if ((_numTypesValid & NR_LONG) != 0) {
2041             _numberDouble = (double) _numberLong;
2042         } else if ((_numTypesValid & NR_INT) != 0) {
2043             _numberDouble = (double) _numberInt;
2044         } else {
2045             _throwInternal();
2046         }
2047         _numTypesValid |= NR_DOUBLE;
2048     }
2049     
2050     protected void convertNumberToBigDecimal() throws IOException
2051     {
2052         // Note: this MUST start with more accurate representations, since we don't know which
2053         //  value is the original one (others get generated when requested)
2054         if ((_numTypesValid & (NR_DOUBLE | NR_FLOAT)) != 0) {
2055             // Let's parse from String representation, to avoid rounding errors that
2056             //non-decimal floating operations would incur
2057             _numberBigDecimal = NumberInput.parseBigDecimal(getText());
2058         } else if ((_numTypesValid & NR_BIGINT) != 0) {
2059             _numberBigDecimal = new BigDecimal(_numberBigInt);
2060         } else if ((_numTypesValid & NR_LONG) != 0) {
2061             _numberBigDecimal = BigDecimal.valueOf(_numberLong);
2062         } else if ((_numTypesValid & NR_INT) != 0) {
2063             _numberBigDecimal = BigDecimal.valueOf(_numberInt);
2064         } else {
2065             _throwInternal();
2066         }
2067         _numTypesValid |= NR_BIGDECIMAL;
2068     }
2069
2070     /*
2071     /**********************************************************
2072     /* Internal methods, secondary parsing
2073     /**********************************************************
2074      */

2075
2076     /**
2077      * Method called to finish parsing of a token so that token contents
2078      * are retriable
2079      */

2080     protected void _finishToken() throws IOException
2081     {
2082         _tokenIncomplete = false;
2083         int ch = _typeByte;
2084         final int type = ((ch >> 5) & 0x7);
2085         ch &= 0x1F;
2086
2087         // Either String or byte[]
2088         if (type != CBORConstants.MAJOR_TYPE_TEXT) {
2089             if (type == CBORConstants.MAJOR_TYPE_BYTES) {
2090                 _binaryValue = _finishBytes(_decodeExplicitLength(ch));
2091                 return;
2092             }
2093             // should never happen so
2094             _throwInternal();
2095         }
2096
2097         // String value, decode
2098         final int len = _decodeExplicitLength(ch);
2099
2100         if (len <= 0) {
2101             if (len < 0) {
2102                 _finishChunkedText();
2103             } else {
2104                 _textBuffer.resetWithEmpty();
2105             }
2106             return;
2107         }
2108         if (len > (_inputEnd - _inputPtr)) {
2109             // or if not, could we read?
2110             if (len >= _inputBuffer.length) {
2111                 // If not enough space, need handling similar to chunked
2112                 _finishLongText(len);
2113                 return;
2114             }
2115             _loadToHaveAtLeast(len);
2116         }
2117         // offline for better optimization
2118         _finishShortText(len);
2119     }
2120
2121     /**
2122      * @since 2.6
2123      */

2124     protected String _finishTextToken(int ch) throws IOException
2125     {
2126         _tokenIncomplete = false;
2127         final int type = ((ch >> 5) & 0x7);
2128         ch &= 0x1F;
2129
2130         // sanity check
2131         if (type != CBORConstants.MAJOR_TYPE_TEXT) {
2132             // should never happen so
2133             _throwInternal();
2134         }
2135
2136         // String value, decode
2137         final int len = _decodeExplicitLength(ch);
2138
2139         if (len <= 0) {
2140             if (len == 0) {
2141                 _textBuffer.resetWithEmpty();
2142                 return "";
2143             }
2144             _finishChunkedText();
2145             return _textBuffer.contentsAsString();
2146         }
2147         if (len > (_inputEnd - _inputPtr)) {
2148             // or if not, could we read?
2149             if (len >= _inputBuffer.length) {
2150                 // If not enough space, need handling similar to chunked
2151                 _finishLongText(len);
2152                 return _textBuffer.contentsAsString();
2153             }
2154             _loadToHaveAtLeast(len);
2155         }
2156         // offline for better optimization
2157         return _finishShortText(len);
2158     }
2159
2160     private final String _finishShortText(int len) throws IOException
2161     {
2162         char[] outBuf = _textBuffer.emptyAndGetCurrentSegment();
2163         if (outBuf.length < len) { // one minor complication
2164             outBuf = _textBuffer.expandCurrentSegment(len);
2165         }
2166         
2167         int outPtr = 0;
2168         int inPtr = _inputPtr;
2169         _inputPtr += len;
2170         final byte[] inputBuf = _inputBuffer;
2171
2172         // Let's actually do a tight loop for ASCII first:
2173         final int end = inPtr + len;
2174
2175         int i;
2176         while ((i = inputBuf[inPtr]) >= 0) {
2177             outBuf[outPtr++] = (char) i;
2178             if (++inPtr == end) {
2179                 return _textBuffer.setCurrentAndReturn(outPtr);
2180             }
2181         }
2182
2183         final int[] codes = UTF8_UNIT_CODES;
2184         do {
2185             i = inputBuf[inPtr++] & 0xFF;
2186             switch (codes[i]) {
2187             case 0:
2188                 break;
2189             case 1:
2190                 i = ((i & 0x1F) << 6) | (inputBuf[inPtr++] & 0x3F);
2191                 break;
2192             case 2:
2193                 i = ((i & 0x0F) << 12)
2194                    | ((inputBuf[inPtr++] & 0x3F) << 6)
2195                    | (inputBuf[inPtr++] & 0x3F);
2196                 break;
2197             case 3:
2198                 i = ((i & 0x07) << 18)
2199                  | ((inputBuf[inPtr++] & 0x3F) << 12)
2200                  | ((inputBuf[inPtr++] & 0x3F) << 6)
2201                  | (inputBuf[inPtr++] & 0x3F);
2202                 // note: this is the codepoint value; need to split, too
2203                 i -= 0x10000;
2204                 outBuf[outPtr++] = (char) (0xD800 | (i >> 10));
2205                 i = 0xDC00 | (i & 0x3FF);
2206                 break;
2207             default// invalid
2208                 _reportError("Invalid byte "+Integer.toHexString(i)+" in Unicode text block");
2209             }
2210             outBuf[outPtr++] = (char) i;
2211         } while (inPtr < end);
2212         return _textBuffer.setCurrentAndReturn(outPtr);
2213     }
2214
2215     private final void _finishLongText(int len) throws IOException
2216     {
2217         char[] outBuf = _textBuffer.emptyAndGetCurrentSegment();
2218         int outPtr = 0;
2219         final int[] codes = UTF8_UNIT_CODES;
2220         int outEnd = outBuf.length;
2221
2222         while (--len >= 0) {
2223             int c = _nextByte() & 0xFF;
2224             int code = codes[c];
2225             if (code == 0 && outPtr < outEnd) {
2226                 outBuf[outPtr++] = (char) c;
2227                 continue;
2228             }
2229             if ((len -= code) < 0) { // may need to improve error here but...
2230                 throw _constructError("Malformed UTF-8 character at end of long (non-chunked) text segment");
2231             }
2232             
2233             switch (code) {
2234             case 0:
2235                 break;
2236             case 1: // 2-byte UTF
2237                 {
2238                     int d = _nextByte();
2239                     if ((d & 0xC0) != 0x080) {
2240                         _reportInvalidOther(d & 0xFF, _inputPtr);
2241                     }
2242                     c = ((c & 0x1F) << 6) | (d & 0x3F);
2243                 }
2244                 break;
2245             case 2: // 3-byte UTF
2246                 c = _decodeUTF8_3(c);
2247                 break;
2248             case 3: // 4-byte UTF
2249                 c = _decodeUTF8_4(c);
2250                 // Let's add first part right away:
2251                 outBuf[outPtr++] = (char) (0xD800 | (c >> 10));
2252                 if (outPtr >= outBuf.length) {
2253                     outBuf = _textBuffer.finishCurrentSegment();
2254                     outPtr = 0;
2255                     outEnd = outBuf.length;
2256                 }
2257                 c = 0xDC00 | (c & 0x3FF);
2258                 // And let the other char output down below
2259                 break;
2260             default:
2261                 // Is this good enough error message?
2262                 _reportInvalidChar(c);
2263             }
2264             // Need more room?
2265             if (outPtr >= outEnd) {
2266                 outBuf = _textBuffer.finishCurrentSegment();
2267                 outPtr = 0;
2268                 outEnd = outBuf.length;
2269             }
2270             // Ok, let's add char to output:
2271             outBuf[outPtr++] = (char) c;
2272         }
2273         _textBuffer.setCurrentLength(outPtr);
2274     }
2275
2276     private final void _finishChunkedText() throws IOException
2277     {
2278         char[] outBuf = _textBuffer.emptyAndGetCurrentSegment();
2279         int outPtr = 0;
2280         final int[] codes = UTF8_UNIT_CODES;
2281         int outEnd = outBuf.length;
2282         final byte[] input = _inputBuffer;
2283
2284         _chunkEnd = _inputPtr;
2285         _chunkLeft = 0;
2286         
2287         while (true) {
2288             // at byte boundary fine to get break marker, hence different:
2289             if (_inputPtr >= _chunkEnd) {
2290                 // end of chunk? get a new one, if there is one; if not, we are done
2291                 if (_chunkLeft == 0) {
2292                     int len = _decodeChunkLength(CBORConstants.MAJOR_TYPE_TEXT);
2293                     if (len < 0) { // fine at this point (but not later)
2294                         break;
2295                     }
2296                     _chunkLeft = len;
2297                     int end = _inputPtr + len;
2298                     if (end <= _inputEnd) { // all within buffer
2299                         _chunkLeft = 0;
2300                         _chunkEnd = end;
2301                     } else { // stretches beyond
2302                         _chunkLeft = (end - _inputEnd);
2303                         _chunkEnd = _inputEnd;
2304                     }
2305                 }
2306                 // besides of which just need to ensure there's content
2307                 if (_inputPtr >= _inputEnd) { // end of buffer, but not necessarily chunk
2308                     loadMoreGuaranteed();
2309                     int end = _inputPtr + _chunkLeft;
2310                     if (end <= _inputEnd) { // all within buffer
2311                         _chunkLeft = 0;
2312                         _chunkEnd = end;
2313                     } else { // stretches beyond
2314                         _chunkLeft = (end - _inputEnd);
2315                         _chunkEnd = _inputEnd;
2316                     }
2317                 }
2318             }
2319             int c = input[_inputPtr++] & 0xFF;
2320             int code = codes[c];
2321             if (code == 0 && outPtr < outEnd) {
2322                 outBuf[outPtr++] = (char) c;
2323                 continue;
2324             }
2325             switch (code) {
2326             case 0:
2327                 break;
2328             case 1: // 2-byte UTF
2329                 {
2330                     int d = _nextChunkedByte();
2331                     if ((d & 0xC0) != 0x080) {
2332                         _reportInvalidOther(d & 0xFF, _inputPtr);
2333                     }
2334                     c = ((c & 0x1F) << 6) | (d & 0x3F);
2335                 }
2336                 break;
2337             case 2: // 3-byte UTF
2338                 c = _decodeChunkedUTF8_3(c);
2339                 break;
2340             case 3: // 4-byte UTF
2341                 c = _decodeChunkedUTF8_4(c);
2342                 // Let's add first part right away:
2343                 if (outPtr >= outBuf.length) {
2344                     outBuf = _textBuffer.finishCurrentSegment();
2345                     outPtr = 0;
2346                     outEnd = outBuf.length;
2347                 }
2348                 outBuf[outPtr++] = (char) (0xD800 | (c >> 10));
2349                 c = 0xDC00 | (c & 0x3FF);
2350                 // And let the other char output down below
2351                 break;
2352             default:
2353                 // Is this good enough error message?
2354                 _reportInvalidChar(c);
2355             }
2356             // Need more room?
2357             if (outPtr >= outEnd) {
2358                 outBuf = _textBuffer.finishCurrentSegment();
2359                 outPtr = 0;
2360                 outEnd = outBuf.length;
2361             }
2362             // Ok, let's add char to output:
2363             outBuf[outPtr++] = (char) c;
2364         }
2365         _textBuffer.setCurrentLength(outPtr);
2366     }
2367
2368     private final int _nextByte() throws IOException {
2369         int inPtr = _inputPtr;
2370         if (inPtr < _inputEnd) {
2371             int ch = _inputBuffer[inPtr];
2372             _inputPtr = inPtr+1;
2373             return ch;
2374         }
2375         loadMoreGuaranteed();
2376         return _inputBuffer[_inputPtr++];
2377     }
2378
2379     private final int _nextChunkedByte() throws IOException {
2380         int inPtr = _inputPtr;
2381         
2382         // NOTE: _chunkEnd less than or equal to _inputEnd
2383         if (inPtr >= _chunkEnd) {
2384             return _nextChunkedByte2();
2385         }
2386         int ch = _inputBuffer[inPtr];
2387         _inputPtr = inPtr+1;
2388         return ch;
2389     }
2390
2391     private final int _nextChunkedByte2() throws IOException
2392     {
2393         // two possibilities: either end of buffer (in which case, just load more),
2394         // or end of chunk
2395
2396         if (_inputPtr >= _inputEnd) { // end of buffer, but not necessarily chunk
2397             loadMoreGuaranteed();
2398             if (_chunkLeft > 0) {
2399                 int end = _inputPtr + _chunkLeft;
2400                 if (end <= _inputEnd) { // all within buffer
2401                     _chunkLeft = 0;
2402                     _chunkEnd = end;
2403                 } else { // stretches beyond
2404                     _chunkLeft = (end - _inputEnd);
2405                     _chunkEnd = _inputEnd;
2406                 }
2407                 // either way, got it now
2408                 return _inputBuffer[_inputPtr++];
2409             }
2410         }
2411         int len = _decodeChunkLength(CBORConstants.MAJOR_TYPE_TEXT);
2412         // not actually acceptable if we got a split character
2413         if (len < 0) {
2414             _reportInvalidEOF(": chunked Text ends with partial UTF-8 character",
2415                     JsonToken.VALUE_STRING);
2416         }
2417         int end = _inputPtr + len;
2418         if (end <= _inputEnd) { // all within buffer
2419             _chunkLeft = 0;
2420             _chunkEnd = end;
2421         } else { // stretches beyond
2422             _chunkLeft = (end - _inputEnd);
2423             _chunkEnd = _inputEnd;
2424         }
2425         // either way, got it now
2426         return _inputBuffer[_inputPtr++];
2427     }
2428     
2429     @SuppressWarnings("resource")
2430     protected byte[] _finishBytes(int len) throws IOException
2431     {
2432         // First, simple: non-chunked
2433         if (len >= 0) {
2434             if (len == 0) {
2435                 return NO_BYTES;
2436             }
2437             byte[] b = new byte[len];
2438             if (_inputPtr >= _inputEnd) {
2439                 loadMoreGuaranteed();
2440             }
2441             int ptr = 0;
2442             while (true) {
2443                 int toAdd = Math.min(len, _inputEnd - _inputPtr);
2444                 System.arraycopy(_inputBuffer, _inputPtr, b, ptr, toAdd);
2445                 _inputPtr += toAdd;
2446                 ptr += toAdd;
2447                 len -= toAdd;
2448                 if (len <= 0) {
2449                     return b;
2450                 }
2451                 loadMoreGuaranteed();
2452             }
2453         }
2454
2455         // or, if not, chunked...
2456         ByteArrayBuilder bb = _getByteArrayBuilder();
2457         while (true) {
2458             if (_inputPtr >= _inputEnd) {
2459                 loadMoreGuaranteed();
2460             }
2461             int ch = _inputBuffer[_inputPtr++] & 0xFF;
2462             if (ch == 0xFF) { // end marker
2463                 break;
2464             }
2465             // verify that type matches
2466             int type = (ch >> 5);
2467             if (type != CBORConstants.MAJOR_TYPE_BYTES) {
2468                 throw _constructError("Mismatched chunk in chunked content: expected "+CBORConstants.MAJOR_TYPE_BYTES
2469                         +" but encountered "+type);
2470             }
2471             len = _decodeExplicitLength(ch & 0x1F);
2472             if (len < 0) {
2473                 throw _constructError("Illegal chunked-length indicator within chunked-length value (type "+CBORConstants.MAJOR_TYPE_BYTES+")");
2474             }
2475             while (len > 0) {
2476                 int avail = _inputEnd - _inputPtr;
2477                 if (_inputPtr >= _inputEnd) {
2478                     loadMoreGuaranteed();
2479                     avail = _inputEnd - _inputPtr;
2480                 }
2481                 int count = Math.min(avail, len);
2482                 bb.write(_inputBuffer, _inputPtr, count);
2483                 _inputPtr += count;
2484                 len -= count;
2485             }
2486         }
2487         return bb.toByteArray();
2488     }
2489     
2490     protected final JsonToken _decodeFieldName() throws IOException
2491     {     
2492         if (_inputPtr >= _inputEnd) {
2493             loadMoreGuaranteed();
2494         }
2495         final int ch = _inputBuffer[_inputPtr++];
2496         final int type = ((ch >> 5) & 0x7);
2497
2498         // Expecting a String, but may need to allow other types too
2499         if (type != CBORConstants.MAJOR_TYPE_TEXT) { // the usual case
2500             if (ch == -1) {
2501                 if (!_parsingContext.hasExpectedLength()) {
2502                     _parsingContext = _parsingContext.getParent();
2503                     return JsonToken.END_OBJECT;
2504                 }
2505                 _reportUnexpectedBreak();
2506             }
2507             // offline non-String cases, as they are expected to be rare
2508             _decodeNonStringName(ch);
2509             return JsonToken.FIELD_NAME;
2510         }
2511         final int lenMarker = ch & 0x1F;
2512         String name;
2513         if (lenMarker <= 23) {
2514             if (lenMarker == 0) {
2515                 name = "";
2516             } else {
2517                 name = _findDecodedFromSymbols(lenMarker);
2518                 if (name != null) {
2519                     _inputPtr += lenMarker;
2520                 } else {
2521                     name = _decodeShortName(lenMarker);
2522                     name = _addDecodedToSymbols(lenMarker, name);
2523                 }
2524             }
2525         } else {
2526             final int actualLen = _decodeExplicitLength(lenMarker);
2527             if (actualLen < 0) {
2528                 name = _decodeChunkedName();
2529             } else {
2530                 name = _decodeLongerName(actualLen);
2531             }
2532         }
2533         _parsingContext.setCurrentName(name);
2534         return JsonToken.FIELD_NAME;
2535     }
2536     
2537     private final String _decodeShortName(int len) throws IOException
2538     {
2539         // note: caller ensures we have enough bytes available
2540         int outPtr = 0;
2541         char[] outBuf = _textBuffer.emptyAndGetCurrentSegment();
2542         if (outBuf.length < len) { // one minor complication
2543             outBuf = _textBuffer.expandCurrentSegment(len);
2544         }
2545         int inPtr = _inputPtr;
2546         _inputPtr += len;
2547         final int[] codes = UTF8_UNIT_CODES;
2548         final byte[] inBuf = _inputBuffer;
2549
2550         // First a tight loop for Ascii
2551         final int end = inPtr + len;
2552         while (true) {
2553             int i = inBuf[inPtr] & 0xFF;
2554             int code = codes[i];
2555             if (code != 0) {
2556                 break;
2557             }
2558             outBuf[outPtr++] = (char) i;
2559             if (++inPtr == end) {
2560                 return _textBuffer.setCurrentAndReturn(outPtr);
2561             }
2562         }
2563
2564         // But in case there's multi-byte char, use a full loop
2565         while (inPtr < end) {
2566             int i = inBuf[inPtr++] & 0xFF;
2567             int code = codes[i];
2568             if (code != 0) {
2569                 // trickiest one, need surrogate handling
2570                 switch (code) {
2571                 case 1:
2572                     i = ((i & 0x1F) << 6) | (inBuf[inPtr++] & 0x3F);
2573                     break;
2574                 case 2:
2575                     i = ((i & 0x0F) << 12)
2576                     | ((inBuf[inPtr++] & 0x3F) << 6)
2577                     | (inBuf[inPtr++] & 0x3F);
2578                     break;
2579                 case 3:
2580                     i = ((i & 0x07) << 18)
2581                     | ((inBuf[inPtr++] & 0x3F) << 12)
2582                     | ((inBuf[inPtr++] & 0x3F) << 6)
2583                     | (inBuf[inPtr++] & 0x3F);
2584                     // note: this is the codepoint value; need to split, too
2585                     i -= 0x10000;
2586                     outBuf[outPtr++] = (char) (0xD800 | (i >> 10));
2587                     i = 0xDC00 | (i & 0x3FF);
2588                     break;
2589                 default// invalid
2590                     _reportError("Invalid byte "+Integer.toHexString(i)+" in Object name");
2591                 }
2592             }
2593             outBuf[outPtr++] = (char) i;
2594         }
2595         return _textBuffer.setCurrentAndReturn(outPtr);
2596     }
2597
2598     private final String _decodeLongerName(int len) throws IOException
2599     {
2600         // Do we have enough buffered content to read?
2601         if ((_inputEnd - _inputPtr) < len) {
2602             // or if not, could we read?
2603             if (len >= _inputBuffer.length) {
2604                 // If not enough space, need handling similar to chunked
2605                 _finishLongText(len);
2606                 return _textBuffer.contentsAsString();
2607             }
2608             _loadToHaveAtLeast(len);
2609         }
2610         String name = _findDecodedFromSymbols(len);
2611         if (name != null) {
2612             _inputPtr += len;
2613             return name;
2614         }
2615         name = _decodeShortName(len);
2616         return _addDecodedToSymbols(len, name);
2617     }
2618     
2619     private final String _decodeChunkedName() throws IOException
2620     {
2621         _finishChunkedText();
2622         return _textBuffer.contentsAsString();
2623     }
2624     
2625     /**
2626      * Method that handles initial token type recognition for token
2627      * that has to be either FIELD_NAME or END_OBJECT.
2628      */

2629     protected final void _decodeNonStringName(int ch) throws IOException
2630     {
2631         final int type = ((ch >> 5) & 0x7);
2632         String name;
2633         if (type == CBORConstants.MAJOR_TYPE_INT_POS) {
2634             name = _numberToName(ch, false);
2635         } else if (type == CBORConstants.MAJOR_TYPE_INT_NEG) {
2636             name = _numberToName(ch, true);
2637         } else if (type == CBORConstants.MAJOR_TYPE_BYTES) {
2638             /* 08-Sep-2014, tatu: As per [Issue#5], there are codecs
2639              *   (f.ex. Perl module "CBOR::XS") that use Binary data...
2640              */

2641             final int blen = _decodeExplicitLength(ch & 0x1F);
2642             byte[] b = _finishBytes(blen);
2643             // TODO: Optimize, if this becomes commonly used & bottleneck; we have
2644             //  more optimized UTF-8 codecs available.
2645             name = new String(b, UTF8);
2646         } else {
2647             if ((ch & 0xFF) == CBORConstants.INT_BREAK) {
2648                 _reportUnexpectedBreak();
2649             }
2650             throw _constructError("Unsupported major type ("+type+") for CBOR Objects, not (yet?) supported, only Strings");
2651         }
2652         _parsingContext.setCurrentName(name);
2653     }
2654     
2655     private final String _findDecodedFromSymbols(final int len) throws IOException
2656     {
2657         if ((_inputEnd - _inputPtr) < len) {
2658             _loadToHaveAtLeast(len);
2659         }
2660         // First: maybe we already have this name decoded?
2661         if (len < 5) {
2662             int inPtr = _inputPtr;
2663             final byte[] inBuf = _inputBuffer;
2664             int q = inBuf[inPtr] & 0xFF;
2665             if (len > 1) {
2666                 q = (q << 8) + (inBuf[++inPtr] & 0xFF);
2667                 if (len > 2) {
2668                     q = (q << 8) + (inBuf[++inPtr] & 0xFF);
2669                     if (len > 3) {
2670                         q = (q << 8) + (inBuf[++inPtr] & 0xFF);
2671                     }
2672                 }
2673             }
2674             _quad1 = q;
2675             return _symbols.findName(q);
2676         }
2677
2678         final byte[] inBuf = _inputBuffer;
2679         int inPtr = _inputPtr;
2680
2681         // First quadbyte is easy
2682         int q1 = (inBuf[inPtr++] & 0xFF);
2683         q1 =  (q1 << 8) | (inBuf[inPtr++] & 0xFF);
2684         q1 =  (q1 << 8) | (inBuf[inPtr++] & 0xFF);
2685         q1 =  (q1 << 8) | (inBuf[inPtr++] & 0xFF);
2686         
2687         if (len < 9) {
2688             int q2 = (inBuf[inPtr++] & 0xFF);
2689             int left = len - 5;
2690             if (left > 0) {
2691                 q2 = (q2 << 8) + (inBuf[inPtr++] & 0xFF);
2692                 if (left > 1) {
2693                     q2 = (q2 << 8) + (inBuf[inPtr++] & 0xFF);
2694                     if (left > 2) {
2695                         q2 = (q2 << 8) + (inBuf[inPtr++] & 0xFF);
2696                     }
2697                 }
2698             }
2699             _quad1 = q1;
2700             _quad2 = q2;
2701             return _symbols.findName(q1, q2);
2702         }
2703
2704         int q2 = (inBuf[inPtr++] & 0xFF);
2705         q2 =  (q2 << 8) | (inBuf[inPtr++] & 0xFF);
2706         q2 =  (q2 << 8) | (inBuf[inPtr++] & 0xFF);
2707         q2 =  (q2 << 8) | (inBuf[inPtr++] & 0xFF);
2708
2709         if (len < 13) {
2710             int q3 = (inBuf[inPtr++] & 0xFF);
2711             int left = len - 9;
2712             if (left > 0) {
2713                 q3 = (q3 << 8) + (inBuf[inPtr++] & 0xFF);
2714                 if (left > 1) {
2715                     q3 = (q3 << 8) + (inBuf[inPtr++] & 0xFF);
2716                     if (left > 2) {
2717                         q3 = (q3 << 8) + (inBuf[inPtr++] & 0xFF);
2718                     }
2719                 }
2720             }
2721             _quad1 = q1;
2722             _quad2 = q2;
2723             _quad3 = q3;
2724             return _symbols.findName(q1, q2, q3);
2725         }
2726         return _findDecodedLong(len, q1, q2);
2727     }
2728
2729     /**
2730      * Method for locating names longer than 8 bytes (in UTF-8)
2731      */

2732     private final String _findDecodedLong(int len, int q1, int q2) throws IOException
2733     {
2734         // first, need enough buffer to store bytes as ints:
2735         {
2736             int bufLen = (len + 3) >> 2;
2737             if (bufLen > _quadBuffer.length) {
2738                 _quadBuffer = _growArrayTo(_quadBuffer, bufLen);
2739             }
2740         }
2741         _quadBuffer[0] = q1;
2742         _quadBuffer[1] = q2;
2743         
2744         // then decode, full quads first
2745         int offset = 2;
2746         int inPtr = _inputPtr+8;
2747         len -= 8;
2748         
2749         final byte[] inBuf = _inputBuffer;
2750         do {
2751             int q = (inBuf[inPtr++] & 0xFF);
2752             q = (q << 8) | inBuf[inPtr++] & 0xFF;
2753             q = (q << 8) | inBuf[inPtr++] & 0xFF;
2754             q = (q << 8) | inBuf[inPtr++] & 0xFF;
2755             _quadBuffer[offset++] = q;
2756         } while ((len -= 4) > 3);
2757         // and then leftovers
2758         if (len > 0) {
2759             int q = inBuf[inPtr] & 0xFF;
2760             if (len > 1) {
2761                 q = (q << 8) + (inBuf[++inPtr] & 0xFF);
2762                 if (len > 2) {
2763                     q = (q << 8) + (inBuf[++inPtr] & 0xFF);
2764                 }
2765             }
2766             _quadBuffer[offset++] = q;
2767         }
2768         return _symbols.findName(_quadBuffer, offset);
2769     }
2770
2771     private final String _addDecodedToSymbols(int len, String name) {
2772         if (len < 5) {
2773             return _symbols.addName(name, _quad1);
2774         }
2775         if (len < 9) {
2776             return _symbols.addName(name, _quad1, _quad2);
2777         }
2778         if (len < 13) {
2779             return _symbols.addName(name, _quad1, _quad2, _quad3);
2780         }
2781         int qlen = (len + 3) >> 2;
2782         return _symbols.addName(name, _quadBuffer, qlen);
2783     }
2784     
2785     private static int[] _growArrayTo(int[] arr, int minSize) {
2786         return Arrays.copyOf(arr, minSize+4);
2787     }    
2788
2789     /*
2790     /**********************************************************
2791     /* Internal methods, skipping
2792     /**********************************************************
2793      */

2794
2795     /**
2796      * Method called to skip remainders of an incomplete token, when
2797      * contents themselves will not be needed any more.
2798      * Only called or byte array and text.
2799      */

2800     protected void _skipIncomplete() throws IOException
2801     {
2802         _tokenIncomplete = false;
2803         final int type = ((_typeByte >> 5) & 0x7);
2804
2805         // Either String or byte[]
2806         if (type != CBORConstants.MAJOR_TYPE_TEXT
2807                 && type == CBORConstants.MAJOR_TYPE_TEXT) {
2808             _throwInternal();
2809         }
2810         final int lowBits = _typeByte & 0x1F;
2811
2812         if (lowBits <= 23) {
2813             if (lowBits > 0) {
2814                 _skipBytes(lowBits);
2815             }
2816             return;
2817         }
2818         switch (lowBits) {
2819         case 24:
2820             _skipBytes(_decode8Bits());
2821             break;
2822         case 25:
2823             _skipBytes(_decode16Bits());
2824             break;
2825         case 26:
2826             _skipBytes(_decode32Bits());
2827             break;
2828         case 27: // seriously?
2829             _skipBytesL(_decode64Bits());
2830             break;
2831         case 31:
2832             _skipChunked(type);
2833             break;
2834         default:
2835             _invalidToken(_typeByte);
2836         }
2837     }
2838     
2839     protected void _skipChunked(int expectedType) throws IOException
2840     {
2841         while (true) {
2842             if (_inputPtr >= _inputEnd) {
2843                 loadMoreGuaranteed();
2844             }
2845             int ch = _inputBuffer[_inputPtr++] & 0xFF;
2846             if (ch == 0xFF) {
2847                 return;
2848             }
2849             // verify that type matches
2850             int type = (ch >> 5);
2851             if (type != expectedType) {
2852                 throw _constructError("Mismatched chunk in chunked content: expected "+expectedType
2853                         +" but encountered "+type);
2854             }
2855
2856             final int lowBits = ch & 0x1F;
2857
2858             if (lowBits <= 23) {
2859                 if (lowBits > 0) {
2860                     _skipBytes(lowBits);
2861                 }
2862                 continue;
2863             }
2864             switch (lowBits) {
2865             case 24:
2866                 _skipBytes(_decode8Bits());
2867                 break;
2868             case 25:
2869                 _skipBytes(_decode16Bits());
2870                 break;
2871             case 26:
2872                 _skipBytes(_decode32Bits());
2873                 break;
2874             case 27: // seriously?
2875                 _skipBytesL(_decode64Bits());
2876                 break;
2877             case 31:
2878                 throw _constructError("Illegal chunked-length indicator within chunked-length value (type "+expectedType+")");
2879             default:
2880                 _invalidToken(_typeByte);
2881             }
2882         }
2883     }
2884     
2885     protected void _skipBytesL(long llen) throws IOException
2886     {
2887         while (llen > MAX_INT_L) {
2888             _skipBytes((int) MAX_INT_L);
2889             llen -= MAX_INT_L;
2890         }
2891         _skipBytes((int) llen);
2892     }
2893
2894     protected void _skipBytes(int len) throws IOException
2895     {
2896         while (true) {
2897             int toAdd = Math.min(len, _inputEnd - _inputPtr);
2898             _inputPtr += toAdd;
2899             len -= toAdd;
2900             if (len <= 0) {
2901                 return;
2902             }
2903             loadMoreGuaranteed();
2904         }
2905     }
2906
2907     /*
2908     /**********************************************************
2909     /* Internal methods, length/number decoding
2910     /**********************************************************
2911      */

2912
2913     private final int _decodeTag(int lowBits) throws IOException
2914     {
2915         if (lowBits <= 23) {
2916             return lowBits;
2917         }
2918         switch (lowBits - 24) {
2919         case 0:
2920             return _decode8Bits();
2921         case 1:
2922             return _decode16Bits();
2923         case 2:
2924             return _decode32Bits();
2925         case 3:
2926             // 16-Jan-2014, tatu: Technically legal, but nothing defined, so let's
2927             //   only allow for cases where encoder is being wasteful...
2928             long l = _decode64Bits();
2929             if (l < MIN_INT_L || l > MAX_INT_L) {
2930                 _reportError("Illegal Tag value: "+l);
2931             }
2932             return (int) l;
2933         }
2934         throw _constructError("Invalid low bits for Tag token: 0x"+Integer.toHexString(lowBits));
2935     }
2936     
2937     /**
2938      * Method used to decode explicit length of a variable-length value
2939      * (or, for indefinite/chunked, indicate that one is not known).
2940      * Note that long (64-bit) length is only allowed if it fits in
2941      * 32-bit signed intfor now; expectation being that longer values
2942      * are always encoded as chunks.
2943      */

2944     private final int _decodeExplicitLength(int lowBits) throws IOException
2945     {
2946         // common case, indefinite length; relies on marker
2947         if (lowBits == 31) {
2948             return -1;
2949         }
2950         if (lowBits <= 23) {
2951             return lowBits;
2952         }
2953         switch (lowBits - 24) {
2954         case 0:
2955             return _decode8Bits();
2956         case 1:
2957             return _decode16Bits();
2958         case 2:
2959             return _decode32Bits();
2960         case 3:
2961             long l = _decode64Bits();
2962             if (l < 0 || l > MAX_INT_L) {
2963                 throw _constructError("Illegal length for "+currentToken()+": "+l);
2964             }
2965             return (int) l;
2966         }
2967         throw _constructError("Invalid length for "+currentToken()+": 0x"+Integer.toHexString(lowBits));
2968     }
2969
2970     private int _decodeChunkLength(int expType) throws IOException
2971     {
2972         if (_inputPtr >= _inputEnd) {
2973             loadMoreGuaranteed();
2974         }
2975         int ch = (int) _inputBuffer[_inputPtr++] & 0xFF;
2976         if (ch == CBORConstants.INT_BREAK) {
2977             return -1;
2978         }
2979         int type = (ch >> 5);
2980         if (type != expType) {
2981             throw _constructError("Mismatched chunk in chunked content: expected "
2982                     +expType+" but encountered "+type+" (byte 0x"+Integer.toHexString(ch)+")");
2983         }
2984         int len = _decodeExplicitLength(ch & 0x1F);
2985         if (len < 0) {
2986             throw _constructError("Illegal chunked-length indicator within chunked-length value (type "+expType+")");
2987         }
2988         return len;
2989     }
2990     
2991     private float _decodeHalfSizeFloat() throws IOException
2992     {
2993         int i16 = _decode16Bits() & 0xFFFF;
2994
2995         boolean neg = (i16 >> 15) != 0;
2996         int e = (i16 >> 10) & 0x1F;
2997         int f = i16 & 0x03FF;
2998
2999         if (e == 0) {
3000             float result = (float) (MATH_POW_2_NEG14 * (f / MATH_POW_2_10));
3001             return neg ? -result : result;
3002         }
3003         if (e == 0x1F) {
3004             if (f != 0) return Float.NaN;
3005             return neg ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
3006         }
3007         float result = (float) (Math.pow(2, e - 15) * (1 + f / MATH_POW_2_10));
3008         return neg ? -result : result;
3009     }
3010
3011     private final int _decode8Bits() throws IOException {
3012         if (_inputPtr >= _inputEnd) {
3013             loadMoreGuaranteed();
3014         }
3015         return _inputBuffer[_inputPtr++] & 0xFF;
3016     }
3017     
3018     private final int _decode16Bits() throws IOException {
3019         int ptr = _inputPtr;
3020         if ((ptr + 1) >= _inputEnd) {
3021             return _slow16();
3022         }
3023         final byte[] b = _inputBuffer;
3024         int v = ((b[ptr] & 0xFF) << 8) + (b[ptr+1] & 0xFF);
3025         _inputPtr = ptr+2;
3026         return v;
3027     }
3028
3029     private final int _slow16() throws IOException {
3030         if (_inputPtr >= _inputEnd) {
3031             loadMoreGuaranteed();
3032         }
3033         int v = (_inputBuffer[_inputPtr++] & 0xFF);
3034         if (_inputPtr >= _inputEnd) {
3035             loadMoreGuaranteed();
3036         }
3037         return (v << 8) + (_inputBuffer[_inputPtr++] & 0xFF);
3038     }
3039     
3040     private final int _decode32Bits() throws IOException {
3041         int ptr = _inputPtr;
3042         if ((ptr + 3) >= _inputEnd) {
3043             return _slow32();
3044         }
3045         final byte[] b = _inputBuffer;
3046         int v = (b[ptr++] << 24) + ((b[ptr++] & 0xFF) << 16)
3047                 + ((b[ptr++] & 0xFF) << 8) + (b[ptr++] & 0xFF);
3048         _inputPtr = ptr;
3049         return v;
3050     }
3051
3052     private final int _slow32() throws IOException {
3053         if (_inputPtr >= _inputEnd) {
3054             loadMoreGuaranteed();
3055         }
3056         int v = _inputBuffer[_inputPtr++]; // sign will disappear anyway
3057         if (_inputPtr >= _inputEnd) {
3058             loadMoreGuaranteed();
3059         }
3060         v = (v << 8) + (_inputBuffer[_inputPtr++] & 0xFF);
3061         if (_inputPtr >= _inputEnd) {
3062             loadMoreGuaranteed();
3063         }
3064         v = (v << 8) + (_inputBuffer[_inputPtr++] & 0xFF);
3065         if (_inputPtr >= _inputEnd) {
3066             loadMoreGuaranteed();
3067         }
3068         return (v << 8) + (_inputBuffer[_inputPtr++] & 0xFF);
3069     }
3070     
3071     private final long _decode64Bits() throws IOException {
3072         int ptr = _inputPtr;
3073         if ((ptr + 7) >= _inputEnd) {
3074             return _slow64();
3075         }
3076         final byte[] b = _inputBuffer;
3077         int i1 = (b[ptr++] << 24) + ((b[ptr++] & 0xFF) << 16)
3078                 + ((b[ptr++] & 0xFF) << 8) + (b[ptr++] & 0xFF);
3079         int i2 = (b[ptr++] << 24) + ((b[ptr++] & 0xFF) << 16)
3080                 + ((b[ptr++] & 0xFF) << 8) + (b[ptr++] & 0xFF);
3081         _inputPtr = ptr;
3082         return _long(i1, i2);
3083     }
3084
3085     private final long _slow64() throws IOException {
3086         return _long(_decode32Bits(), _decode32Bits());
3087     }
3088     
3089     private final static long _long(int i1, int i2)
3090     {
3091         long l1 = i1;
3092         long l2 = i2;
3093         l2 = (l2 << 32) >>> 32;
3094         return (l1 << 32) + l2;
3095     }
3096
3097     /**
3098      * Helper method to encapsulate details of handling of mysterious `undefined` value
3099      * that is allowed to be used as something encoder could not handle (as per spec),
3100      * whatever the heck that should be.
3101      * Current definition for 2.9 is that we will be return {@link JsonToken#VALUE_NULL}, but
3102      * for later versions it is likely that we will alternatively allow decoding as
3103      * {@link JsonToken#VALUE_EMBEDDED_OBJECT} with "embedded value" of `null`.
3104      *
3105      * @since 2.9.6
3106      */

3107     protected JsonToken _decodeUndefinedValue() throws IOException {
3108         return JsonToken.VALUE_NULL;
3109     }
3110
3111     /*
3112     /**********************************************************
3113     /* Internal methods, UTF8 decoding
3114     /**********************************************************
3115      */

3116
3117     /*
3118     private final int X_decodeUTF8_2(int c) throws IOException {
3119         int d = _nextByte();
3120         if ((d & 0xC0) != 0x080) {
3121             _reportInvalidOther(d & 0xFF, _inputPtr);
3122         }
3123         return ((c & 0x1F) << 6) | (d & 0x3F);
3124     }
3125     */

3126
3127     private final int _decodeUTF8_3(int c1) throws IOException
3128     {
3129         c1 &= 0x0F;
3130         int d = _nextByte();
3131         if ((d & 0xC0) != 0x080) {
3132             _reportInvalidOther(d & 0xFF, _inputPtr);
3133         }
3134         int c = (c1 << 6) | (d & 0x3F);
3135         d = _nextByte();
3136         if ((d & 0xC0) != 0x080) {
3137             _reportInvalidOther(d & 0xFF, _inputPtr);
3138         }
3139         c = (c << 6) | (d & 0x3F);
3140         return c;
3141     }
3142
3143     private final int _decodeChunkedUTF8_3(int c1) throws IOException
3144     {
3145         c1 &= 0x0F;
3146         int d = _nextChunkedByte();
3147         if ((d & 0xC0) != 0x080) {
3148             _reportInvalidOther(d & 0xFF, _inputPtr);
3149         }
3150         int c = (c1 << 6) | (d & 0x3F);
3151         d = _nextChunkedByte();
3152         if ((d & 0xC0) != 0x080) {
3153             _reportInvalidOther(d & 0xFF, _inputPtr);
3154         }
3155         c = (c << 6) | (d & 0x3F);
3156         return c;
3157     }
3158     
3159     /**
3160      * @return Character value <b>minus 0x10000</c>; this so that caller
3161      *    can readily expand it to actual surrogates
3162      */

3163     private final int _decodeUTF8_4(int c) throws IOException
3164     {
3165         int d = _nextByte();
3166         if ((d & 0xC0) != 0x080) {
3167             _reportInvalidOther(d & 0xFF, _inputPtr);
3168         }
3169         c = ((c & 0x07) << 6) | (d & 0x3F);
3170         d = _nextByte();
3171         if ((d & 0xC0) != 0x080) {
3172             _reportInvalidOther(d & 0xFF, _inputPtr);
3173         }
3174         c = (c << 6) | (d & 0x3F);
3175         d = _nextByte();
3176         if ((d & 0xC0) != 0x080) {
3177             _reportInvalidOther(d & 0xFF, _inputPtr);
3178         }
3179         return ((c << 6) | (d & 0x3F)) - 0x10000;
3180     }
3181
3182     private final int _decodeChunkedUTF8_4(int c) throws IOException
3183     {
3184         int d = _nextChunkedByte();
3185         if ((d & 0xC0) != 0x080) {
3186             _reportInvalidOther(d & 0xFF, _inputPtr);
3187         }
3188         c = ((c & 0x07) << 6) | (d & 0x3F);
3189         d = _nextChunkedByte();
3190         if ((d & 0xC0) != 0x080) {
3191             _reportInvalidOther(d & 0xFF, _inputPtr);
3192         }
3193         c = (c << 6) | (d & 0x3F);
3194         d = _nextChunkedByte();
3195         if ((d & 0xC0) != 0x080) {
3196             _reportInvalidOther(d & 0xFF, _inputPtr);
3197         }
3198         return ((c << 6) | (d & 0x3F)) - 0x10000;
3199     }
3200
3201     /*
3202     /**********************************************************
3203     /* Low-level reading, other
3204     /**********************************************************
3205      */

3206
3207     protected final boolean loadMore() throws IOException
3208     {
3209         if (_inputStream != null) {
3210             _currInputProcessed += _inputEnd;
3211
3212             int count = _inputStream.read(_inputBuffer, 0, _inputBuffer.length);
3213             if (count > 0) {
3214                 _inputPtr = 0;
3215                 _inputEnd = count;
3216                 return true;
3217             }
3218             // End of input
3219             _closeInput();
3220             // Should never return 0, so let's fail
3221             if (count == 0) {
3222                 throw new IOException("InputStream.read() returned 0 characters when trying to read "+_inputBuffer.length+" bytes");
3223             }
3224         }
3225         return false;
3226     }
3227
3228     protected final void loadMoreGuaranteed() throws IOException {
3229         if (!loadMore()) { _reportInvalidEOF(); }
3230     }
3231     
3232     /**
3233      * Helper method that will try to load at least specified number bytes in
3234      * input buffer, possible moving existing data around if necessary
3235      */

3236     protected final void _loadToHaveAtLeast(int minAvailable) throws IOException
3237     {
3238         // No input stream, no leading (either we are closed, or have non-stream input source)
3239         if (_inputStream == null) {
3240             throw _constructError("Needed to read "+minAvailable+" bytes, reached end-of-input");
3241         }
3242         // Need to move remaining data in front?
3243         int amount = _inputEnd - _inputPtr;
3244         if (amount > 0 && _inputPtr > 0) {
3245             //_currInputRowStart -= _inputPtr;
3246             System.arraycopy(_inputBuffer, _inputPtr, _inputBuffer, 0, amount);
3247             _inputEnd = amount;
3248         } else {
3249             _inputEnd = 0;
3250         }
3251         // Needs to be done here, as per [dataformats-binary#178]
3252         _currInputProcessed += _inputPtr;
3253         _inputPtr = 0;
3254         while (_inputEnd < minAvailable) {
3255             int count = _inputStream.read(_inputBuffer, _inputEnd, _inputBuffer.length - _inputEnd);
3256             if (count < 1) {
3257                 // End of input
3258                 _closeInput();
3259                 // Should never return 0, so let's fail
3260                 if (count == 0) {
3261                     throw new IOException("InputStream.read() returned 0 characters when trying to read "+amount+" bytes");
3262                 }
3263                 throw _constructError("Needed to read "+minAvailable+" bytes, missed "+minAvailable+" before end-of-input");
3264             }
3265             _inputEnd += count;
3266         }
3267     }
3268
3269     protected ByteArrayBuilder _getByteArrayBuilder() {
3270         if (_byteArrayBuilder == null) {
3271             _byteArrayBuilder = new ByteArrayBuilder();
3272         } else {
3273             _byteArrayBuilder.reset();
3274         }
3275         return _byteArrayBuilder;
3276     }
3277
3278     @SuppressWarnings("deprecation")
3279     protected void _closeInput() throws IOException {
3280         if (_inputStream != null) {
3281             if (_ioContext.isResourceManaged() || isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)) {
3282                 _inputStream.close();
3283             }
3284             _inputStream = null;
3285         }
3286     }
3287
3288     @Override
3289     protected void _handleEOF() throws JsonParseException {
3290         if (!_parsingContext.inRoot()) {
3291             String marker = _parsingContext.inArray() ? "Array" : "Object";
3292             _reportInvalidEOF(String.format(
3293                     ": expected close marker for %s (start marker at %s)",
3294                     marker,
3295                     _parsingContext.getStartLocation(_ioContext.getSourceReference())),
3296                     null);
3297         }
3298     }
3299
3300     /*
3301     /**********************************************************
3302     /* Internal methods, error handling, reporting
3303     /**********************************************************
3304      */

3305
3306     protected JsonToken _handleCBOREOF() throws IOException {
3307         /* NOTE: here we can and should close input, release buffers,
3308          * since this is "hard" EOF, not a boundary imposed by
3309          * header token.
3310          */

3311         _tagValue = -1;
3312         close();
3313         return (_currToken = null);
3314     }
3315
3316     protected void _invalidToken(int ch) throws JsonParseException {
3317         ch &= 0xFF;
3318         if (ch == 0xFF) {
3319             throw _constructError("Mismatched BREAK byte (0xFF): encountered where value expected");
3320         }
3321         throw _constructError("Invalid CBOR value token (first byte): 0x"+Integer.toHexString(ch));
3322     }
3323
3324     protected void _reportUnexpectedBreak() throws IOException {
3325         if (_parsingContext.inRoot()) {
3326             throw _constructError("Unexpected Break (0xFF) token in Root context");
3327         }
3328         throw _constructError("Unexpected Break (0xFF) token in definite length ("
3329                 +_parsingContext.getExpectedLength()+") "
3330                 +(_parsingContext.inObject() ? "Object" : "Array" ));
3331     }
3332
3333     protected void _reportInvalidChar(int c) throws JsonParseException {
3334         // Either invalid WS or illegal UTF-8 start char
3335         if (c < ' ') {
3336             _throwInvalidSpace(c);
3337         }
3338         _reportInvalidInitial(c);
3339     }
3340
3341     protected void _reportInvalidInitial(int mask) throws JsonParseException {
3342         _reportError("Invalid UTF-8 start byte 0x"+Integer.toHexString(mask));
3343     }
3344
3345     protected void _reportInvalidOther(int mask) throws JsonParseException {
3346         _reportError("Invalid UTF-8 middle byte 0x"+Integer.toHexString(mask));
3347     }
3348
3349     protected void _reportInvalidOther(int mask, int ptr) throws JsonParseException {
3350         _inputPtr = ptr;
3351         _reportInvalidOther(mask);
3352     }
3353
3354     /*
3355     /**********************************************************
3356     /* Internal methods, other
3357     /**********************************************************
3358      */

3359
3360     private final static BigInteger BIT_63 = BigInteger.ONE.shiftLeft(63);
3361
3362     private final BigInteger _bigPositive(long l) {
3363         BigInteger biggie = BigInteger.valueOf((l << 1) >>> 1);
3364         return biggie.or(BIT_63);
3365     }
3366
3367     private final BigInteger _bigNegative(long l) {
3368         // 03-Dec-2017, tatu: [dataformats-binary#149] Careful with overflow
3369         BigInteger unsignedBase = _bigPositive(l);
3370         return unsignedBase.negate().subtract(BigInteger.ONE);
3371     }
3372 }
3373