1 /*******************************************************************************
2  * Copyright (c) 2005, 2011 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *     David Foerster - patch for toUpperCase as described in https://bugs.eclipse.org/bugs/show_bug.cgi?id=153125
11  *******************************************************************************/
12 package org.eclipse.jdt.internal.compiler.parser;
13 
14 import java.io.BufferedInputStream;
15 import java.io.DataInputStream;
16 import java.io.FileNotFoundException;
17 import java.io.IOException;
18 
19 import org.eclipse.jdt.core.compiler.InvalidInputException;
20 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
21 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
22 
23 public class ScannerHelper {
24 
25 	public final static long[] Bits = {
26 		ASTNode.Bit1, ASTNode.Bit2, ASTNode.Bit3, ASTNode.Bit4, ASTNode.Bit5, ASTNode.Bit6,
27 		ASTNode.Bit7, ASTNode.Bit8, ASTNode.Bit9, ASTNode.Bit10, ASTNode.Bit11, ASTNode.Bit12,
28 		ASTNode.Bit13, ASTNode.Bit14, ASTNode.Bit15, ASTNode.Bit16, ASTNode.Bit17, ASTNode.Bit18,
29 		ASTNode.Bit19, ASTNode.Bit20, ASTNode.Bit21, ASTNode.Bit22, ASTNode.Bit23, ASTNode.Bit24,
30 		ASTNode.Bit25, ASTNode.Bit26, ASTNode.Bit27, ASTNode.Bit28, ASTNode.Bit29, ASTNode.Bit30,
31 		ASTNode.Bit31, ASTNode.Bit32L, ASTNode.Bit33L, ASTNode.Bit34L, ASTNode.Bit35L, ASTNode.Bit36L,
32 		ASTNode.Bit37L, ASTNode.Bit38L, ASTNode.Bit39L, ASTNode.Bit40L, ASTNode.Bit41L, ASTNode.Bit42L,
33 		ASTNode.Bit43L, ASTNode.Bit44L, ASTNode.Bit45L, ASTNode.Bit46L, ASTNode.Bit47L, ASTNode.Bit48L,
34 		ASTNode.Bit49L, ASTNode.Bit50L, ASTNode.Bit51L, ASTNode.Bit52L, ASTNode.Bit53L, ASTNode.Bit54L,
35 		ASTNode.Bit55L, ASTNode.Bit56L, ASTNode.Bit57L, ASTNode.Bit58L, ASTNode.Bit59L, ASTNode.Bit60L,
36 		ASTNode.Bit61L, ASTNode.Bit62L, ASTNode.Bit63L, ASTNode.Bit64L,
37 	};
38 
39 	private static final int START_INDEX = 0;
40 	private static final int PART_INDEX = 1;
41 
42 	private static long[][][] Tables;
43 	private static long[][][] Tables7;
44 	private static long[][][] Tables8;
45 
46 	public final static int MAX_OBVIOUS = 128;
47 	public final static int[] OBVIOUS_IDENT_CHAR_NATURES = new int[MAX_OBVIOUS];
48 
49 	public final static int C_JLS_SPACE = ASTNode.Bit9;
50 	public final static int C_SPECIAL = ASTNode.Bit8;
51 	public final static int C_IDENT_START = ASTNode.Bit7;
52 	public final static int C_UPPER_LETTER = ASTNode.Bit6;
53 	public final static int C_LOWER_LETTER = ASTNode.Bit5;
54 	public final static int C_IDENT_PART = ASTNode.Bit4;
55 	public final static int C_DIGIT = ASTNode.Bit3;
56 	public final static int C_SEPARATOR = ASTNode.Bit2;
57 	public final static int C_SPACE = ASTNode.Bit1;
58 
59 	static {
60 		OBVIOUS_IDENT_CHAR_NATURES[0] = C_IDENT_PART;
61 		OBVIOUS_IDENT_CHAR_NATURES[1] = C_IDENT_PART;
62 		OBVIOUS_IDENT_CHAR_NATURES[2] = C_IDENT_PART;
63 		OBVIOUS_IDENT_CHAR_NATURES[3] = C_IDENT_PART;
64 		OBVIOUS_IDENT_CHAR_NATURES[4] = C_IDENT_PART;
65 		OBVIOUS_IDENT_CHAR_NATURES[5] = C_IDENT_PART;
66 		OBVIOUS_IDENT_CHAR_NATURES[6] = C_IDENT_PART;
67 		OBVIOUS_IDENT_CHAR_NATURES[7] = C_IDENT_PART;
68 		OBVIOUS_IDENT_CHAR_NATURES[8] = C_IDENT_PART;
69 		OBVIOUS_IDENT_CHAR_NATURES[14] = C_IDENT_PART;
70 		OBVIOUS_IDENT_CHAR_NATURES[15] = C_IDENT_PART;
71 		OBVIOUS_IDENT_CHAR_NATURES[16] = C_IDENT_PART;
72 		OBVIOUS_IDENT_CHAR_NATURES[17] = C_IDENT_PART;
73 		OBVIOUS_IDENT_CHAR_NATURES[18] = C_IDENT_PART;
74 		OBVIOUS_IDENT_CHAR_NATURES[19] = C_IDENT_PART;
75 		OBVIOUS_IDENT_CHAR_NATURES[20] = C_IDENT_PART;
76 		OBVIOUS_IDENT_CHAR_NATURES[21] = C_IDENT_PART;
77 		OBVIOUS_IDENT_CHAR_NATURES[22] = C_IDENT_PART;
78 		OBVIOUS_IDENT_CHAR_NATURES[23] = C_IDENT_PART;
79 		OBVIOUS_IDENT_CHAR_NATURES[24] = C_IDENT_PART;
80 		OBVIOUS_IDENT_CHAR_NATURES[25] = C_IDENT_PART;
81 		OBVIOUS_IDENT_CHAR_NATURES[26] = C_IDENT_PART;
82 		OBVIOUS_IDENT_CHAR_NATURES[27] = C_IDENT_PART;
83 		OBVIOUS_IDENT_CHAR_NATURES[127] = C_IDENT_PART;
84 
85 		for (int i = '0'; i <= '9'; i++)
86 			OBVIOUS_IDENT_CHAR_NATURES[i] = C_DIGIT | C_IDENT_PART;
87 
88 		for (int i = 'a'; i <= 'z'; i++)
89 			OBVIOUS_IDENT_CHAR_NATURES[i] = C_LOWER_LETTER | C_IDENT_PART | C_IDENT_START;
90 		for (int i = 'A'; i <= 'Z'; i++)
91 			OBVIOUS_IDENT_CHAR_NATURES[i] = C_UPPER_LETTER | C_IDENT_PART | C_IDENT_START;
92 
93 		OBVIOUS_IDENT_CHAR_NATURES['_'] = C_SPECIAL | C_IDENT_PART | C_IDENT_START;
94 		OBVIOUS_IDENT_CHAR_NATURES['$'] = C_SPECIAL | C_IDENT_PART | C_IDENT_START;
95 
96 		OBVIOUS_IDENT_CHAR_NATURES[9] = C_SPACE | C_JLS_SPACE; // \ u0009: HORIZONTAL TABULATION
97 		OBVIOUS_IDENT_CHAR_NATURES[10] = C_SPACE | C_JLS_SPACE; // \ u000a: LINE FEED
98 		OBVIOUS_IDENT_CHAR_NATURES[11] = C_SPACE;
99 		OBVIOUS_IDENT_CHAR_NATURES[12] = C_SPACE | C_JLS_SPACE; // \ u000c: FORM FEED
100 		OBVIOUS_IDENT_CHAR_NATURES[13] = C_SPACE | C_JLS_SPACE; //  \ u000d: CARRIAGE RETURN
101 		OBVIOUS_IDENT_CHAR_NATURES[28] = C_SPACE;
102 		OBVIOUS_IDENT_CHAR_NATURES[29] = C_SPACE;
103 		OBVIOUS_IDENT_CHAR_NATURES[30] = C_SPACE;
104 		OBVIOUS_IDENT_CHAR_NATURES[31] = C_SPACE;
105 		OBVIOUS_IDENT_CHAR_NATURES[32] = C_SPACE | C_JLS_SPACE; //  \ u0020: SPACE
106 
107 		OBVIOUS_IDENT_CHAR_NATURES['.'] = C_SEPARATOR;
108 		OBVIOUS_IDENT_CHAR_NATURES[':'] = C_SEPARATOR;
109 		OBVIOUS_IDENT_CHAR_NATURES[';'] = C_SEPARATOR;
110 		OBVIOUS_IDENT_CHAR_NATURES[','] = C_SEPARATOR;
111 		OBVIOUS_IDENT_CHAR_NATURES['['] = C_SEPARATOR;
112 		OBVIOUS_IDENT_CHAR_NATURES[']'] = C_SEPARATOR;
113 		OBVIOUS_IDENT_CHAR_NATURES['('] = C_SEPARATOR;
114 		OBVIOUS_IDENT_CHAR_NATURES[')'] = C_SEPARATOR;
115 		OBVIOUS_IDENT_CHAR_NATURES['{'] = C_SEPARATOR;
116 		OBVIOUS_IDENT_CHAR_NATURES['}'] = C_SEPARATOR;
117 		OBVIOUS_IDENT_CHAR_NATURES['+'] = C_SEPARATOR;
118 		OBVIOUS_IDENT_CHAR_NATURES['-'] = C_SEPARATOR;
119 		OBVIOUS_IDENT_CHAR_NATURES['*'] = C_SEPARATOR;
120 		OBVIOUS_IDENT_CHAR_NATURES['/'] = C_SEPARATOR;
121 		OBVIOUS_IDENT_CHAR_NATURES['='] = C_SEPARATOR;
122 		OBVIOUS_IDENT_CHAR_NATURES['&'] = C_SEPARATOR;
123 		OBVIOUS_IDENT_CHAR_NATURES['|'] = C_SEPARATOR;
124 		OBVIOUS_IDENT_CHAR_NATURES['?'] = C_SEPARATOR;
125 		OBVIOUS_IDENT_CHAR_NATURES['<'] = C_SEPARATOR;
126 		OBVIOUS_IDENT_CHAR_NATURES['>'] = C_SEPARATOR;
127 		OBVIOUS_IDENT_CHAR_NATURES['!'] = C_SEPARATOR;
128 		OBVIOUS_IDENT_CHAR_NATURES['%'] = C_SEPARATOR;
129 		OBVIOUS_IDENT_CHAR_NATURES['^'] = C_SEPARATOR;
130 		OBVIOUS_IDENT_CHAR_NATURES['~'] = C_SEPARATOR;
131 		OBVIOUS_IDENT_CHAR_NATURES['"'] = C_SEPARATOR;
132 		OBVIOUS_IDENT_CHAR_NATURES['\''] = C_SEPARATOR;
133 	}
initializeTable()134 static void initializeTable() {
135 	Tables = initializeTables("unicode"); //$NON-NLS-1$
136 }
initializeTable17()137 static void initializeTable17() {
138 	Tables7 = initializeTables("unicode6"); //$NON-NLS-1$
139 }
initializeTable18()140 static void initializeTable18() {
141 	Tables8 = initializeTables("unicode6_2"); //$NON-NLS-1$
142 }
initializeTables(String unicode_path)143 static long[][][] initializeTables(String unicode_path) {
144 	long[][][] tempTable = new long[2][][];
145 	tempTable[START_INDEX] = new long[3][];
146 	tempTable[PART_INDEX] = new long[4][];
147 	try {
148 		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/start0.rsc"))); //$NON-NLS-1$
149 		long[] readValues = new long[1024];
150 		for (int i = 0; i < 1024; i++) {
151 			readValues[i] = inputStream.readLong();
152 		}
153 		inputStream.close();
154 		tempTable[START_INDEX][0] = readValues;
155 	} catch (FileNotFoundException e) {
156 		e.printStackTrace();
157 	} catch (IOException e) {
158 		e.printStackTrace();
159 	}
160 	try {
161 		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/start1.rsc"))); //$NON-NLS-1$
162 		long[] readValues = new long[1024];
163 		for (int i = 0; i < 1024; i++) {
164 			readValues[i] = inputStream.readLong();
165 		}
166 		inputStream.close();
167 		tempTable[START_INDEX][1] = readValues;
168 	} catch (FileNotFoundException e) {
169 		e.printStackTrace();
170 	} catch (IOException e) {
171 		e.printStackTrace();
172 	}
173 	try {
174 		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/start2.rsc"))); //$NON-NLS-1$
175 		long[] readValues = new long[1024];
176 		for (int i = 0; i < 1024; i++) {
177 			readValues[i] = inputStream.readLong();
178 		}
179 		inputStream.close();
180 		tempTable[START_INDEX][2] = readValues;
181 	} catch (FileNotFoundException e) {
182 		e.printStackTrace();
183 	} catch (IOException e) {
184 		e.printStackTrace();
185 	}
186 	try {
187 		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part0.rsc"))); //$NON-NLS-1$
188 		long[] readValues = new long[1024];
189 		for (int i = 0; i < 1024; i++) {
190 			readValues[i] = inputStream.readLong();
191 		}
192 		inputStream.close();
193 		tempTable[PART_INDEX][0] = readValues;
194 	} catch (FileNotFoundException e) {
195 		e.printStackTrace();
196 	} catch (IOException e) {
197 		e.printStackTrace();
198 	}
199 	try {
200 		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part1.rsc"))); //$NON-NLS-1$
201 		long[] readValues = new long[1024];
202 		for (int i = 0; i < 1024; i++) {
203 			readValues[i] = inputStream.readLong();
204 		}
205 		inputStream.close();
206 		tempTable[PART_INDEX][1] = readValues;
207 	} catch (FileNotFoundException e) {
208 		e.printStackTrace();
209 	} catch (IOException e) {
210 		e.printStackTrace();
211 	}
212 	try {
213 		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part2.rsc"))); //$NON-NLS-1$
214 		long[] readValues = new long[1024];
215 		for (int i = 0; i < 1024; i++) {
216 			readValues[i] = inputStream.readLong();
217 		}
218 		inputStream.close();
219 		tempTable[PART_INDEX][2] = readValues;
220 	} catch (FileNotFoundException e) {
221 		e.printStackTrace();
222 	} catch (IOException e) {
223 		e.printStackTrace();
224 	}
225 	try {
226 		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part14.rsc"))); //$NON-NLS-1$
227 		long[] readValues = new long[1024];
228 		for (int i = 0; i < 1024; i++) {
229 			readValues[i] = inputStream.readLong();
230 		}
231 		inputStream.close();
232 		tempTable[PART_INDEX][3] = readValues;
233 	} catch (FileNotFoundException e) {
234 		e.printStackTrace();
235 	} catch (IOException e) {
236 		e.printStackTrace();
237 	}
238 	return tempTable;
239 }
isBitSet(long[] values, int i)240 private final static boolean isBitSet(long[] values, int i) {
241 	try {
242 		return (values[i / 64] & Bits[i % 64]) != 0;
243 	} catch (NullPointerException e) {
244 		return false;
245 	}
246 }
isJavaIdentifierPart(char c)247 public static boolean isJavaIdentifierPart(char c) {
248 	if (c < MAX_OBVIOUS) {
249 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_PART) != 0;
250 	}
251 	return Character.isJavaIdentifierPart(c);
252 }
isJavaIdentifierPart(long complianceLevel, char c)253 public static boolean isJavaIdentifierPart(long complianceLevel, char c) {
254 	if (c < MAX_OBVIOUS) {
255 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_PART) != 0;
256 	}
257 	return isJavaIdentifierPart(complianceLevel, (int) c);
258 }
isJavaIdentifierPart(long complianceLevel, int codePoint)259 public static boolean isJavaIdentifierPart(long complianceLevel, int codePoint) {
260 	if (complianceLevel <= ClassFileConstants.JDK1_6) {
261 		if (Tables == null) {
262 			initializeTable();
263 		}
264 		switch((codePoint & 0x1F0000) >> 16) {
265 			case 0 :
266 				return isBitSet(Tables[PART_INDEX][0], codePoint & 0xFFFF);
267 			case 1 :
268 				return isBitSet(Tables[PART_INDEX][1], codePoint & 0xFFFF);
269 			case 2 :
270 				return isBitSet(Tables[PART_INDEX][2], codePoint & 0xFFFF);
271 			case 14 :
272 				return isBitSet(Tables[PART_INDEX][3], codePoint & 0xFFFF);
273 		}
274 	} else if (complianceLevel <= ClassFileConstants.JDK1_7) {
275 		// java 7 supports Unicode 6
276 		if (Tables7 == null) {
277 			initializeTable17();
278 		}
279 		switch((codePoint & 0x1F0000) >> 16) {
280 			case 0 :
281 				return isBitSet(Tables7[PART_INDEX][0], codePoint & 0xFFFF);
282 			case 1 :
283 				return isBitSet(Tables7[PART_INDEX][1], codePoint & 0xFFFF);
284 			case 2 :
285 				return isBitSet(Tables7[PART_INDEX][2], codePoint & 0xFFFF);
286 			case 14 :
287 				return isBitSet(Tables7[PART_INDEX][3], codePoint & 0xFFFF);
288 		}
289 	} else {
290 		// java 7 supports Unicode 6.2
291 		if (Tables8 == null) {
292 			initializeTable18();
293 		}
294 		switch((codePoint & 0x1F0000) >> 16) {
295 			case 0 :
296 				return isBitSet(Tables8[PART_INDEX][0], codePoint & 0xFFFF);
297 			case 1 :
298 				return isBitSet(Tables8[PART_INDEX][1], codePoint & 0xFFFF);
299 			case 2 :
300 				return isBitSet(Tables8[PART_INDEX][2], codePoint & 0xFFFF);
301 			case 14 :
302 				return isBitSet(Tables8[PART_INDEX][3], codePoint & 0xFFFF);
303 		}
304 	}
305 	return false;
306 }
isJavaIdentifierPart(long complianceLevel, char high, char low)307 public static boolean isJavaIdentifierPart(long complianceLevel, char high, char low) {
308 	return isJavaIdentifierPart(complianceLevel, toCodePoint(high, low));
309 }
isJavaIdentifierStart(char c)310 public static boolean isJavaIdentifierStart(char c) {
311 	if (c < MAX_OBVIOUS) {
312 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0;
313 	}
314 	return Character.isJavaIdentifierStart(c);
315 }
isJavaIdentifierStart(long complianceLevel, char c)316 public static boolean isJavaIdentifierStart(long complianceLevel, char c) {
317 	if (c < MAX_OBVIOUS) {
318 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0;
319 	}
320 	return ScannerHelper.isJavaIdentifierStart(complianceLevel, (int) c);
321 }
isJavaIdentifierStart(long complianceLevel, char high, char low)322 public static boolean isJavaIdentifierStart(long complianceLevel, char high, char low) {
323 	return isJavaIdentifierStart(complianceLevel, toCodePoint(high, low));
324 }
isJavaIdentifierStart(long complianceLevel, int codePoint)325 public static boolean isJavaIdentifierStart(long complianceLevel, int codePoint) {
326 	if (complianceLevel <= ClassFileConstants.JDK1_6) {
327 		if (Tables == null) {
328 			initializeTable();
329 		}
330 		switch((codePoint & 0x1F0000) >> 16) {
331 			case 0 :
332 				return isBitSet(Tables[START_INDEX][0], codePoint & 0xFFFF);
333 			case 1 :
334 				return isBitSet(Tables[START_INDEX][1], codePoint & 0xFFFF);
335 			case 2 :
336 				return isBitSet(Tables[START_INDEX][2], codePoint & 0xFFFF);
337 		}
338 	} else if (complianceLevel <= ClassFileConstants.JDK1_7) {
339 		// java 7 supports Unicode 6
340 		if (Tables7 == null) {
341 			initializeTable17();
342 		}
343 		switch((codePoint & 0x1F0000) >> 16) {
344 			case 0 :
345 				return isBitSet(Tables7[START_INDEX][0], codePoint & 0xFFFF);
346 			case 1 :
347 				return isBitSet(Tables7[START_INDEX][1], codePoint & 0xFFFF);
348 			case 2 :
349 				return isBitSet(Tables7[START_INDEX][2], codePoint & 0xFFFF);
350 		}
351 	} else {
352 		// java 7 supports Unicode 6
353 		if (Tables8 == null) {
354 			initializeTable18();
355 		}
356 		switch((codePoint & 0x1F0000) >> 16) {
357 			case 0 :
358 				return isBitSet(Tables8[START_INDEX][0], codePoint & 0xFFFF);
359 			case 1 :
360 				return isBitSet(Tables8[START_INDEX][1], codePoint & 0xFFFF);
361 			case 2 :
362 				return isBitSet(Tables8[START_INDEX][2], codePoint & 0xFFFF);
363 		}
364 	}
365 	return false;
366 }
toCodePoint(char high, char low)367 private static int toCodePoint(char high, char low) {
368 	return (high - Scanner.HIGH_SURROGATE_MIN_VALUE) * 0x400 + (low - Scanner.LOW_SURROGATE_MIN_VALUE) + 0x10000;
369 }
isDigit(char c)370 public static boolean isDigit(char c) throws InvalidInputException {
371 	if(c < ScannerHelper.MAX_OBVIOUS) {
372 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0;
373 	}
374 	if (Character.isDigit(c)) {
375 		throw new InvalidInputException(Scanner.INVALID_DIGIT);
376 	}
377 	return false;
378 }
digit(char c, int radix)379 public static int digit(char c, int radix) {
380 	if (c < ScannerHelper.MAX_OBVIOUS) {
381 		switch(radix) {
382 			case 8 :
383 				if (c >= 48 && c <= 55) {
384 					return c - 48;
385 				}
386 				return -1;
387 			case 10 :
388 				if (c >= 48 && c <= 57) {
389 					return c - 48;
390 				}
391 				return -1;
392 			case 16 :
393 				if (c >= 48 && c <= 57) {
394 					return c - 48;
395 				}
396 				if (c >= 65 && c <= 70) {
397 					return c - 65 + 10;
398 				}
399 				if (c >= 97 && c <= 102) {
400 					return c - 97 + 10;
401 				}
402 				return -1;
403 		}
404 	}
405 	return Character.digit(c, radix);
406 }
getNumericValue(char c)407 public static int getNumericValue(char c) {
408 	if (c < ScannerHelper.MAX_OBVIOUS) {
409 		switch(ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c]) {
410 			case C_DIGIT :
411 				return c - '0';
412 			case C_LOWER_LETTER :
413 				return 10 + c - 'a';
414 			case C_UPPER_LETTER :
415 				return 10 + c - 'A';
416 		}
417 	}
418 	return Character.getNumericValue(c);
419 }
getHexadecimalValue(char c)420 public static int getHexadecimalValue(char c) {
421 	switch(c) {
422 		case '0' :
423 			return 0;
424 		case '1' :
425 			return 1;
426 		case '2' :
427 			return 2;
428 		case '3' :
429 			return 3;
430 		case '4' :
431 			return 4;
432 		case '5' :
433 			return 5;
434 		case '6' :
435 			return 6;
436 		case '7' :
437 			return 7;
438 		case '8' :
439 			return 8;
440 		case '9' :
441 			return 9;
442 		case 'A' :
443 		case 'a' :
444 			return 10;
445 		case 'B' :
446 		case 'b' :
447 			return 11;
448 		case 'C' :
449 		case 'c' :
450 			return 12;
451 		case 'D' :
452 		case 'd' :
453 			return 13;
454 		case 'E' :
455 		case 'e' :
456 			return 14;
457 		case 'F' :
458 		case 'f' :
459 			return 15;
460 		default:
461 			return -1;
462 	}
463 }
toUpperCase(char c)464 public static char toUpperCase(char c) {
465 	if (c < MAX_OBVIOUS) {
466 		if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0) {
467 			return c;
468 		} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0) {
469 			return (char) (c - 32);
470 		}
471 	}
472 	return Character.toUpperCase(c);
473 }
toLowerCase(char c)474 public static char toLowerCase(char c) {
475 	if (c < MAX_OBVIOUS) {
476 		if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0) {
477 			return c;
478 		} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0) {
479 			return (char) (32 + c);
480 		}
481 	}
482 	return Character.toLowerCase(c);
483 }
isLowerCase(char c)484 public static boolean isLowerCase(char c) {
485 	if (c < MAX_OBVIOUS) {
486 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0;
487 	}
488 	return Character.isLowerCase(c);
489 }
isUpperCase(char c)490 public static boolean isUpperCase(char c) {
491 	if (c < MAX_OBVIOUS) {
492 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0;
493 	}
494 	return Character.isUpperCase(c);
495 }
496 /**
497  * Include also non JLS whitespaces.
498  *
499  * return true if Character.isWhitespace(c) would return true
500  */
isWhitespace(char c)501 public static boolean isWhitespace(char c) {
502 	if (c < MAX_OBVIOUS) {
503 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_SPACE) != 0;
504 	}
505 	return Character.isWhitespace(c);
506 }
isLetter(char c)507 public static boolean isLetter(char c) {
508 	if (c < MAX_OBVIOUS) {
509 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER)) != 0;
510 	}
511 	return Character.isLetter(c);
512 }
isLetterOrDigit(char c)513 public static boolean isLetterOrDigit(char c) {
514 	if (c < MAX_OBVIOUS) {
515 		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_DIGIT)) != 0;
516 	}
517 	return Character.isLetterOrDigit(c);
518 }
519 }
520