Remove unused luni java.util.regex.* implementation.
Change-Id: I70ffe3c09be45ffd760cb4bdeee63ec1ddf86596
diff --git a/luni/src/main/java/java/util/regex/MatchResult.java b/luni/src/main/java/java/util/regex/MatchResult.java
deleted file mode 100644
index c77206d..0000000
--- a/luni/src/main/java/java/util/regex/MatchResult.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.regex;
-
-/**
- * Holds the results of a successful match of a {@link Pattern} against a
- * given string. Typically this is an instance of {@link Matcher}, but
- * since that's a mutable class it's also possible to freeze its current
- * state using {@link Matcher#toMatchResult}.
- */
-public interface MatchResult {
-
- /**
- * Returns the index of the first character following the text that matched
- * the whole regular expression.
- */
- int end();
-
- /**
- * Returns the index of the first character following the text that matched
- * a given group. See {@link #group} for an explanation of group indexes.
- */
- int end(int group);
-
- /**
- * Returns the text that matched the whole regular expression.
- */
- String group();
-
- /**
- * Returns the text that matched a given group of the regular expression.
- *
- * <p>Explicit capturing groups in the pattern are numbered left to right in order
- * of their <i>opening</i> parenthesis, starting at 1.
- * The special group 0 represents the entire match (as if the entire pattern is surrounded
- * by an implicit capturing group).
- * For example, "a((b)c)" matching "abc" would give the following groups:
- * <pre>
- * 0 "abc"
- * 1 "bc"
- * 2 "b"
- * </pre>
- *
- * <p>An optional capturing group that failed to match as part of an overall
- * successful match (for example, "a(b)?c" matching "ac") returns null.
- * A capturing group that matched the empty string (for example, "a(b?)c" matching "ac")
- * returns the empty string.
- */
- String group(int group);
-
- /**
- * Returns the number of groups in the results, which is always equal to
- * the number of groups in the original regular expression.
- */
- int groupCount();
-
- /**
- * Returns the index of the first character of the text that matched the
- * whole regular expression.
- */
- int start();
-
- /**
- * Returns the index of the first character of the text that matched a given
- * group. See {@link #group} for an explanation of group indexes.
- */
- int start(int group);
-}
diff --git a/luni/src/main/java/java/util/regex/MatchResultImpl.java b/luni/src/main/java/java/util/regex/MatchResultImpl.java
deleted file mode 100644
index 6a0d948..0000000
--- a/luni/src/main/java/java/util/regex/MatchResultImpl.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.regex;
-
-/**
- * Holds the results of a successful match of a regular expression against a
- * given string. Only used internally, thus sparsely documented (though the
- * defining public interface has full documentation).
- *
- * @see java.util.regex.MatchResult
- */
-class MatchResultImpl implements MatchResult {
-
- /**
- * Holds the original input text.
- */
- private String text;
-
- /**
- * Holds the offsets of the groups in the input text. The first two
- * elements specify start and end of the zero group, the next two specify
- * group 1, and so on.
- */
- private int[] offsets;
-
- MatchResultImpl(String text, int[] offsets) {
- this.text = text;
- this.offsets = offsets.clone();
- }
-
- public int end() {
- return end(0);
- }
-
- public int end(int group) {
- return offsets[2 * group + 1];
- }
-
- public String group() {
- return text.substring(start(), end());
- }
-
- public String group(int group) {
- int from = offsets[group * 2];
- int to = offsets[(group * 2) + 1];
- if (from == -1 || to == -1) {
- return null;
- } else {
- return text.substring(from, to);
- }
- }
-
- public int groupCount() {
- return (offsets.length / 2) - 1;
- }
-
- public int start() {
- return start(0);
- }
-
- public int start(int group) {
- return offsets[2 * group];
- }
-
-}
diff --git a/luni/src/main/java/java/util/regex/Matcher.java b/luni/src/main/java/java/util/regex/Matcher.java
deleted file mode 100644
index d181d45..0000000
--- a/luni/src/main/java/java/util/regex/Matcher.java
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.regex;
-
-/**
- * The result of applying a {@code Pattern} to a given input. See {@link Pattern} for
- * example uses.
- */
-public final class Matcher implements MatchResult {
-
- /**
- * Holds the pattern, that is, the compiled regular expression.
- */
- private Pattern pattern;
-
- /**
- * The address of the native peer.
- * Uses of this must be manually synchronized to avoid native crashes.
- */
- private long address;
-
- /**
- * Holds the input text.
- */
- private String input;
-
- /**
- * Holds the start of the region, or 0 if the matching should start at the
- * beginning of the text.
- */
- private int regionStart;
-
- /**
- * Holds the end of the region, or input.length() if the matching should
- * go until the end of the input.
- */
- private int regionEnd;
-
- /**
- * Holds the position where the next append operation will take place.
- */
- private int appendPos;
-
- /**
- * Reflects whether a match has been found during the most recent find
- * operation.
- */
- private boolean matchFound;
-
- /**
- * Holds the offsets for the most recent match.
- */
- private int[] matchOffsets;
-
- /**
- * Reflects whether the bounds of the region are anchoring.
- */
- private boolean anchoringBounds = true;
-
- /**
- * Reflects whether the bounds of the region are transparent.
- */
- private boolean transparentBounds;
-
- /**
- * Creates a matcher for a given combination of pattern and input. Both
- * elements can be changed later on.
- *
- * @param pattern
- * the pattern to use.
- * @param input
- * the input to use.
- */
- Matcher(Pattern pattern, CharSequence input) {
- usePattern(pattern);
- reset(input);
- }
-
- /**
- * Appends a literal part of the input plus a replacement for the current
- * match to a given {@link StringBuffer}. The literal part is exactly the
- * part of the input between the previous match and the current match. The
- * method can be used in conjunction with {@link #find()} and
- * {@link #appendTail(StringBuffer)} to walk through the input and replace
- * all occurrences of the {@code Pattern} with something else.
- *
- * @param buffer
- * the {@code StringBuffer} to append to.
- * @param replacement
- * the replacement text.
- * @return the {@code Matcher} itself.
- * @throws IllegalStateException
- * if no successful match has been made.
- */
- public Matcher appendReplacement(StringBuffer buffer, String replacement) {
- buffer.append(input.substring(appendPos, start()));
- appendEvaluated(buffer, replacement);
- appendPos = end();
-
- return this;
- }
-
- /**
- * Internal helper method to append a given string to a given string buffer.
- * If the string contains any references to groups, these are replaced by
- * the corresponding group's contents.
- *
- * @param buffer
- * the string buffer.
- * @param s
- * the string to append.
- */
- private void appendEvaluated(StringBuffer buffer, String s) {
- boolean escape = false;
- boolean dollar = false;
-
- for (int i = 0; i < s.length(); i++) {
- char c = s.charAt(i);
- if (c == '\\' && !escape) {
- escape = true;
- } else if (c == '$' && !escape) {
- dollar = true;
- } else if (c >= '0' && c <= '9' && dollar) {
- buffer.append(group(c - '0'));
- dollar = false;
- } else {
- buffer.append(c);
- dollar = false;
- escape = false;
- }
- }
-
- // This seemingly stupid piece of code reproduces a JDK bug.
- if (escape) {
- throw new ArrayIndexOutOfBoundsException(s.length());
- }
- }
-
- /**
- * Resets the {@code Matcher}. This results in the region being set to the
- * whole input. Results of a previous find get lost. The next attempt to
- * find an occurrence of the {@link Pattern} in the string will start at the
- * beginning of the input.
- *
- * @return the {@code Matcher} itself.
- */
- public Matcher reset() {
- return reset(input, 0, input.length());
- }
-
- /**
- * Provides a new input and resets the {@code Matcher}. This results in the
- * region being set to the whole input. Results of a previous find get lost.
- * The next attempt to find an occurrence of the {@link Pattern} in the
- * string will start at the beginning of the input.
- *
- * @param input
- * the new input sequence.
- *
- * @return the {@code Matcher} itself.
- */
- public Matcher reset(CharSequence input) {
- return reset(input, 0, input.length());
- }
-
- /**
- * Resets the Matcher. A new input sequence and a new region can be
- * specified. Results of a previous find get lost. The next attempt to find
- * an occurrence of the Pattern in the string will start at the beginning of
- * the region. This is the internal version of reset() to which the several
- * public versions delegate.
- *
- * @param input
- * the input sequence.
- * @param start
- * the start of the region.
- * @param end
- * the end of the region.
- *
- * @return the matcher itself.
- */
- private Matcher reset(CharSequence input, int start, int end) {
- if (input == null) {
- throw new IllegalArgumentException("input == null");
- }
-
- if (start < 0 || end < 0 || start > input.length() || end > input.length() || start > end) {
- throw new IndexOutOfBoundsException();
- }
-
- this.input = input.toString();
- this.regionStart = start;
- this.regionEnd = end;
- resetForInput();
-
- matchFound = false;
- appendPos = 0;
-
- return this;
- }
-
- /**
- * Sets a new pattern for the {@code Matcher}. Results of a previous find
- * get lost. The next attempt to find an occurrence of the {@link Pattern}
- * in the string will start at the beginning of the input.
- *
- * @param pattern
- * the new {@code Pattern}.
- *
- * @return the {@code Matcher} itself.
- */
- public Matcher usePattern(Pattern pattern) {
- if (pattern == null) {
- throw new IllegalArgumentException("pattern == null");
- }
-
- this.pattern = pattern;
-
- synchronized (this) {
- if (address != 0) {
- closeImpl(address);
- address = 0; // In case openImpl throws.
- }
- address = openImpl(pattern.address);
- }
-
- if (input != null) {
- resetForInput();
- }
-
- matchOffsets = new int[(groupCount() + 1) * 2];
- matchFound = false;
- return this;
- }
-
- private void resetForInput() {
- synchronized (this) {
- setInputImpl(address, input, regionStart, regionEnd);
- useAnchoringBoundsImpl(address, anchoringBounds);
- useTransparentBoundsImpl(address, transparentBounds);
- }
- }
-
- /**
- * Resets this matcher and sets a region. Only characters inside the region
- * are considered for a match.
- *
- * @param start
- * the first character of the region.
- * @param end
- * the first character after the end of the region.
- * @return the {@code Matcher} itself.
- */
- public Matcher region(int start, int end) {
- return reset(input, start, end);
- }
-
- /**
- * Appends the (unmatched) remainder of the input to the given
- * {@link StringBuffer}. The method can be used in conjunction with
- * {@link #find()} and {@link #appendReplacement(StringBuffer, String)} to
- * walk through the input and replace all matches of the {@code Pattern}
- * with something else.
- *
- * @return the {@code StringBuffer}.
- * @throws IllegalStateException
- * if no successful match has been made.
- */
- public StringBuffer appendTail(StringBuffer buffer) {
- if (appendPos < regionEnd) {
- buffer.append(input.substring(appendPos, regionEnd));
- }
- return buffer;
- }
-
- /**
- * Replaces the first occurrence of this matcher's pattern in the input with
- * a given string.
- *
- * @param replacement
- * the replacement text.
- * @return the modified input string.
- */
- public String replaceFirst(String replacement) {
- reset();
- StringBuffer buffer = new StringBuffer(input.length());
- if (find()) {
- appendReplacement(buffer, replacement);
- }
- return appendTail(buffer).toString();
- }
-
- /**
- * Replaces all occurrences of this matcher's pattern in the input with a
- * given string.
- *
- * @param replacement
- * the replacement text.
- * @return the modified input string.
- */
- public String replaceAll(String replacement) {
- reset();
- StringBuffer buffer = new StringBuffer(input.length());
- while (find()) {
- appendReplacement(buffer, replacement);
- }
- return appendTail(buffer).toString();
- }
-
- /**
- * Returns the {@link Pattern} instance used inside this matcher.
- */
- public Pattern pattern() {
- return pattern;
- }
-
- /**
- * Returns true if there is another match in the input, starting
- * from the given position. The region is ignored.
- *
- * @throws IndexOutOfBoundsException if {@code start < 0 || start > input.length()}
- */
- public boolean find(int start) {
- if (start < 0 || start > input.length()) {
- throw new IndexOutOfBoundsException("start=" + start + "; length=" + input.length());
- }
-
- synchronized (this) {
- matchFound = findImpl(address, input, start, matchOffsets);
- }
- return matchFound;
- }
-
- /**
- * Moves to the next occurrence of the pattern in the input. If a
- * previous match was successful, the method continues the search from the
- * first character following that match in the input. Otherwise it searches
- * either from the region start (if one has been set), or from position 0.
- *
- * @return true if (and only if) a match has been found.
- */
- public boolean find() {
- synchronized (this) {
- matchFound = findNextImpl(address, input, matchOffsets);
- }
- return matchFound;
- }
-
- /**
- * Tries to match the {@link Pattern}, starting from the beginning of the
- * region (or the beginning of the input, if no region has been set).
- * Doesn't require the {@code Pattern} to match against the whole region.
- *
- * @return true if (and only if) the {@code Pattern} matches.
- */
- public boolean lookingAt() {
- synchronized (this) {
- matchFound = lookingAtImpl(address, input, matchOffsets);
- }
- return matchFound;
- }
-
- /**
- * Tries to match the {@link Pattern} against the entire region (or the
- * entire input, if no region has been set).
- *
- * @return true if (and only if) the {@code Pattern} matches the entire
- * region.
- */
- public boolean matches() {
- synchronized (this) {
- matchFound = matchesImpl(address, input, matchOffsets);
- }
- return matchFound;
- }
-
- /**
- * Returns a replacement string for the given one that has all backslashes
- * and dollar signs escaped.
- */
- public static String quoteReplacement(String s) {
- StringBuilder result = new StringBuilder(s.length());
- for (int i = 0; i < s.length(); i++) {
- char c = s.charAt(i);
- if (c == '\\' || c == '$') {
- result.append('\\');
- }
- result.append(c);
- }
- return result.toString();
- }
-
- /**
- * Converts the current match into a separate {@link MatchResult} instance
- * that is independent from this matcher. The new object is unaffected when
- * the state of this matcher changes.
- *
- * @throws IllegalStateException
- * if no successful match has been made.
- */
- public MatchResult toMatchResult() {
- ensureMatch();
- return new MatchResultImpl(input, matchOffsets);
- }
-
- /**
- * Determines whether this matcher has anchoring bounds enabled or not. When
- * anchoring bounds are enabled, the start and end of the input match the
- * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
- * by default.
- *
- * @return the {@code Matcher} itself.
- */
- public Matcher useAnchoringBounds(boolean value) {
- synchronized (this) {
- anchoringBounds = value;
- useAnchoringBoundsImpl(address, value);
- }
- return this;
- }
-
- /**
- * Returns true if this matcher has anchoring bounds enabled. When
- * anchoring bounds are enabled, the start and end of the input match the
- * '^' and '$' meta-characters, otherwise not. Anchoring bounds are enabled
- * by default.
- */
- public boolean hasAnchoringBounds() {
- return anchoringBounds;
- }
-
- /**
- * Determines whether this matcher has transparent bounds enabled or not.
- * When transparent bounds are enabled, the parts of the input outside the
- * region are subject to lookahead and lookbehind, otherwise they are not.
- * Transparent bounds are disabled by default.
- *
- * @return the {@code Matcher} itself.
- */
- public Matcher useTransparentBounds(boolean value) {
- synchronized (this) {
- transparentBounds = value;
- useTransparentBoundsImpl(address, value);
- }
- return this;
- }
-
- /**
- * Makes sure that a successful match has been made. Is invoked internally
- * from various places in the class.
- *
- * @throws IllegalStateException
- * if no successful match has been made.
- */
- private void ensureMatch() {
- if (!matchFound) {
- throw new IllegalStateException("No successful match so far");
- }
- }
-
- /**
- * Returns true if this matcher has transparent bounds enabled. When
- * transparent bounds are enabled, the parts of the input outside the region
- * are subject to lookahead and lookbehind, otherwise they are not.
- * Transparent bounds are disabled by default.
- */
- public boolean hasTransparentBounds() {
- return transparentBounds;
- }
-
- /**
- * Returns this matcher's region start, that is, the index of the first character that is
- * considered for a match.
- */
- public int regionStart() {
- return regionStart;
- }
-
- /**
- * Returns this matcher's region end, that is, the index of the first character that is
- * not considered for a match.
- */
- public int regionEnd() {
- return regionEnd;
- }
-
- /**
- * Returns true if the most recent match succeeded and additional input could cause
- * it to fail. If this method returns false and a match was found, then more input
- * might change the match but the match won't be lost. If a match was not found,
- * then requireEnd has no meaning.
- */
- public boolean requireEnd() {
- synchronized (this) {
- return requireEndImpl(address);
- }
- }
-
- /**
- * Returns true if the most recent matching operation attempted to access
- * additional text beyond the available input, meaning that additional input
- * could change the results of the match.
- */
- public boolean hitEnd() {
- synchronized (this) {
- return hitEndImpl(address);
- }
- }
-
- @Override protected void finalize() throws Throwable {
- try {
- synchronized (this) {
- closeImpl(address);
- }
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Returns a string representing this {@code Matcher}.
- * The format of this string is unspecified.
- */
- @Override public String toString() {
- return getClass().getName() + "[pattern=" + pattern() +
- " region=" + regionStart() + "," + regionEnd() +
- " lastmatch=" + (matchFound ? group() : "") + "]";
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws IllegalStateException if no successful match has been made.
- */
- public int end() {
- return end(0);
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws IllegalStateException if no successful match has been made.
- */
- public int end(int group) {
- ensureMatch();
- return matchOffsets[(group * 2) + 1];
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws IllegalStateException if no successful match has been made.
- */
- public String group() {
- return group(0);
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws IllegalStateException if no successful match has been made.
- */
- public String group(int group) {
- ensureMatch();
- int from = matchOffsets[group * 2];
- int to = matchOffsets[(group * 2) + 1];
- if (from == -1 || to == -1) {
- return null;
- } else {
- return input.substring(from, to);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public int groupCount() {
- synchronized (this) {
- return groupCountImpl(address);
- }
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws IllegalStateException if no successful match has been made.
- */
- public int start() {
- return start(0);
- }
-
- /**
- * {@inheritDoc}
- *
- * @throws IllegalStateException if no successful match has been made.
- */
- public int start(int group) throws IllegalStateException {
- ensureMatch();
- return matchOffsets[group * 2];
- }
-
- private static native void closeImpl(long addr);
- private static native boolean findImpl(long addr, String s, int startIndex, int[] offsets);
- private static native boolean findNextImpl(long addr, String s, int[] offsets);
- private static native int groupCountImpl(long addr);
- private static native boolean hitEndImpl(long addr);
- private static native boolean lookingAtImpl(long addr, String s, int[] offsets);
- private static native boolean matchesImpl(long addr, String s, int[] offsets);
- private static native long openImpl(long patternAddr);
- private static native boolean requireEndImpl(long addr);
- private static native void setInputImpl(long addr, String s, int start, int end);
- private static native void useAnchoringBoundsImpl(long addr, boolean value);
- private static native void useTransparentBoundsImpl(long addr, boolean value);
-}
diff --git a/luni/src/main/java/java/util/regex/Pattern.java b/luni/src/main/java/java/util/regex/Pattern.java
deleted file mode 100644
index 8f3fb12..0000000
--- a/luni/src/main/java/java/util/regex/Pattern.java
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.regex;
-
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.Serializable;
-
-/**
- * Patterns are compiled regular expressions. In many cases, convenience methods such as
- * {@link String#matches String.matches}, {@link String#replaceAll String.replaceAll} and
- * {@link String#split String.split} will be preferable, but if you need to do a lot of work
- * with the same regular expression, it may be more efficient to compile it once and reuse it.
- * The {@code Pattern} class and its companion, {@link Matcher}, also offer more functionality
- * than the small amount exposed by {@code String}.
- *
- * <pre>
- * // String convenience methods:
- * boolean sawFailures = s.matches("Failures: \\d+");
- * String farewell = s.replaceAll("Hello, (\\S+)", "Goodbye, $1");
- * String[] fields = s.split(":");
- *
- * // Direct use of Pattern:
- * Pattern p = Pattern.compile("Hello, (\\S+)");
- * Matcher m = p.matcher(inputString);
- * while (m.find()) { // Find each match in turn; String can't do this.
- * String name = m.group(1); // Access a submatch group; String can't do this.
- * }
- * </pre>
- *
- * <h3>Regular expression syntax</h3>
- * <span class="datatable">
- * <style type="text/css">
- * .datatable td { padding-right: 20px; }
- * </style>
- *
- * <p>Java supports a subset of Perl 5 regular expression syntax. An important gotcha is that Java
- * has no regular expression literals, and uses plain old string literals instead. This means that
- * you need an extra level of escaping. For example, the regular expression {@code \s+} has to
- * be represented as the string {@code "\\s+"}.
- *
- * <h3>Escape sequences</h3>
- * <p><table>
- * <tr> <td> \ </td> <td>Quote the following metacharacter (so {@code \.} matches a literal {@code .}).</td> </tr>
- * <tr> <td> \Q </td> <td>Quote all following metacharacters until {@code \E}.</td> </tr>
- * <tr> <td> \E </td> <td>Stop quoting metacharacters (started by {@code \Q}).</td> </tr>
- * <tr> <td> \\ </td> <td>A literal backslash.</td> </tr>
- * <tr> <td> \u<i>hhhh</i> </td> <td>The Unicode character U+hhhh (in hex).</td> </tr>
- * <tr> <td> \x<i>hh</i> </td> <td>The Unicode character U+00hh (in hex).</td> </tr>
- * <tr> <td> \c<i>x</i> </td> <td>The ASCII control character ^x (so {@code \cH} would be ^H, U+0008).</td> </tr>
- *
- * <tr> <td> \a </td> <td>The ASCII bell character (U+0007).</td> </tr>
- * <tr> <td> \e </td> <td>The ASCII ESC character (U+001b).</td> </tr>
- * <tr> <td> \f </td> <td>The ASCII form feed character (U+000c).</td> </tr>
- * <tr> <td> \n </td> <td>The ASCII newline character (U+000a).</td> </tr>
- * <tr> <td> \r </td> <td>The ASCII carriage return character (U+000d).</td> </tr>
- * <tr> <td> \t </td> <td>The ASCII tab character (U+0009).</td> </tr>
- * </table>
- *
- * <h3>Character classes</h3>
- * <p>It's possible to construct arbitrary character classes using set operations:
- * <table>
- * <tr> <td> [abc] </td> <td>Any one of {@code a}, {@code b}, or {@code c}. (Enumeration.)</td> </tr>
- * <tr> <td> [a-c] </td> <td>Any one of {@code a}, {@code b}, or {@code c}. (Range.)</td> </tr>
- * <tr> <td> [^abc] </td> <td>Any character <i>except</i> {@code a}, {@code b}, or {@code c}. (Negation.)</td> </tr>
- * <tr> <td> [[a-f][0-9]] </td> <td>Any character in either range. (Union.)</td> </tr>
- * <tr> <td> [[a-z]&&[jkl]] </td> <td>Any character in both ranges. (Intersection.)</td> </tr>
- * </table>
- * <p>Most of the time, the built-in character classes are more useful:
- * <table>
- * <tr> <td> \d </td> <td>Any digit character (see note below).</td> </tr>
- * <tr> <td> \D </td> <td>Any non-digit character (see note below).</td> </tr>
- * <tr> <td> \s </td> <td>Any whitespace character (see note below).</td> </tr>
- * <tr> <td> \S </td> <td>Any non-whitespace character (see note below).</td> </tr>
- * <tr> <td> \w </td> <td>Any word character (see note below).</td> </tr>
- * <tr> <td> \W </td> <td>Any non-word character (see note below).</td> </tr>
- * <tr> <td> \p{<i>NAME</i>} </td> <td> Any character in the class with the given <i>NAME</i>. </td> </tr>
- * <tr> <td> \P{<i>NAME</i>} </td> <td> Any character <i>not</i> in the named class. </td> </tr>
- * </table>
- * <p>Note that these built-in classes don't just cover the traditional ASCII range. For example,
- * <code>\w</code> is equivalent to the character class <code>[\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}]</code>.
- * For more details see <a href="http://www.unicode.org/reports/tr18/#Compatibility_Properties">Unicode TR-18</a>,
- * and bear in mind that the set of characters in each class can vary between Unicode releases.
- * If you actually want to match only ASCII characters, specify the explicit characters you want;
- * if you mean 0-9 use <code>[0-9]</code> rather than <code>\d</code>, which would also include
- * Gurmukhi digits and so forth.
- * <p>There are also a variety of named classes:
- * <ul>
- * <li><a href="../../lang/Character.html#unicode_categories">Unicode category names</a>,
- * prefixed by {@code Is}. For example {@code \p{IsLu}} for all uppercase letters.
- * <li>POSIX class names. These are 'Alnum', 'Alpha', 'ASCII', 'Blank', 'Cntrl', 'Digit',
- * 'Graph', 'Lower', 'Print', 'Punct', 'Upper', 'XDigit'.
- * <li>Unicode block names, as accepted as input to {@link java.lang.Character.UnicodeBlock#forName},
- * prefixed by {@code In}. For example {@code \p{InHebrew}} for all characters in the Hebrew block.
- * <li>Character method names. These are all non-deprecated methods from {@link java.lang.Character}
- * whose name starts with {@code is}, but with the {@code is} replaced by {@code java}.
- * For example, {@code \p{javaLowerCase}}.
- * </ul>
- *
- * <h3>Quantifiers</h3>
- * <p>Quantifiers match some number of instances of the preceding regular expression.
- * <table>
- * <tr> <td> * </td> <td>Zero or more.</td> </tr>
- * <tr> <td> ? </td> <td>Zero or one.</td> </tr>
- * <tr> <td> + </td> <td>One or more.</td> </tr>
- * <tr> <td> {<i>n</i>} </td> <td>Exactly <i>n</i>.</td> </tr>
- * <tr> <td> {<i>n,</i>} </td> <td>At least <i>n</i>.</td> </tr>
- * <tr> <td> {<i>n</i>,<i>m</i>} </td> <td>At least <i>n</i> but not more than <i>m</i>.</td> </tr>
- * </table>
- * <p>Quantifiers are "greedy" by default, meaning that they will match the longest possible input
- * sequence. There are also non-greedy quantifiers that match the shortest possible input sequence.
- * They're same as the greedy ones but with a trailing {@code ?}:
- * <table>
- * <tr> <td> *? </td> <td>Zero or more (non-greedy).</td> </tr>
- * <tr> <td> ?? </td> <td>Zero or one (non-greedy).</td> </tr>
- * <tr> <td> +? </td> <td>One or more (non-greedy).</td> </tr>
- * <tr> <td> {<i>n</i>}? </td> <td>Exactly <i>n</i> (non-greedy).</td> </tr>
- * <tr> <td> {<i>n,</i>}? </td> <td>At least <i>n</i> (non-greedy).</td> </tr>
- * <tr> <td> {<i>n</i>,<i>m</i>}? </td> <td>At least <i>n</i> but not more than <i>m</i> (non-greedy).</td> </tr>
- * </table>
- * <p>Quantifiers allow backtracking by default. There are also possessive quantifiers to prevent
- * backtracking. They're same as the greedy ones but with a trailing {@code +}:
- * <table>
- * <tr> <td> *+ </td> <td>Zero or more (possessive).</td> </tr>
- * <tr> <td> ?+ </td> <td>Zero or one (possessive).</td> </tr>
- * <tr> <td> ++ </td> <td>One or more (possessive).</td> </tr>
- * <tr> <td> {<i>n</i>}+ </td> <td>Exactly <i>n</i> (possessive).</td> </tr>
- * <tr> <td> {<i>n,</i>}+ </td> <td>At least <i>n</i> (possessive).</td> </tr>
- * <tr> <td> {<i>n</i>,<i>m</i>}+ </td> <td>At least <i>n</i> but not more than <i>m</i> (possessive).</td> </tr>
- * </table>
- *
- * <h3>Zero-width assertions</h3>
- * <p><table>
- * <tr> <td> ^ </td> <td>At beginning of line.</td> </tr>
- * <tr> <td> $ </td> <td>At end of line.</td> </tr>
- * <tr> <td> \A </td> <td>At beginning of input.</td> </tr>
- * <tr> <td> \b </td> <td>At word boundary.</td> </tr>
- * <tr> <td> \B </td> <td>At non-word boundary.</td> </tr>
- * <tr> <td> \G </td> <td>At end of previous match.</td> </tr>
- * <tr> <td> \z </td> <td>At end of input.</td> </tr>
- * <tr> <td> \Z </td> <td>At end of input, or before newline at end.</td> </tr>
- * </table>
- *
- * <h3>Look-around assertions</h3>
- * <p>Look-around assertions assert that the subpattern does (positive) or doesn't (negative) match
- * after (look-ahead) or before (look-behind) the current position, without including the matched
- * text in the containing match. The maximum length of possible matches for look-behind patterns
- * must not be unbounded.
- * <p><table>
- * <tr> <td> (?=<i>a</i>) </td> <td>Zero-width positive look-ahead.</td> </tr>
- * <tr> <td> (?!<i>a</i>) </td> <td>Zero-width negative look-ahead.</td> </tr>
- * <tr> <td> (?<=<i>a</i>) </td> <td>Zero-width positive look-behind.</td> </tr>
- * <tr> <td> (?<!<i>a</i>) </td> <td>Zero-width negative look-behind.</td> </tr>
- * </table>
- *
- * <h3>Groups</h3>
- *
- * <p><table>
- * <tr> <td> (<i>a</i>) </td> <td>A capturing group.</td> </tr>
- * <tr> <td> (?:<i>a</i>) </td> <td>A non-capturing group.</td> </tr>
- * <tr> <td> (?><i>a</i>) </td> <td>An independent non-capturing group. (The first match of the subgroup is the only match tried.)</td> </tr>
- * <tr> <td> \<i>n</i> </td> <td>The text already matched by capturing group <i>n</i>.</td> </tr>
- * </table>
- * <p>See {@link Matcher#group} for details of how capturing groups are numbered and accessed.
- *
- * <h3>Operators</h3>
- * <p><table>
- * <tr> <td> <i>ab</i> </td> <td>Expression <i>a</i> followed by expression <i>b</i>.</td> </tr>
- * <tr> <td> <i>a</i>|<i>b</i> </td> <td>Either expression <i>a</i> or expression <i>b</i>.</td> </tr>
- * </table>
- *
- * <a name="flags"></a><h3>Flags</h3>
- * <p><table>
- * <tr> <td> (?dimsux-dimsux:<i>a</i>) </td> <td>Evaluates the expression <i>a</i> with the given flags enabled/disabled.</td> </tr>
- * <tr> <td> (?dimsux-dimsux) </td> <td>Evaluates the rest of the pattern with the given flags enabled/disabled.</td> </tr>
- * </table>
- *
- * <p>The flags are:
- * <table>
- * <tr><td>{@code i}</td> <td>{@link #CASE_INSENSITIVE}</td> <td>case insensitive matching</td></tr>
- * <tr><td>{@code d}</td> <td>{@link #UNIX_LINES}</td> <td>only accept {@code '\n'} as a line terminator</td></tr>
- * <tr><td>{@code m}</td> <td>{@link #MULTILINE}</td> <td>allow {@code ^} and {@code $} to match beginning/end of any line</td></tr>
- * <tr><td>{@code s}</td> <td>{@link #DOTALL}</td> <td>allow {@code .} to match {@code '\n'} ("s" for "single line")</td></tr>
- * <tr><td>{@code u}</td> <td>{@link #UNICODE_CASE}</td> <td>enable Unicode case folding</td></tr>
- * <tr><td>{@code x}</td> <td>{@link #COMMENTS}</td> <td>allow whitespace and comments</td></tr>
- * </table>
- * <p>Either set of flags may be empty. For example, {@code (?i-m)} would turn on case-insensitivity
- * and turn off multiline mode, {@code (?i)} would just turn on case-insensitivity,
- * and {@code (?-m)} would just turn off multiline mode.
- * <p>Note that on Android, {@code UNICODE_CASE} is always on: case-insensitive matching will
- * always be Unicode-aware.
- * <p>There are two other flags not settable via this mechanism: {@link #CANON_EQ} and
- * {@link #LITERAL}. Attempts to use {@link #CANON_EQ} on Android will throw an exception.
- * </span>
- *
- * <h3>Implementation notes</h3>
- *
- * <p>The regular expression implementation used in Android is provided by
- * <a href="http://www.icu-project.org">ICU</a>. The notation for the regular
- * expressions is mostly a superset of those used in other Java language
- * implementations. This means that existing applications will normally work as
- * expected, but in rare cases Android may accept a regular expression that is
- * not accepted by other implementations.
- *
- * <p>In some cases, Android will recognize that a regular expression is a simple
- * special case that can be handled more efficiently. This is true of both the convenience methods
- * in {@code String} and the methods in {@code Pattern}.
- *
- * @see Matcher
- */
-public final class Pattern implements Serializable {
-
- private static final long serialVersionUID = 5073258162644648461L;
-
- /**
- * This constant specifies that a pattern matches Unix line endings ('\n')
- * only against the '.', '^', and '$' meta characters. Corresponds to {@code (?d)}.
- */
- public static final int UNIX_LINES = 0x01;
-
- /**
- * This constant specifies that a {@code Pattern} is matched
- * case-insensitively. That is, the patterns "a+" and "A+" would both match
- * the string "aAaAaA". See {@link #UNICODE_CASE}. Corresponds to {@code (?i)}.
- */
- public static final int CASE_INSENSITIVE = 0x02;
-
- /**
- * This constant specifies that a {@code Pattern} may contain whitespace or
- * comments. Otherwise comments and whitespace are taken as literal
- * characters. Corresponds to {@code (?x)}.
- */
- public static final int COMMENTS = 0x04;
-
- /**
- * This constant specifies that the meta characters '^' and '$' match only
- * the beginning and end of an input line, respectively. Normally, they
- * match the beginning and the end of the complete input. Corresponds to {@code (?m)}.
- */
- public static final int MULTILINE = 0x08;
-
- /**
- * This constant specifies that the whole {@code Pattern} is to be taken
- * literally, that is, all meta characters lose their meanings.
- */
- public static final int LITERAL = 0x10;
-
- /**
- * This constant specifies that the '.' meta character matches arbitrary
- * characters, including line endings, which is normally not the case.
- * Corresponds to {@code (?s)}.
- */
- public static final int DOTALL = 0x20;
-
- /**
- * This constant specifies that a {@code Pattern} that uses case-insensitive matching
- * will use Unicode case folding. On Android, {@code UNICODE_CASE} is always on:
- * case-insensitive matching will always be Unicode-aware. If your code is intended to
- * be portable and uses case-insensitive matching on non-ASCII characters, you should
- * use this flag. Corresponds to {@code (?u)}.
- */
- public static final int UNICODE_CASE = 0x40;
-
- /**
- * This constant specifies that a character in a {@code Pattern} and a
- * character in the input string only match if they are canonically
- * equivalent. It is (currently) not supported in Android.
- */
- public static final int CANON_EQ = 0x80;
-
- private final String pattern;
- private final int flags;
-
- transient long address;
-
- /**
- * Returns a {@link Matcher} for this pattern applied to the given {@code input}.
- * The {@code Matcher} can be used to match the {@code Pattern} against the
- * whole input, find occurrences of the {@code Pattern} in the input, or
- * replace parts of the input.
- */
- public Matcher matcher(CharSequence input) {
- return new Matcher(this, input);
- }
-
- /**
- * Splits the given {@code input} at occurrences of this pattern.
- *
- * <p>If this pattern does not occur in the input, the result is an
- * array containing the input (converted from a {@code CharSequence} to
- * a {@code String}).
- *
- * <p>Otherwise, the {@code limit} parameter controls the contents of the
- * returned array as described below.
- *
- * @param limit
- * Determines the maximum number of entries in the resulting
- * array, and the treatment of trailing empty strings.
- * <ul>
- * <li>For n > 0, the resulting array contains at most n
- * entries. If this is fewer than the number of matches, the
- * final entry will contain all remaining input.
- * <li>For n < 0, the length of the resulting array is
- * exactly the number of occurrences of the {@code Pattern}
- * plus one for the text after the final separator.
- * All entries are included.
- * <li>For n == 0, the result is as for n < 0, except
- * trailing empty strings will not be returned. (Note that
- * the case where the input is itself an empty string is
- * special, as described above, and the limit parameter does
- * not apply there.)
- * </ul>
- */
- public String[] split(CharSequence input, int limit) {
- return Splitter.split(this, pattern, input.toString(), limit);
- }
-
- /**
- * Equivalent to {@code split(input, 0)}.
- */
- public String[] split(CharSequence input) {
- return split(input, 0);
- }
-
- /**
- * Returns the regular expression supplied to {@code compile}.
- */
- public String pattern() {
- return pattern;
- }
-
- @Override
- public String toString() {
- return pattern;
- }
-
- /**
- * Returns the flags supplied to {@code compile}.
- */
- public int flags() {
- return flags;
- }
-
- /**
- * Returns a compiled form of the given {@code regularExpression}, as modified by the
- * given {@code flags}. See the <a href="#flags">flags overview</a> for more on flags.
- *
- * @throws PatternSyntaxException if the regular expression is syntactically incorrect.
- *
- * @see #CANON_EQ
- * @see #CASE_INSENSITIVE
- * @see #COMMENTS
- * @see #DOTALL
- * @see #LITERAL
- * @see #MULTILINE
- * @see #UNICODE_CASE
- * @see #UNIX_LINES
- */
- public static Pattern compile(String regularExpression, int flags) throws PatternSyntaxException {
- return new Pattern(regularExpression, flags);
- }
-
- /**
- * Equivalent to {@code Pattern.compile(pattern, 0)}.
- */
- public static Pattern compile(String pattern) {
- return new Pattern(pattern, 0);
- }
-
- private Pattern(String pattern, int flags) throws PatternSyntaxException {
- if ((flags & CANON_EQ) != 0) {
- throw new UnsupportedOperationException("CANON_EQ flag not supported");
- }
- int supportedFlags = CASE_INSENSITIVE | COMMENTS | DOTALL | LITERAL | MULTILINE | UNICODE_CASE | UNIX_LINES;
- if ((flags & ~supportedFlags) != 0) {
- throw new IllegalArgumentException("Unsupported flags: " + (flags & ~supportedFlags));
- }
- this.pattern = pattern;
- this.flags = flags;
- compile();
- }
-
- private void compile() throws PatternSyntaxException {
- if (pattern == null) {
- throw new NullPointerException("pattern == null");
- }
-
- String icuPattern = pattern;
- if ((flags & LITERAL) != 0) {
- icuPattern = quote(pattern);
- }
-
- // These are the flags natively supported by ICU.
- // They even have the same value in native code.
- int icuFlags = flags & (CASE_INSENSITIVE | COMMENTS | MULTILINE | DOTALL | UNIX_LINES);
-
- address = compileImpl(icuPattern, icuFlags);
- }
-
- /**
- * Tests whether the given {@code regularExpression} matches the given {@code input}.
- * Equivalent to {@code Pattern.compile(regularExpression).matcher(input).matches()}.
- * If the same regular expression is to be used for multiple operations, it may be more
- * efficient to reuse a compiled {@code Pattern}.
- *
- * @see Pattern#compile(java.lang.String, int)
- * @see Matcher#matches()
- */
- public static boolean matches(String regularExpression, CharSequence input) {
- return new Matcher(new Pattern(regularExpression, 0), input).matches();
- }
-
- /**
- * Quotes the given {@code string} using "\Q" and "\E", so that all
- * meta-characters lose their special meaning. This method correctly
- * escapes embedded instances of "\Q" or "\E". If the entire result
- * is to be passed verbatim to {@link #compile}, it's usually clearer
- * to use the {@link #LITERAL} flag instead.
- */
- public static String quote(String string) {
- StringBuilder sb = new StringBuilder();
- sb.append("\\Q");
- int apos = 0;
- int k;
- while ((k = string.indexOf("\\E", apos)) >= 0) {
- sb.append(string.substring(apos, k + 2)).append("\\\\E\\Q");
- apos = k + 2;
- }
- return sb.append(string.substring(apos)).append("\\E").toString();
- }
-
- @Override protected void finalize() throws Throwable {
- try {
- closeImpl(address);
- } finally {
- super.finalize();
- }
- }
-
- private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
- s.defaultReadObject();
- compile();
- }
-
- private static native void closeImpl(long addr);
- private static native long compileImpl(String regex, int flags);
-}
diff --git a/luni/src/main/java/java/util/regex/PatternSyntaxException.java b/luni/src/main/java/java/util/regex/PatternSyntaxException.java
deleted file mode 100644
index 0c1de4b..0000000
--- a/luni/src/main/java/java/util/regex/PatternSyntaxException.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.regex;
-
-import java.util.Arrays;
-
-/**
- * Encapsulates a syntax error that occurred during the compilation of a
- * {@link Pattern}. Might include a detailed description, the original regular
- * expression, and the index at which the error occurred.
- *
- * @see Pattern#compile(String)
- * @see Pattern#compile(java.lang.String,int)
- */
-public class PatternSyntaxException extends IllegalArgumentException {
-
- private static final long serialVersionUID = -3864639126226059218L;
-
- /**
- * Holds the description of the syntax error, or null if the description is
- * not known.
- */
- private String desc;
-
- /**
- * Holds the syntactically incorrect regular expression, or null if the
- * regular expression is not known.
- */
- private String pattern;
-
- /**
- * Holds the index around which the error occured, or -1, in case it is
- * unknown.
- */
- private int index = -1;
-
- /**
- * Creates a new PatternSyntaxException for a given message, pattern, and
- * error index.
- *
- * @param description
- * the description of the syntax error, or {@code null} if the
- * description is not known.
- * @param pattern
- * the syntactically incorrect regular expression, or
- * {@code null} if the regular expression is not known.
- * @param index
- * the character index around which the error occurred, or -1 if
- * the index is not known.
- */
- public PatternSyntaxException(String description, String pattern, int index) {
- this.desc = description;
- this.pattern = pattern;
- this.index = index;
- }
-
- /**
- * Returns the syntactically incorrect regular expression.
- *
- * @return the regular expression.
- *
- */
- public String getPattern() {
- return pattern;
- }
-
- /**
- * Returns a detailed error message for the exception. The message is
- * potentially multi-line, and it might include a detailed description, the
- * original regular expression, and the index at which the error occurred.
- *
- * @return the error message.
- */
- @Override
- public String getMessage() {
- StringBuilder sb = new StringBuilder();
- if (desc != null) {
- sb.append(desc);
- }
-
- if (index >= 0) {
- if (desc != null) {
- sb.append(' ');
- }
- sb.append("near index ");
- sb.append(index);
- sb.append(':');
- }
-
- if (pattern != null) {
- sb.append('\n');
- sb.append(pattern);
-
- if (index >= 0) {
- char[] spaces = new char[index];
- Arrays.fill(spaces, ' ');
- sb.append('\n');
- sb.append(spaces);
- sb.append('^');
- }
- }
-
- return sb.toString();
- }
-
- /**
- * Returns the description of the syntax error, or {@code null} if the
- * description is not known.
- *
- * @return the description.
- */
- public String getDescription() {
- return desc;
- }
-
- /**
- * Returns the character index around which the error occurred, or -1 if the
- * index is not known.
- *
- * @return the index.
- *
- */
- public int getIndex() {
- return index;
- }
-}
diff --git a/luni/src/main/java/java/util/regex/Splitter.java b/luni/src/main/java/java/util/regex/Splitter.java
deleted file mode 100644
index a4cb52c..0000000
--- a/luni/src/main/java/java/util/regex/Splitter.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.util.regex;
-
-import java.util.ArrayList;
-import java.util.List;
-import libcore.util.EmptyArray;
-
-/**
- * Used to make {@code String.split} fast (and to help {@code Pattern.split} too).
- * @hide
- */
-public class Splitter {
- // The RI allows regular expressions beginning with ] or }, but that's probably a bug.
- private static final String METACHARACTERS = "\\?*+[](){}^$.|";
-
- private Splitter() {
- }
-
- /**
- * Returns a result equivalent to {@code s.split(separator, limit)} if it's able
- * to compute it more cheaply than ICU, or null if the caller should fall back to
- * using ICU.
- */
- public static String[] fastSplit(String re, String input, int limit) {
- // Can we do it cheaply?
- int len = re.length();
- if (len == 0) {
- return null;
- }
- char ch = re.charAt(0);
- if (len == 1 && METACHARACTERS.indexOf(ch) == -1) {
- // We're looking for a single non-metacharacter. Easy.
- } else if (len == 2 && ch == '\\') {
- // We're looking for a quoted character.
- // Quoted metacharacters are effectively single non-metacharacters.
- ch = re.charAt(1);
- if (METACHARACTERS.indexOf(ch) == -1) {
- return null;
- }
- } else {
- return null;
- }
-
- // We can do this cheaply...
-
- // Unlike Perl, which considers the result of splitting the empty string to be the empty
- // array, Java returns an array containing the empty string.
- if (input.isEmpty()) {
- return new String[] { "" };
- }
-
- // Count separators
- int separatorCount = 0;
- int begin = 0;
- int end;
- while (separatorCount + 1 != limit && (end = input.indexOf(ch, begin)) != -1) {
- ++separatorCount;
- begin = end + 1;
- }
- int lastPartEnd = input.length();
- if (limit == 0 && begin == lastPartEnd) {
- // Last part is empty for limit == 0, remove all trailing empty matches.
- if (separatorCount == lastPartEnd) {
- // Input contains only separators.
- return EmptyArray.STRING;
- }
- // Find the beginning of trailing separators.
- do {
- --begin;
- } while (input.charAt(begin - 1) == ch);
- // Reduce separatorCount and fix lastPartEnd.
- separatorCount -= input.length() - begin;
- lastPartEnd = begin;
- }
-
- // Collect the result parts.
- String[] result = new String[separatorCount + 1];
- begin = 0;
- for (int i = 0; i != separatorCount; ++i) {
- end = input.indexOf(ch, begin);
- result[i] = input.substring(begin, end);
- begin = end + 1;
- }
- // Add last part.
- result[separatorCount] = input.substring(begin, lastPartEnd);
- return result;
- }
-
- public static String[] split(Pattern pattern, String re, String input, int limit) {
- String[] fastResult = fastSplit(re, input, limit);
- if (fastResult != null) {
- return fastResult;
- }
-
- // Unlike Perl, which considers the result of splitting the empty string to be the empty
- // array, Java returns an array containing the empty string.
- if (input.isEmpty()) {
- return new String[] { "" };
- }
-
- // Collect text preceding each occurrence of the separator, while there's enough space.
- ArrayList<String> list = new ArrayList<String>();
- Matcher matcher = new Matcher(pattern, input);
- int begin = 0;
- while (list.size() + 1 != limit && matcher.find()) {
- list.add(input.substring(begin, matcher.start()));
- begin = matcher.end();
- }
- return finishSplit(list, input, begin, limit);
- }
-
- private static String[] finishSplit(List<String> list, String input, int begin, int limit) {
- // Add trailing text.
- if (begin < input.length()) {
- list.add(input.substring(begin));
- } else if (limit != 0) {
- list.add("");
- } else {
- // Remove all trailing empty matches in the limit == 0 case.
- int i = list.size() - 1;
- while (i >= 0 && list.get(i).isEmpty()) {
- list.remove(i);
- i--;
- }
- }
- // Convert to an array.
- return list.toArray(new String[list.size()]);
- }
-}