@@ -877,36 +877,195 @@ protected JsonToken _handleTaggedArray(int tag, int len) throws IOException
877877 _reportError ("Unexpected array size (" +len +") for tagged 'bigfloat' value; should have exactly 2 number elements" );
878878 }
879879 // and then use recursion to get values
880- JsonToken t = nextToken ();
881880 // First: exponent, which MUST be a simple integer value
882- if (t != JsonToken . VALUE_NUMBER_INT ) {
883- _reportError ("Unexpected token (" +t +") as the first part of 'bigfloat' value: should get VALUE_NUMBER_INT" );
881+ if (! _checkNextIsIntInArray ( "bigfloat" ) ) {
882+ _reportError ("Unexpected token (" +currentToken () +") as the first part of 'bigfloat' value: should get VALUE_NUMBER_INT" );
884883 }
885884 // 27-Nov-2019, tatu: As per [dataformats-binary#139] need to change sign here
886885 int exp = -getIntValue ();
887886
888- t = nextToken ();
889887 // Should get an integer value; int/long/BigInteger
890- if (t != JsonToken . VALUE_NUMBER_INT ) {
891- _reportError ("Unexpected token (" +t +") as the second part of 'bigfloat' value: should get VALUE_NUMBER_INT" );
888+ if (! _checkNextIsIntInArray ( "bigfloat" ) ) {
889+ _reportError ("Unexpected token (" +currentToken () +") as the second part of 'bigfloat' value: should get VALUE_NUMBER_INT" );
892890 }
893-
894- BigDecimal dec ;
895891
892+ // important: check number type here
893+ BigDecimal dec ;
896894 NumberType numberType = getNumberType ();
897895 if (numberType == NumberType .BIG_INTEGER ) {
898896 dec = new BigDecimal (getBigIntegerValue (), exp );
899897 } else {
900898 dec = BigDecimal .valueOf (getLongValue (), exp );
901899 }
902- t = nextToken ();
903- if (t != JsonToken .END_ARRAY ) {
904- _reportError ("Unexpected token (" +t +") after 2 elements of 'bigfloat' value" );
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" );
905904 }
905+
906+ // which needs to be reset here
906907 _numberBigDecimal = dec ;
907908 _numTypesValid = NR_BIGDECIMAL ;
908909 return (_currToken = JsonToken .VALUE_NUMBER_FLOAT );
909910 }
911+
912+ /**
913+ * Heavily simplified method that does a subset of what {@code nextTokendoes 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: Although we don't use tag for anything, might as well decode it
941+ // for funsies and just ignore.
942+ int tagValue = -1 ;
943+ if (type == 6 ) {
944+ tagValue = _decodeTag (ch & 0x1F );
945+ if (_inputPtr >= _inputEnd ) {
946+ if (!loadMore ()) {
947+ _handleCBOREOF ();
948+ return false ;
949+ }
950+ }
951+ ch = _inputBuffer [_inputPtr ++];
952+ type = (ch >> 5 ) & 0x7 ;
953+ }
954+
955+ final int lowBits = ch & 0x1F ;
956+ switch (type ) {
957+ case 0 : // positive int
958+ _numTypesValid = NR_INT ;
959+ if (lowBits <= 23 ) {
960+ _numberInt = lowBits ;
961+ } else {
962+ switch (lowBits - 24 ) {
963+ case 0 :
964+ _numberInt = _decode8Bits ();
965+ break ;
966+ case 1 :
967+ _numberInt = _decode16Bits ();
968+ break ;
969+ case 2 :
970+ {
971+ int v = _decode32Bits ();
972+ if (v >= 0 ) {
973+ _numberInt = v ;
974+ } else {
975+ long l = (long ) v ;
976+ _numberLong = l & 0xFFFFFFFFL ;
977+ _numTypesValid = NR_LONG ;
978+ }
979+ }
980+ break ;
981+ case 3 :
982+ {
983+ long l = _decode64Bits ();
984+ if (l >= 0L ) {
985+ _numberLong = l ;
986+ _numTypesValid = NR_LONG ;
987+ } else {
988+ _numberBigInt = _bigPositive (l );
989+ _numTypesValid = NR_BIGINT ;
990+ }
991+ }
992+ break ;
993+ default :
994+ _invalidToken (ch );
995+ }
996+ }
997+ _currToken = JsonToken .VALUE_NUMBER_INT ;
998+ return true ;
999+ case 1 : // negative int
1000+ _numTypesValid = NR_INT ;
1001+ if (lowBits <= 23 ) {
1002+ _numberInt = -lowBits - 1 ;
1003+ } else {
1004+ switch (lowBits - 24 ) {
1005+ case 0 :
1006+ _numberInt = -_decode8Bits () - 1 ;
1007+ break ;
1008+ case 1 :
1009+ _numberInt = -_decode16Bits () - 1 ;
1010+ break ;
1011+ case 2 :
1012+ // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
1013+ {
1014+ int v = _decode32Bits ();
1015+ if (v < 0 ) {
1016+ long unsignedBase = (long ) v & 0xFFFFFFFFL ;
1017+ _numberLong = -unsignedBase - 1L ;
1018+ _numTypesValid = NR_LONG ;
1019+ } else {
1020+ _numberInt = -v - 1 ;
1021+ }
1022+ }
1023+ break ;
1024+ case 3 :
1025+ // 15-Oct-2016, as per [dataformats-binary#30], we got an edge case here
1026+ {
1027+ long l = _decode64Bits ();
1028+ if (l >= 0L ) {
1029+ _numberLong = -l - 1L ;
1030+ _numTypesValid = NR_LONG ;
1031+ } else {
1032+ _numberBigInt = _bigNegative (l );
1033+ _numTypesValid = NR_BIGINT ;
1034+ }
1035+ }
1036+ break ;
1037+ default :
1038+ _invalidToken (ch );
1039+ }
1040+ }
1041+ _currToken = JsonToken .VALUE_NUMBER_INT ;
1042+ return true ;
1043+
1044+ case 2 : // byte[]
1045+ // ... but we only really care about very specific case of `BigInteger`
1046+ if (tagValue < 0 ) {
1047+ break ;
1048+ }
1049+ _typeByte = ch ;
1050+ _tokenIncomplete = true ;
1051+ _currToken = _handleTaggedBinary (tagValue );
1052+ return (_currToken == JsonToken .VALUE_NUMBER_INT );
1053+
1054+ case 6 : // another tag; not allowed
1055+ _reportError ("Multiple tags not allowed per value (first tag: " +tagValue +")" );
1056+ }
1057+
1058+ // Important! Need to push back the last byte read (but not consumed)
1059+ --_inputPtr ;
1060+ // and now it is safe to decode next token, too
1061+ nextToken ();
1062+ return false ;
1063+ }
1064+
1065+ protected final boolean _checkNextIsEndArray () throws IOException
1066+ {
1067+ return nextToken () == JsonToken .END_ARRAY ;
1068+ }
9101069
9111070 // base impl is fine:
9121071 //public String getCurrentName() throws IOException
@@ -1467,7 +1626,7 @@ public byte[] getBinaryValue(Base64Variant b64variant) throws IOException
14671626 }
14681627 if (_currToken != JsonToken .VALUE_EMBEDDED_OBJECT ) {
14691628 // TODO, maybe: support base64 for text?
1470- _reportError ("Current token (" +getCurrentToken ()+") not VALUE_EMBEDDED_OBJECT, can not access as binary" );
1629+ _reportError ("Current token (" +currentToken ()+") not VALUE_EMBEDDED_OBJECT, can not access as binary" );
14711630 }
14721631 return _binaryValue ;
14731632 }
@@ -1489,7 +1648,7 @@ public int readBinaryValue(Base64Variant b64variant, OutputStream out) throws IO
14891648 {
14901649 if (_currToken != JsonToken .VALUE_EMBEDDED_OBJECT ) {
14911650 // Todo, maybe: support base64 for text?
1492- _reportError ("Current token (" +getCurrentToken ()+") not VALUE_EMBEDDED_OBJECT, can not access as binary" );
1651+ _reportError ("Current token (" +currentToken ()+") not VALUE_EMBEDDED_OBJECT, can not access as binary" );
14931652 }
14941653 if (!_tokenIncomplete ) { // someone already decoded or read
14951654 if (_binaryValue == null ) { // if this method called twice in a row
@@ -1724,7 +1883,7 @@ protected void _checkNumericValue(int expType) throws IOException
17241883 if (_currToken == JsonToken .VALUE_NUMBER_INT || _currToken == JsonToken .VALUE_NUMBER_FLOAT ) {
17251884 return ;
17261885 }
1727- _reportError ("Current token (" +getCurrentToken ()+") not numeric, can not use numeric value accessors" );
1886+ _reportError ("Current token (" +currentToken ()+") not numeric, can not use numeric value accessors" );
17281887 }
17291888
17301889 protected void convertNumberToInt () throws IOException
@@ -2770,11 +2929,11 @@ private final int _decodeExplicitLength(int lowBits) throws IOException
27702929 case 3 :
27712930 long l = _decode64Bits ();
27722931 if (l < 0 || l > MAX_INT_L ) {
2773- throw _constructError ("Illegal length for " +getCurrentToken ()+": " +l );
2932+ throw _constructError ("Illegal length for " +currentToken ()+": " +l );
27742933 }
27752934 return (int ) l ;
27762935 }
2777- throw _constructError ("Invalid length for " +getCurrentToken ()+": 0x" +Integer .toHexString (lowBits ));
2936+ throw _constructError ("Invalid length for " +currentToken ()+": 0x" +Integer .toHexString (lowBits ));
27782937 }
27792938
27802939 private int _decodeChunkLength (int expType ) throws IOException
0 commit comments