Improve the performance of replacing strings (cherry picked from commit 099fbbc)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/e9fb7840 Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/e9fb7840 Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/e9fb7840 Branch: refs/heads/GROOVY_2_6_X Commit: e9fb784062ab7b4e8f20519312ac855b184d8e25 Parents: cff0df4 Author: sunlan <sun...@apache.org> Authored: Wed Aug 30 02:05:18 2017 +0800 Committer: sunlan <sun...@apache.org> Committed: Wed Aug 30 02:15:06 2017 +0800 ---------------------------------------------------------------------- src/main/antlr/GroovyParser.g4 | 4 +- .../groovy/parser/antlr4/util/StringUtils.java | 42 ++++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/groovy/blob/e9fb7840/src/main/antlr/GroovyParser.g4 ---------------------------------------------------------------------- diff --git a/src/main/antlr/GroovyParser.g4 b/src/main/antlr/GroovyParser.g4 index 861160b..d806baa 100644 --- a/src/main/antlr/GroovyParser.g4 +++ b/src/main/antlr/GroovyParser.g4 @@ -1283,7 +1283,7 @@ keywords rparen : RPAREN | - // !!!Error Alternative + // !!!Error Alternative, impact the performance of parsing ~LPAREN { require(false, "Missing ')'", -1); } ; @@ -1291,7 +1291,7 @@ rparen rbrack : RBRACK | - // !!!Error Alternative + // !!!Error Alternative, impact the performance of parsing ~LBRACK { require(false, "Missing ']'", -1); } ; http://git-wip-us.apache.org/repos/asf/groovy/blob/e9fb7840/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/util/StringUtils.java ---------------------------------------------------------------------- diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/util/StringUtils.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/util/StringUtils.java index 5aad139..4c58256 100644 --- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/util/StringUtils.java +++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/util/StringUtils.java @@ -80,7 +80,7 @@ public class StringUtils { } }); - return result.replace("\\\\", "\\"); + return replace(result, Maps.of("\\\\", "\\")); } public static final int NONE_SLASHY = 0; @@ -92,15 +92,17 @@ public class StringUtils { text = StringUtils.replaceHexEscapes(text); text = StringUtils.replaceLineEscape(text); + StringBuilder sb = new StringBuilder(text); if (slashyType == SLASHY) { - text = text.replace("\\/", "/"); + replace(sb, Maps.of("\\/", "/")); } if (slashyType == DOLLAR_SLASHY) { - text = text.replace("$$", "$"); - text = text.replace("$/", "/"); + replace(sb, Maps.of("$$", "$")); + replace(sb, Maps.of("$/", "/")); } + text = sb.toString(); } else if (slashyType == NONE_SLASHY) { text = StringUtils.replaceEscapes(text); } else { @@ -111,8 +113,7 @@ public class StringUtils { } private static String replaceEscapes(String text) { - text = text.replace("\\$", "$"); - + text = replace(text, Maps.of("\\$", "$")); text = StringUtils.replaceLineEscape(text); return StringUtils.replaceStandardEscapes(replaceHexEscapes(replaceOctalEscapes(text))); @@ -138,7 +139,7 @@ public class StringUtils { } public static String removeCR(String text) { - return text.replace("\r\n", "\n"); + return replace(text, Maps.of("\r\n", "\n")); } public static long countChar(String text, char c) { @@ -150,9 +151,34 @@ public class StringUtils { return count; // return text.chars().filter(e -> c == e).count(); } + public static String replace(String str, Map<String, String> replacements) { + return replace(new StringBuilder(str), replacements).toString(); + } + + public static StringBuilder replace(StringBuilder sb, Map<String, String> replacements) { + + for (Map.Entry<String, String> entry : replacements.entrySet()) { + String key = entry.getKey(); + int keyLength = key.length(); + + String value = entry.getValue(); + int valueLength = value.length(); + + int start = sb.indexOf(key, 0); + while (start > -1) { + int end = start + keyLength; + int nextSearchStart = start + valueLength; + sb.replace(start, end, value); + start = sb.indexOf(key, nextSearchStart); + } + } + + return sb; + } + public static String trimQuotations(String text, int quotationLength) { int length = text.length(); - return length == quotationLength * 2 ? "" : text.substring(quotationLength, length - quotationLength); + return length == quotationLength << 1 ? "" : text.substring(quotationLength, length - quotationLength); } } \ No newline at end of file