@@ -36,20 +36,32 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3636class IterImplNumber {
3737
3838 final static int [] digits = new int [256 ];
39+ final static int [] zeroToNineDigits = new int [256 ];
40+ final static int END_OF_NUMBER = -2 ;
41+ final static int DOT_IN_NUMBER = -3 ;
42+ final static int INVALID_CHAR_FOR_NUMBER = -1 ;
43+ private static final int POW10 [] = {1 , 10 , 100 , 1000 , 10000 , 100000 , 1000000 };
3944
4045 static {
4146 for (int i = 0 ; i < digits .length ; i ++) {
42- digits [i ] = -1 ;
47+ digits [i ] = INVALID_CHAR_FOR_NUMBER ;
48+ zeroToNineDigits [i ] = INVALID_CHAR_FOR_NUMBER ;
4349 }
4450 for (int i = '0' ; i <= '9' ; ++i ) {
4551 digits [i ] = (i - '0' );
52+ zeroToNineDigits [i ] = (i - '0' );
4653 }
4754 for (int i = 'a' ; i <= 'f' ; ++i ) {
4855 digits [i ] = ((i - 'a' ) + 10 );
4956 }
5057 for (int i = 'A' ; i <= 'F' ; ++i ) {
5158 digits [i ] = ((i - 'A' ) + 10 );
5259 }
60+ zeroToNineDigits [',' ] = END_OF_NUMBER ;
61+ zeroToNineDigits [']' ] = END_OF_NUMBER ;
62+ zeroToNineDigits ['}' ] = END_OF_NUMBER ;
63+ zeroToNineDigits [' ' ] = END_OF_NUMBER ;
64+ zeroToNineDigits ['.' ] = DOT_IN_NUMBER ;
5365 }
5466
5567 public static final double readDouble (JsonIterator iter ) throws IOException {
@@ -147,84 +159,61 @@ public static final double readDoubleSlowPath(JsonIterator iter) throws IOExcept
147159
148160 public static final float readFloat (JsonIterator iter ) throws IOException {
149161 final byte c = IterImpl .nextToken (iter );
150- // when re-read using slowpath, it should include the first byte
151- iter .unreadByte ();
152162 if (c == '-' ) {
153- // skip '-' by + 1
154- return readNegativeFloat (iter , iter .head + 1 );
163+ return -readPositiveFloat (iter );
164+ } else {
165+ iter .unreadByte ();
166+ return readPositiveFloat (iter );
155167 }
156- return readPositiveFloat (iter , iter .head );
157168 }
158169
159- private static final float readPositiveFloat (JsonIterator iter , int start ) throws IOException {
160- long value = 0 ;
161- byte c = ' ' ;
162- int i = start ;
163- for (; i < iter .tail ; i ++) {
164- c = iter .buf [i ];
165- if (c == ',' || c == '}' || c == ']' || c == ' ' ) {
166- iter .head = i ;
167- return value ;
168- }
169- if (c == '.' ) break ;
170- final int ind = digits [c ];
171- value = (value << 3 ) + (value << 1 ) + ind ;
172- if (ind < 0 || ind > 9 ) {
173- return readFloatSlowPath (iter );
174- }
175- }
176- if (c == '.' ) {
177- i ++;
178- long div = 1 ;
179- for (; i < iter .tail ; i ++) {
180- c = iter .buf [i ];
181- if (c == ',' || c == '}' || c == ']' || c == ' ' ) {
182- iter .head = i ;
183- return value / (float ) div ;
184- }
185- final int ind = digits [c ];
186- div = (div << 3 ) + (div << 1 );
187- value = (value << 3 ) + (value << 1 ) + ind ;
188- if (ind < 0 || ind > 9 ) {
189- return readFloatSlowPath (iter );
190- }
191- }
192- }
193- return readFloatSlowPath (iter );
194- }
170+ private final static long SAFE_TO_MULTIPLY_10 = (Long .MAX_VALUE / 10 ) - 10 ;
195171
196- private static final float readNegativeFloat (JsonIterator iter , int start ) throws IOException {
197- long value = 0 ;
172+ private static final float readPositiveFloat (JsonIterator iter ) throws IOException {
173+ long value = 0 ; // without the dot
198174 byte c = ' ' ;
199- int i = start ;
175+ int i = iter .head ;
176+ non_decimal_loop :
200177 for (; i < iter .tail ; i ++) {
201178 c = iter .buf [i ];
202- if (c == ',' || c == '}' || c == ']' || c == ' ' ) {
203- iter .head = i ;
204- return value ;
179+ final int ind = zeroToNineDigits [c ];
180+ switch (ind ) {
181+ case INVALID_CHAR_FOR_NUMBER :
182+ return readFloatSlowPath (iter );
183+ case END_OF_NUMBER :
184+ iter .head = i ;
185+ return value ;
186+ case DOT_IN_NUMBER :
187+ break non_decimal_loop ;
205188 }
206- if (c == '.' ) break ;
207- final int ind = digits [c ];
208- value = (value << 3 ) + (value << 1 ) - ind ;
209- if (ind < 0 || ind > 9 ) {
189+ if (value > SAFE_TO_MULTIPLY_10 ) {
210190 return readFloatSlowPath (iter );
211191 }
192+ value = (value << 3 ) + (value << 1 ) + ind ; // value = value * 10 + ind;
212193 }
213194 if (c == '.' ) {
214195 i ++;
215- long div = 1 ;
196+ int decimalPlaces = 0 ;
216197 for (; i < iter .tail ; i ++) {
217198 c = iter .buf [i ];
218- if (c == ',' || c == '}' || c == ']' || c == ' ' ) {
219- iter .head = i ;
220- return value / (float ) div ;
199+ final int ind = zeroToNineDigits [c ];
200+ switch (ind ) {
201+ case END_OF_NUMBER :
202+ if (decimalPlaces > 0 && decimalPlaces < POW10 .length ) {
203+ iter .head = i ;
204+ return value / (float ) POW10 [decimalPlaces ];
205+ }
206+ // too many decimal places
207+ return readFloatSlowPath (iter );
208+ case INVALID_CHAR_FOR_NUMBER :
209+ case DOT_IN_NUMBER :
210+ return readFloatSlowPath (iter );
221211 }
222- final int ind = digits [c ];
223- div = (div << 3 ) + (div << 1 );
224- value = (value << 3 ) + (value << 1 ) - ind ;
225- if (ind < 0 || ind > 9 ) {
212+ decimalPlaces ++;
213+ if (value > SAFE_TO_MULTIPLY_10 ) {
226214 return readFloatSlowPath (iter );
227215 }
216+ value = (value << 3 ) + (value << 1 ) + ind ; // value = value * 10 + ind;
228217 }
229218 }
230219 return readFloatSlowPath (iter );
@@ -248,7 +237,6 @@ public static final String readNumber(JsonIterator iter) throws IOException {
248237 }
249238 switch (c ) {
250239 case '-' :
251- case '+' :
252240 case '.' :
253241 case 'e' :
254242 case 'E' :
0 commit comments