private long readNumber ( int firstChar , boolean isNeg ) throws IOException { out . unsafeWrite ( firstChar ) ; // unsafe OK since we know output is big enough // We build up the number in the negative plane since it's larger (by one) than // the positive plane. long v = ' ' - firstChar ; // can't overflow a long in 18 decimal digits (i.e. 17 additional after the first). // we also need 22 additional to handle double so we'll handle in 2 separate loops. int i ; for ( i = 0 ; i < 17 ; i ++ ) { int ch = getChar ( ) ; // TODO: is this switch faster as an if-then-else? switch ( ch ) { case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : v = v * 10 - ( ch - ' ' ) ; out . unsafeWrite ( ch ) ; continue ; case ' ' : out . unsafeWrite ( ' ' ) ; valstate = readFrac ( out , 22 - i ) ; return 0 ; case ' ' : case ' ' : out . unsafeWrite ( ch ) ; nstate = 0 ; valstate = readExp ( out , 22 - i ) ; return 0 ; default : // return the number, relying on nextEvent() to return an error // for invalid chars following the number. if ( ch != - 1 ) -- start ; // push back last char if not EOF valstate = LONG ; return isNeg ? v : - v ; } } // after this, we could overflow a long and need to do extra checking boolean overflow = false ; long maxval = isNeg ? Long . MIN_VALUE : - Long . MAX_VALUE ; for ( ; i < 22 ; i ++ ) { int ch = getChar ( ) ; switch ( ch ) { case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : if ( v < ( 0x8000000000000000 L / 10 ) ) overflow = true ; // can't multiply by 10 w/o overflowing v *= 10 ; int digit = ch - ' ' ; if ( v < maxval + digit ) overflow = true ; // can't add digit w/o overflowing v -= digit ; out . unsafeWrite ( ch ) ; continue ; case ' ' : out . unsafeWrite ( ' ' ) ; valstate = readFrac ( out , 22 - i ) ; return 0 ; case ' ' : case ' ' : out . unsafeWrite ( ch ) ; nstate = 0 ; valstate = readExp ( out , 22 - i ) ; return 0 ; default : // return the number, relying on nextEvent() to return an error // for invalid chars following the number. if ( ch != - 1 ) -- start ; // push back last char if not EOF valstate = overflow ? BIGNUMBER : LONG ; return isNeg ? v : - v ; } } nstate = 0 ; valstate = BIGNUMBER ; return 0 ; }
Returns the long read ... only significant if valstate == LONG after this call . firstChar should be the first numeric digit read .