    001    /*
    002     * Copyright (C) 2010 The Guava Authors
    003     *
    004     * Licensed under the Apache License, Version 2.0 (the "License");
    005     * you may not use this file except in compliance with the License.
    006     * You may obtain a copy of the License at
    007     *
    008     * http://www.apache.org/licenses/LICENSE-2.0
    009     *
    010     * Unless required by applicable law or agreed to in writing, software
    011     * distributed under the License is distributed on an "AS IS" BASIS,
    012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    013     * See the License for the specific language governing permissions and
    014     * limitations under the License.
    015     */
    016
    017    package com.google.common.base;
    018
    019    import static com.google.common.base.Preconditions.checkArgument;
    020    import static com.google.common.base.Preconditions.checkNotNull;
    021
    022    import com.google.common.annotations.GwtCompatible;
    023    import com.google.common.annotations.VisibleForTesting;
    024
    025    import java.util.Formatter;
    026
    027    import javax.annotation.Nullable;
    028
    029    /**
    030     * Static utility methods pertaining to {@code String} or {@code CharSequence}
    031     * instances.
    032     *
    033     * @author Kevin Bourrillion
    034     * @since 3.0
    035     */
    036    @GwtCompatible
    037    public final class Strings {
    038      private Strings() {}
    039
    040      /**
    041       * Returns the given string if it is non-null; the empty string otherwise.
    042       *
    043       * @param string the string to test and possibly return
    044       * @return {@code string} itself if it is non-null; {@code ""} if it is null
    045       */
    046      public static String nullToEmpty(@Nullable String string) {
    047        return (string == null) ? "" : string;
    048      }
    049
    050      /**
    051       * Returns the given string if it is nonempty; {@code null} otherwise.
    052       *
    053       * @param string the string to test and possibly return
    054       * @return {@code string} itself if it is nonempty; {@code null} if it is
    055       *     empty or null
    056       */
    057      public static @Nullable String emptyToNull(@Nullable String string) {
    058        return isNullOrEmpty(string) ? null : string;
    059      }
    060
    061      /**
    062       * Returns {@code true} if the given string is null or is the empty string.
    063       *
    064       * <p>Consider normalizing your string references with {@link #nullToEmpty}.
    065       * If you do, you can use {@link String#isEmpty()} instead of this
    066       * method, and you won't need special null-safe forms of methods like {@link
    067       * String#toUpperCase} either. Or, if you'd like to normalize "in the other
    068       * direction," converting empty strings to {@code null}, you can use {@link
    069       * #emptyToNull}.
    070       *
    071       * @param string a string reference to check
    072       * @return {@code true} if the string is null or is the empty string
    073       */
    074      public static boolean isNullOrEmpty(@Nullable String string) {
    075        return string == null || string.length() == 0; // string.isEmpty() in Java 6
    076      }
    077
    078      /**
    079       * Returns a string, of length at least {@code minLength}, consisting of
    080       * {@code string} prepended with as many copies of {@code padChar} as are
    081       * necessary to reach that length. For example,
    082       *
    083       * <ul>
    084       * <li>{@code padStart("7", 3, '0')} returns {@code "007"}
    085       * <li>{@code padStart("2010", 3, '0')} returns {@code "2010"}
    086       * </ul>
    087       *
    088       * <p>See {@link Formatter} for a richer set of formatting capabilities.
    089       *
    090       * @param string the string which should appear at the end of the result
    091       * @param minLength the minimum length the resulting string must have. Can be
    092       *     zero or negative, in which case the input string is always returned.
    093       * @param padChar the character to insert at the beginning of the result until
    094       *     the minimum length is reached
    095       * @return the padded string
    096       */
    097      public static String padStart(String string, int minLength, char padChar) {
    098        checkNotNull(string);  // eager for GWT.
    099        if (string.length() >= minLength) {
    100          return string;
    101        }
    102        StringBuilder sb = new StringBuilder(minLength);
    103        for (int i = string.length(); i < minLength; i++) {
    104          sb.append(padChar);
    105        }
    106        sb.append(string);
    107        return sb.toString();
    108      }
    109
    110      /**
    111       * Returns a string, of length at least {@code minLength}, consisting of
    112       * {@code string} appended with as many copies of {@code padChar} as are
    113       * necessary to reach that length. For example,
    114       *
    115       * <ul>
    116       * <li>{@code padEnd("4.", 5, '0')} returns {@code "4.000"}
    117       * <li>{@code padEnd("2010", 3, '!')} returns {@code "2010"}
    118       * </ul>
    119       *
    120       * <p>See {@link Formatter} for a richer set of formatting capabilities.
    121       *
    122       * @param string the string which should appear at the beginning of the result
    123       * @param minLength the minimum length the resulting string must have. Can be
    124       *     zero or negative, in which case the input string is always returned.
    125       * @param padChar the character to append to the end of the result until the
    126       *     minimum length is reached
    127       * @return the padded string
    128       */
    129      public static String padEnd(String string, int minLength, char padChar) {
    130        checkNotNull(string);  // eager for GWT.
    131        if (string.length() >= minLength) {
    132          return string;
    133        }
    134        StringBuilder sb = new StringBuilder(minLength);
    135        sb.append(string);
    136        for (int i = string.length(); i < minLength; i++) {
    137          sb.append(padChar);
    138        }
    139        return sb.toString();
    140      }
    141
    142      /**
    143       * Returns a string consisting of a specific number of concatenated copies of
    144       * an input string. For example, {@code repeat("hey", 3)} returns the string
    145       * {@code "heyheyhey"}.
    146       *
    147       * @param string any non-null string
    148       * @param count the number of times to repeat it; a nonnegative integer
    149       * @return a string containing {@code string} repeated {@code count} times
    150       *     (the empty string if {@code count} is zero)
    151       * @throws IllegalArgumentException if {@code count} is negative
    152       */
    153      public static String repeat(String string, int count) {
    154        checkNotNull(string);  // eager for GWT.
    155
    156        if (count <= 1) {
    157          checkArgument(count >= 0, "invalid count: %s", count);
    158          return (count == 0) ? "" : string;
    159        }
    160
    161        // IF YOU MODIFY THE CODE HERE, you must update StringsRepeatBenchmark
    162        final int len = string.length();
    163        final long longSize = (long) len * (long) count;
    164        final int size = (int) longSize;
    165        if (size != longSize) {
    166          throw new ArrayIndexOutOfBoundsException("Required array size too large: "
    167              + String.valueOf(longSize));
    168        }
    169
    170        final char[] array = new char[size];
    171        string.getChars(0, len, array, 0);
    172        int n;
    173        for (n = len; n < size - n; n <<= 1) {
    174          System.arraycopy(array, 0, array, n, n);
    175        }
    176        System.arraycopy(array, 0, array, n, size - n);
    177        return new String(array);
    178      }
    179
    180      /**
    181       * Returns the longest string {@code prefix} such that
    182       * {@code a.toString().startsWith(prefix) && b.toString().startsWith(prefix)},
    183       * taking care not to split surrogate pairs. If {@code a} and {@code b} have
    184       * no common prefix, returns the empty string.
    185       *
    186       * @since 11.0
    187       */
    188      public static String commonPrefix(CharSequence a, CharSequence b) {
    189        checkNotNull(a);
    190        checkNotNull(b);
    191
    192        int maxPrefixLength = Math.min(a.length(), b.length());
    193        int p = 0;
    194        while (p < maxPrefixLength && a.charAt(p) == b.charAt(p)) {
    195          p++;
    196        }
    197        if (validSurrogatePairAt(a, p - 1) || validSurrogatePairAt(b, p - 1)) {
    198          p--;
    199        }
    200        return a.subSequence(0, p).toString();
    201      }
    202
    203      /**
    204       * Returns the longest string {@code suffix} such that
    205       * {@code a.toString().endsWith(suffix) && b.toString().endsWith(suffix)},
    206       * taking care not to split surrogate pairs. If {@code a} and {@code b} have
    207       * no common suffix, returns the empty string.
    208       *
    209       * @since 11.0
    210       */
    211      public static String commonSuffix(CharSequence a, CharSequence b) {
    212        checkNotNull(a);
    213        checkNotNull(b);
    214
    215        int maxSuffixLength = Math.min(a.length(), b.length());
    216        int s = 0;
    217        while (s < maxSuffixLength
    218            && a.charAt(a.length() - s - 1) == b.charAt(b.length() - s - 1)) {
    219          s++;
    220        }
    221        if (validSurrogatePairAt(a, a.length() - s - 1)
    222            || validSurrogatePairAt(b, b.length() - s - 1)) {
    223          s--;
    224        }
    225        return a.subSequence(a.length() - s, a.length()).toString();
    226      }
    227
    228      /**
    229       * True when a valid surrogate pair starts at the given {@code index} in the
    230       * given {@code string}. Out-of-range indexes return false.
    231       */
    232      @VisibleForTesting
    233      static boolean validSurrogatePairAt(CharSequence string, int index) {
    234        return index >= 0 && index <= (string.length() - 2)
    235            && Character.isHighSurrogate(string.charAt(index))
    236            && Character.isLowSurrogate(string.charAt(index + 1));
    237      }
    238    }