From: jia.shao.peng Date: Thu, 20 May 2010 00:54:27 +0000 (+0000) Subject: Improve performance of AsYouTypeFormatter by precompliling regular expressions and... X-Git-Tag: upstream/5.3.2~481 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0fca53cde2a3dc3747f6e8efb255b0f94f1f7412;p=platform%2Fupstream%2Flibphonenumber.git Improve performance of AsYouTypeFormatter by precompliling regular expressions and decrease object allocation by reusing StringBuffers. git-svn-id: http://libphonenumber.googlecode.com/svn/trunk@19 ee073f10-1060-11df-b6a4-87a95322a99c --- diff --git a/java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java b/java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java index 37e4262..c5999bf 100644 --- a/java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java +++ b/java/src/com/google/i18n/phonenumbers/AsYouTypeFormatter.java @@ -58,7 +58,9 @@ public class AsYouTypeFormatter { private Pattern internationalPrefix; private StringBuffer prefixBeforeNationalNumber; private StringBuffer nationalNumber; - private static Pattern UNSUPPORTED_SYNTAX_PATTERN = Pattern.compile("\\|"); + private final Pattern UNSUPPORTED_SYNTAX = Pattern.compile("[*#;,a-zA-Z]"); + private final Pattern CHARACTER_CLASS_PATTERN = Pattern.compile("\\[([^\\[\\]])*\\]"); + private final Pattern STANDALONE_DIGIT_PATTERN = Pattern.compile("\\d(?=[^,}][^,}])"); /** * Constructs a light-weight formatter which does no formatting, but outputs exactly what is @@ -125,17 +127,16 @@ public class AsYouTypeFormatter { String numberPattern = format.getPattern(); // The formatter doesn't format numbers when numberPattern contains "|", e.g. - // (20|3)\d{4,5}. In those cases we quickly return. - Matcher unsupportedSyntax = UNSUPPORTED_SYNTAX_PATTERN.matcher(numberPattern); - if (unsupportedSyntax.find()) { + // (20|3)\d{4}. In those cases we quickly return. + if (numberPattern.indexOf('|') != -1) { return false; } // Replace anything in the form of [..] with \d - numberPattern = numberPattern.replaceAll("\\[([^\\[\\]])*\\]","\\\\d"); + numberPattern = CHARACTER_CLASS_PATTERN.matcher(numberPattern).replaceAll("\\\\d"); // Replace any standalone digit (not the one in d{}) with \d - numberPattern = numberPattern.replaceAll("\\d(?=[^,}])", "\\\\d"); + numberPattern = STANDALONE_DIGIT_PATTERN.matcher(numberPattern).replaceAll("\\\\d"); formattingTemplate = getFormattingTemplate(numberPattern, numberFormat); return true; @@ -161,12 +162,12 @@ public class AsYouTypeFormatter { * Clears the internal state of the formatter, so it could be reused. */ public void clear() { - accruedInput = new StringBuffer(); - accruedInputWithoutFormatting = new StringBuffer(); - currentOutput = new StringBuffer(); + accruedInput.setLength(0); + accruedInputWithoutFormatting.setLength(0); + currentOutput.setLength(0); lastMatchPosition = 0; - prefixBeforeNationalNumber = new StringBuffer(); - nationalNumber = new StringBuffer(); + prefixBeforeNationalNumber.setLength(0); + nationalNumber.setLength(0); ableToFormat = true; isInternationalFormatting = false; if (!currentMetaData.equals(defaultMetaData)) { @@ -185,7 +186,7 @@ public class AsYouTypeFormatter { public String inputDigit(char nextChar) { accruedInput.append(nextChar); // * and # are normally used in mobile codes, which we do not format. - if (nextChar == '*' || nextChar == '#' || Character.isLetter(nextChar)) { + if (UNSUPPORTED_SYNTAX.matcher(Character.toString(nextChar)).matches()) { ableToFormat = false; } if (!ableToFormat) { @@ -269,7 +270,7 @@ public class AsYouTypeFormatter { * It returns true for all other cases. */ private boolean extractIddAndValidCountryCode() { - nationalNumber = new StringBuffer(); + nationalNumber.setLength(0); Matcher iddMatcher = internationalPrefix.matcher(accruedInputWithoutFormatting); if (iddMatcher.lookingAt()) { isInternationalFormatting = true; @@ -292,7 +293,8 @@ public class AsYouTypeFormatter { prefixBeforeNationalNumber.append(countryCode).append(" "); } } else { - nationalNumber = new StringBuffer(accruedInputWithoutFormatting); + nationalNumber.setLength(0); + nationalNumber.append(accruedInputWithoutFormatting); } return true; } diff --git a/java/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java b/java/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java index 01e14d8..cefb3ec 100644 --- a/java/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java +++ b/java/test/com/google/i18n/phonenumbers/AsYouTypeFormatterTest.java @@ -63,7 +63,9 @@ public class AsYouTypeFormatterTest extends TestCase { assertEquals("650 253 2", formatter.inputDigit('2')); assertEquals("650 253 22", formatter.inputDigit('2')); assertEquals("650 253 222", formatter.inputDigit('2')); - assertEquals("650 253 2222", formatter.inputDigit('2')); + // No more formatting when semicolon is entered. + assertEquals("650253222;", formatter.inputDigit(';')); + assertEquals("650253222;2", formatter.inputDigit('2')); formatter.clear(); assertEquals("6", formatter.inputDigit('6')); @@ -191,7 +193,7 @@ public class AsYouTypeFormatterTest extends TestCase { assertEquals("800 MY AP", formatter.inputDigit('P')); assertEquals("800 MY APP", formatter.inputDigit('P')); assertEquals("800 MY APPL", formatter.inputDigit('L')); - assertEquals("800 MY APPLE", formatter.inputDigit('E')); + assertEquals("800 MY APPLE", formatter.inputDigit('E')); } public void testAsYouTypeFormatterGBFixedLine() { @@ -260,7 +262,7 @@ public class AsYouTypeFormatterTest extends TestCase { assertEquals("0301", formatter.inputDigit('1')); assertEquals("03012", formatter.inputDigit('2')); assertEquals("030 123", formatter.inputDigit('3')); - assertEquals("030 1234", formatter.inputDigit('4')); + assertEquals("030 1234", formatter.inputDigit('4')); } public void testAsYouTypeFormatterAR() {