1 /*
2 * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
411 Pattern bp = boolPattern;
412 if (bp == null)
413 boolPattern = bp = Pattern.compile(BOOLEAN_PATTERN,
414 Pattern.CASE_INSENSITIVE);
415 return bp;
416 }
417
418 /**
419 * Fields and methods to match bytes, shorts, ints, and longs
420 */
421 private Pattern integerPattern;
422 private String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
423 private String non0Digit = "[\\p{javaDigit}&&[^0]]";
424 private int SIMPLE_GROUP_INDEX = 5;
425 private String buildIntegerPatternString() {
426 String radixDigits = digits.substring(0, radix);
427 // \\p{javaDigit} is not guaranteed to be appropriate
428 // here but what can we do? The final authority will be
429 // whatever parse method is invoked, so ultimately the
430 // Scanner will do the right thing
431 String digit = "((?i)["+radixDigits+"]|\\p{javaDigit})";
432 String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
433 groupSeparator+digit+digit+digit+")+)";
434 // digit++ is the possessive form which is necessary for reducing
435 // backtracking that would otherwise cause unacceptable performance
436 String numeral = "(("+ digit+"++)|"+groupedNumeral+")";
437 String javaStyleInteger = "([-+]?(" + numeral + "))";
438 String negativeInteger = negativePrefix + numeral + negativeSuffix;
439 String positiveInteger = positivePrefix + numeral + positiveSuffix;
440 return "("+ javaStyleInteger + ")|(" +
441 positiveInteger + ")|(" +
442 negativeInteger + ")";
443 }
444 private Pattern integerPattern() {
445 if (integerPattern == null) {
446 integerPattern = patternCache.forName(buildIntegerPatternString());
447 }
448 return integerPattern;
449 }
450
451 /**
461 Pattern sp = separatorPattern;
462 if (sp == null)
463 separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
464 return sp;
465 }
466
467 private static Pattern linePattern() {
468 Pattern lp = linePattern;
469 if (lp == null)
470 linePattern = lp = Pattern.compile(LINE_PATTERN);
471 return lp;
472 }
473
474 /**
475 * Fields and methods to match floats and doubles
476 */
477 private Pattern floatPattern;
478 private Pattern decimalPattern;
479 private void buildFloatAndDecimalPattern() {
480 // \\p{javaDigit} may not be perfect, see above
481 String digit = "([0-9]|(\\p{javaDigit}))";
482 String exponent = "([eE][+-]?"+digit+"+)?";
483 String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
484 groupSeparator+digit+digit+digit+")+)";
485 // Once again digit++ is used for performance, as above
486 String numeral = "(("+digit+"++)|"+groupedNumeral+")";
487 String decimalNumeral = "("+numeral+"|"+numeral +
488 decimalSeparator + digit + "*+|"+ decimalSeparator +
489 digit + "++)";
490 String nonNumber = "(NaN|"+nanString+"|Infinity|"+
491 infinityString+")";
492 String positiveFloat = "(" + positivePrefix + decimalNumeral +
493 positiveSuffix + exponent + ")";
494 String negativeFloat = "(" + negativePrefix + decimalNumeral +
495 negativeSuffix + exponent + ")";
496 String decimal = "(([-+]?" + decimalNumeral + exponent + ")|"+
497 positiveFloat + "|" + negativeFloat + ")";
498 String hexFloat =
499 "[-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?";
500 String positiveNonNumber = "(" + positivePrefix + nonNumber +
501 positiveSuffix + ")";
1272 if (nf instanceof DecimalFormat) {
1273 df = (DecimalFormat) nf;
1274 } else {
1275
1276 // In case where NumberFormat.getNumberInstance() returns
1277 // other instance (non DecimalFormat) based on the provider
1278 // used and java.text.spi.NumberFormatProvider implementations,
1279 // DecimalFormat constructor is used to obtain the instance
1280 LocaleProviderAdapter adapter = LocaleProviderAdapter
1281 .getAdapter(NumberFormatProvider.class, locale);
1282 if (!(adapter instanceof ResourceBundleBasedAdapter)) {
1283 adapter = LocaleProviderAdapter.getResourceBundleBased();
1284 }
1285 String[] all = adapter.getLocaleResources(locale)
1286 .getNumberPatterns();
1287 df = new DecimalFormat(all[0], dfs);
1288 }
1289
1290 // These must be literalized to avoid collision with regex
1291 // metacharacters such as dot or parenthesis
1292 groupSeparator = "\\" + dfs.getGroupingSeparator();
1293 decimalSeparator = "\\" + dfs.getDecimalSeparator();
1294
1295 // Quoting the nonzero length locale-specific things
1296 // to avoid potential conflict with metacharacters
1297 nanString = "\\Q" + dfs.getNaN() + "\\E";
1298 infinityString = "\\Q" + dfs.getInfinity() + "\\E";
1299 positivePrefix = df.getPositivePrefix();
1300 if (!positivePrefix.isEmpty())
1301 positivePrefix = "\\Q" + positivePrefix + "\\E";
1302 negativePrefix = df.getNegativePrefix();
1303 if (!negativePrefix.isEmpty())
1304 negativePrefix = "\\Q" + negativePrefix + "\\E";
1305 positiveSuffix = df.getPositiveSuffix();
1306 if (!positiveSuffix.isEmpty())
1307 positiveSuffix = "\\Q" + positiveSuffix + "\\E";
1308 negativeSuffix = df.getNegativeSuffix();
1309 if (!negativeSuffix.isEmpty())
1310 negativeSuffix = "\\Q" + negativeSuffix + "\\E";
1311
1312 // Force rebuilding and recompilation of locale dependent
1313 // primitive patterns
1314 integerPattern = null;
1315 floatPattern = null;
1316
1317 return this;
1318 }
1319
1320 /**
1321 * Returns this scanner's default radix.
1322 *
1323 * <p>A scanner's radix affects elements of its default
1324 * number matching regular expressions; see
1325 * <a href= "#localized-numbers">localized numbers</a> above.
1326 *
1327 * @return the default radix of this scanner
1328 */
1329 public int radix() {
1330 return this.defaultRadix;
|
1 /*
2 * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
411 Pattern bp = boolPattern;
412 if (bp == null)
413 boolPattern = bp = Pattern.compile(BOOLEAN_PATTERN,
414 Pattern.CASE_INSENSITIVE);
415 return bp;
416 }
417
418 /**
419 * Fields and methods to match bytes, shorts, ints, and longs
420 */
421 private Pattern integerPattern;
422 private String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
423 private String non0Digit = "[\\p{javaDigit}&&[^0]]";
424 private int SIMPLE_GROUP_INDEX = 5;
425 private String buildIntegerPatternString() {
426 String radixDigits = digits.substring(0, radix);
427 // \\p{javaDigit} is not guaranteed to be appropriate
428 // here but what can we do? The final authority will be
429 // whatever parse method is invoked, so ultimately the
430 // Scanner will do the right thing
431 String digit = "((?i)["+radixDigits+"\\p{javaDigit}])";
432 String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
433 groupSeparator+digit+digit+digit+")+)";
434 // digit++ is the possessive form which is necessary for reducing
435 // backtracking that would otherwise cause unacceptable performance
436 String numeral = "(("+ digit+"++)|"+groupedNumeral+")";
437 String javaStyleInteger = "([-+]?(" + numeral + "))";
438 String negativeInteger = negativePrefix + numeral + negativeSuffix;
439 String positiveInteger = positivePrefix + numeral + positiveSuffix;
440 return "("+ javaStyleInteger + ")|(" +
441 positiveInteger + ")|(" +
442 negativeInteger + ")";
443 }
444 private Pattern integerPattern() {
445 if (integerPattern == null) {
446 integerPattern = patternCache.forName(buildIntegerPatternString());
447 }
448 return integerPattern;
449 }
450
451 /**
461 Pattern sp = separatorPattern;
462 if (sp == null)
463 separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
464 return sp;
465 }
466
467 private static Pattern linePattern() {
468 Pattern lp = linePattern;
469 if (lp == null)
470 linePattern = lp = Pattern.compile(LINE_PATTERN);
471 return lp;
472 }
473
474 /**
475 * Fields and methods to match floats and doubles
476 */
477 private Pattern floatPattern;
478 private Pattern decimalPattern;
479 private void buildFloatAndDecimalPattern() {
480 // \\p{javaDigit} may not be perfect, see above
481 String digit = "(([0-9\\p{javaDigit}]))";
482 String exponent = "([eE][+-]?"+digit+"+)?";
483 String groupedNumeral = "("+non0Digit+digit+"?"+digit+"?("+
484 groupSeparator+digit+digit+digit+")+)";
485 // Once again digit++ is used for performance, as above
486 String numeral = "(("+digit+"++)|"+groupedNumeral+")";
487 String decimalNumeral = "("+numeral+"|"+numeral +
488 decimalSeparator + digit + "*+|"+ decimalSeparator +
489 digit + "++)";
490 String nonNumber = "(NaN|"+nanString+"|Infinity|"+
491 infinityString+")";
492 String positiveFloat = "(" + positivePrefix + decimalNumeral +
493 positiveSuffix + exponent + ")";
494 String negativeFloat = "(" + negativePrefix + decimalNumeral +
495 negativeSuffix + exponent + ")";
496 String decimal = "(([-+]?" + decimalNumeral + exponent + ")|"+
497 positiveFloat + "|" + negativeFloat + ")";
498 String hexFloat =
499 "[-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?";
500 String positiveNonNumber = "(" + positivePrefix + nonNumber +
501 positiveSuffix + ")";
1272 if (nf instanceof DecimalFormat) {
1273 df = (DecimalFormat) nf;
1274 } else {
1275
1276 // In case where NumberFormat.getNumberInstance() returns
1277 // other instance (non DecimalFormat) based on the provider
1278 // used and java.text.spi.NumberFormatProvider implementations,
1279 // DecimalFormat constructor is used to obtain the instance
1280 LocaleProviderAdapter adapter = LocaleProviderAdapter
1281 .getAdapter(NumberFormatProvider.class, locale);
1282 if (!(adapter instanceof ResourceBundleBasedAdapter)) {
1283 adapter = LocaleProviderAdapter.getResourceBundleBased();
1284 }
1285 String[] all = adapter.getLocaleResources(locale)
1286 .getNumberPatterns();
1287 df = new DecimalFormat(all[0], dfs);
1288 }
1289
1290 // These must be literalized to avoid collision with regex
1291 // metacharacters such as dot or parenthesis
1292 groupSeparator = "\\x{" + Integer.toHexString(dfs.getGroupingSeparator()) + "}";
1293 decimalSeparator = "\\x{" + Integer.toHexString(dfs.getDecimalSeparator()) + "}";
1294
1295 // Quoting the nonzero length locale-specific things
1296 // to avoid potential conflict with metacharacters
1297 nanString = Pattern.quote(dfs.getNaN());
1298 infinityString = Pattern.quote(dfs.getInfinity());
1299 positivePrefix = df.getPositivePrefix();
1300 if (!positivePrefix.isEmpty())
1301 positivePrefix = Pattern.quote(positivePrefix);
1302 negativePrefix = df.getNegativePrefix();
1303 if (!negativePrefix.isEmpty())
1304 negativePrefix = Pattern.quote(negativePrefix);
1305 positiveSuffix = df.getPositiveSuffix();
1306 if (!positiveSuffix.isEmpty())
1307 positiveSuffix = Pattern.quote(positiveSuffix);
1308 negativeSuffix = df.getNegativeSuffix();
1309 if (!negativeSuffix.isEmpty())
1310 negativeSuffix = Pattern.quote(negativeSuffix);
1311
1312 // Force rebuilding and recompilation of locale dependent
1313 // primitive patterns
1314 integerPattern = null;
1315 floatPattern = null;
1316
1317 return this;
1318 }
1319
1320 /**
1321 * Returns this scanner's default radix.
1322 *
1323 * <p>A scanner's radix affects elements of its default
1324 * number matching regular expressions; see
1325 * <a href= "#localized-numbers">localized numbers</a> above.
1326 *
1327 * @return the default radix of this scanner
1328 */
1329 public int radix() {
1330 return this.defaultRadix;
|