diff --git a/java/com/google/re2j/Matcher.java b/java/com/google/re2j/Matcher.java index 678186d0..e0f6415d 100644 --- a/java/com/google/re2j/Matcher.java +++ b/java/com/google/re2j/Matcher.java @@ -393,6 +393,10 @@ String substring(int start, int end) { return matcherInput.asCharSequence().subSequence(start, end).toString(); } + void appendTo(Appendable sb, int end) { + matcherInput.appendTo(sb, appendPos, end); + } + /** Helper for Pattern: return input length. */ int inputLength() { return inputLength; @@ -475,7 +479,7 @@ public Matcher appendReplacement(StringBuilder sb, String replacement) { int s = start(); int e = end(); if (appendPos < s) { - sb.append(substring(appendPos, s)); + appendTo(sb, s); } appendPos = e; appendReplacementInternal(sb, replacement); @@ -489,7 +493,7 @@ private void appendReplacementInternal(StringBuilder sb, String replacement) { for (; i < m - 1; i++) { if (replacement.charAt(i) == '\\') { if (last < i) { - sb.append(replacement.substring(last, i)); + sb.append(replacement, last, i); } i++; last = i; @@ -500,7 +504,7 @@ private void appendReplacementInternal(StringBuilder sb, String replacement) { if ('0' <= c && c <= '9') { int n = c - '0'; if (last < i) { - sb.append(replacement.substring(last, i)); + sb.append(replacement, last, i); } for (i += 2; i < m; i++) { c = replacement.charAt(i); @@ -521,7 +525,7 @@ private void appendReplacementInternal(StringBuilder sb, String replacement) { continue; } else if (c == '{') { if (last < i) { - sb.append(replacement.substring(last, i)); + sb.append(replacement, last, i); } i++; // skip { int j = i + 1; @@ -552,7 +556,7 @@ private void appendReplacementInternal(StringBuilder sb, String replacement) { * @return the argument {@code sb}, for method chaining */ public StringBuffer appendTail(StringBuffer sb) { - sb.append(substring(appendPos, inputLength)); + appendTo(sb, inputLength); return sb; } @@ -564,7 +568,7 @@ public StringBuffer appendTail(StringBuffer sb) { * @return the argument {@code sb}, for method chaining */ public StringBuilder appendTail(StringBuilder sb) { - sb.append(substring(appendPos, inputLength)); + appendTo(sb, inputLength); return sb; } diff --git a/java/com/google/re2j/MatcherInput.java b/java/com/google/re2j/MatcherInput.java index 8af494ba..5fcec334 100644 --- a/java/com/google/re2j/MatcherInput.java +++ b/java/com/google/re2j/MatcherInput.java @@ -6,6 +6,7 @@ */ package com.google.re2j; +import java.io.IOException; import java.nio.charset.Charset; /** @@ -41,6 +42,8 @@ static MatcherInput utf8(String input) { abstract Encoding getEncoding(); + abstract void appendTo(Appendable sb, int beg, int end); + abstract CharSequence asCharSequence(); abstract byte[] asBytes(); @@ -59,6 +62,15 @@ public Encoding getEncoding() { return Encoding.UTF_8; } + @Override + public void appendTo(Appendable sb, int beg, int end) { + try { + sb.append(new String(bytes, beg, end - beg, "UTF-8")); + } catch (IOException e) { + throw new RuntimeException(e); // Not possible. + } + } + @Override public CharSequence asCharSequence() { return new String(bytes, Charset.forName("UTF-8")); @@ -87,6 +99,15 @@ public Encoding getEncoding() { return Encoding.UTF_16; } + @Override + public void appendTo(Appendable sb, int beg, int end) { + try { + sb.append(charSequence, beg, end); + } catch (IOException e) { + throw new RuntimeException(e); // Not possible. + } + } + @Override public CharSequence asCharSequence() { return charSequence;