001/*
002 * Copyright (C) 2008 The Guava Authors
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
005 * in compliance with the License. You may obtain a copy of the License at
006 *
007 * http://www.apache.org/licenses/LICENSE-2.0
008 *
009 * Unless required by applicable law or agreed to in writing, software distributed under the License
010 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
011 * or implied. See the License for the specific language governing permissions and limitations under
012 * the License.
013 */
014
015package com.google.common.base;
016
017import static com.google.common.base.Preconditions.checkArgument;
018import static com.google.common.base.Preconditions.checkNotNull;
019import static com.google.common.base.Preconditions.checkPositionIndex;
020
021import com.google.common.annotations.GwtCompatible;
022import com.google.common.annotations.GwtIncompatible;
023import com.google.common.annotations.VisibleForTesting;
024import com.google.errorprone.annotations.InlineMe;
025import com.google.errorprone.annotations.InlineMeValidationDisabled;
026import java.util.Arrays;
027import java.util.BitSet;
028
029/**
030 * Determines a true or false value for any Java {@code char} value, just as {@link Predicate} does
031 * for any {@link Object}. Also offers basic text processing methods based on this function.
032 * Implementations are strongly encouraged to be side-effect-free and immutable.
033 *
034 * <p>Throughout the documentation of this class, the phrase "matching character" is used to mean
035 * "any {@code char} value {@code c} for which {@code this.matches(c)} returns {@code true}".
036 *
037 * <p><b>Warning:</b> This class deals only with {@code char} values, that is, <a
038 * href="http://www.unicode.org/glossary/#BMP_character">BMP characters</a>. It does not understand
039 * <a href="http://www.unicode.org/glossary/#supplementary_code_point">supplementary Unicode code
040 * points</a> in the range {@code 0x10000} to {@code 0x10FFFF} which includes the majority of
041 * assigned characters, including important CJK characters and emoji.
042 *
043 * <p>Supplementary characters are <a
044 * href="https://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#supplementary">encoded
045 * into a {@code String} using surrogate pairs</a>, and a {@code CharMatcher} treats these just as
046 * two separate characters. {@link #countIn} counts each supplementary character as 2 {@code char}s.
047 *
048 * <p>For up-to-date Unicode character properties (digit, letter, etc.) and support for
049 * supplementary code points, use ICU4J UCharacter and UnicodeSet (freeze() after building). For
050 * basic text processing based on UnicodeSet use the ICU4J UnicodeSetSpanner.
051 *
052 * <p>Example usages:
053 *
054 * <pre>
055 *   String trimmed = {@link #whitespace() whitespace()}.{@link #trimFrom trimFrom}(userInput);
056 *   if ({@link #ascii() ascii()}.{@link #matchesAllOf matchesAllOf}(s)) { ... }</pre>
057 *
058 * <p>See the Guava User Guide article on <a
059 * href="https://github.com/google/guava/wiki/StringsExplained#charmatcher">{@code CharMatcher}
060 * </a>.
061 *
062 * @author Kevin Bourrillion
063 * @since 1.0
064 */
065@GwtCompatible(emulated = true)
066public abstract class CharMatcher implements Predicate<Character> {
067  /*
068   *           N777777777NO
069   *         N7777777777777N
070   *        M777777777777777N
071   *        $N877777777D77777M
072   *       N M77777777ONND777M
073   *       MN777777777NN  D777
074   *     N7ZN777777777NN ~M7778
075   *    N777777777777MMNN88777N
076   *    N777777777777MNZZZ7777O
077   *    DZN7777O77777777777777
078   *     N7OONND7777777D77777N
079   *      8$M++++?N???$77777$
080   *       M7++++N+M77777777N
081   *        N77O777777777777$                              M
082   *          DNNM$$$$777777N                              D
083   *         N$N:=N$777N7777M                             NZ
084   *        77Z::::N777777777                          ODZZZ
085   *       77N::::::N77777777M                         NNZZZ$
086   *     $777:::::::77777777MN                        ZM8ZZZZZ
087   *     777M::::::Z7777777Z77                        N++ZZZZNN
088   *    7777M:::::M7777777$777M                       $++IZZZZM
089   *   M777$:::::N777777$M7777M                       +++++ZZZDN
090   *     NN$::::::7777$$M777777N                      N+++ZZZZNZ
091   *       N::::::N:7$O:77777777                      N++++ZZZZN
092   *       M::::::::::::N77777777+                   +?+++++ZZZM
093   *       8::::::::::::D77777777M                    O+++++ZZ
094   *        ::::::::::::M777777777N                      O+?D
095   *        M:::::::::::M77777777778                     77=
096   *        D=::::::::::N7777777777N                    777
097   *       INN===::::::=77777777777N                  I777N
098   *      ?777N========N7777777777787M               N7777
099   *      77777$D======N77777777777N777N?         N777777
100   *     I77777$$$N7===M$$77777777$77777777$MMZ77777777N
101   *      $$$$$$$$$$$NIZN$$$$$$$$$M$$7777777777777777ON
102   *       M$$$$$$$$M    M$$$$$$$$N=N$$$$7777777$$$ND
103   *      O77Z$$$$$$$     M$$$$$$$$MNI==$DNNNNM=~N
104   *   7 :N MNN$$$$M$      $$$777$8      8D8I
105   *     NMM.:7O           777777778
106   *                       7777777MN
107   *                       M NO .7:
108   *                       M   :   M
109   *                            8
110   */
111
112  // Constant matcher factory methods
113
114  /**
115   * Matches any character.
116   *
117   * @since 19.0 (since 1.0 as constant {@code ANY})
118   */
119  public static CharMatcher any() {
120    return Any.INSTANCE;
121  }
122
123  /**
124   * Matches no characters.
125   *
126   * @since 19.0 (since 1.0 as constant {@code NONE})
127   */
128  public static CharMatcher none() {
129    return None.INSTANCE;
130  }
131
132  /**
133   * Determines whether a character is whitespace according to the latest Unicode standard, as
134   * illustrated <a
135   * href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bwhitespace%7D">here</a>.
136   * This is not the same definition used by other Java APIs. (See a <a
137   * href="https://docs.google.com/spreadsheets/d/1kq4ECwPjHX9B8QUCTPclgsDCXYaj7T-FlT4tB5q3ahk/edit">comparison
138   * of several definitions of "whitespace"</a>.)
139   *
140   * <p>All Unicode White_Space characters are on the BMP and thus supported by this API.
141   *
142   * <p><b>Note:</b> as the Unicode definition evolves, we will modify this matcher to keep it up to
143   * date.
144   *
145   * @since 19.0 (since 1.0 as constant {@code WHITESPACE})
146   */
147  public static CharMatcher whitespace() {
148    return Whitespace.INSTANCE;
149  }
150
151  /**
152   * Determines whether a character is a breaking whitespace (that is, a whitespace which can be
153   * interpreted as a break between words for formatting purposes). See {@link #whitespace()} for a
154   * discussion of that term.
155   *
156   * @since 19.0 (since 2.0 as constant {@code BREAKING_WHITESPACE})
157   */
158  public static CharMatcher breakingWhitespace() {
159    return BreakingWhitespace.INSTANCE;
160  }
161
162  /**
163   * Determines whether a character is ASCII, meaning that its code point is less than 128.
164   *
165   * @since 19.0 (since 1.0 as constant {@code ASCII})
166   */
167  public static CharMatcher ascii() {
168    return Ascii.INSTANCE;
169  }
170
171  /**
172   * Determines whether a character is a BMP digit according to <a
173   * href="http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7Bdigit%7D">Unicode</a>. If
174   * you only care to match ASCII digits, you can use {@code inRange('0', '9')}.
175   *
176   * @deprecated Many digits are supplementary characters; see the class documentation.
177   * @since 19.0 (since 1.0 as constant {@code DIGIT})
178   */
179  @Deprecated
180  public static CharMatcher digit() {
181    return Digit.INSTANCE;
182  }
183
184  /**
185   * Determines whether a character is a BMP digit according to {@linkplain Character#isDigit(char)
186   * Java's definition}. If you only care to match ASCII digits, you can use {@code inRange('0',
187   * '9')}.
188   *
189   * @deprecated Many digits are supplementary characters; see the class documentation.
190   * @since 19.0 (since 1.0 as constant {@code JAVA_DIGIT})
191   */
192  @Deprecated
193  public static CharMatcher javaDigit() {
194    return JavaDigit.INSTANCE;
195  }
196
197  /**
198   * Determines whether a character is a BMP letter according to {@linkplain
199   * Character#isLetter(char) Java's definition}. If you only care to match letters of the Latin
200   * alphabet, you can use {@code inRange('a', 'z').or(inRange('A', 'Z'))}.
201   *
202   * @deprecated Most letters are supplementary characters; see the class documentation.
203   * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER})
204   */
205  @Deprecated
206  public static CharMatcher javaLetter() {
207    return JavaLetter.INSTANCE;
208  }
209
210  /**
211   * Determines whether a character is a BMP letter or digit according to {@linkplain
212   * Character#isLetterOrDigit(char) Java's definition}.
213   *
214   * @deprecated Most letters and digits are supplementary characters; see the class documentation.
215   * @since 19.0 (since 1.0 as constant {@code JAVA_LETTER_OR_DIGIT}).
216   */
217  @Deprecated
218  public static CharMatcher javaLetterOrDigit() {
219    return JavaLetterOrDigit.INSTANCE;
220  }
221
222  /**
223   * Determines whether a BMP character is upper case according to {@linkplain
224   * Character#isUpperCase(char) Java's definition}.
225   *
226   * @deprecated Some uppercase characters are supplementary characters; see the class
227   *     documentation.
228   * @since 19.0 (since 1.0 as constant {@code JAVA_UPPER_CASE})
229   */
230  @Deprecated
231  public static CharMatcher javaUpperCase() {
232    return JavaUpperCase.INSTANCE;
233  }
234
235  /**
236   * Determines whether a BMP character is lower case according to {@linkplain
237   * Character#isLowerCase(char) Java's definition}.
238   *
239   * @deprecated Some lowercase characters are supplementary characters; see the class
240   *     documentation.
241   * @since 19.0 (since 1.0 as constant {@code JAVA_LOWER_CASE})
242   */
243  @Deprecated
244  public static CharMatcher javaLowerCase() {
245    return JavaLowerCase.INSTANCE;
246  }
247
248  /**
249   * Determines whether a character is an ISO control character as specified by {@link
250   * Character#isISOControl(char)}.
251   *
252   * <p>All ISO control codes are on the BMP and thus supported by this API.
253   *
254   * @since 19.0 (since 1.0 as constant {@code JAVA_ISO_CONTROL})
255   */
256  public static CharMatcher javaIsoControl() {
257    return JavaIsoControl.INSTANCE;
258  }
259
260  /**
261   * Determines whether a character is invisible; that is, if its Unicode category is any of
262   * SPACE_SEPARATOR, LINE_SEPARATOR, PARAGRAPH_SEPARATOR, CONTROL, FORMAT, SURROGATE, and
263   * PRIVATE_USE according to ICU4J.
264   *
265   * <p>See also the Unicode Default_Ignorable_Code_Point property (available via ICU).
266   *
267   * @deprecated Most invisible characters are supplementary characters; see the class
268   *     documentation.
269   * @since 19.0 (since 1.0 as constant {@code INVISIBLE})
270   */
271  @Deprecated
272  public static CharMatcher invisible() {
273    return Invisible.INSTANCE;
274  }
275
276  /**
277   * Determines whether a character is single-width (not double-width). When in doubt, this matcher
278   * errs on the side of returning {@code false} (that is, it tends to assume a character is
279   * double-width).
280   *
281   * <p><b>Note:</b> as the reference file evolves, we will modify this matcher to keep it up to
282   * date.
283   *
284   * <p>See also <a href="http://www.unicode.org/reports/tr11/">UAX #11 East Asian Width</a>.
285   *
286   * @deprecated Many such characters are supplementary characters; see the class documentation.
287   * @since 19.0 (since 1.0 as constant {@code SINGLE_WIDTH})
288   */
289  @Deprecated
290  public static CharMatcher singleWidth() {
291    return SingleWidth.INSTANCE;
292  }
293
294  // Static factories
295
296  /** Returns a {@code char} matcher that matches only one specified BMP character. */
297  public static CharMatcher is(char match) {
298    return new Is(match);
299  }
300
301  /**
302   * Returns a {@code char} matcher that matches any character except the BMP character specified.
303   *
304   * <p>To negate another {@code CharMatcher}, use {@link #negate()}.
305   */
306  public static CharMatcher isNot(char match) {
307    return new IsNot(match);
308  }
309
310  /**
311   * Returns a {@code char} matcher that matches any BMP character present in the given character
312   * sequence. Returns a bogus matcher if the sequence contains supplementary characters.
313   */
314  public static CharMatcher anyOf(CharSequence sequence) {
315    switch (sequence.length()) {
316      case 0:
317        return none();
318      case 1:
319        return is(sequence.charAt(0));
320      case 2:
321        return isEither(sequence.charAt(0), sequence.charAt(1));
322      default:
323        // TODO(lowasser): is it potentially worth just going ahead and building a precomputed
324        // matcher?
325        return new AnyOf(sequence);
326    }
327  }
328
329  /**
330   * Returns a {@code char} matcher that matches any BMP character not present in the given
331   * character sequence. Returns a bogus matcher if the sequence contains supplementary characters.
332   */
333  public static CharMatcher noneOf(CharSequence sequence) {
334    return anyOf(sequence).negate();
335  }
336
337  /**
338   * Returns a {@code char} matcher that matches any character in a given BMP range (both endpoints
339   * are inclusive). For example, to match any lowercase letter of the English alphabet, use {@code
340   * CharMatcher.inRange('a', 'z')}.
341   *
342   * @throws IllegalArgumentException if {@code endInclusive < startInclusive}
343   */
344  public static CharMatcher inRange(char startInclusive, char endInclusive) {
345    return new InRange(startInclusive, endInclusive);
346  }
347
348  /**
349   * Returns a matcher with identical behavior to the given {@link Character}-based predicate, but
350   * which operates on primitive {@code char} instances instead.
351   */
352  public static CharMatcher forPredicate(Predicate<? super Character> predicate) {
353    return predicate instanceof CharMatcher ? (CharMatcher) predicate : new ForPredicate(predicate);
354  }
355
356  // Constructors
357
358  /**
359   * Constructor for use by subclasses. When subclassing, you may want to override {@code
360   * toString()} to provide a useful description.
361   */
362  protected CharMatcher() {}
363
364  // Abstract methods
365
366  /** Determines a true or false value for the given character. */
367  public abstract boolean matches(char c);
368
369  // Non-static factories
370
371  /** Returns a matcher that matches any character not matched by this matcher. */
372  // This is not an override in java7, where Guava's Predicate does not extend the JDK's Predicate.
373  @SuppressWarnings("MissingOverride")
374  public CharMatcher negate() {
375    return new Negated(this);
376  }
377
378  /**
379   * Returns a matcher that matches any character matched by both this matcher and {@code other}.
380   */
381  public CharMatcher and(CharMatcher other) {
382    return new And(this, other);
383  }
384
385  /**
386   * Returns a matcher that matches any character matched by either this matcher or {@code other}.
387   */
388  public CharMatcher or(CharMatcher other) {
389    return new Or(this, other);
390  }
391
392  /**
393   * Returns a {@code char} matcher functionally equivalent to this one, but which may be faster to
394   * query than the original; your mileage may vary. Precomputation takes time and requires more
395   * memory, so it is only likely to be worthwhile if the precomputed matcher is queried very often.
396   *
397   * <p>This method has no effect (returns {@code this}) when called in GWT: it's unclear whether a
398   * precomputed matcher is faster, but it certainly would consume more memory (which doesn't seem
399   * like a worthwhile tradeoff in a browser).
400   */
401  public CharMatcher precomputed() {
402    return Platform.precomputeCharMatcher(this);
403  }
404
405  private static final int DISTINCT_CHARS = Character.MAX_VALUE - Character.MIN_VALUE + 1;
406
407  /**
408   * This is the actual implementation of {@link #precomputed}, but we bounce calls through a method
409   * on {@link Platform} so that we can have different behavior in GWT.
410   *
411   * <p>This implementation tries to be smart in a number of ways. It recognizes cases where the
412   * negation is cheaper to precompute than the matcher itself; it tries to build small hash tables
413   * for matchers that only match a few characters, and so on. In the worst-case scenario, it
414   * constructs an eight-kilobyte bit array and queries that. In many situations this produces a
415   * matcher which is faster to query than the original.
416   */
417  @GwtIncompatible // SmallCharMatcher
418  CharMatcher precomputedInternal() {
419    BitSet table = new BitSet();
420    setBits(table);
421    int totalCharacters = table.cardinality();
422    if (totalCharacters * 2 <= DISTINCT_CHARS) {
423      return precomputedPositive(totalCharacters, table, toString());
424    } else {
425      // TODO(lowasser): is it worth it to worry about the last character of large matchers?
426      table.flip(Character.MIN_VALUE, Character.MAX_VALUE + 1);
427      int negatedCharacters = DISTINCT_CHARS - totalCharacters;
428      String suffix = ".negate()";
429      String description = toString();
430      String negatedDescription =
431          description.endsWith(suffix)
432              ? description.substring(0, description.length() - suffix.length())
433              : description + suffix;
434      return new NegatedFastMatcher(
435          precomputedPositive(negatedCharacters, table, negatedDescription)) {
436        @Override
437        public String toString() {
438          return description;
439        }
440      };
441    }
442  }
443
444  /**
445   * Helper method for {@link #precomputedInternal} that doesn't test if the negation is cheaper.
446   */
447  @GwtIncompatible // SmallCharMatcher
448  private static CharMatcher precomputedPositive(
449      int totalCharacters, BitSet table, String description) {
450    switch (totalCharacters) {
451      case 0:
452        return none();
453      case 1:
454        return is((char) table.nextSetBit(0));
455      case 2:
456        char c1 = (char) table.nextSetBit(0);
457        char c2 = (char) table.nextSetBit(c1 + 1);
458        return isEither(c1, c2);
459      default:
460        return isSmall(totalCharacters, table.length())
461            ? SmallCharMatcher.from(table, description)
462            : new BitSetMatcher(table, description);
463    }
464  }
465
466  @GwtIncompatible // SmallCharMatcher
467  private static boolean isSmall(int totalCharacters, int tableLength) {
468    return totalCharacters <= SmallCharMatcher.MAX_SIZE
469        && tableLength > (totalCharacters * 4 * Character.SIZE);
470    // err on the side of BitSetMatcher
471  }
472
473  /** Sets bits in {@code table} matched by this matcher. */
474  @GwtIncompatible // used only from other GwtIncompatible code
475  void setBits(BitSet table) {
476    for (int c = Character.MAX_VALUE; c >= Character.MIN_VALUE; c--) {
477      if (matches((char) c)) {
478        table.set(c);
479      }
480    }
481  }
482
483  // Text processing routines
484
485  /**
486   * Returns {@code true} if a character sequence contains at least one matching BMP character.
487   * Equivalent to {@code !matchesNoneOf(sequence)}.
488   *
489   * <p>The default implementation iterates over the sequence, invoking {@link #matches} for each
490   * character, until this returns {@code true} or the end is reached.
491   *
492   * @param sequence the character sequence to examine, possibly empty
493   * @return {@code true} if this matcher matches at least one character in the sequence
494   * @since 8.0
495   */
496  public boolean matchesAnyOf(CharSequence sequence) {
497    return !matchesNoneOf(sequence);
498  }
499
500  /**
501   * Returns {@code true} if a character sequence contains only matching BMP characters.
502   *
503   * <p>The default implementation iterates over the sequence, invoking {@link #matches} for each
504   * character, until this returns {@code false} or the end is reached.
505   *
506   * @param sequence the character sequence to examine, possibly empty
507   * @return {@code true} if this matcher matches every character in the sequence, including when
508   *     the sequence is empty
509   */
510  public boolean matchesAllOf(CharSequence sequence) {
511    for (int i = sequence.length() - 1; i >= 0; i--) {
512      if (!matches(sequence.charAt(i))) {
513        return false;
514      }
515    }
516    return true;
517  }
518
519  /**
520   * Returns {@code true} if a character sequence contains no matching BMP characters. Equivalent to
521   * {@code !matchesAnyOf(sequence)}.
522   *
523   * <p>The default implementation iterates over the sequence, invoking {@link #matches} for each
524   * character, until this returns {@code true} or the end is reached.
525   *
526   * @param sequence the character sequence to examine, possibly empty
527   * @return {@code true} if this matcher matches no characters in the sequence, including when the
528   *     sequence is empty
529   */
530  public boolean matchesNoneOf(CharSequence sequence) {
531    return indexIn(sequence) == -1;
532  }
533
534  /**
535   * Returns the index of the first matching BMP character in a character sequence, or {@code -1} if
536   * no matching character is present.
537   *
538   * <p>The default implementation iterates over the sequence in forward order calling {@link
539   * #matches} for each character.
540   *
541   * @param sequence the character sequence to examine from the beginning
542   * @return an index, or {@code -1} if no character matches
543   */
544  public int indexIn(CharSequence sequence) {
545    return indexIn(sequence, 0);
546  }
547
548  /**
549   * Returns the index of the first matching BMP character in a character sequence, starting from a
550   * given position, or {@code -1} if no character matches after that position.
551   *
552   * <p>The default implementation iterates over the sequence in forward order, beginning at {@code
553   * start}, calling {@link #matches} for each character.
554   *
555   * @param sequence the character sequence to examine
556   * @param start the first index to examine; must be nonnegative and no greater than {@code
557   *     sequence.length()}
558   * @return the index of the first matching character, guaranteed to be no less than {@code start},
559   *     or {@code -1} if no character matches
560   * @throws IndexOutOfBoundsException if start is negative or greater than {@code
561   *     sequence.length()}
562   */
563  public int indexIn(CharSequence sequence, int start) {
564    int length = sequence.length();
565    checkPositionIndex(start, length);
566    for (int i = start; i < length; i++) {
567      if (matches(sequence.charAt(i))) {
568        return i;
569      }
570    }
571    return -1;
572  }
573
574  /**
575   * Returns the index of the last matching BMP character in a character sequence, or {@code -1} if
576   * no matching character is present.
577   *
578   * <p>The default implementation iterates over the sequence in reverse order calling {@link
579   * #matches} for each character.
580   *
581   * @param sequence the character sequence to examine from the end
582   * @return an index, or {@code -1} if no character matches
583   */
584  public int lastIndexIn(CharSequence sequence) {
585    for (int i = sequence.length() - 1; i >= 0; i--) {
586      if (matches(sequence.charAt(i))) {
587        return i;
588      }
589    }
590    return -1;
591  }
592
593  /**
594   * Returns the number of matching {@code char}s found in a character sequence.
595   *
596   * <p>Counts 2 per supplementary character, such as for {@link #whitespace}().{@link #negate}().
597   */
598  public int countIn(CharSequence sequence) {
599    int count = 0;
600    for (int i = 0; i < sequence.length(); i++) {
601      if (matches(sequence.charAt(i))) {
602        count++;
603      }
604    }
605    return count;
606  }
607
608  /**
609   * Returns a string containing all non-matching characters of a character sequence, in order. For
610   * example:
611   *
612   * <pre>{@code
613   * CharMatcher.is('a').removeFrom("bazaar")
614   * }</pre>
615   *
616   * ... returns {@code "bzr"}.
617   */
618  public String removeFrom(CharSequence sequence) {
619    String string = sequence.toString();
620    int pos = indexIn(string);
621    if (pos == -1) {
622      return string;
623    }
624
625    char[] chars = string.toCharArray();
626    int spread = 1;
627
628    // This unusual loop comes from extensive benchmarking
629    OUT:
630    while (true) {
631      pos++;
632      while (true) {
633        if (pos == chars.length) {
634          break OUT;
635        }
636        if (matches(chars[pos])) {
637          break;
638        }
639        chars[pos - spread] = chars[pos];
640        pos++;
641      }
642      spread++;
643    }
644    return new String(chars, 0, pos - spread);
645  }
646
647  /**
648   * Returns a string containing all matching BMP characters of a character sequence, in order. For
649   * example:
650   *
651   * <pre>{@code
652   * CharMatcher.is('a').retainFrom("bazaar")
653   * }</pre>
654   *
655   * ... returns {@code "aaa"}.
656   */
657  public String retainFrom(CharSequence sequence) {
658    return negate().removeFrom(sequence);
659  }
660
661  /**
662   * Returns a string copy of the input character sequence, with each matching BMP character
663   * replaced by a given replacement character. For example:
664   *
665   * <pre>{@code
666   * CharMatcher.is('a').replaceFrom("radar", 'o')
667   * }</pre>
668   *
669   * ... returns {@code "rodor"}.
670   *
671   * <p>The default implementation uses {@link #indexIn(CharSequence)} to find the first matching
672   * character, then iterates the remainder of the sequence calling {@link #matches(char)} for each
673   * character.
674   *
675   * @param sequence the character sequence to replace matching characters in
676   * @param replacement the character to append to the result string in place of each matching
677   *     character in {@code sequence}
678   * @return the new string
679   */
680  public String replaceFrom(CharSequence sequence, char replacement) {
681    String string = sequence.toString();
682    int pos = indexIn(string);
683    if (pos == -1) {
684      return string;
685    }
686    char[] chars = string.toCharArray();
687    chars[pos] = replacement;
688    for (int i = pos + 1; i < chars.length; i++) {
689      if (matches(chars[i])) {
690        chars[i] = replacement;
691      }
692    }
693    return new String(chars);
694  }
695
696  /**
697   * Returns a string copy of the input character sequence, with each matching BMP character
698   * replaced by a given replacement sequence. For example:
699   *
700   * <pre>{@code
701   * CharMatcher.is('a').replaceFrom("yaha", "oo")
702   * }</pre>
703   *
704   * ... returns {@code "yoohoo"}.
705   *
706   * <p><b>Note:</b> If the replacement is a fixed string with only one character, you are better
707   * off calling {@link #replaceFrom(CharSequence, char)} directly.
708   *
709   * @param sequence the character sequence to replace matching characters in
710   * @param replacement the characters to append to the result string in place of each matching
711   *     character in {@code sequence}
712   * @return the new string
713   */
714  public String replaceFrom(CharSequence sequence, CharSequence replacement) {
715    int replacementLen = replacement.length();
716    if (replacementLen == 0) {
717      return removeFrom(sequence);
718    }
719    if (replacementLen == 1) {
720      return replaceFrom(sequence, replacement.charAt(0));
721    }
722
723    String string = sequence.toString();
724    int pos = indexIn(string);
725    if (pos == -1) {
726      return string;
727    }
728
729    int len = string.length();
730    StringBuilder buf = new StringBuilder((len * 3 / 2) + 16);
731
732    int oldpos = 0;
733    do {
734      buf.append(string, oldpos, pos);
735      buf.append(replacement);
736      oldpos = pos + 1;
737      pos = indexIn(string, oldpos);
738    } while (pos != -1);
739
740    buf.append(string, oldpos, len);
741    return buf.toString();
742  }
743
744  /**
745   * Returns a substring of the input character sequence that omits all matching BMP characters from
746   * the beginning and from the end of the string. For example:
747   *
748   * <pre>{@code
749   * CharMatcher.anyOf("ab").trimFrom("abacatbab")
750   * }</pre>
751   *
752   * ... returns {@code "cat"}.
753   *
754   * <p>Note that:
755   *
756   * <pre>{@code
757   * CharMatcher.inRange('\0', ' ').trimFrom(str)
758   * }</pre>
759   *
760   * ... is equivalent to {@link String#trim()}.
761   */
762  public String trimFrom(CharSequence sequence) {
763    int len = sequence.length();
764    int first;
765    int last;
766
767    for (first = 0; first < len; first++) {
768      if (!matches(sequence.charAt(first))) {
769        break;
770      }
771    }
772    for (last = len - 1; last > first; last--) {
773      if (!matches(sequence.charAt(last))) {
774        break;
775      }
776    }
777
778    return sequence.subSequence(first, last + 1).toString();
779  }
780
781  /**
782   * Returns a substring of the input character sequence that omits all matching BMP characters from
783   * the beginning of the string. For example:
784   *
785   * <pre>{@code
786   * CharMatcher.anyOf("ab").trimLeadingFrom("abacatbab")
787   * }</pre>
788   *
789   * ... returns {@code "catbab"}.
790   */
791  public String trimLeadingFrom(CharSequence sequence) {
792    int len = sequence.length();
793    for (int first = 0; first < len; first++) {
794      if (!matches(sequence.charAt(first))) {
795        return sequence.subSequence(first, len).toString();
796      }
797    }
798    return "";
799  }
800
801  /**
802   * Returns a substring of the input character sequence that omits all matching BMP characters from
803   * the end of the string. For example:
804   *
805   * <pre>{@code
806   * CharMatcher.anyOf("ab").trimTrailingFrom("abacatbab")
807   * }</pre>
808   *
809   * ... returns {@code "abacat"}.
810   */
811  public String trimTrailingFrom(CharSequence sequence) {
812    int len = sequence.length();
813    for (int last = len - 1; last >= 0; last--) {
814      if (!matches(sequence.charAt(last))) {
815        return sequence.subSequence(0, last + 1).toString();
816      }
817    }
818    return "";
819  }
820
821  /**
822   * Returns a string copy of the input character sequence, with each group of consecutive matching
823   * BMP characters replaced by a single replacement character. For example:
824   *
825   * <pre>{@code
826   * CharMatcher.anyOf("eko").collapseFrom("bookkeeper", '-')
827   * }</pre>
828   *
829   * ... returns {@code "b-p-r"}.
830   *
831   * <p>The default implementation uses {@link #indexIn(CharSequence)} to find the first matching
832   * character, then iterates the remainder of the sequence calling {@link #matches(char)} for each
833   * character.
834   *
835   * @param sequence the character sequence to replace matching groups of characters in
836   * @param replacement the character to append to the result string in place of each group of
837   *     matching characters in {@code sequence}
838   * @return the new string
839   */
840  public String collapseFrom(CharSequence sequence, char replacement) {
841    // This implementation avoids unnecessary allocation.
842    int len = sequence.length();
843    for (int i = 0; i < len; i++) {
844      char c = sequence.charAt(i);
845      if (matches(c)) {
846        if (c == replacement && (i == len - 1 || !matches(sequence.charAt(i + 1)))) {
847          // a no-op replacement
848          i++;
849        } else {
850          StringBuilder builder = new StringBuilder(len).append(sequence, 0, i).append(replacement);
851          return finishCollapseFrom(sequence, i + 1, len, replacement, builder, true);
852        }
853      }
854    }
855    // no replacement needed
856    return sequence.toString();
857  }
858
859  /**
860   * Collapses groups of matching characters exactly as {@link #collapseFrom} does, except that
861   * groups of matching BMP characters at the start or end of the sequence are removed without
862   * replacement.
863   */
864  public String trimAndCollapseFrom(CharSequence sequence, char replacement) {
865    // This implementation avoids unnecessary allocation.
866    int len = sequence.length();
867    int first = 0;
868    int last = len - 1;
869
870    while (first < len && matches(sequence.charAt(first))) {
871      first++;
872    }
873
874    while (last > first && matches(sequence.charAt(last))) {
875      last--;
876    }
877
878    return (first == 0 && last == len - 1)
879        ? collapseFrom(sequence, replacement)
880        : finishCollapseFrom(
881            sequence, first, last + 1, replacement, new StringBuilder(last + 1 - first), false);
882  }
883
884  private String finishCollapseFrom(
885      CharSequence sequence,
886      int start,
887      int end,
888      char replacement,
889      StringBuilder builder,
890      boolean inMatchingGroup) {
891    for (int i = start; i < end; i++) {
892      char c = sequence.charAt(i);
893      if (matches(c)) {
894        if (!inMatchingGroup) {
895          builder.append(replacement);
896          inMatchingGroup = true;
897        }
898      } else {
899        builder.append(c);
900        inMatchingGroup = false;
901      }
902    }
903    return builder.toString();
904  }
905
906  /**
907   * @deprecated Provided only to satisfy the {@link Predicate} interface; use {@link #matches}
908   *     instead.
909   */
910  @InlineMe(replacement = "this.matches(character)")
911  @Deprecated
912  @Override
913  // We can't compatibly make this `final` now.
914  @InlineMeValidationDisabled(
915      "While apply() is not final, the inlining is still safe because all known overrides of"
916          + " apply() call matches().")
917  public boolean apply(Character character) {
918    return matches(character);
919  }
920
921  /**
922   * Returns a string representation of this {@code CharMatcher}, such as {@code
923   * CharMatcher.or(WHITESPACE, JAVA_DIGIT)}.
924   */
925  @Override
926  public String toString() {
927    return super.toString();
928  }
929
930  /**
931   * Returns the Java Unicode escape sequence for the given {@code char}, in the form "\u12AB" where
932   * "12AB" is the four hexadecimal digits representing the 16-bit code unit.
933   */
934  private static String showCharacter(char c) {
935    String hex = "0123456789ABCDEF";
936    char[] tmp = {'\\', 'u', '\0', '\0', '\0', '\0'};
937    for (int i = 0; i < 4; i++) {
938      tmp[5 - i] = hex.charAt(c & 0xF);
939      c = (char) (c >> 4);
940    }
941    return String.copyValueOf(tmp);
942  }
943
944  // Fast matchers
945
946  /** A matcher for which precomputation will not yield any significant benefit. */
947  abstract static class FastMatcher extends CharMatcher {
948
949    @Override
950    public final CharMatcher precomputed() {
951      return this;
952    }
953
954    @Override
955    public CharMatcher negate() {
956      return new NegatedFastMatcher(this);
957    }
958  }
959
960  /** {@link FastMatcher} which overrides {@code toString()} with a custom name. */
961  abstract static class NamedFastMatcher extends FastMatcher {
962
963    private final String description;
964
965    NamedFastMatcher(String description) {
966      this.description = checkNotNull(description);
967    }
968
969    @Override
970    public final String toString() {
971      return description;
972    }
973  }
974
975  /** Negation of a {@link FastMatcher}. */
976  private static class NegatedFastMatcher extends Negated {
977
978    NegatedFastMatcher(CharMatcher original) {
979      super(original);
980    }
981
982    @Override
983    public final CharMatcher precomputed() {
984      return this;
985    }
986  }
987
988  /** Fast matcher using a {@link BitSet} table of matching characters. */
989  @GwtIncompatible // used only from other GwtIncompatible code
990  private static final class BitSetMatcher extends NamedFastMatcher {
991
992    private final BitSet table;
993
994    private BitSetMatcher(BitSet table, String description) {
995      super(description);
996      if (table.length() + Long.SIZE < table.size()) {
997        table = (BitSet) table.clone();
998        // If only we could actually call BitSet.trimToSize() ourselves...
999      }
1000      this.table = table;
1001    }
1002
1003    @Override
1004    public boolean matches(char c) {
1005      return table.get(c);
1006    }
1007
1008    @Override
1009    void setBits(BitSet bitSet) {
1010      bitSet.or(table);
1011    }
1012  }
1013
1014  // Static constant implementation classes
1015
1016  /** Implementation of {@link #any()}. */
1017  private static final class Any extends NamedFastMatcher {
1018
1019    static final CharMatcher INSTANCE = new Any();
1020
1021    private Any() {
1022      super("CharMatcher.any()");
1023    }
1024
1025    @Override
1026    public boolean matches(char c) {
1027      return true;
1028    }
1029
1030    @Override
1031    public int indexIn(CharSequence sequence) {
1032      return (sequence.length() == 0) ? -1 : 0;
1033    }
1034
1035    @Override
1036    public int indexIn(CharSequence sequence, int start) {
1037      int length = sequence.length();
1038      checkPositionIndex(start, length);
1039      return (start == length) ? -1 : start;
1040    }
1041
1042    @Override
1043    public int lastIndexIn(CharSequence sequence) {
1044      return sequence.length() - 1;
1045    }
1046
1047    @Override
1048    public boolean matchesAllOf(CharSequence sequence) {
1049      checkNotNull(sequence);
1050      return true;
1051    }
1052
1053    @Override
1054    public boolean matchesNoneOf(CharSequence sequence) {
1055      return sequence.length() == 0;
1056    }
1057
1058    @Override
1059    public String removeFrom(CharSequence sequence) {
1060      checkNotNull(sequence);
1061      return "";
1062    }
1063
1064    @Override
1065    public String replaceFrom(CharSequence sequence, char replacement) {
1066      char[] array = new char[sequence.length()];
1067      Arrays.fill(array, replacement);
1068      return new String(array);
1069    }
1070
1071    @Override
1072    public String replaceFrom(CharSequence sequence, CharSequence replacement) {
1073      StringBuilder result = new StringBuilder(sequence.length() * replacement.length());
1074      for (int i = 0; i < sequence.length(); i++) {
1075        result.append(replacement);
1076      }
1077      return result.toString();
1078    }
1079
1080    @Override
1081    public String collapseFrom(CharSequence sequence, char replacement) {
1082      return (sequence.length() == 0) ? "" : String.valueOf(replacement);
1083    }
1084
1085    @Override
1086    public String trimFrom(CharSequence sequence) {
1087      checkNotNull(sequence);
1088      return "";
1089    }
1090
1091    @Override
1092    public int countIn(CharSequence sequence) {
1093      return sequence.length();
1094    }
1095
1096    @Override
1097    public CharMatcher and(CharMatcher other) {
1098      return checkNotNull(other);
1099    }
1100
1101    @Override
1102    public CharMatcher or(CharMatcher other) {
1103      checkNotNull(other);
1104      return this;
1105    }
1106
1107    @Override
1108    public CharMatcher negate() {
1109      return none();
1110    }
1111  }
1112
1113  /** Implementation of {@link #none()}. */
1114  private static final class None extends NamedFastMatcher {
1115
1116    static final CharMatcher INSTANCE = new None();
1117
1118    private None() {
1119      super("CharMatcher.none()");
1120    }
1121
1122    @Override
1123    public boolean matches(char c) {
1124      return false;
1125    }
1126
1127    @Override
1128    public int indexIn(CharSequence sequence) {
1129      checkNotNull(sequence);
1130      return -1;
1131    }
1132
1133    @Override
1134    public int indexIn(CharSequence sequence, int start) {
1135      int length = sequence.length();
1136      checkPositionIndex(start, length);
1137      return -1;
1138    }
1139
1140    @Override
1141    public int lastIndexIn(CharSequence sequence) {
1142      checkNotNull(sequence);
1143      return -1;
1144    }
1145
1146    @Override
1147    public boolean matchesAllOf(CharSequence sequence) {
1148      return sequence.length() == 0;
1149    }
1150
1151    @Override
1152    public boolean matchesNoneOf(CharSequence sequence) {
1153      checkNotNull(sequence);
1154      return true;
1155    }
1156
1157    @Override
1158    public String removeFrom(CharSequence sequence) {
1159      return sequence.toString();
1160    }
1161
1162    @Override
1163    public String replaceFrom(CharSequence sequence, char replacement) {
1164      return sequence.toString();
1165    }
1166
1167    @Override
1168    public String replaceFrom(CharSequence sequence, CharSequence replacement) {
1169      checkNotNull(replacement);
1170      return sequence.toString();
1171    }
1172
1173    @Override
1174    public String collapseFrom(CharSequence sequence, char replacement) {
1175      return sequence.toString();
1176    }
1177
1178    @Override
1179    public String trimFrom(CharSequence sequence) {
1180      return sequence.toString();
1181    }
1182
1183    @Override
1184    public String trimLeadingFrom(CharSequence sequence) {
1185      return sequence.toString();
1186    }
1187
1188    @Override
1189    public String trimTrailingFrom(CharSequence sequence) {
1190      return sequence.toString();
1191    }
1192
1193    @Override
1194    public int countIn(CharSequence sequence) {
1195      checkNotNull(sequence);
1196      return 0;
1197    }
1198
1199    @Override
1200    public CharMatcher and(CharMatcher other) {
1201      checkNotNull(other);
1202      return this;
1203    }
1204
1205    @Override
1206    public CharMatcher or(CharMatcher other) {
1207      return checkNotNull(other);
1208    }
1209
1210    @Override
1211    public CharMatcher negate() {
1212      return any();
1213    }
1214  }
1215
1216  /** Implementation of {@link #whitespace()}. */
1217  @VisibleForTesting
1218  static final class Whitespace extends NamedFastMatcher {
1219
1220    // TABLE is a precomputed hashset of whitespace characters. MULTIPLIER serves as a hash function
1221    // whose key property is that it maps 25 characters into the 32-slot table without collision.
1222    // Basically this is an opportunistic fast implementation as opposed to "good code". For most
1223    // other use-cases, the reduction in readability isn't worth it.
1224    static final String TABLE =
1225        "\u2002\u3000\r\u0085\u200A\u2005\u2000\u3000"
1226            + "\u2029\u000B\u3000\u2008\u2003\u205F\u3000\u1680"
1227            + "\u0009\u0020\u2006\u2001\u202F\u00A0\u000C\u2009"
1228            + "\u3000\u2004\u3000\u3000\u2028\n\u2007\u3000";
1229    static final int MULTIPLIER = 1682554634;
1230    static final int SHIFT = Integer.numberOfLeadingZeros(TABLE.length() - 1);
1231
1232    static final CharMatcher INSTANCE = new Whitespace();
1233
1234    Whitespace() {
1235      super("CharMatcher.whitespace()");
1236    }
1237
1238    @Override
1239    public boolean matches(char c) {
1240      return TABLE.charAt((MULTIPLIER * c) >>> SHIFT) == c;
1241    }
1242
1243    @GwtIncompatible // used only from other GwtIncompatible code
1244    @Override
1245    void setBits(BitSet table) {
1246      for (int i = 0; i < TABLE.length(); i++) {
1247        table.set(TABLE.charAt(i));
1248      }
1249    }
1250  }
1251
1252  /** Implementation of {@link #breakingWhitespace()}. */
1253  private static final class BreakingWhitespace extends CharMatcher {
1254
1255    static final CharMatcher INSTANCE = new BreakingWhitespace();
1256
1257    @Override
1258    public boolean matches(char c) {
1259      switch (c) {
1260        case '\t':
1261        case '\n':
1262        case '\013':
1263        case '\f':
1264        case '\r':
1265        case ' ':
1266        case '\u0085':
1267        case '\u1680':
1268        case '\u2028':
1269        case '\u2029':
1270        case '\u205f':
1271        case '\u3000':
1272          return true;
1273        case '\u2007':
1274          return false;
1275        default:
1276          return c >= '\u2000' && c <= '\u200a';
1277      }
1278    }
1279
1280    @Override
1281    public String toString() {
1282      return "CharMatcher.breakingWhitespace()";
1283    }
1284  }
1285
1286  /** Implementation of {@link #ascii()}. */
1287  private static final class Ascii extends NamedFastMatcher {
1288
1289    static final CharMatcher INSTANCE = new Ascii();
1290
1291    Ascii() {
1292      super("CharMatcher.ascii()");
1293    }
1294
1295    @Override
1296    public boolean matches(char c) {
1297      return c <= '\u007f';
1298    }
1299  }
1300
1301  /** Implementation that matches characters that fall within multiple ranges. */
1302  private static class RangesMatcher extends CharMatcher {
1303
1304    private final String description;
1305    private final char[] rangeStarts;
1306    private final char[] rangeEnds;
1307
1308    RangesMatcher(String description, char[] rangeStarts, char[] rangeEnds) {
1309      this.description = description;
1310      this.rangeStarts = rangeStarts;
1311      this.rangeEnds = rangeEnds;
1312      checkArgument(rangeStarts.length == rangeEnds.length);
1313      for (int i = 0; i < rangeStarts.length; i++) {
1314        checkArgument(rangeStarts[i] <= rangeEnds[i]);
1315        if (i + 1 < rangeStarts.length) {
1316          checkArgument(rangeEnds[i] < rangeStarts[i + 1]);
1317        }
1318      }
1319    }
1320
1321    @Override
1322    public boolean matches(char c) {
1323      int index = Arrays.binarySearch(rangeStarts, c);
1324      if (index >= 0) {
1325        return true;
1326      } else {
1327        index = ~index - 1;
1328        return index >= 0 && c <= rangeEnds[index];
1329      }
1330    }
1331
1332    @Override
1333    public String toString() {
1334      return description;
1335    }
1336  }
1337
1338  /** Implementation of {@link #digit()}. */
1339  private static final class Digit extends RangesMatcher {
1340    // Plug the following UnicodeSet pattern into
1341    // https://unicode.org/cldr/utility/list-unicodeset.jsp
1342    // [[:Nd:]&[:nv=0:]&[\u0000-\uFFFF]]
1343    // and get the zeroes from there.
1344
1345    // Must be in ascending order.
1346    private static final String ZEROES =
1347        "0\u0660\u06f0\u07c0\u0966\u09e6\u0a66\u0ae6\u0b66\u0be6\u0c66\u0ce6\u0d66\u0de6"
1348            + "\u0e50\u0ed0\u0f20\u1040\u1090\u17e0\u1810\u1946\u19d0\u1a80\u1a90\u1b50\u1bb0"
1349            + "\u1c40\u1c50\ua620\ua8d0\ua900\ua9d0\ua9f0\uaa50\uabf0\uff10";
1350
1351    private static char[] zeroes() {
1352      return ZEROES.toCharArray();
1353    }
1354
1355    private static char[] nines() {
1356      char[] nines = new char[ZEROES.length()];
1357      for (int i = 0; i < ZEROES.length(); i++) {
1358        nines[i] = (char) (ZEROES.charAt(i) + 9);
1359      }
1360      return nines;
1361    }
1362
1363    static final CharMatcher INSTANCE = new Digit();
1364
1365    private Digit() {
1366      super("CharMatcher.digit()", zeroes(), nines());
1367    }
1368  }
1369
1370  /** Implementation of {@link #javaDigit()}. */
1371  private static final class JavaDigit extends CharMatcher {
1372
1373    static final CharMatcher INSTANCE = new JavaDigit();
1374
1375    @Override
1376    public boolean matches(char c) {
1377      return Character.isDigit(c);
1378    }
1379
1380    @Override
1381    public String toString() {
1382      return "CharMatcher.javaDigit()";
1383    }
1384  }
1385
1386  /** Implementation of {@link #javaLetter()}. */
1387  private static final class JavaLetter extends CharMatcher {
1388
1389    static final CharMatcher INSTANCE = new JavaLetter();
1390
1391    @Override
1392    public boolean matches(char c) {
1393      return Character.isLetter(c);
1394    }
1395
1396    @Override
1397    public String toString() {
1398      return "CharMatcher.javaLetter()";
1399    }
1400  }
1401
1402  /** Implementation of {@link #javaLetterOrDigit()}. */
1403  private static final class JavaLetterOrDigit extends CharMatcher {
1404
1405    static final CharMatcher INSTANCE = new JavaLetterOrDigit();
1406
1407    @Override
1408    public boolean matches(char c) {
1409      return Character.isLetterOrDigit(c);
1410    }
1411
1412    @Override
1413    public String toString() {
1414      return "CharMatcher.javaLetterOrDigit()";
1415    }
1416  }
1417
1418  /** Implementation of {@link #javaUpperCase()}. */
1419  private static final class JavaUpperCase extends CharMatcher {
1420
1421    static final CharMatcher INSTANCE = new JavaUpperCase();
1422
1423    @Override
1424    public boolean matches(char c) {
1425      return Character.isUpperCase(c);
1426    }
1427
1428    @Override
1429    public String toString() {
1430      return "CharMatcher.javaUpperCase()";
1431    }
1432  }
1433
1434  /** Implementation of {@link #javaLowerCase()}. */
1435  private static final class JavaLowerCase extends CharMatcher {
1436
1437    static final CharMatcher INSTANCE = new JavaLowerCase();
1438
1439    @Override
1440    public boolean matches(char c) {
1441      return Character.isLowerCase(c);
1442    }
1443
1444    @Override
1445    public String toString() {
1446      return "CharMatcher.javaLowerCase()";
1447    }
1448  }
1449
1450  /** Implementation of {@link #javaIsoControl()}. */
1451  private static final class JavaIsoControl extends NamedFastMatcher {
1452
1453    static final CharMatcher INSTANCE = new JavaIsoControl();
1454
1455    private JavaIsoControl() {
1456      super("CharMatcher.javaIsoControl()");
1457    }
1458
1459    @Override
1460    public boolean matches(char c) {
1461      return c <= '\u001f' || (c >= '\u007f' && c <= '\u009f');
1462    }
1463  }
1464
1465  /** Implementation of {@link #invisible()}. */
1466  private static final class Invisible extends RangesMatcher {
1467    // Plug the following UnicodeSet pattern into
1468    // https://unicode.org/cldr/utility/list-unicodeset.jsp
1469    // [[[:Zs:][:Zl:][:Zp:][:Cc:][:Cf:][:Cs:][:Co:]]&[\u0000-\uFFFF]]
1470    // with the "Abbreviate" option, and get the ranges from there.
1471    private static final String RANGE_STARTS =
1472        "\u0000\u007f\u00ad\u0600\u061c\u06dd\u070f\u0890\u08e2\u1680\u180e\u2000\u2028\u205f\u2066"
1473            + "\u3000\ud800\ufeff\ufff9";
1474    private static final String RANGE_ENDS = // inclusive ends
1475        "\u0020\u00a0\u00ad\u0605\u061c\u06dd\u070f\u0891\u08e2\u1680\u180e\u200f\u202f\u2064\u206f"
1476            + "\u3000\uf8ff\ufeff\ufffb";
1477
1478    static final CharMatcher INSTANCE = new Invisible();
1479
1480    private Invisible() {
1481      super("CharMatcher.invisible()", RANGE_STARTS.toCharArray(), RANGE_ENDS.toCharArray());
1482    }
1483  }
1484
1485  /** Implementation of {@link #singleWidth()}. */
1486  private static final class SingleWidth extends RangesMatcher {
1487
1488    static final CharMatcher INSTANCE = new SingleWidth();
1489
1490    private SingleWidth() {
1491      super(
1492          "CharMatcher.singleWidth()",
1493          "\u0000\u05be\u05d0\u05f3\u0600\u0750\u0e00\u1e00\u2100\ufb50\ufe70\uff61".toCharArray(),
1494          "\u04f9\u05be\u05ea\u05f4\u06ff\u077f\u0e7f\u20af\u213a\ufdff\ufeff\uffdc".toCharArray());
1495    }
1496  }
1497
1498  // Non-static factory implementation classes
1499
1500  /** Implementation of {@link #negate()}. */
1501  private static class Negated extends CharMatcher {
1502
1503    final CharMatcher original;
1504
1505    Negated(CharMatcher original) {
1506      this.original = checkNotNull(original);
1507    }
1508
1509    @Override
1510    public boolean matches(char c) {
1511      return !original.matches(c);
1512    }
1513
1514    @Override
1515    public boolean matchesAllOf(CharSequence sequence) {
1516      return original.matchesNoneOf(sequence);
1517    }
1518
1519    @Override
1520    public boolean matchesNoneOf(CharSequence sequence) {
1521      return original.matchesAllOf(sequence);
1522    }
1523
1524    @Override
1525    public int countIn(CharSequence sequence) {
1526      return sequence.length() - original.countIn(sequence);
1527    }
1528
1529    @GwtIncompatible // used only from other GwtIncompatible code
1530    @Override
1531    void setBits(BitSet table) {
1532      BitSet tmp = new BitSet();
1533      original.setBits(tmp);
1534      tmp.flip(Character.MIN_VALUE, Character.MAX_VALUE + 1);
1535      table.or(tmp);
1536    }
1537
1538    @Override
1539    public CharMatcher negate() {
1540      return original;
1541    }
1542
1543    @Override
1544    public String toString() {
1545      return original + ".negate()";
1546    }
1547  }
1548
1549  /** Implementation of {@link #and(CharMatcher)}. */
1550  private static final class And extends CharMatcher {
1551
1552    final CharMatcher first;
1553    final CharMatcher second;
1554
1555    And(CharMatcher a, CharMatcher b) {
1556      first = checkNotNull(a);
1557      second = checkNotNull(b);
1558    }
1559
1560    @Override
1561    public boolean matches(char c) {
1562      return first.matches(c) && second.matches(c);
1563    }
1564
1565    @GwtIncompatible // used only from other GwtIncompatible code
1566    @Override
1567    void setBits(BitSet table) {
1568      BitSet tmp1 = new BitSet();
1569      first.setBits(tmp1);
1570      BitSet tmp2 = new BitSet();
1571      second.setBits(tmp2);
1572      tmp1.and(tmp2);
1573      table.or(tmp1);
1574    }
1575
1576    @Override
1577    public String toString() {
1578      return "CharMatcher.and(" + first + ", " + second + ")";
1579    }
1580  }
1581
1582  /** Implementation of {@link #or(CharMatcher)}. */
1583  private static final class Or extends CharMatcher {
1584
1585    final CharMatcher first;
1586    final CharMatcher second;
1587
1588    Or(CharMatcher a, CharMatcher b) {
1589      first = checkNotNull(a);
1590      second = checkNotNull(b);
1591    }
1592
1593    @GwtIncompatible // used only from other GwtIncompatible code
1594    @Override
1595    void setBits(BitSet table) {
1596      first.setBits(table);
1597      second.setBits(table);
1598    }
1599
1600    @Override
1601    public boolean matches(char c) {
1602      return first.matches(c) || second.matches(c);
1603    }
1604
1605    @Override
1606    public String toString() {
1607      return "CharMatcher.or(" + first + ", " + second + ")";
1608    }
1609  }
1610
1611  // Static factory implementations
1612
1613  /** Implementation of {@link #is(char)}. */
1614  private static final class Is extends FastMatcher {
1615
1616    private final char match;
1617
1618    Is(char match) {
1619      this.match = match;
1620    }
1621
1622    @Override
1623    public boolean matches(char c) {
1624      return c == match;
1625    }
1626
1627    @Override
1628    public String replaceFrom(CharSequence sequence, char replacement) {
1629      return sequence.toString().replace(match, replacement);
1630    }
1631
1632    @Override
1633    public CharMatcher and(CharMatcher other) {
1634      return other.matches(match) ? this : none();
1635    }
1636
1637    @Override
1638    public CharMatcher or(CharMatcher other) {
1639      return other.matches(match) ? other : super.or(other);
1640    }
1641
1642    @Override
1643    public CharMatcher negate() {
1644      return isNot(match);
1645    }
1646
1647    @GwtIncompatible // used only from other GwtIncompatible code
1648    @Override
1649    void setBits(BitSet table) {
1650      table.set(match);
1651    }
1652
1653    @Override
1654    public String toString() {
1655      return "CharMatcher.is('" + showCharacter(match) + "')";
1656    }
1657  }
1658
1659  /** Implementation of {@link #isNot(char)}. */
1660  private static final class IsNot extends FastMatcher {
1661
1662    private final char match;
1663
1664    IsNot(char match) {
1665      this.match = match;
1666    }
1667
1668    @Override
1669    public boolean matches(char c) {
1670      return c != match;
1671    }
1672
1673    @Override
1674    public CharMatcher and(CharMatcher other) {
1675      return other.matches(match) ? super.and(other) : other;
1676    }
1677
1678    @Override
1679    public CharMatcher or(CharMatcher other) {
1680      return other.matches(match) ? any() : this;
1681    }
1682
1683    @GwtIncompatible // used only from other GwtIncompatible code
1684    @Override
1685    void setBits(BitSet table) {
1686      table.set(0, match);
1687      table.set(match + 1, Character.MAX_VALUE + 1);
1688    }
1689
1690    @Override
1691    public CharMatcher negate() {
1692      return is(match);
1693    }
1694
1695    @Override
1696    public String toString() {
1697      return "CharMatcher.isNot('" + showCharacter(match) + "')";
1698    }
1699  }
1700
1701  private static CharMatcher.IsEither isEither(char c1, char c2) {
1702    return new CharMatcher.IsEither(c1, c2);
1703  }
1704
1705  /** Implementation of {@link #anyOf(CharSequence)} for exactly two characters. */
1706  private static final class IsEither extends FastMatcher {
1707
1708    private final char match1;
1709    private final char match2;
1710
1711    IsEither(char match1, char match2) {
1712      this.match1 = match1;
1713      this.match2 = match2;
1714    }
1715
1716    @Override
1717    public boolean matches(char c) {
1718      return c == match1 || c == match2;
1719    }
1720
1721    @GwtIncompatible // used only from other GwtIncompatible code
1722    @Override
1723    void setBits(BitSet table) {
1724      table.set(match1);
1725      table.set(match2);
1726    }
1727
1728    @Override
1729    public String toString() {
1730      return "CharMatcher.anyOf(\"" + showCharacter(match1) + showCharacter(match2) + "\")";
1731    }
1732  }
1733
1734  /** Implementation of {@link #anyOf(CharSequence)} for three or more characters. */
1735  private static final class AnyOf extends CharMatcher {
1736
1737    private final char[] chars;
1738
1739    public AnyOf(CharSequence chars) {
1740      this.chars = chars.toString().toCharArray();
1741      Arrays.sort(this.chars);
1742    }
1743
1744    @Override
1745    public boolean matches(char c) {
1746      return Arrays.binarySearch(chars, c) >= 0;
1747    }
1748
1749    @Override
1750    @GwtIncompatible // used only from other GwtIncompatible code
1751    void setBits(BitSet table) {
1752      for (char c : chars) {
1753        table.set(c);
1754      }
1755    }
1756
1757    @Override
1758    public String toString() {
1759      StringBuilder description = new StringBuilder("CharMatcher.anyOf(\"");
1760      for (char c : chars) {
1761        description.append(showCharacter(c));
1762      }
1763      description.append("\")");
1764      return description.toString();
1765    }
1766  }
1767
1768  /** Implementation of {@link #inRange(char, char)}. */
1769  private static final class InRange extends FastMatcher {
1770
1771    private final char startInclusive;
1772    private final char endInclusive;
1773
1774    InRange(char startInclusive, char endInclusive) {
1775      checkArgument(endInclusive >= startInclusive);
1776      this.startInclusive = startInclusive;
1777      this.endInclusive = endInclusive;
1778    }
1779
1780    @Override
1781    public boolean matches(char c) {
1782      return startInclusive <= c && c <= endInclusive;
1783    }
1784
1785    @GwtIncompatible // used only from other GwtIncompatible code
1786    @Override
1787    void setBits(BitSet table) {
1788      table.set(startInclusive, endInclusive + 1);
1789    }
1790
1791    @Override
1792    public String toString() {
1793      return "CharMatcher.inRange('"
1794          + showCharacter(startInclusive)
1795          + "', '"
1796          + showCharacter(endInclusive)
1797          + "')";
1798    }
1799  }
1800
1801  /** Implementation of {@link #forPredicate(Predicate)}. */
1802  private static final class ForPredicate extends CharMatcher {
1803
1804    private final Predicate<? super Character> predicate;
1805
1806    ForPredicate(Predicate<? super Character> predicate) {
1807      this.predicate = checkNotNull(predicate);
1808    }
1809
1810    @Override
1811    public boolean matches(char c) {
1812      return predicate.apply(c);
1813    }
1814
1815    @Override
1816    public String toString() {
1817      return "CharMatcher.forPredicate(" + predicate + ")";
1818    }
1819  }
1820}