001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.lang3;
018
019import java.io.UnsupportedEncodingException;
020import java.nio.CharBuffer;
021import java.nio.charset.Charset;
022import java.text.Normalizer;
023import java.util.ArrayList;
024import java.util.Arrays;
025import java.util.Iterator;
026import java.util.List;
027import java.util.Locale;
028import java.util.Objects;
029import java.util.Set;
030import java.util.function.Supplier;
031import java.util.regex.Pattern;
032import java.util.stream.Collectors;
033
034import org.apache.commons.lang3.function.Suppliers;
035import org.apache.commons.lang3.stream.LangCollectors;
036import org.apache.commons.lang3.stream.Streams;
037
038/**
039 * Operations on {@link String} that are
040 * {@code null} safe.
041 *
042 * <ul>
043 *  <li><strong>IsEmpty/IsBlank</strong>
044 *      - checks if a String contains text</li>
045 *  <li><strong>Trim/Strip</strong>
046 *      - removes leading and trailing whitespace</li>
047 *  <li><strong>Equals/Compare</strong>
048 *      - compares two strings in a null-safe manner</li>
049 *  <li><strong>startsWith</strong>
050 *      - check if a String starts with a prefix in a null-safe manner</li>
051 *  <li><strong>endsWith</strong>
052 *      - check if a String ends with a suffix in a null-safe manner</li>
053 *  <li><strong>IndexOf/LastIndexOf/Contains</strong>
054 *      - null-safe index-of checks</li>
055 *  <li><strong>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</strong>
056 *      - index-of any of a set of Strings</li>
057 *  <li><strong>ContainsOnly/ContainsNone/ContainsAny</strong>
058 *      - checks if String contains only/none/any of these characters</li>
059 *  <li><strong>Substring/Left/Right/Mid</strong>
060 *      - null-safe substring extractions</li>
061 *  <li><strong>SubstringBefore/SubstringAfter/SubstringBetween</strong>
062 *      - substring extraction relative to other strings</li>
063 *  <li><strong>Split/Join</strong>
064 *      - splits a String into an array of substrings and vice versa</li>
065 *  <li><strong>Remove/Delete</strong>
066 *      - removes part of a String</li>
067 *  <li><strong>Replace/Overlay</strong>
068 *      - Searches a String and replaces one String with another</li>
069 *  <li><strong>Chomp/Chop</strong>
070 *      - removes the last part of a String</li>
071 *  <li><strong>AppendIfMissing</strong>
072 *      - appends a suffix to the end of the String if not present</li>
073 *  <li><strong>PrependIfMissing</strong>
074 *      - prepends a prefix to the start of the String if not present</li>
075 *  <li><strong>LeftPad/RightPad/Center/Repeat</strong>
076 *      - pads a String</li>
077 *  <li><strong>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</strong>
078 *      - changes the case of a String</li>
079 *  <li><strong>CountMatches</strong>
080 *      - counts the number of occurrences of one String in another</li>
081 *  <li><strong>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</strong>
082 *      - checks the characters in a String</li>
083 *  <li><strong>DefaultString</strong>
084 *      - protects against a null input String</li>
085 *  <li><strong>Rotate</strong>
086 *      - rotate (circular shift) a String</li>
087 *  <li><strong>Reverse/ReverseDelimited</strong>
088 *      - reverses a String</li>
089 *  <li><strong>Abbreviate</strong>
090 *      - abbreviates a string using ellipses or another given String</li>
091 *  <li><strong>Difference</strong>
092 *      - compares Strings and reports on their differences</li>
093 *  <li><strong>LevenshteinDistance</strong>
094 *      - the number of changes needed to change one String into another</li>
095 * </ul>
096 *
097 * <p>The {@link StringUtils} class defines certain words related to
098 * String handling.</p>
099 *
100 * <ul>
101 *  <li>null - {@code null}</li>
102 *  <li>empty - a zero-length string ({@code ""})</li>
103 *  <li>space - the space character ({@code ' '}, char 32)</li>
104 *  <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
105 *  <li>trim - the characters &lt;= 32 as in {@link String#trim()}</li>
106 * </ul>
107 *
108 * <p>{@link StringUtils} handles {@code null} input Strings quietly.
109 * That is to say that a {@code null} input will return {@code null}.
110 * Where a {@code boolean} or {@code int} is being returned
111 * details vary by method.</p>
112 *
113 * <p>A side effect of the {@code null} handling is that a
114 * {@link NullPointerException} should be considered a bug in
115 * {@link StringUtils}.</p>
116 *
117 * <p>Methods in this class include sample code in their Javadoc comments to explain their operation.
118 * The symbol {@code *} is used to indicate any input including {@code null}.</p>
119 *
120 * <p>#ThreadSafe#</p>
121 *
122 * @see String
123 * @since 1.0
124 */
125//@Immutable
126public class StringUtils {
127
128    // Performance testing notes (JDK 1.4, Jul03, scolebourne)
129    // Whitespace:
130    // Character.isWhitespace() is faster than WHITESPACE.indexOf()
131    // where WHITESPACE is a string of all whitespace characters
132    //
133    // Character access:
134    // String.charAt(n) versus toCharArray(), then array[n]
135    // String.charAt(n) is about 15% worse for a 10K string
136    // They are about equal for a length 50 string
137    // String.charAt(n) is about 4 times better for a length 3 string
138    // String.charAt(n) is best bet overall
139    //
140    // Append:
141    // String.concat about twice as fast as StringBuffer.append
142    // (not sure who tested this)
143
144    /**
145     * This is a 3 character version of an ellipsis. There is a Unicode character for a HORIZONTAL ELLIPSIS, U+2026 '…', this isn't it.
146     */
147    private static final String ELLIPSIS3 = "...";
148
149    /**
150     * A String for a space character.
151     *
152     * @since 3.2
153     */
154    public static final String SPACE = " ";
155
156    /**
157     * The empty String {@code ""}.
158     *
159     * @since 2.0
160     */
161    public static final String EMPTY = "";
162
163    /**
164     * The null String {@code null}. Package-private only.
165     */
166    static final String NULL = null;
167
168    /**
169     * A String for linefeed LF ("\n").
170     *
171     * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
172     *      for Character and String Literals</a>
173     * @since 3.2
174     */
175    public static final String LF = "\n";
176
177    /**
178     * A String for carriage return CR ("\r").
179     *
180     * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
181     *      for Character and String Literals</a>
182     * @since 3.2
183     */
184    public static final String CR = "\r";
185
186    /**
187     * Represents a failed index search.
188     *
189     * @since 2.1
190     */
191    public static final int INDEX_NOT_FOUND = -1;
192
193    /**
194     * The maximum size to which the padding constant(s) can expand.
195     */
196    private static final int PAD_LIMIT = 8192;
197
198    /**
199     * The default maximum depth at which recursive replacement will continue until no further search replacements are possible.
200     */
201    private static final int DEFAULT_TTL = 5;
202
203    /**
204     * Pattern used in {@link #stripAccents(String)}.
205     */
206    private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$
207
208    /**
209     * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "Now is the time for..."
210     *
211     * <p>
212     * Specifically:
213     * </p>
214     * <ul>
215     * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li>
216     * <li>Else abbreviate it to {@code (substring(str, 0, max - 3) + "...")}.</li>
217     * <li>If {@code maxWidth} is less than {@code 4}, throw an {@link IllegalArgumentException}.</li>
218     * <li>In no case will it return a String of length greater than {@code maxWidth}.</li>
219     * </ul>
220     *
221     * <pre>
222     * StringUtils.abbreviate(null, *)      = null
223     * StringUtils.abbreviate("", 4)        = ""
224     * StringUtils.abbreviate("abcdefg", 6) = "abc..."
225     * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
226     * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
227     * StringUtils.abbreviate("abcdefg", 4) = "a..."
228     * StringUtils.abbreviate("abcdefg", 3) = Throws {@link IllegalArgumentException}.
229     * </pre>
230     *
231     * @param str      the String to check, may be null.
232     * @param maxWidth maximum length of result String, must be at least 4.
233     * @return abbreviated String, {@code null} if null String input.
234     * @throws IllegalArgumentException if the width is too small.
235     * @since 2.0
236     */
237    public static String abbreviate(final String str, final int maxWidth) {
238        return abbreviate(str, ELLIPSIS3, 0, maxWidth);
239    }
240
241    /**
242     * Abbreviates a String using ellipses. This will convert "Now is the time for all good men" into "...is the time for...".
243     *
244     * <p>
245     * Works like {@code abbreviate(String, int)}, but allows you to specify a "left edge" offset. Note that this left edge is not necessarily going to be the
246     * leftmost character in the result, or the first character following the ellipses, but it will appear somewhere in the result.
247     * </p>
248     * <p>
249     * In no case will it return a String of length greater than {@code maxWidth}.
250     * </p>
251     *
252     * <pre>
253     * StringUtils.abbreviate(null, *, *)                = null
254     * StringUtils.abbreviate("", 0, 4)                  = ""
255     * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
256     * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
257     * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
258     * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
259     * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
260     * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
261     * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
262     * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
263     * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
264     * StringUtils.abbreviate("abcdefghij", 0, 3)        = Throws {@link IllegalArgumentException}.
265     * StringUtils.abbreviate("abcdefghij", 5, 6)        = Throws {@link IllegalArgumentException}.
266     * </pre>
267     *
268     * @param str      the String to check, may be null.
269     * @param offset   left edge of source String.
270     * @param maxWidth maximum length of result String, must be at least 4.
271     * @return abbreviated String, {@code null} if null String input.
272     * @throws IllegalArgumentException if the width is too small.
273     * @since 2.0
274     */
275    public static String abbreviate(final String str, final int offset, final int maxWidth) {
276        return abbreviate(str, ELLIPSIS3, offset, maxWidth);
277    }
278
279    /**
280     * Abbreviates a String using another given String as replacement marker. This will convert "Now is the time for all good men" into "Now is the time for..."
281     * when "..." is the replacement marker.
282     *
283     * <p>
284     * Specifically:
285     * </p>
286     * <ul>
287     * <li>If the number of characters in {@code str} is less than or equal to {@code maxWidth}, return {@code str}.</li>
288     * <li>Else abbreviate it to {@code (substring(str, 0, max - abbrevMarker.length) + abbrevMarker)}.</li>
289     * <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an {@link IllegalArgumentException}.</li>
290     * <li>In no case will it return a String of length greater than {@code maxWidth}.</li>
291     * </ul>
292     *
293     * <pre>
294     * StringUtils.abbreviate(null, "...", *)      = null
295     * StringUtils.abbreviate("abcdefg", null, *)  = "abcdefg"
296     * StringUtils.abbreviate("", "...", 4)        = ""
297     * StringUtils.abbreviate("abcdefg", ".", 5)   = "abcd."
298     * StringUtils.abbreviate("abcdefg", ".", 7)   = "abcdefg"
299     * StringUtils.abbreviate("abcdefg", ".", 8)   = "abcdefg"
300     * StringUtils.abbreviate("abcdefg", "..", 4)  = "ab.."
301     * StringUtils.abbreviate("abcdefg", "..", 3)  = "a.."
302     * StringUtils.abbreviate("abcdefg", "..", 2)  = Throws {@link IllegalArgumentException}.
303     * StringUtils.abbreviate("abcdefg", "...", 3) = Throws {@link IllegalArgumentException}.
304     * </pre>
305     *
306     * @param str          the String to check, may be null.
307     * @param abbrevMarker the String used as replacement marker.
308     * @param maxWidth     maximum length of result String, must be at least {@code abbrevMarker.length + 1}.
309     * @return abbreviated String, {@code null} if null String input.
310     * @throws IllegalArgumentException if the width is too small.
311     * @since 3.6
312     */
313    public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) {
314        return abbreviate(str, abbrevMarker, 0, maxWidth);
315    }
316
317    /**
318     * Abbreviates a String using a given replacement marker. This will convert "Now is the time for all good men" into "...is the time for..." when "..." is
319     * the replacement marker.
320     * <p>
321     * Works like {@code abbreviate(String, String, int)}, but allows you to specify a "left edge" offset. Note that this left edge is not necessarily going to
322     * be the leftmost character in the result, or the first character following the replacement marker, but it will appear somewhere in the result.
323     * </p>
324     * <p>
325     * In no case will it return a String of length greater than {@code maxWidth}.
326     * </p>
327     *
328     * <pre>
329     * StringUtils.abbreviate(null, null, *, *)                 = null
330     * StringUtils.abbreviate("abcdefghijklmno", null, *, *)    = "abcdefghijklmno"
331     * StringUtils.abbreviate("", "...", 0, 4)                  = ""
332     * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---"
333     * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10)    = "abcdefghi,"
334     * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10)    = "abcdefghi,"
335     * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10)    = "abcdefghi,"
336     * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10)   = "::efghij::"
337     * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10)  = "...ghij..."
338     * StringUtils.abbreviate("abcdefghijklmno", "…", 6, 10)    = "…ghij…"
339     * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10)    = "*ghijklmno"
340     * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10)   = "'ghijklmno"
341     * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10)   = "!ghijklmno"
342     * StringUtils.abbreviate("abcdefghij", "abra", 0, 4)       = Throws {@link IllegalArgumentException}.
343     * StringUtils.abbreviate("abcdefghij", "...", 5, 6)        = Throws {@link IllegalArgumentException}.
344     * </pre>
345     *
346     * @param str          the String to check, may be null.
347     * @param abbrevMarker the String used as replacement marker, for example "...", or Unicode HORIZONTAL ELLIPSIS, U+2026 '…'.
348     * @param offset       left edge of source String.
349     * @param maxWidth     maximum length of result String, must be at least 4.
350     * @return abbreviated String, {@code null} if null String input.
351     * @throws IllegalArgumentException if the width is too small.
352     * @since 3.6
353     */
354    public static String abbreviate(final String str, String abbrevMarker, int offset, final int maxWidth) {
355        if (isEmpty(str)) {
356            return str;
357        }
358        if (abbrevMarker == null) {
359            abbrevMarker = EMPTY;
360        }
361        final int abbrevMarkerLength = abbrevMarker.length();
362        final int minAbbrevWidth = abbrevMarkerLength + 1;
363        final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1;
364
365        if (maxWidth < minAbbrevWidth) {
366            throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth));
367        }
368        final int strLen = str.length();
369        if (strLen <= maxWidth) {
370            return str;
371        }
372        if (strLen - offset <= maxWidth - abbrevMarkerLength) {
373            return abbrevMarker + str.substring(strLen - (maxWidth - abbrevMarkerLength));
374        }
375        if (offset <= abbrevMarkerLength + 1) {
376            return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker;
377        }
378        if (maxWidth < minAbbrevWidthOffset) {
379            throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset));
380        }
381        return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength);
382    }
383
384    /**
385     * Abbreviates a String to the length passed, replacing the middle characters with the supplied replacement String.
386     *
387     * <p>
388     * This abbreviation only occurs if the following criteria is met:
389     * </p>
390     * <ul>
391     * <li>Neither the String for abbreviation nor the replacement String are null or empty</li>
392     * <li>The length to truncate to is less than the length of the supplied String</li>
393     * <li>The length to truncate to is greater than 0</li>
394     * <li>The abbreviated String will have enough room for the length supplied replacement String and the first and last characters of the supplied String for
395     * abbreviation</li>
396     * </ul>
397     * <p>
398     * Otherwise, the returned String will be the same as the supplied String for abbreviation.
399     * </p>
400     *
401     * <pre>
402     * StringUtils.abbreviateMiddle(null, null, 0)    = null
403     * StringUtils.abbreviateMiddle("abc", null, 0)   = "abc"
404     * StringUtils.abbreviateMiddle("abc", ".", 0)    = "abc"
405     * StringUtils.abbreviateMiddle("abc", ".", 3)    = "abc"
406     * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f"
407     * </pre>
408     *
409     * @param str    the String to abbreviate, may be null.
410     * @param middle the String to replace the middle characters with, may be null.
411     * @param length the length to abbreviate {@code str} to.
412     * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
413     * @since 2.5
414     */
415    public static String abbreviateMiddle(final String str, final String middle, final int length) {
416        if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length() + 2) {
417            return str;
418        }
419        final int targetString = length - middle.length();
420        final int startOffset = targetString / 2 + targetString % 2;
421        final int endOffset = str.length() - targetString / 2;
422        return str.substring(0, startOffset) + middle + str.substring(endOffset);
423    }
424
425    /**
426     * Appends the suffix to the end of the string if the string does not already end with any of the suffixes.
427     *
428     * <pre>
429     * StringUtils.appendIfMissing(null, null)      = null
430     * StringUtils.appendIfMissing("abc", null)     = "abc"
431     * StringUtils.appendIfMissing("", "xyz"        = "xyz"
432     * StringUtils.appendIfMissing("abc", "xyz")    = "abcxyz"
433     * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz"
434     * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz"
435     * </pre>
436     * <p>
437     * With additional suffixes,
438     * </p>
439     *
440     * <pre>
441     * StringUtils.appendIfMissing(null, null, null)       = null
442     * StringUtils.appendIfMissing("abc", null, null)      = "abc"
443     * StringUtils.appendIfMissing("", "xyz", null)        = "xyz"
444     * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
445     * StringUtils.appendIfMissing("abc", "xyz", "")       = "abc"
446     * StringUtils.appendIfMissing("abc", "xyz", "mno")    = "abcxyz"
447     * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz"
448     * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno"
449     * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz"
450     * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz"
451     * </pre>
452     *
453     * @param str      The string.
454     * @param suffix   The suffix to append to the end of the string.
455     * @param suffixes Additional suffixes that are valid terminators.
456     * @return A new String if suffix was appended, the same string otherwise.
457     * @since 3.2
458     * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CS.appendIfMissing(String, CharSequence, CharSequence...)}.
459     */
460    @Deprecated
461    public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) {
462        return Strings.CS.appendIfMissing(str, suffix, suffixes);
463    }
464
465    /**
466     * Appends the suffix to the end of the string if the string does not
467     * already end, case-insensitive, with any of the suffixes.
468     *
469     * <pre>
470     * StringUtils.appendIfMissingIgnoreCase(null, null)      = null
471     * StringUtils.appendIfMissingIgnoreCase("abc", null)     = "abc"
472     * StringUtils.appendIfMissingIgnoreCase("", "xyz")       = "xyz"
473     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz")    = "abcxyz"
474     * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz"
475     * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ"
476     * </pre>
477     * <p>With additional suffixes,</p>
478     * <pre>
479     * StringUtils.appendIfMissingIgnoreCase(null, null, null)       = null
480     * StringUtils.appendIfMissingIgnoreCase("abc", null, null)      = "abc"
481     * StringUtils.appendIfMissingIgnoreCase("", "xyz", null)        = "xyz"
482     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
483     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "")       = "abc"
484     * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno")    = "abcxyz"
485     * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz"
486     * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno"
487     * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ"
488     * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO"
489     * </pre>
490     *
491     * @param str The string.
492     * @param suffix The suffix to append to the end of the string.
493     * @param suffixes Additional suffixes that are valid terminators.
494     * @return A new String if suffix was appended, the same string otherwise.
495     * @since 3.2
496     * @deprecated Use {@link Strings#appendIfMissing(String, CharSequence, CharSequence...) Strings.CI.appendIfMissing(String, CharSequence, CharSequence...)}.
497     */
498    @Deprecated
499    public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) {
500        return Strings.CI.appendIfMissing(str, suffix, suffixes);
501    }
502
503    /**
504     * Computes the capacity required for a StringBuilder to hold {@code items} of {@code maxElementChars} characters plus the separators between them. The
505     * separator is assumed to be 1 character.
506     *
507     * @param count           The number of items.
508     * @param maxElementChars The maximum number of characters per item.
509     * @return A StringBuilder with the appropriate capacity.
510     */
511    private static StringBuilder capacity(final int count, final byte maxElementChars) {
512        return new StringBuilder(count * maxElementChars + count - 1);
513    }
514
515    /**
516     * Capitalizes a String changing the first character to title case as per {@link Character#toTitleCase(int)}. No other characters are changed.
517     *
518     * <p>
519     * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#capitalize(String)}. A {@code null} input String returns {@code null}.
520     * </p>
521     *
522     * <pre>
523     * StringUtils.capitalize(null)    = null
524     * StringUtils.capitalize("")      = ""
525     * StringUtils.capitalize("cat")   = "Cat"
526     * StringUtils.capitalize("cAt")   = "CAt"
527     * StringUtils.capitalize("'cat'") = "'cat'"
528     * </pre>
529     *
530     * @param str the String to capitalize, may be null.
531     * @return the capitalized String, {@code null} if null String input.
532     * @see org.apache.commons.text.WordUtils#capitalize(String)
533     * @see #uncapitalize(String)
534     * @since 2.0
535     */
536    public static String capitalize(final String str) {
537        if (isEmpty(str)) {
538            return str;
539        }
540        final int firstCodepoint = str.codePointAt(0);
541        final int newCodePoint = Character.toTitleCase(firstCodepoint);
542        if (firstCodepoint == newCodePoint) {
543            // already capitalized
544            return str;
545        }
546        final int[] newCodePoints = str.codePoints().toArray();
547        newCodePoints[0] = newCodePoint; // copy the first code point
548        return new String(newCodePoints, 0, newCodePoints.length);
549    }
550
551    /**
552     * Centers a String in a larger String of size {@code size} using the space character (' ').
553     *
554     * <p>
555     * If the size is less than the String length, the original String is returned. A {@code null} String returns {@code null}. A negative size is treated as
556     * zero.
557     * </p>
558     *
559     * <p>
560     * Equivalent to {@code center(str, size, " ")}.
561     * </p>
562     *
563     * <pre>
564     * StringUtils.center(null, *)   = null
565     * StringUtils.center("", 4)     = "    "
566     * StringUtils.center("ab", -1)  = "ab"
567     * StringUtils.center("ab", 4)   = " ab "
568     * StringUtils.center("abcd", 2) = "abcd"
569     * StringUtils.center("a", 4)    = " a  "
570     * </pre>
571     *
572     * @param str  the String to center, may be null.
573     * @param size the int size of new String, negative treated as zero.
574     * @return centered String, {@code null} if null String input.
575     */
576    public static String center(final String str, final int size) {
577        return center(str, size, ' ');
578    }
579
580    /**
581     * Centers a String in a larger String of size {@code size}. Uses a supplied character as the value to pad the String with.
582     *
583     * <p>
584     * If the size is less than the String length, the String is returned. A {@code null} String returns {@code null}. A negative size is treated as zero.
585     * </p>
586     *
587     * <pre>
588     * StringUtils.center(null, *, *)     = null
589     * StringUtils.center("", 4, ' ')     = "    "
590     * StringUtils.center("ab", -1, ' ')  = "ab"
591     * StringUtils.center("ab", 4, ' ')   = " ab "
592     * StringUtils.center("abcd", 2, ' ') = "abcd"
593     * StringUtils.center("a", 4, ' ')    = " a  "
594     * StringUtils.center("a", 4, 'y')    = "yayy"
595     * </pre>
596     *
597     * @param str     the String to center, may be null.
598     * @param size    the int size of new String, negative treated as zero.
599     * @param padChar the character to pad the new String with.
600     * @return centered String, {@code null} if null String input.
601     * @since 2.0
602     */
603    public static String center(String str, final int size, final char padChar) {
604        if (str == null || size <= 0) {
605            return str;
606        }
607        final int strLen = str.length();
608        final int pads = size - strLen;
609        if (pads <= 0) {
610            return str;
611        }
612        str = leftPad(str, strLen + pads / 2, padChar);
613        return rightPad(str, size, padChar);
614    }
615
616    /**
617     * Centers a String in a larger String of size {@code size}. Uses a supplied String as the value to pad the String with.
618     *
619     * <p>
620     * If the size is less than the String length, the String is returned. A {@code null} String returns {@code null}. A negative size is treated as zero.
621     * </p>
622     *
623     * <pre>
624     * StringUtils.center(null, *, *)     = null
625     * StringUtils.center("", 4, " ")     = "    "
626     * StringUtils.center("ab", -1, " ")  = "ab"
627     * StringUtils.center("ab", 4, " ")   = " ab "
628     * StringUtils.center("abcd", 2, " ") = "abcd"
629     * StringUtils.center("a", 4, " ")    = " a  "
630     * StringUtils.center("a", 4, "yz")   = "yayz"
631     * StringUtils.center("abc", 7, null) = "  abc  "
632     * StringUtils.center("abc", 7, "")   = "  abc  "
633     * </pre>
634     *
635     * @param str    the String to center, may be null.
636     * @param size   the int size of new String, negative treated as zero.
637     * @param padStr the String to pad the new String with, must not be null or empty.
638     * @return centered String, {@code null} if null String input.
639     * @throws IllegalArgumentException if padStr is {@code null} or empty.
640     */
641    public static String center(String str, final int size, String padStr) {
642        if (str == null || size <= 0) {
643            return str;
644        }
645        if (isEmpty(padStr)) {
646            padStr = SPACE;
647        }
648        final int strLen = str.length();
649        final int pads = size - strLen;
650        if (pads <= 0) {
651            return str;
652        }
653        str = leftPad(str, strLen + pads / 2, padStr);
654        return rightPad(str, size, padStr);
655    }
656
657    /**
658     * Removes one newline from end of a String if it's there, otherwise leave it alone. A newline is &quot;{@code \n}&quot;, &quot;{@code \r}&quot;, or
659     * &quot;{@code \r\n}&quot;.
660     *
661     * <p>
662     * NOTE: This method changed in 2.0. It now more closely matches Perl chomp.
663     * </p>
664     *
665     * <pre>
666     * StringUtils.chomp(null)          = null
667     * StringUtils.chomp("")            = ""
668     * StringUtils.chomp("abc \r")      = "abc "
669     * StringUtils.chomp("abc\n")       = "abc"
670     * StringUtils.chomp("abc\r\n")     = "abc"
671     * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
672     * StringUtils.chomp("abc\n\r")     = "abc\n"
673     * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
674     * StringUtils.chomp("\r")          = ""
675     * StringUtils.chomp("\n")          = ""
676     * StringUtils.chomp("\r\n")        = ""
677     * </pre>
678     *
679     * @param str the String to chomp a newline from, may be null.
680     * @return String without newline, {@code null} if null String input.
681     */
682    public static String chomp(final String str) {
683        if (isEmpty(str)) {
684            return str;
685        }
686        if (str.length() == 1) {
687            final char ch = str.charAt(0);
688            if (ch == CharUtils.CR || ch == CharUtils.LF) {
689                return EMPTY;
690            }
691            return str;
692        }
693        int lastIdx = str.length() - 1;
694        final char last = str.charAt(lastIdx);
695        if (last == CharUtils.LF) {
696            if (str.charAt(lastIdx - 1) == CharUtils.CR) {
697                lastIdx--;
698            }
699        } else if (last != CharUtils.CR) {
700            lastIdx++;
701        }
702        return str.substring(0, lastIdx);
703    }
704
705    /**
706     * Removes {@code separator} from the end of {@code str} if it's there, otherwise leave it alone.
707     *
708     * <p>
709     * NOTE: This method changed in version 2.0. It now more closely matches Perl chomp. For the previous behavior, use
710     * {@link #substringBeforeLast(String, String)}. This method uses {@link String#endsWith(String)}.
711     * </p>
712     *
713     * <pre>
714     * StringUtils.chomp(null, *)         = null
715     * StringUtils.chomp("", *)           = ""
716     * StringUtils.chomp("foobar", "bar") = "foo"
717     * StringUtils.chomp("foobar", "baz") = "foobar"
718     * StringUtils.chomp("foo", "foo")    = ""
719     * StringUtils.chomp("foo ", "foo")   = "foo "
720     * StringUtils.chomp(" foo", "foo")   = " "
721     * StringUtils.chomp("foo", "foooo")  = "foo"
722     * StringUtils.chomp("foo", "")       = "foo"
723     * StringUtils.chomp("foo", null)     = "foo"
724     * </pre>
725     *
726     * @param str       the String to chomp from, may be null.
727     * @param separator separator String, may be null.
728     * @return String without trailing separator, {@code null} if null String input.
729     * @deprecated This feature will be removed in Lang 4, use {@link StringUtils#removeEnd(String, String)} instead.
730     */
731    @Deprecated
732    public static String chomp(final String str, final String separator) {
733        return Strings.CS.removeEnd(str, separator);
734    }
735
736    /**
737     * Removes the last character from a String.
738     *
739     * <p>
740     * If the String ends in {@code \r\n}, then remove both of them.
741     * </p>
742     *
743     * <pre>
744     * StringUtils.chop(null)          = null
745     * StringUtils.chop("")            = ""
746     * StringUtils.chop("abc \r")      = "abc "
747     * StringUtils.chop("abc\n")       = "abc"
748     * StringUtils.chop("abc\r\n")     = "abc"
749     * StringUtils.chop("abc")         = "ab"
750     * StringUtils.chop("abc\nabc")    = "abc\nab"
751     * StringUtils.chop("a")           = ""
752     * StringUtils.chop("\r")          = ""
753     * StringUtils.chop("\n")          = ""
754     * StringUtils.chop("\r\n")        = ""
755     * </pre>
756     *
757     * @param str the String to chop last character from, may be null.
758     * @return String without last character, {@code null} if null String input.
759     */
760    public static String chop(final String str) {
761        if (str == null) {
762            return null;
763        }
764        final int strLen = str.length();
765        if (strLen < 2) {
766            return EMPTY;
767        }
768        final int lastIdx = strLen - 1;
769        final String ret = str.substring(0, lastIdx);
770        final char last = str.charAt(lastIdx);
771        if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
772            return ret.substring(0, lastIdx - 1);
773        }
774        return ret;
775    }
776
777    /**
778     * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
779     * <ul>
780     * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
781     * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
782     * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
783     * </ul>
784     *
785     * <p>
786     * This is a {@code null} safe version of:
787     * </p>
788     *
789     * <pre>
790     * str1.compareTo(str2)
791     * </pre>
792     *
793     * <p>
794     * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal.
795     * </p>
796     *
797     * <pre>{@code
798     * StringUtils.compare(null, null)   = 0
799     * StringUtils.compare(null , "a")   < 0
800     * StringUtils.compare("a", null)   > 0
801     * StringUtils.compare("abc", "abc") = 0
802     * StringUtils.compare("a", "b")     < 0
803     * StringUtils.compare("b", "a")     > 0
804     * StringUtils.compare("a", "B")     > 0
805     * StringUtils.compare("ab", "abc")  < 0
806     * }</pre>
807     *
808     * @param str1 the String to compare from.
809     * @param str2 the String to compare to.
810     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal or greater than {@code str2}.
811     * @see #compare(String, String, boolean)
812     * @see String#compareTo(String)
813     * @since 3.5
814     * @deprecated Use {@link Strings#compare(String, String) Strings.CS.compare(String, String)}.
815     */
816    @Deprecated
817    public static int compare(final String str1, final String str2) {
818        return Strings.CS.compare(str1, str2);
819    }
820
821    /**
822     * Compares two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
823     * <ul>
824     * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
825     * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
826     * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
827     * </ul>
828     *
829     * <p>
830     * This is a {@code null} safe version of :
831     * </p>
832     *
833     * <pre>
834     * str1.compareTo(str2)
835     * </pre>
836     *
837     * <p>
838     * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal.
839     * </p>
840     *
841     * <pre>{@code
842     * StringUtils.compare(null, null, *)     = 0
843     * StringUtils.compare(null , "a", true)  < 0
844     * StringUtils.compare(null , "a", false) > 0
845     * StringUtils.compare("a", null, true)   > 0
846     * StringUtils.compare("a", null, false)  < 0
847     * StringUtils.compare("abc", "abc", *)   = 0
848     * StringUtils.compare("a", "b", *)       < 0
849     * StringUtils.compare("b", "a", *)       > 0
850     * StringUtils.compare("a", "B", *)       > 0
851     * StringUtils.compare("ab", "abc", *)    < 0
852     * }</pre>
853     *
854     * @param str1       the String to compare from.
855     * @param str2       the String to compare to.
856     * @param nullIsLess whether consider {@code null} value less than non-{@code null} value.
857     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2}.
858     * @see String#compareTo(String)
859     * @since 3.5
860     */
861    public static int compare(final String str1, final String str2, final boolean nullIsLess) {
862        if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null
863            return 0;
864        }
865        if (str1 == null) {
866            return nullIsLess ? -1 : 1;
867        }
868        if (str2 == null) {
869            return nullIsLess ? 1 : -1;
870        }
871        return str1.compareTo(str2);
872    }
873
874    /**
875     * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning :
876     * <ul>
877     * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
878     * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
879     * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
880     * </ul>
881     *
882     * <p>
883     * This is a {@code null} safe version of:
884     * </p>
885     *
886     * <pre>
887     * str1.compareToIgnoreCase(str2)
888     * </pre>
889     *
890     * <p>
891     * {@code null} value is considered less than non-{@code null} value. Two {@code null} references are considered equal. Comparison is case insensitive.
892     * </p>
893     *
894     * <pre>{@code
895     * StringUtils.compareIgnoreCase(null, null)   = 0
896     * StringUtils.compareIgnoreCase(null , "a")   < 0
897     * StringUtils.compareIgnoreCase("a", null)    > 0
898     * StringUtils.compareIgnoreCase("abc", "abc") = 0
899     * StringUtils.compareIgnoreCase("abc", "ABC") = 0
900     * StringUtils.compareIgnoreCase("a", "b")     < 0
901     * StringUtils.compareIgnoreCase("b", "a")     > 0
902     * StringUtils.compareIgnoreCase("a", "B")     < 0
903     * StringUtils.compareIgnoreCase("A", "b")     < 0
904     * StringUtils.compareIgnoreCase("ab", "ABC")  < 0
905     * }</pre>
906     *
907     * @param str1 the String to compare from.
908     * @param str2 the String to compare to.
909     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences.
910     * @see #compareIgnoreCase(String, String, boolean)
911     * @see String#compareToIgnoreCase(String)
912     * @since 3.5
913     * @deprecated Use {@link Strings#compare(String, String) Strings.CI.compare(String, String)}.
914     */
915    @Deprecated
916    public static int compareIgnoreCase(final String str1, final String str2) {
917        return Strings.CI.compare(str1, str2);
918    }
919
920    /**
921     * Compares two Strings lexicographically, ignoring case differences, as per {@link String#compareToIgnoreCase(String)}, returning :
922     * <ul>
923     * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
924     * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
925     * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
926     * </ul>
927     *
928     * <p>
929     * This is a {@code null} safe version of :
930     * </p>
931     * <pre>
932     * str1.compareToIgnoreCase(str2)
933     * </pre>
934     *
935     * <p>
936     * {@code null} inputs are handled according to the {@code nullIsLess} parameter. Two {@code null} references are considered equal. Comparison is case
937     * insensitive.
938     * </p>
939     *
940     * <pre>{@code
941     * StringUtils.compareIgnoreCase(null, null, *)     = 0
942     * StringUtils.compareIgnoreCase(null , "a", true)  < 0
943     * StringUtils.compareIgnoreCase(null , "a", false) > 0
944     * StringUtils.compareIgnoreCase("a", null, true)   > 0
945     * StringUtils.compareIgnoreCase("a", null, false)  < 0
946     * StringUtils.compareIgnoreCase("abc", "abc", *)   = 0
947     * StringUtils.compareIgnoreCase("abc", "ABC", *)   = 0
948     * StringUtils.compareIgnoreCase("a", "b", *)       < 0
949     * StringUtils.compareIgnoreCase("b", "a", *)       > 0
950     * StringUtils.compareIgnoreCase("a", "B", *)       < 0
951     * StringUtils.compareIgnoreCase("A", "b", *)       < 0
952     * StringUtils.compareIgnoreCase("ab", "abc", *)    < 0
953     * }</pre>
954     *
955     * @param str1       the String to compare from.
956     * @param str2       the String to compare to.
957     * @param nullIsLess whether consider {@code null} value less than non-{@code null} value.
958     * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, ignoring case differences.
959     * @see String#compareToIgnoreCase(String)
960     * @since 3.5
961     */
962    public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) {
963        if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null
964            return 0;
965        }
966        if (str1 == null) {
967            return nullIsLess ? -1 : 1;
968        }
969        if (str2 == null) {
970            return nullIsLess ? 1 : -1;
971        }
972        return str1.compareToIgnoreCase(str2);
973    }
974
975    /**
976     * Tests if CharSequence contains a search CharSequence, handling {@code null}.
977     * This method uses {@link String#indexOf(String)} if possible.
978     *
979     * <p>A {@code null} CharSequence will return {@code false}.</p>
980     *
981     * <pre>
982     * StringUtils.contains(null, *)     = false
983     * StringUtils.contains(*, null)     = false
984     * StringUtils.contains("", "")      = true
985     * StringUtils.contains("abc", "")   = true
986     * StringUtils.contains("abc", "a")  = true
987     * StringUtils.contains("abc", "z")  = false
988     * </pre>
989     *
990     * @param seq  the CharSequence to check, may be null
991     * @param searchSeq  the CharSequence to find, may be null
992     * @return true if the CharSequence contains the search CharSequence,
993     *  false if not or {@code null} string input
994     * @since 2.0
995     * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence)
996     * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CS.contains(CharSequence, CharSequence)}.
997     */
998    @Deprecated
999    public static boolean contains(final CharSequence seq, final CharSequence searchSeq) {
1000        return Strings.CS.contains(seq, searchSeq);
1001    }
1002
1003    /**
1004     * Tests if CharSequence contains a search character, handling {@code null}. This method uses {@link String#indexOf(int)} if possible.
1005     *
1006     * <p>
1007     * A {@code null} or empty ("") CharSequence will return {@code false}.
1008     * </p>
1009     *
1010     * <pre>
1011     * StringUtils.contains(null, *)    = false
1012     * StringUtils.contains("", *)      = false
1013     * StringUtils.contains("abc", 'a') = true
1014     * StringUtils.contains("abc", 'z') = false
1015     * </pre>
1016     *
1017     * @param seq        the CharSequence to check, may be null
1018     * @param searchChar the character to find
1019     * @return true if the CharSequence contains the search character, false if not or {@code null} string input
1020     * @since 2.0
1021     * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int)
1022     */
1023    public static boolean contains(final CharSequence seq, final int searchChar) {
1024        if (isEmpty(seq)) {
1025            return false;
1026        }
1027        return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0;
1028    }
1029
1030    /**
1031     * Tests if the CharSequence contains any character in the given set of characters.
1032     *
1033     * <p>
1034     * A {@code null} CharSequence will return {@code false}. A {@code null} or zero length search array will return {@code false}.
1035     * </p>
1036     *
1037     * <pre>
1038     * StringUtils.containsAny(null, *)                  = false
1039     * StringUtils.containsAny("", *)                    = false
1040     * StringUtils.containsAny(*, null)                  = false
1041     * StringUtils.containsAny(*, [])                    = false
1042     * StringUtils.containsAny("zzabyycdxx", 'z', 'a')   = true
1043     * StringUtils.containsAny("zzabyycdxx", 'b', 'y')   = true
1044     * StringUtils.containsAny("zzabyycdxx", 'z', 'y')   = true
1045     * StringUtils.containsAny("aba", 'z])               = false
1046     * </pre>
1047     *
1048     * @param cs          the CharSequence to check, may be null.
1049     * @param searchChars the chars to search for, may be null.
1050     * @return the {@code true} if any of the chars are found, {@code false} if no match or null input.
1051     * @since 2.4
1052     * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...)
1053     */
1054    public static boolean containsAny(final CharSequence cs, final char... searchChars) {
1055        if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
1056            return false;
1057        }
1058        final int csLength = cs.length();
1059        final int searchLength = searchChars.length;
1060        final int csLast = csLength - 1;
1061        final int searchLast = searchLength - 1;
1062        for (int i = 0; i < csLength; i++) {
1063            final char ch = cs.charAt(i);
1064            for (int j = 0; j < searchLength; j++) {
1065                if (searchChars[j] == ch) {
1066                    if (!Character.isHighSurrogate(ch) || j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
1067                        return true;
1068                    }
1069                }
1070            }
1071        }
1072        return false;
1073    }
1074
1075    /**
1076     * Tests if the CharSequence contains any character in the given set of characters.
1077     *
1078     * <p>
1079     * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return {@code false}.
1080     * </p>
1081     *
1082     * <pre>
1083     * StringUtils.containsAny(null, *)               = false
1084     * StringUtils.containsAny("", *)                 = false
1085     * StringUtils.containsAny(*, null)               = false
1086     * StringUtils.containsAny(*, "")                 = false
1087     * StringUtils.containsAny("zzabyycdxx", "za")    = true
1088     * StringUtils.containsAny("zzabyycdxx", "by")    = true
1089     * StringUtils.containsAny("zzabyycdxx", "zy")    = true
1090     * StringUtils.containsAny("zzabyycdxx", "\tx")   = true
1091     * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true
1092     * StringUtils.containsAny("aba", "z")            = false
1093     * </pre>
1094     *
1095     * @param cs          the CharSequence to check, may be null.
1096     * @param searchChars the chars to search for, may be null.
1097     * @return the {@code true} if any of the chars are found, {@code false} if no match or null input.
1098     * @since 2.4
1099     * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence)
1100     */
1101    public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) {
1102        if (searchChars == null) {
1103            return false;
1104        }
1105        return containsAny(cs, CharSequenceUtils.toCharArray(searchChars));
1106    }
1107
1108    /**
1109     * Tests if the CharSequence contains any of the CharSequences in the given array.
1110     *
1111     * <p>
1112     * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will
1113     * return {@code false}.
1114     * </p>
1115     *
1116     * <pre>
1117     * StringUtils.containsAny(null, *)            = false
1118     * StringUtils.containsAny("", *)              = false
1119     * StringUtils.containsAny(*, null)            = false
1120     * StringUtils.containsAny(*, [])              = false
1121     * StringUtils.containsAny("abcd", "ab", null) = true
1122     * StringUtils.containsAny("abcd", "ab", "cd") = true
1123     * StringUtils.containsAny("abc", "d", "abc")  = true
1124     * </pre>
1125     *
1126     * @param cs The CharSequence to check, may be null.
1127     * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be
1128     *        null as well.
1129     * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise.
1130     * @since 3.4
1131     * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CS.containsAny(CharSequence, CharSequence...)}.
1132     */
1133    @Deprecated
1134    public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) {
1135        return Strings.CS.containsAny(cs, searchCharSequences);
1136    }
1137
1138    /**
1139     * Tests if the CharSequence contains any of the CharSequences in the given array, ignoring case.
1140     *
1141     * <p>
1142     * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will
1143     * return {@code false}.
1144     * </p>
1145     *
1146     * <pre>
1147     * StringUtils.containsAny(null, *)            = false
1148     * StringUtils.containsAny("", *)              = false
1149     * StringUtils.containsAny(*, null)            = false
1150     * StringUtils.containsAny(*, [])              = false
1151     * StringUtils.containsAny("abcd", "ab", null) = true
1152     * StringUtils.containsAny("abcd", "ab", "cd") = true
1153     * StringUtils.containsAny("abc", "d", "abc")  = true
1154     * StringUtils.containsAny("abc", "D", "ABC")  = true
1155     * StringUtils.containsAny("ABC", "d", "abc")  = true
1156     * </pre>
1157     *
1158     * @param cs The CharSequence to check, may be null.
1159     * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be
1160     *        null as well.
1161     * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
1162     * @since 3.12.0
1163     * @deprecated Use {@link Strings#containsAny(CharSequence, CharSequence...) Strings.CI.containsAny(CharSequence, CharSequence...)}.
1164     */
1165    @Deprecated
1166    public static boolean containsAnyIgnoreCase(final CharSequence cs, final CharSequence... searchCharSequences) {
1167        return Strings.CI.containsAny(cs, searchCharSequences);
1168    }
1169
1170    /**
1171     * Tests if CharSequence contains a search CharSequence irrespective of case, handling {@code null}. Case-insensitivity is defined as by
1172     * {@link String#equalsIgnoreCase(String)}.
1173     *
1174     * <p>
1175     * A {@code null} CharSequence will return {@code false}.
1176     * </p>
1177     *
1178     * <pre>
1179     * StringUtils.containsIgnoreCase(null, *)    = false
1180     * StringUtils.containsIgnoreCase(*, null)    = false
1181     * StringUtils.containsIgnoreCase("", "")     = true
1182     * StringUtils.containsIgnoreCase("abc", "")  = true
1183     * StringUtils.containsIgnoreCase("abc", "a") = true
1184     * StringUtils.containsIgnoreCase("abc", "z") = false
1185     * StringUtils.containsIgnoreCase("abc", "A") = true
1186     * StringUtils.containsIgnoreCase("abc", "Z") = false
1187     * </pre>
1188     *
1189     * @param str       the CharSequence to check, may be null.
1190     * @param searchStr the CharSequence to find, may be null.
1191     * @return true if the CharSequence contains the search CharSequence irrespective of case or false if not or {@code null} string input.
1192     * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence).
1193     * @deprecated Use {@link Strings#contains(CharSequence, CharSequence) Strings.CI.contains(CharSequence, CharSequence)}.
1194     */
1195    @Deprecated
1196    public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
1197        return Strings.CI.contains(str, searchStr);
1198    }
1199
1200    /**
1201     * Tests that the CharSequence does not contain certain characters.
1202     *
1203     * <p>
1204     * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty CharSequence (length()=0)
1205     * always returns true.
1206     * </p>
1207     *
1208     * <pre>
1209     * StringUtils.containsNone(null, *)               = true
1210     * StringUtils.containsNone(*, null)               = true
1211     * StringUtils.containsNone("", *)                 = true
1212     * StringUtils.containsNone("ab", '')              = true
1213     * StringUtils.containsNone("abab", 'x', 'y', 'z') = true
1214     * StringUtils.containsNone("ab1", 'x', 'y', 'z')  = true
1215     * StringUtils.containsNone("abz", 'x', 'y', 'z')  = false
1216     * </pre>
1217     *
1218     * @param cs          the CharSequence to check, may be null.
1219     * @param searchChars an array of invalid chars, may be null.
1220     * @return true if it contains none of the invalid chars, or is null.
1221     * @since 2.0
1222     * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...)
1223     */
1224    public static boolean containsNone(final CharSequence cs, final char... searchChars) {
1225        if (cs == null || searchChars == null) {
1226            return true;
1227        }
1228        final int csLen = cs.length();
1229        final int csLast = csLen - 1;
1230        final int searchLen = searchChars.length;
1231        final int searchLast = searchLen - 1;
1232        for (int i = 0; i < csLen; i++) {
1233            final char ch = cs.charAt(i);
1234            for (int j = 0; j < searchLen; j++) {
1235                if (searchChars[j] == ch) {
1236                    if (!Character.isHighSurrogate(ch) || j == searchLast || i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
1237                        return false;
1238                    }
1239                }
1240            }
1241        }
1242        return true;
1243    }
1244
1245    /**
1246     * Tests that the CharSequence does not contain certain characters.
1247     *
1248     * <p>
1249     * A {@code null} CharSequence will return {@code true}. A {@code null} invalid character array will return {@code true}. An empty String ("") always
1250     * returns true.
1251     * </p>
1252     *
1253     * <pre>
1254     * StringUtils.containsNone(null, *)       = true
1255     * StringUtils.containsNone(*, null)       = true
1256     * StringUtils.containsNone("", *)         = true
1257     * StringUtils.containsNone("ab", "")      = true
1258     * StringUtils.containsNone("abab", "xyz") = true
1259     * StringUtils.containsNone("ab1", "xyz")  = true
1260     * StringUtils.containsNone("abz", "xyz")  = false
1261     * </pre>
1262     *
1263     * @param cs           the CharSequence to check, may be null.
1264     * @param invalidChars a String of invalid chars, may be null.
1265     * @return true if it contains none of the invalid chars, or is null.
1266     * @since 2.0
1267     * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String)
1268     */
1269    public static boolean containsNone(final CharSequence cs, final String invalidChars) {
1270        if (invalidChars == null) {
1271            return true;
1272        }
1273        return containsNone(cs, invalidChars.toCharArray());
1274    }
1275
1276    /**
1277     * Tests if the CharSequence contains only certain characters.
1278     *
1279     * <p>
1280     * A {@code null} CharSequence will return {@code false}. A {@code null} valid character array will return {@code false}. An empty CharSequence (length()=0)
1281     * always returns {@code true}.
1282     * </p>
1283     *
1284     * <pre>
1285     * StringUtils.containsOnly(null, *)               = false
1286     * StringUtils.containsOnly(*, null)               = false
1287     * StringUtils.containsOnly("", *)                 = true
1288     * StringUtils.containsOnly("ab", '')              = false
1289     * StringUtils.containsOnly("abab", 'a', 'b', 'c') = true
1290     * StringUtils.containsOnly("ab1", 'a', 'b', 'c')  = false
1291     * StringUtils.containsOnly("abz", 'a', 'b', 'c')  = false
1292     * </pre>
1293     *
1294     * @param cs    the String to check, may be null.
1295     * @param valid an array of valid chars, may be null.
1296     * @return true if it only contains valid chars and is non-null.
1297     * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...)
1298     */
1299    public static boolean containsOnly(final CharSequence cs, final char... valid) {
1300        // All these pre-checks are to maintain API with an older version
1301        if (valid == null || cs == null) {
1302            return false;
1303        }
1304        if (cs.length() == 0) {
1305            return true;
1306        }
1307        if (valid.length == 0) {
1308            return false;
1309        }
1310        return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND;
1311    }
1312
1313    /**
1314     * Tests if the CharSequence contains only certain characters.
1315     *
1316     * <p>
1317     * A {@code null} CharSequence will return {@code false}. A {@code null} valid character String will return {@code false}. An empty String (length()=0)
1318     * always returns {@code true}.
1319     * </p>
1320     *
1321     * <pre>
1322     * StringUtils.containsOnly(null, *)       = false
1323     * StringUtils.containsOnly(*, null)       = false
1324     * StringUtils.containsOnly("", *)         = true
1325     * StringUtils.containsOnly("ab", "")      = false
1326     * StringUtils.containsOnly("abab", "abc") = true
1327     * StringUtils.containsOnly("ab1", "abc")  = false
1328     * StringUtils.containsOnly("abz", "abc")  = false
1329     * </pre>
1330     *
1331     * @param cs         the CharSequence to check, may be null.
1332     * @param validChars a String of valid chars, may be null.
1333     * @return true if it only contains valid chars and is non-null.
1334     * @since 2.0
1335     * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String)
1336     */
1337    public static boolean containsOnly(final CharSequence cs, final String validChars) {
1338        if (cs == null || validChars == null) {
1339            return false;
1340        }
1341        return containsOnly(cs, validChars.toCharArray());
1342    }
1343
1344    /**
1345     * Tests whether the given CharSequence contains any whitespace characters.
1346     *
1347     * <p>
1348     * Whitespace is defined by {@link Character#isWhitespace(char)}.
1349     * </p>
1350     *
1351     * <pre>
1352     * StringUtils.containsWhitespace(null)       = false
1353     * StringUtils.containsWhitespace("")         = false
1354     * StringUtils.containsWhitespace("ab")       = false
1355     * StringUtils.containsWhitespace(" ab")      = true
1356     * StringUtils.containsWhitespace("a b")      = true
1357     * StringUtils.containsWhitespace("ab ")      = true
1358     * </pre>
1359     *
1360     * @param seq the CharSequence to check (may be {@code null}).
1361     * @return {@code true} if the CharSequence is not empty and contains at least 1 (breaking) whitespace character.
1362     * @since 3.0
1363     */
1364    public static boolean containsWhitespace(final CharSequence seq) {
1365        if (isEmpty(seq)) {
1366            return false;
1367        }
1368        final int strLen = seq.length();
1369        for (int i = 0; i < strLen; i++) {
1370            if (Character.isWhitespace(seq.charAt(i))) {
1371                return true;
1372            }
1373        }
1374        return false;
1375    }
1376
1377    private static void convertRemainingAccentCharacters(final StringBuilder decomposed) {
1378        for (int i = 0; i < decomposed.length(); i++) {
1379            final char charAt = decomposed.charAt(i);
1380            switch (charAt) {
1381            case '\u0141':
1382                decomposed.setCharAt(i, 'L');
1383                break;
1384            case '\u0142':
1385                decomposed.setCharAt(i, 'l');
1386                break;
1387            // D with stroke
1388            case '\u0110':
1389                // LATIN CAPITAL LETTER D WITH STROKE
1390                decomposed.setCharAt(i, 'D');
1391                break;
1392            case '\u0111':
1393                // LATIN SMALL LETTER D WITH STROKE
1394                decomposed.setCharAt(i, 'd');
1395                break;
1396            // I with bar
1397            case '\u0197':
1398                decomposed.setCharAt(i, 'I');
1399                break;
1400            case '\u0268':
1401                decomposed.setCharAt(i, 'i');
1402                break;
1403            case '\u1D7B':
1404                decomposed.setCharAt(i, 'I');
1405                break;
1406            case '\u1DA4':
1407                decomposed.setCharAt(i, 'i');
1408                break;
1409            case '\u1DA7':
1410                decomposed.setCharAt(i, 'I');
1411                break;
1412            // U with bar
1413            case '\u0244':
1414                // LATIN CAPITAL LETTER U BAR
1415                decomposed.setCharAt(i, 'U');
1416                break;
1417            case '\u0289':
1418                // LATIN SMALL LETTER U BAR
1419                decomposed.setCharAt(i, 'u');
1420                break;
1421            case '\u1D7E':
1422                // LATIN SMALL CAPITAL LETTER U WITH STROKE
1423                decomposed.setCharAt(i, 'U');
1424                break;
1425            case '\u1DB6':
1426                // MODIFIER LETTER SMALL U BAR
1427                decomposed.setCharAt(i, 'u');
1428                break;
1429            // T with stroke
1430            case '\u0166':
1431                // LATIN CAPITAL LETTER T WITH STROKE
1432                decomposed.setCharAt(i, 'T');
1433                break;
1434            case '\u0167':
1435                // LATIN SMALL LETTER T WITH STROKE
1436                decomposed.setCharAt(i, 't');
1437                break;
1438            default:
1439                break;
1440            }
1441        }
1442    }
1443
1444    /**
1445     * Counts how many times the char appears in the given string.
1446     *
1447     * <p>
1448     * A {@code null} or empty ("") String input returns {@code 0}.
1449     * </p>
1450     *
1451     * <pre>
1452     * StringUtils.countMatches(null, *)     = 0
1453     * StringUtils.countMatches("", *)       = 0
1454     * StringUtils.countMatches("abba", 0)   = 0
1455     * StringUtils.countMatches("abba", 'a') = 2
1456     * StringUtils.countMatches("abba", 'b') = 2
1457     * StringUtils.countMatches("abba", 'x') = 0
1458     * </pre>
1459     *
1460     * @param str the CharSequence to check, may be null.
1461     * @param ch  the char to count.
1462     * @return the number of occurrences, 0 if the CharSequence is {@code null}.
1463     * @since 3.4
1464     */
1465    public static int countMatches(final CharSequence str, final char ch) {
1466        if (isEmpty(str)) {
1467            return 0;
1468        }
1469        int count = 0;
1470        // We could also call str.toCharArray() for faster lookups but that would generate more garbage.
1471        for (int i = 0; i < str.length(); i++) {
1472            if (ch == str.charAt(i)) {
1473                count++;
1474            }
1475        }
1476        return count;
1477    }
1478
1479    /**
1480     * Counts how many times the substring appears in the larger string. Note that the code only counts non-overlapping matches.
1481     *
1482     * <p>
1483     * A {@code null} or empty ("") String input returns {@code 0}.
1484     * </p>
1485     *
1486     * <pre>
1487     * StringUtils.countMatches(null, *)        = 0
1488     * StringUtils.countMatches("", *)          = 0
1489     * StringUtils.countMatches("abba", null)   = 0
1490     * StringUtils.countMatches("abba", "")     = 0
1491     * StringUtils.countMatches("abba", "a")    = 2
1492     * StringUtils.countMatches("abba", "ab")   = 1
1493     * StringUtils.countMatches("abba", "xxx")  = 0
1494     * StringUtils.countMatches("ababa", "aba") = 1
1495     * </pre>
1496     *
1497     * @param str the CharSequence to check, may be null.
1498     * @param sub the substring to count, may be null.
1499     * @return the number of occurrences, 0 if either CharSequence is {@code null}.
1500     * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
1501     */
1502    public static int countMatches(final CharSequence str, final CharSequence sub) {
1503        if (isEmpty(str) || isEmpty(sub)) {
1504            return 0;
1505        }
1506        int count = 0;
1507        int idx = 0;
1508        while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) {
1509            count++;
1510            idx += sub.length();
1511        }
1512        return count;
1513    }
1514
1515    /**
1516     * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or
1517     * {@code null}), the value of {@code defaultStr}.
1518     *
1519     * <p>
1520     * Whitespace is defined by {@link Character#isWhitespace(char)}.
1521     * </p>
1522     *
1523     * <pre>
1524     * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"
1525     * StringUtils.defaultIfBlank("", "NULL")    = "NULL"
1526     * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"
1527     * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
1528     * StringUtils.defaultIfBlank("", null)      = null
1529     * </pre>
1530     *
1531     * @param <T>        the specific kind of CharSequence.
1532     * @param str        the CharSequence to check, may be null.
1533     * @param defaultStr the default CharSequence to return if {@code str} is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or
1534     *                   {@code null}); may be null.
1535     * @return the passed in CharSequence, or the default.
1536     * @see StringUtils#defaultString(String, String)
1537     * @see #isBlank(CharSequence)
1538     */
1539    public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) {
1540        return isBlank(str) ? defaultStr : str;
1541    }
1542
1543    /**
1544     * Returns either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value of {@code defaultStr}.
1545     *
1546     * <pre>
1547     * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
1548     * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
1549     * StringUtils.defaultIfEmpty(" ", "NULL")   = " "
1550     * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
1551     * StringUtils.defaultIfEmpty("", null)      = null
1552     * </pre>
1553     *
1554     * @param <T>        the specific kind of CharSequence.
1555     * @param str        the CharSequence to check, may be null.
1556     * @param defaultStr the default CharSequence to return if the input is empty ("") or {@code null}, may be null.
1557     * @return the passed in CharSequence, or the default.
1558     * @see StringUtils#defaultString(String, String)
1559     */
1560    public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) {
1561        return isEmpty(str) ? defaultStr : str;
1562    }
1563
1564    /**
1565     * Returns either the passed in String, or if the String is {@code null}, an empty String ("").
1566     *
1567     * <pre>
1568     * StringUtils.defaultString(null)  = ""
1569     * StringUtils.defaultString("")    = ""
1570     * StringUtils.defaultString("bat") = "bat"
1571     * </pre>
1572     *
1573     * @param str the String to check, may be null.
1574     * @return the passed in String, or the empty String if it was {@code null}.
1575     * @see Objects#toString(Object, String)
1576     * @see String#valueOf(Object)
1577     */
1578    public static String defaultString(final String str) {
1579        return Objects.toString(str, EMPTY);
1580    }
1581
1582    /**
1583     * Returns either the given String, or if the String is {@code null}, {@code nullDefault}.
1584     *
1585     * <pre>
1586     * StringUtils.defaultString(null, "NULL")  = "NULL"
1587     * StringUtils.defaultString("", "NULL")    = ""
1588     * StringUtils.defaultString("bat", "NULL") = "bat"
1589     * </pre>
1590     * <p>
1591     * Since this is now provided by Java, instead call {@link Objects#toString(Object, String)}:
1592     * </p>
1593     *
1594     * <pre>
1595     * Objects.toString(null, "NULL")  = "NULL"
1596     * Objects.toString("", "NULL")    = ""
1597     * Objects.toString("bat", "NULL") = "bat"
1598     * </pre>
1599     *
1600     * @param str         the String to check, may be null.
1601     * @param nullDefault the default String to return if the input is {@code null}, may be null.
1602     * @return the passed in String, or the default if it was {@code null}.
1603     * @see Objects#toString(Object, String)
1604     * @see String#valueOf(Object)
1605     * @deprecated Use {@link Objects#toString(Object, String)}.
1606     */
1607    @Deprecated
1608    public static String defaultString(final String str, final String nullDefault) {
1609        return Objects.toString(str, nullDefault);
1610    }
1611
1612    /**
1613     * Deletes all whitespaces from a String as defined by {@link Character#isWhitespace(char)}.
1614     *
1615     * <pre>
1616     * StringUtils.deleteWhitespace(null)         = null
1617     * StringUtils.deleteWhitespace("")           = ""
1618     * StringUtils.deleteWhitespace("abc")        = "abc"
1619     * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
1620     * </pre>
1621     *
1622     * @param str the String to delete whitespace from, may be null.
1623     * @return the String without whitespaces, {@code null} if null String input.
1624     */
1625    public static String deleteWhitespace(final String str) {
1626        if (isEmpty(str)) {
1627            return str;
1628        }
1629        final int sz = str.length();
1630        final char[] chs = new char[sz];
1631        int count = 0;
1632        for (int i = 0; i < sz; i++) {
1633            if (!Character.isWhitespace(str.charAt(i))) {
1634                chs[count++] = str.charAt(i);
1635            }
1636        }
1637        if (count == sz) {
1638            return str;
1639        }
1640        if (count == 0) {
1641            return EMPTY;
1642        }
1643        return new String(chs, 0, count);
1644    }
1645
1646    /**
1647     * Compares two Strings, and returns the portion where they differ. More precisely, return the remainder of the second String, starting from where it's
1648     * different from the first. This means that the difference between "abc" and "ab" is the empty String and not "c".
1649     *
1650     * <p>
1651     * For example, {@code difference("i am a machine", "i am a robot") -> "robot"}.
1652     * </p>
1653     *
1654     * <pre>
1655     * StringUtils.difference(null, null)       = null
1656     * StringUtils.difference("", "")           = ""
1657     * StringUtils.difference("", "abc")        = "abc"
1658     * StringUtils.difference("abc", "")        = ""
1659     * StringUtils.difference("abc", "abc")     = ""
1660     * StringUtils.difference("abc", "ab")      = ""
1661     * StringUtils.difference("ab", "abxyz")    = "xyz"
1662     * StringUtils.difference("abcde", "abxyz") = "xyz"
1663     * StringUtils.difference("abcde", "xyz")   = "xyz"
1664     * </pre>
1665     *
1666     * @param str1 the first String, may be null.
1667     * @param str2 the second String, may be null.
1668     * @return the portion of str2 where it differs from str1; returns the empty String if they are equal.
1669     * @see #indexOfDifference(CharSequence,CharSequence)
1670     * @since 2.0
1671     */
1672    public static String difference(final String str1, final String str2) {
1673        if (str1 == null) {
1674            return str2;
1675        }
1676        if (str2 == null) {
1677            return str1;
1678        }
1679        final int at = indexOfDifference(str1, str2);
1680        if (at == INDEX_NOT_FOUND) {
1681            return EMPTY;
1682        }
1683        return str2.substring(at);
1684    }
1685
1686    /**
1687     * Tests if a CharSequence ends with a specified suffix.
1688     *
1689     * <p>
1690     * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive.
1691     * </p>
1692     *
1693     * <pre>
1694     * StringUtils.endsWith(null, null)      = true
1695     * StringUtils.endsWith(null, "def")     = false
1696     * StringUtils.endsWith("abcdef", null)  = false
1697     * StringUtils.endsWith("abcdef", "def") = true
1698     * StringUtils.endsWith("ABCDEF", "def") = false
1699     * StringUtils.endsWith("ABCDEF", "cde") = false
1700     * StringUtils.endsWith("ABCDEF", "")    = true
1701     * </pre>
1702     *
1703     * @param str    the CharSequence to check, may be null.
1704     * @param suffix the suffix to find, may be null.
1705     * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or both {@code null}.
1706     * @see String#endsWith(String)
1707     * @since 2.4
1708     * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence)
1709     * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CS.endsWith(CharSequence, CharSequence)}.
1710     */
1711    @Deprecated
1712    public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
1713        return Strings.CS.endsWith(str, suffix);
1714    }
1715
1716    /**
1717     * Tests if a CharSequence ends with any of the provided case-sensitive suffixes.
1718     *
1719     * <pre>
1720     * StringUtils.endsWithAny(null, null)                  = false
1721     * StringUtils.endsWithAny(null, new String[] {"abc"})  = false
1722     * StringUtils.endsWithAny("abcxyz", null)              = false
1723     * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
1724     * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
1725     * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
1726     * StringUtils.endsWithAny("abcXYZ", "def", "XYZ")      = true
1727     * StringUtils.endsWithAny("abcXYZ", "def", "xyz")      = false
1728     * </pre>
1729     *
1730     * @param sequence      the CharSequence to check, may be null.
1731     * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null}.
1732     * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} ends in any
1733     *         of the provided case-sensitive {@code searchStrings}.
1734     * @see StringUtils#endsWith(CharSequence, CharSequence)
1735     * @since 3.0
1736     * @deprecated Use {@link Strings#endsWithAny(CharSequence, CharSequence...) Strings.CS.endsWithAny(CharSequence, CharSequence...)}.
1737     */
1738    @Deprecated
1739    public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
1740        return Strings.CS.endsWithAny(sequence, searchStrings);
1741    }
1742
1743    /**
1744     * Case-insensitive check if a CharSequence ends with a specified suffix.
1745     *
1746     * <p>
1747     * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive.
1748     * </p>
1749     *
1750     * <pre>
1751     * StringUtils.endsWithIgnoreCase(null, null)      = true
1752     * StringUtils.endsWithIgnoreCase(null, "def")     = false
1753     * StringUtils.endsWithIgnoreCase("abcdef", null)  = false
1754     * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
1755     * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
1756     * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
1757     * </pre>
1758     *
1759     * @param str    the CharSequence to check, may be null
1760     * @param suffix the suffix to find, may be null
1761     * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or both {@code null}
1762     * @see String#endsWith(String)
1763     * @since 2.4
1764     * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence)
1765     * @deprecated Use {@link Strings#endsWith(CharSequence, CharSequence) Strings.CI.endsWith(CharSequence, CharSequence)}.
1766     */
1767    @Deprecated
1768    public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) {
1769        return Strings.CI.endsWith(str, suffix);
1770    }
1771
1772    /**
1773     * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters.
1774     *
1775     * <p>
1776     * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is <strong>case-sensitive</strong>.
1777     * </p>
1778     *
1779     * <pre>
1780     * StringUtils.equals(null, null)   = true
1781     * StringUtils.equals(null, "abc")  = false
1782     * StringUtils.equals("abc", null)  = false
1783     * StringUtils.equals("abc", "abc") = true
1784     * StringUtils.equals("abc", "ABC") = false
1785     * </pre>
1786     *
1787     * @param cs1 the first CharSequence, may be {@code null}.
1788     * @param cs2 the second CharSequence, may be {@code null}.
1789     * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}.
1790     * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
1791     * @see Object#equals(Object)
1792     * @see #equalsIgnoreCase(CharSequence, CharSequence)
1793     * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CS.equals(CharSequence, CharSequence)}.
1794     */
1795    @Deprecated
1796    public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
1797        return Strings.CS.equals(cs1, cs2);
1798    }
1799
1800    /**
1801     * Compares given {@code string} to a CharSequences vararg of {@code searchStrings}, returning {@code true} if the {@code string} is equal to any of the
1802     * {@code searchStrings}.
1803     *
1804     * <pre>
1805     * StringUtils.equalsAny(null, (CharSequence[]) null) = false
1806     * StringUtils.equalsAny(null, null, null)    = true
1807     * StringUtils.equalsAny(null, "abc", "def")  = false
1808     * StringUtils.equalsAny("abc", null, "def")  = false
1809     * StringUtils.equalsAny("abc", "abc", "def") = true
1810     * StringUtils.equalsAny("abc", "ABC", "DEF") = false
1811     * </pre>
1812     *
1813     * @param string        to compare, may be {@code null}.
1814     * @param searchStrings a vararg of strings, may be {@code null}.
1815     * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings}; {@code false} if {@code searchStrings} is
1816     *         null or contains no matches.
1817     * @since 3.5
1818     * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CS.equalsAny(CharSequence, CharSequence...)}.
1819     */
1820    @Deprecated
1821    public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) {
1822        return Strings.CS.equalsAny(string, searchStrings);
1823    }
1824
1825    /**
1826     * Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
1827     * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case.
1828     *
1829     * <pre>
1830     * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
1831     * StringUtils.equalsAnyIgnoreCase(null, null, null)    = true
1832     * StringUtils.equalsAnyIgnoreCase(null, "abc", "def")  = false
1833     * StringUtils.equalsAnyIgnoreCase("abc", null, "def")  = false
1834     * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
1835     * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
1836     * </pre>
1837     *
1838     * @param string to compare, may be {@code null}.
1839     * @param searchStrings a vararg of strings, may be {@code null}.
1840     * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings};
1841     * {@code false} if {@code searchStrings} is null or contains no matches.
1842     * @since 3.5
1843     * @deprecated Use {@link Strings#equalsAny(CharSequence, CharSequence...) Strings.CI.equalsAny(CharSequence, CharSequence...)}.
1844     */
1845    @Deprecated
1846    public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings) {
1847        return Strings.CI.equalsAny(string, searchStrings);
1848    }
1849
1850    /**
1851     * Compares two CharSequences, returning {@code true} if they represent equal sequences of characters, ignoring case.
1852     *
1853     * <p>
1854     * {@code null}s are handled without exceptions. Two {@code null} references are considered equal. The comparison is <strong>case insensitive</strong>.
1855     * </p>
1856     *
1857     * <pre>
1858     * StringUtils.equalsIgnoreCase(null, null)   = true
1859     * StringUtils.equalsIgnoreCase(null, "abc")  = false
1860     * StringUtils.equalsIgnoreCase("abc", null)  = false
1861     * StringUtils.equalsIgnoreCase("abc", "abc") = true
1862     * StringUtils.equalsIgnoreCase("abc", "ABC") = true
1863     * </pre>
1864     *
1865     * @param cs1 the first CharSequence, may be {@code null}.
1866     * @param cs2 the second CharSequence, may be {@code null}.
1867     * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}.
1868     * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence)
1869     * @see #equals(CharSequence, CharSequence)
1870     * @deprecated Use {@link Strings#equals(CharSequence, CharSequence) Strings.CI.equals(CharSequence, CharSequence)}.
1871     */
1872    @Deprecated
1873    public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) {
1874        return Strings.CI.equals(cs1, cs2);
1875    }
1876
1877    /**
1878     * Returns the first value in the array which is not empty (""), {@code null} or whitespace only.
1879     *
1880     * <p>
1881     * Whitespace is defined by {@link Character#isWhitespace(char)}.
1882     * </p>
1883     *
1884     * <p>
1885     * If all values are blank or the array is {@code null} or empty then {@code null} is returned.
1886     * </p>
1887     *
1888     * <pre>
1889     * StringUtils.firstNonBlank(null, null, null)     = null
1890     * StringUtils.firstNonBlank(null, "", " ")        = null
1891     * StringUtils.firstNonBlank("abc")                = "abc"
1892     * StringUtils.firstNonBlank(null, "xyz")          = "xyz"
1893     * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz"
1894     * StringUtils.firstNonBlank(null, "xyz", "abc")   = "xyz"
1895     * StringUtils.firstNonBlank()                     = null
1896     * </pre>
1897     *
1898     * @param <T>    the specific kind of CharSequence.
1899     * @param values the values to test, may be {@code null} or empty.
1900     * @return the first value from {@code values} which is not blank, or {@code null} if there are no non-blank values.
1901     * @since 3.8
1902     */
1903    @SafeVarargs
1904    public static <T extends CharSequence> T firstNonBlank(final T... values) {
1905        if (values != null) {
1906            for (final T val : values) {
1907                if (isNotBlank(val)) {
1908                    return val;
1909                }
1910            }
1911        }
1912        return null;
1913    }
1914
1915    /**
1916     * Returns the first value in the array which is not empty.
1917     *
1918     * <p>
1919     * If all values are empty or the array is {@code null} or empty then {@code null} is returned.
1920     * </p>
1921     *
1922     * <pre>
1923     * StringUtils.firstNonEmpty(null, null, null)   = null
1924     * StringUtils.firstNonEmpty(null, null, "")     = null
1925     * StringUtils.firstNonEmpty(null, "", " ")      = " "
1926     * StringUtils.firstNonEmpty("abc")              = "abc"
1927     * StringUtils.firstNonEmpty(null, "xyz")        = "xyz"
1928     * StringUtils.firstNonEmpty("", "xyz")          = "xyz"
1929     * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz"
1930     * StringUtils.firstNonEmpty()                   = null
1931     * </pre>
1932     *
1933     * @param <T>    the specific kind of CharSequence.
1934     * @param values the values to test, may be {@code null} or empty.
1935     * @return the first value from {@code values} which is not empty, or {@code null} if there are no non-empty values.
1936     * @since 3.8
1937     */
1938    @SafeVarargs
1939    public static <T extends CharSequence> T firstNonEmpty(final T... values) {
1940        if (values != null) {
1941            for (final T val : values) {
1942                if (isNotEmpty(val)) {
1943                    return val;
1944                }
1945            }
1946        }
1947        return null;
1948    }
1949
1950    /**
1951     * Calls {@link String#getBytes(Charset)} in a null-safe manner.
1952     *
1953     * @param string input string.
1954     * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset.
1955     * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise.
1956     * @see String#getBytes(Charset)
1957     * @since 3.10
1958     */
1959    public static byte[] getBytes(final String string, final Charset charset) {
1960        return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset));
1961    }
1962
1963    /**
1964     * Calls {@link String#getBytes(String)} in a null-safe manner.
1965     *
1966     * @param string input string.
1967     * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset.
1968     * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise.
1969     * @throws UnsupportedEncodingException Thrown when the named charset is not supported.
1970     * @see String#getBytes(String)
1971     * @since 3.10
1972     */
1973    public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException {
1974        return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset));
1975    }
1976
1977    /**
1978     * Compares all Strings in an array and returns the initial sequence of characters that is common to all of them.
1979     *
1980     * <p>
1981     * For example, {@code getCommonPrefix("i am a machine", "i am a robot") -&gt; "i am a "}
1982     * </p>
1983     *
1984     * <pre>
1985     * StringUtils.getCommonPrefix(null)                             = ""
1986     * StringUtils.getCommonPrefix(new String[] {})                  = ""
1987     * StringUtils.getCommonPrefix(new String[] {"abc"})             = "abc"
1988     * StringUtils.getCommonPrefix(new String[] {null, null})        = ""
1989     * StringUtils.getCommonPrefix(new String[] {"", ""})            = ""
1990     * StringUtils.getCommonPrefix(new String[] {"", null})          = ""
1991     * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
1992     * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
1993     * StringUtils.getCommonPrefix(new String[] {"", "abc"})         = ""
1994     * StringUtils.getCommonPrefix(new String[] {"abc", ""})         = ""
1995     * StringUtils.getCommonPrefix(new String[] {"abc", "abc"})      = "abc"
1996     * StringUtils.getCommonPrefix(new String[] {"abc", "a"})        = "a"
1997     * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"})     = "ab"
1998     * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"})  = "ab"
1999     * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"})    = ""
2000     * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"})    = ""
2001     * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
2002     * </pre>
2003     *
2004     * @param strs array of String objects, entries may be null.
2005     * @return the initial sequence of characters that are common to all Strings in the array; empty String if the array is null, the elements are all null or
2006     *         if there is no common prefix.
2007     * @since 2.4
2008     */
2009    public static String getCommonPrefix(final String... strs) {
2010        if (ArrayUtils.isEmpty(strs)) {
2011            return EMPTY;
2012        }
2013        final int smallestIndexOfDiff = indexOfDifference(strs);
2014        if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
2015            // all strings were identical
2016            if (strs[0] == null) {
2017                return EMPTY;
2018            }
2019            return strs[0];
2020        }
2021        if (smallestIndexOfDiff == 0) {
2022            // there were no common initial characters
2023            return EMPTY;
2024        }
2025        // we found a common initial character sequence
2026        return strs[0].substring(0, smallestIndexOfDiff);
2027    }
2028
2029    /**
2030     * Checks if a String {@code str} contains Unicode digits, if yes then concatenate all the digits in {@code str} and return it as a String.
2031     *
2032     * <p>
2033     * An empty ("") String will be returned if no digits found in {@code str}.
2034     * </p>
2035     *
2036     * <pre>
2037     * StringUtils.getDigits(null)                 = null
2038     * StringUtils.getDigits("")                   = ""
2039     * StringUtils.getDigits("abc")                = ""
2040     * StringUtils.getDigits("1000$")              = "1000"
2041     * StringUtils.getDigits("1123~45")            = "112345"
2042     * StringUtils.getDigits("(541) 754-3010")     = "5417543010"
2043     * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969"
2044     * </pre>
2045     *
2046     * @param str the String to extract digits from, may be null.
2047     * @return String with only digits, or an empty ("") String if no digits found, or {@code null} String if {@code str} is null.
2048     * @since 3.6
2049     */
2050    public static String getDigits(final String str) {
2051        if (isEmpty(str)) {
2052            return str;
2053        }
2054        final int len = str.length();
2055        final char[] buffer = new char[len];
2056        int count = 0;
2057
2058        for (int i = 0; i < len; i++) {
2059            final char tempChar = str.charAt(i);
2060            if (Character.isDigit(tempChar)) {
2061                buffer[count++] = tempChar;
2062            }
2063        }
2064        return new String(buffer, 0, count);
2065    }
2066
2067    /**
2068     * Gets the Fuzzy Distance which indicates the similarity score between two Strings.
2069     *
2070     * <p>
2071     * This string matching algorithm is similar to the algorithms of editors such as Sublime Text, TextMate, Atom and others. One point is given for every
2072     * matched character. Subsequent matches yield two bonus points. A higher score indicates a higher similarity.
2073     * </p>
2074     *
2075     * <pre>
2076     * StringUtils.getFuzzyDistance(null, null, null)                                    = Throws {@link IllegalArgumentException}
2077     * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH)                              = 0
2078     * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH)                     = 0
2079     * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH)                         = 1
2080     * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH)                     = 1
2081     * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH)                    = 2
2082     * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH)                    = 4
2083     * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3
2084     * </pre>
2085     *
2086     * @param term   a full term that should be matched against, must not be null.
2087     * @param query  the query that will be matched against a term, must not be null.
2088     * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize both Strings to lower case.
2089     * @return result score.
2090     * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null}.
2091     * @since 3.4
2092     * @deprecated As of 3.6, use Apache Commons Text
2093     *             <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html">
2094     *             FuzzyScore</a> instead.
2095     */
2096    @Deprecated
2097    public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) {
2098        if (term == null || query == null) {
2099            throw new IllegalArgumentException("Strings must not be null");
2100        }
2101        if (locale == null) {
2102            throw new IllegalArgumentException("Locale must not be null");
2103        }
2104        // fuzzy logic is case-insensitive. We normalize the Strings to lower
2105        // case right from the start. Turning characters to lower case
2106        // via Character.toLowerCase(char) is unfortunately insufficient
2107        // as it does not accept a locale.
2108        final String termLowerCase = term.toString().toLowerCase(locale);
2109        final String queryLowerCase = query.toString().toLowerCase(locale);
2110        // the resulting score
2111        int score = 0;
2112        // the position in the term which will be scanned next for potential
2113        // query character matches
2114        int termIndex = 0;
2115        // index of the previously matched character in the term
2116        int previousMatchingCharacterIndex = Integer.MIN_VALUE;
2117        for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) {
2118            final char queryChar = queryLowerCase.charAt(queryIndex);
2119            boolean termCharacterMatchFound = false;
2120            for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) {
2121                final char termChar = termLowerCase.charAt(termIndex);
2122                if (queryChar == termChar) {
2123                    // simple character matches result in one point
2124                    score++;
2125                    // subsequent character matches further improve
2126                    // the score.
2127                    if (previousMatchingCharacterIndex + 1 == termIndex) {
2128                        score += 2;
2129                    }
2130                    previousMatchingCharacterIndex = termIndex;
2131                    // we can leave the nested loop. Every character in the
2132                    // query can match at most one character in the term.
2133                    termCharacterMatchFound = true;
2134                }
2135            }
2136        }
2137        return score;
2138    }
2139
2140    /**
2141     * Returns either the passed in CharSequence, or if the CharSequence is {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or
2142     * {@code null}), the value supplied by {@code defaultStrSupplier}.
2143     *
2144     * <p>
2145     * Whitespace is defined by {@link Character#isWhitespace(char)}.
2146     * </p>
2147     *
2148     * <p>
2149     * Caller responsible for thread-safety and exception handling of default value supplier
2150     * </p>
2151     *
2152     * <pre>
2153     * {@code
2154     * StringUtils.getIfBlank(null, () -> "NULL")   = "NULL"
2155     * StringUtils.getIfBlank("", () -> "NULL")     = "NULL"
2156     * StringUtils.getIfBlank(" ", () -> "NULL")    = "NULL"
2157     * StringUtils.getIfBlank("bat", () -> "NULL")  = "bat"
2158     * StringUtils.getIfBlank("", () -> null)       = null
2159     * StringUtils.getIfBlank("", null)             = null
2160     * }</pre>
2161     *
2162     * @param <T>             the specific kind of CharSequence.
2163     * @param str             the CharSequence to check, may be null.
2164     * @param defaultSupplier the supplier of default CharSequence to return if the input is {@link #isBlank(CharSequence) blank} (whitespaces, empty
2165     *                        ({@code ""}), or {@code null}); may be null.
2166     * @return the passed in CharSequence, or the default
2167     * @see StringUtils#defaultString(String, String)
2168     * @see #isBlank(CharSequence)
2169     * @since 3.10
2170     */
2171    public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) {
2172        return isBlank(str) ? Suppliers.get(defaultSupplier) : str;
2173    }
2174
2175    /**
2176     * Returns either the passed in CharSequence, or if the CharSequence is empty or {@code null}, the value supplied by {@code defaultStrSupplier}.
2177     *
2178     * <p>
2179     * Caller responsible for thread-safety and exception handling of default value supplier
2180     * </p>
2181     *
2182     * <pre>
2183     * {@code
2184     * StringUtils.getIfEmpty(null, () -> "NULL")    = "NULL"
2185     * StringUtils.getIfEmpty("", () -> "NULL")      = "NULL"
2186     * StringUtils.getIfEmpty(" ", () -> "NULL")     = " "
2187     * StringUtils.getIfEmpty("bat", () -> "NULL")   = "bat"
2188     * StringUtils.getIfEmpty("", () -> null)        = null
2189     * StringUtils.getIfEmpty("", null)              = null
2190     * }
2191     * </pre>
2192     *
2193     * @param <T>             the specific kind of CharSequence.
2194     * @param str             the CharSequence to check, may be null.
2195     * @param defaultSupplier the supplier of default CharSequence to return if the input is empty ("") or {@code null}, may be null.
2196     * @return the passed in CharSequence, or the default.
2197     * @see StringUtils#defaultString(String, String)
2198     * @since 3.10
2199     */
2200    public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) {
2201        return isEmpty(str) ? Suppliers.get(defaultSupplier) : str;
2202    }
2203
2204    /**
2205     * Gets the Jaro Winkler Distance which indicates the similarity score between two Strings.
2206     *
2207     * <p>
2208     * The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters. Winkler increased this measure for
2209     * matching initial characters.
2210     * </p>
2211     *
2212     * <p>
2213     * This implementation is based on the Jaro Winkler similarity algorithm from
2214     * <a href="https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>.
2215     * </p>
2216     *
2217     * <pre>
2218     * StringUtils.getJaroWinklerDistance(null, null)          = Throws {@link IllegalArgumentException}
2219     * StringUtils.getJaroWinklerDistance("", "")              = 0.0
2220     * StringUtils.getJaroWinklerDistance("", "a")             = 0.0
2221     * StringUtils.getJaroWinklerDistance("aaapppp", "")       = 0.0
2222     * StringUtils.getJaroWinklerDistance("frog", "fog")       = 0.93
2223     * StringUtils.getJaroWinklerDistance("fly", "ant")        = 0.0
2224     * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44
2225     * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44
2226     * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0
2227     * StringUtils.getJaroWinklerDistance("hello", "hallo")    = 0.88
2228     * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93
2229     * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D &amp; H Enterprises, Inc.") = 0.95
2230     * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92
2231     * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88
2232     * </pre>
2233     *
2234     * @param first  the first String, must not be null.
2235     * @param second the second String, must not be null.
2236     * @return result distance.
2237     * @throws IllegalArgumentException if either String input {@code null}.
2238     * @since 3.3
2239     * @deprecated As of 3.6, use Apache Commons Text
2240     *             <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html">
2241     *             JaroWinklerDistance</a> instead.
2242     */
2243    @Deprecated
2244    public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) {
2245        final double DEFAULT_SCALING_FACTOR = 0.1;
2246
2247        if (first == null || second == null) {
2248            throw new IllegalArgumentException("Strings must not be null");
2249        }
2250
2251        final int[] mtp = matches(first, second);
2252        final double m = mtp[0];
2253        if (m == 0) {
2254            return 0D;
2255        }
2256        final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3;
2257        final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j);
2258        return Math.round(jw * 100.0D) / 100.0D;
2259    }
2260
2261    /**
2262     * Gets the Levenshtein distance between two Strings.
2263     *
2264     * <p>
2265     * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or
2266     * substitution).
2267     * </p>
2268     *
2269     * <p>
2270     * The implementation uses a single-dimensional array of length s.length() + 1. See
2271     * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html">
2272     * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.
2273     * </p>
2274     *
2275     * <pre>
2276     * StringUtils.getLevenshteinDistance(null, *)             = Throws {@link IllegalArgumentException}
2277     * StringUtils.getLevenshteinDistance(*, null)             = Throws {@link IllegalArgumentException}
2278     * StringUtils.getLevenshteinDistance("", "")              = 0
2279     * StringUtils.getLevenshteinDistance("", "a")             = 1
2280     * StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
2281     * StringUtils.getLevenshteinDistance("frog", "fog")       = 1
2282     * StringUtils.getLevenshteinDistance("fly", "ant")        = 3
2283     * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
2284     * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
2285     * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
2286     * StringUtils.getLevenshteinDistance("hello", "hallo")    = 1
2287     * </pre>
2288     *
2289     * @param s the first String, must not be null.
2290     * @param t the second String, must not be null.
2291     * @return result distance.
2292     * @throws IllegalArgumentException if either String input {@code null}.
2293     * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to getLevenshteinDistance(CharSequence, CharSequence)
2294     * @deprecated As of 3.6, use Apache Commons Text
2295     *             <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
2296     *             LevenshteinDistance</a> instead.
2297     */
2298    @Deprecated
2299    public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
2300        if (s == null || t == null) {
2301            throw new IllegalArgumentException("Strings must not be null");
2302        }
2303
2304        int n = s.length();
2305        int m = t.length();
2306
2307        if (n == 0) {
2308            return m;
2309        }
2310        if (m == 0) {
2311            return n;
2312        }
2313
2314        if (n > m) {
2315            // swap the input strings to consume less memory
2316            final CharSequence tmp = s;
2317            s = t;
2318            t = tmp;
2319            n = m;
2320            m = t.length();
2321        }
2322
2323        final int[] p = new int[n + 1];
2324        // indexes into strings s and t
2325        int i; // iterates through s
2326        int j; // iterates through t
2327        int upperleft;
2328        int upper;
2329
2330        char jOfT; // jth character of t
2331        int cost;
2332
2333        for (i = 0; i <= n; i++) {
2334            p[i] = i;
2335        }
2336
2337        for (j = 1; j <= m; j++) {
2338            upperleft = p[0];
2339            jOfT = t.charAt(j - 1);
2340            p[0] = j;
2341
2342            for (i = 1; i <= n; i++) {
2343                upper = p[i];
2344                cost = s.charAt(i - 1) == jOfT ? 0 : 1;
2345                // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
2346                p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost);
2347                upperleft = upper;
2348            }
2349        }
2350
2351        return p[n];
2352    }
2353
2354    /**
2355     * Gets the Levenshtein distance between two Strings if it's less than or equal to a given threshold.
2356     *
2357     * <p>
2358     * This is the number of changes needed to change one String into another, where each change is a single character modification (deletion, insertion or
2359     * substitution).
2360     * </p>
2361     *
2362     * <p>
2363     * This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield and Chas Emerick's implementation of the Levenshtein distance
2364     * algorithm.
2365     * </p>
2366     *
2367     * <pre>
2368     * StringUtils.getLevenshteinDistance(null, *, *)             = Throws {@link IllegalArgumentException}
2369     * StringUtils.getLevenshteinDistance(*, null, *)             = Throws {@link IllegalArgumentException}
2370     * StringUtils.getLevenshteinDistance(*, *, -1)               = Throws {@link IllegalArgumentException}
2371     * StringUtils.getLevenshteinDistance("", "", 0)              = 0
2372     * StringUtils.getLevenshteinDistance("aaapppp", "", 8)       = 7
2373     * StringUtils.getLevenshteinDistance("aaapppp", "", 7)       = 7
2374     * StringUtils.getLevenshteinDistance("aaapppp", "", 6))      = -1
2375     * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7
2376     * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1
2377     * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7
2378     * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1
2379     * </pre>
2380     *
2381     * @param s         the first String, must not be null.
2382     * @param t         the second String, must not be null.
2383     * @param threshold the target threshold, must not be negative.
2384     * @return result distance, or {@code -1} if the distance would be greater than the threshold.
2385     * @throws IllegalArgumentException if either String input {@code null} or negative threshold.
2386     * @deprecated As of 3.6, use Apache Commons Text
2387     *             <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
2388     *             LevenshteinDistance</a> instead.
2389     */
2390    @Deprecated
2391    public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) {
2392        if (s == null || t == null) {
2393            throw new IllegalArgumentException("Strings must not be null");
2394        }
2395        if (threshold < 0) {
2396            throw new IllegalArgumentException("Threshold must not be negative");
2397        }
2398
2399        /*
2400        This implementation only computes the distance if it's less than or equal to the
2401        threshold value, returning -1 if it's greater.  The advantage is performance: unbounded
2402        distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only
2403        computing a diagonal stripe of width 2k + 1 of the cost table.
2404        It is also possible to use this to compute the unbounded Levenshtein distance by starting
2405        the threshold at 1 and doubling each time until the distance is found; this is O(dm), where
2406        d is the distance.
2407
2408        One subtlety comes from needing to ignore entries on the border of our stripe
2409        for example,
2410        p[] = |#|#|#|*
2411        d[] =  *|#|#|#|
2412        We must ignore the entry to the left of the leftmost member
2413        We must ignore the entry above the rightmost member
2414
2415        Another subtlety comes from our stripe running off the matrix if the strings aren't
2416        of the same size.  Since string s is always swapped to be the shorter of the two,
2417        the stripe will always run off to the upper right instead of the lower left of the matrix.
2418
2419        As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1.
2420        In this case we're going to walk a stripe of length 3.  The matrix would look like so:
2421
2422           1 2 3 4 5
2423        1 |#|#| | | |
2424        2 |#|#|#| | |
2425        3 | |#|#|#| |
2426        4 | | |#|#|#|
2427        5 | | | |#|#|
2428        6 | | | | |#|
2429        7 | | | | | |
2430
2431        Note how the stripe leads off the table as there is no possible way to turn a string of length 5
2432        into one of length 7 in edit distance of 1.
2433
2434        Additionally, this implementation decreases memory usage by using two
2435        single-dimensional arrays and swapping them back and forth instead of allocating
2436        an entire n by m matrix.  This requires a few minor changes, such as immediately returning
2437        when it's detected that the stripe has run off the matrix and initially filling the arrays with
2438        large values so that entries we don't compute are ignored.
2439
2440        See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion.
2441         */
2442
2443        int n = s.length(); // length of s
2444        int m = t.length(); // length of t
2445
2446        // if one string is empty, the edit distance is necessarily the length of the other
2447        if (n == 0) {
2448            return m <= threshold ? m : -1;
2449        }
2450        if (m == 0) {
2451            return n <= threshold ? n : -1;
2452        }
2453        if (Math.abs(n - m) > threshold) {
2454            // no need to calculate the distance if the length difference is greater than the threshold
2455            return -1;
2456        }
2457
2458        if (n > m) {
2459            // swap the two strings to consume less memory
2460            final CharSequence tmp = s;
2461            s = t;
2462            t = tmp;
2463            n = m;
2464            m = t.length();
2465        }
2466
2467        int[] p = new int[n + 1]; // 'previous' cost array, horizontally
2468        int[] d = new int[n + 1]; // cost array, horizontally
2469        int[] tmp; // placeholder to assist in swapping p and d
2470
2471        // fill in starting table values
2472        final int boundary = Math.min(n, threshold) + 1;
2473        for (int i = 0; i < boundary; i++) {
2474            p[i] = i;
2475        }
2476        // these fills ensure that the value above the rightmost entry of our
2477        // stripe will be ignored in following loop iterations
2478        Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);
2479        Arrays.fill(d, Integer.MAX_VALUE);
2480
2481        // iterates through t
2482        for (int j = 1; j <= m; j++) {
2483            final char jOfT = t.charAt(j - 1); // jth character of t
2484            d[0] = j;
2485
2486            // compute stripe indices, constrain to array size
2487            final int min = Math.max(1, j - threshold);
2488            final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold);
2489
2490            // the stripe may lead off of the table if s and t are of different sizes
2491            if (min > max) {
2492                return -1;
2493            }
2494
2495            // ignore entry left of leftmost
2496            if (min > 1) {
2497                d[min - 1] = Integer.MAX_VALUE;
2498            }
2499
2500            // iterates through [min, max] in s
2501            for (int i = min; i <= max; i++) {
2502                if (s.charAt(i - 1) == jOfT) {
2503                    // diagonally left and up
2504                    d[i] = p[i - 1];
2505                } else {
2506                    // 1 + minimum of cell to the left, to the top, diagonally left and up
2507                    d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);
2508                }
2509            }
2510
2511            // copy current distance counts to 'previous row' distance counts
2512            tmp = p;
2513            p = d;
2514            d = tmp;
2515        }
2516
2517        // if p[n] is greater than the threshold, there's no guarantee on it being the correct
2518        // distance
2519        if (p[n] <= threshold) {
2520            return p[n];
2521        }
2522        return -1;
2523    }
2524
2525    /**
2526     * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible.
2527     *
2528     * <p>
2529     * A {@code null} CharSequence will return {@code -1}.
2530     * </p>
2531     *
2532     * <pre>
2533     * StringUtils.indexOf(null, *)          = -1
2534     * StringUtils.indexOf(*, null)          = -1
2535     * StringUtils.indexOf("", "")           = 0
2536     * StringUtils.indexOf("", *)            = -1 (except when * = "")
2537     * StringUtils.indexOf("aabaabaa", "a")  = 0
2538     * StringUtils.indexOf("aabaabaa", "b")  = 2
2539     * StringUtils.indexOf("aabaabaa", "ab") = 1
2540     * StringUtils.indexOf("aabaabaa", "")   = 0
2541     * </pre>
2542     *
2543     * @param seq       the CharSequence to check, may be null.
2544     * @param searchSeq the CharSequence to find, may be null.
2545     * @return the first index of the search CharSequence, -1 if no match or {@code null} string input.
2546     * @since 2.0
2547     * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence)
2548     * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CS.indexOf(CharSequence, CharSequence)}.
2549     */
2550    @Deprecated
2551    public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
2552        return Strings.CS.indexOf(seq, searchSeq);
2553    }
2554
2555    /**
2556     * Finds the first index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String, int)} if possible.
2557     *
2558     * <p>
2559     * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A
2560     * start position greater than the string length only matches an empty search CharSequence.
2561     * </p>
2562     *
2563     * <pre>
2564     * StringUtils.indexOf(null, *, *)          = -1
2565     * StringUtils.indexOf(*, null, *)          = -1
2566     * StringUtils.indexOf("", "", 0)           = 0
2567     * StringUtils.indexOf("", *, 0)            = -1 (except when * = "")
2568     * StringUtils.indexOf("aabaabaa", "a", 0)  = 0
2569     * StringUtils.indexOf("aabaabaa", "b", 0)  = 2
2570     * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
2571     * StringUtils.indexOf("aabaabaa", "b", 3)  = 5
2572     * StringUtils.indexOf("aabaabaa", "b", 9)  = -1
2573     * StringUtils.indexOf("aabaabaa", "b", -1) = 2
2574     * StringUtils.indexOf("aabaabaa", "", 2)   = 2
2575     * StringUtils.indexOf("abc", "", 9)        = 3
2576     * </pre>
2577     *
2578     * @param seq       the CharSequence to check, may be null.
2579     * @param searchSeq the CharSequence to find, may be null.
2580     * @param startPos  the start position, negative treated as zero.
2581     * @return the first index of the search CharSequence (always &ge; startPos), -1 if no match or {@code null} string input.
2582     * @since 2.0
2583     * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int)
2584     * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CS.indexOf(CharSequence, CharSequence, int)}.
2585     */
2586    @Deprecated
2587    public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
2588        return Strings.CS.indexOf(seq, searchSeq, startPos);
2589    }
2590
2591    /**
2592     * Returns the index within {@code seq} of the first occurrence of the specified character. If a character with value {@code searchChar} occurs in the
2593     * character sequence represented by {@code seq} {@link CharSequence} object, then the index (in Unicode code units) of the first such occurrence is
2594     * returned. For values of {@code searchChar} in the range from 0 to 0xFFFF (inclusive), this is the smallest value <em>k</em> such that:
2595     *
2596     * <pre>
2597     * this.charAt(<em>k</em>) == searchChar
2598     * </pre>
2599     *
2600     * <p>
2601     * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that:
2602     * </p>
2603     *
2604     * <pre>
2605     * this.codePointAt(<em>k</em>) == searchChar
2606     * </pre>
2607     *
2608     * <p>
2609     * is true. In either case, if no such character occurs in {@code seq}, then {@code INDEX_NOT_FOUND (-1)} is returned.
2610     * </p>
2611     *
2612     * <p>
2613     * Furthermore, a {@code null} or empty ("") CharSequence will return {@code INDEX_NOT_FOUND (-1)}.
2614     * </p>
2615     *
2616     * <pre>
2617     * StringUtils.indexOf(null, *)         = -1
2618     * StringUtils.indexOf("", *)           = -1
2619     * StringUtils.indexOf("aabaabaa", 'a') = 0
2620     * StringUtils.indexOf("aabaabaa", 'b') = 2
2621     * StringUtils.indexOf("aaaaaaaa", 'Z') = -1
2622     * </pre>
2623     *
2624     * @param seq        the CharSequence to check, may be null.
2625     * @param searchChar the character to find.
2626     * @return the first index of the search character, -1 if no match or {@code null} string input.
2627     * @since 2.0
2628     * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int)
2629     * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
2630     */
2631    public static int indexOf(final CharSequence seq, final int searchChar) {
2632        if (isEmpty(seq)) {
2633            return INDEX_NOT_FOUND;
2634        }
2635        return CharSequenceUtils.indexOf(seq, searchChar, 0);
2636    }
2637
2638    /**
2639     * Returns the index within {@code seq} of the first occurrence of the specified character, starting the search at the specified index.
2640     * <p>
2641     * If a character with value {@code searchChar} occurs in the character sequence represented by the {@code seq} {@link CharSequence} object at an index no
2642     * smaller than {@code startPos}, then the index of the first such occurrence is returned. For values of {@code searchChar} in the range from 0 to 0xFFFF
2643     * (inclusive), this is the smallest value <em>k</em> such that:
2644     * </p>
2645     *
2646     * <pre>
2647     * (this.charAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &gt;= startPos)
2648     * </pre>
2649     *
2650     * <p>
2651     * is true. For other values of {@code searchChar}, it is the smallest value <em>k</em> such that:
2652     * </p>
2653     *
2654     * <pre>
2655     * (this.codePointAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &gt;= startPos)
2656     * </pre>
2657     *
2658     * <p>
2659     * is true. In either case, if no such character occurs in {@code seq} at or after position {@code startPos}, then {@code -1} is returned.
2660     * </p>
2661     *
2662     * <p>
2663     * There is no restriction on the value of {@code startPos}. If it is negative, it has the same effect as if it were zero: this entire string may be
2664     * searched. If it is greater than the length of this string, it has the same effect as if it were equal to the length of this string:
2665     * {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a {@code null} or empty ("") CharSequence will return {@code (INDEX_NOT_FOUND) -1}.
2666     * </p>
2667     * <p>
2668     * All indices are specified in {@code char} values (Unicode code units).
2669     * </p>
2670     *
2671     * <pre>
2672     * StringUtils.indexOf(null, *, *)          = -1
2673     * StringUtils.indexOf("", *, *)            = -1
2674     * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2
2675     * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5
2676     * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1
2677     * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
2678     * </pre>
2679     *
2680     * @param seq        the CharSequence to check, may be null.
2681     * @param searchChar the character to find.
2682     * @param startPos   the start position, negative treated as zero.
2683     * @return the first index of the search character (always &ge; startPos), -1 if no match or {@code null} string input.
2684     * @since 2.0
2685     * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int)
2686     * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
2687     */
2688    public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) {
2689        if (isEmpty(seq)) {
2690            return INDEX_NOT_FOUND;
2691        }
2692        return CharSequenceUtils.indexOf(seq, searchChar, startPos);
2693    }
2694
2695    /**
2696     * Search a CharSequence to find the first index of any character in the given set of characters.
2697     *
2698     * <p>
2699     * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}.
2700     * </p>
2701     *
2702     * <pre>
2703     * StringUtils.indexOfAny(null, *)                  = -1
2704     * StringUtils.indexOfAny("", *)                    = -1
2705     * StringUtils.indexOfAny(*, null)                  = -1
2706     * StringUtils.indexOfAny(*, [])                    = -1
2707     * StringUtils.indexOfAny("zzabyycdxx", 'z', 'a')   = 0
2708     * StringUtils.indexOfAny("zzabyycdxx", 'b', 'y')   = 3
2709     * StringUtils.indexOfAny("aba", 'z')               = -1
2710     * </pre>
2711     *
2712     * @param cs          the CharSequence to check, may be null.
2713     * @param searchChars the chars to search for, may be null.
2714     * @return the index of any of the chars, -1 if no match or null input.
2715     * @since 2.0
2716     * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
2717     */
2718    public static int indexOfAny(final CharSequence cs, final char... searchChars) {
2719        return indexOfAny(cs, 0, searchChars);
2720    }
2721
2722    /**
2723     * Find the first index of any of a set of potential substrings.
2724     *
2725     * <p>
2726     * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}. A {@code null} search array entry
2727     * will be ignored, but a search array containing "" will return {@code 0} if {@code str} is not null. This method uses {@link String#indexOf(String)} if
2728     * possible.
2729     * </p>
2730     *
2731     * <pre>
2732     * StringUtils.indexOfAny(null, *)                    = -1
2733     * StringUtils.indexOfAny(*, null)                    = -1
2734     * StringUtils.indexOfAny(*, [])                      = -1
2735     * StringUtils.indexOfAny("zzabyycdxx", "ab", "cd")   = 2
2736     * StringUtils.indexOfAny("zzabyycdxx", "cd", "ab")   = 2
2737     * StringUtils.indexOfAny("zzabyycdxx", "mn", "op")   = -1
2738     * StringUtils.indexOfAny("zzabyycdxx", "zab", "aby") = 1
2739     * StringUtils.indexOfAny("zzabyycdxx", "")           = 0
2740     * StringUtils.indexOfAny("", "")                     = 0
2741     * StringUtils.indexOfAny("", "a")                    = -1
2742     * </pre>
2743     *
2744     * @param str        the CharSequence to check, may be null.
2745     * @param searchStrs the CharSequences to search for, may be null.
2746     * @return the first index of any of the searchStrs in str, -1 if no match.
2747     * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...)
2748     */
2749    public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) {
2750        if (str == null || searchStrs == null) {
2751            return INDEX_NOT_FOUND;
2752        }
2753        // String's can't have a MAX_VALUEth index.
2754        int ret = Integer.MAX_VALUE;
2755        int tmp;
2756        for (final CharSequence search : searchStrs) {
2757            if (search == null) {
2758                continue;
2759            }
2760            tmp = CharSequenceUtils.indexOf(str, search, 0);
2761            if (tmp == INDEX_NOT_FOUND) {
2762                continue;
2763            }
2764            if (tmp < ret) {
2765                ret = tmp;
2766            }
2767        }
2768        return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret;
2769    }
2770
2771    /**
2772     * Search a CharSequence to find the first index of any character in the given set of characters.
2773     *
2774     * <p>
2775     * A {@code null} String will return {@code -1}. A {@code null} or zero length search array will return {@code -1}.
2776     * </p>
2777     * <p>
2778     * The following is the same as {@code indexOfAny(cs, 0, searchChars)}.
2779     * </p>
2780     * <pre>
2781     * StringUtils.indexOfAny(null, 0, *)                  = -1
2782     * StringUtils.indexOfAny("", 0, *)                    = -1
2783     * StringUtils.indexOfAny(*, 0, null)                  = -1
2784     * StringUtils.indexOfAny(*, 0, [])                    = -1
2785     * StringUtils.indexOfAny("zzabyycdxx", 0, ['z', 'a']) = 0
2786     * StringUtils.indexOfAny("zzabyycdxx", 0, ['b', 'y']) = 3
2787     * StringUtils.indexOfAny("aba", 0, ['z'])             = -1
2788     * </pre>
2789     *
2790     * @param cs          the CharSequence to check, may be null.
2791     * @param csStart Start searching the input {@code cs} at this index.
2792     * @param searchChars the chars to search for, may be null.
2793     * @return the index of any of the chars, -1 if no match or null input.
2794     * @since 2.0
2795     * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
2796     */
2797    public static int indexOfAny(final CharSequence cs, final int csStart, final char... searchChars) {
2798        if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
2799            return INDEX_NOT_FOUND;
2800        }
2801        final int csLen = cs.length();
2802        final int csLast = csLen - 1;
2803        final int searchLen = searchChars.length;
2804        final int searchLast = searchLen - 1;
2805        for (int i = csStart; i < csLen; i++) {
2806            final char ch = cs.charAt(i);
2807            for (int j = 0; j < searchLen; j++) {
2808                if (searchChars[j] == ch) {
2809                    // ch is a supplementary character
2810                    if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch) || searchChars[j + 1] == cs.charAt(i + 1)) {
2811                        return i;
2812                    }
2813                }
2814            }
2815        }
2816        return INDEX_NOT_FOUND;
2817    }
2818
2819    /**
2820     * Search a CharSequence to find the first index of any character in the given set of characters.
2821     *
2822     * <p>
2823     * A {@code null} String will return {@code -1}. A {@code null} search string will return {@code -1}.
2824     * </p>
2825     *
2826     * <pre>
2827     * StringUtils.indexOfAny(null, *)            = -1
2828     * StringUtils.indexOfAny("", *)              = -1
2829     * StringUtils.indexOfAny(*, null)            = -1
2830     * StringUtils.indexOfAny(*, "")              = -1
2831     * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
2832     * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
2833     * StringUtils.indexOfAny("aba", "z")         = -1
2834     * </pre>
2835     *
2836     * @param cs          the CharSequence to check, may be null.
2837     * @param searchChars the chars to search for, may be null.
2838     * @return the index of any of the chars, -1 if no match or null input.
2839     * @since 2.0
2840     * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String)
2841     */
2842    public static int indexOfAny(final CharSequence cs, final String searchChars) {
2843        if (isEmpty(cs) || isEmpty(searchChars)) {
2844            return INDEX_NOT_FOUND;
2845        }
2846        return indexOfAny(cs, searchChars.toCharArray());
2847    }
2848
2849    /**
2850     * Searches a CharSequence to find the first index of any character not in the given set of characters, i.e., find index i of first char in cs such that
2851     * (cs.codePointAt(i) ∉ { x ∈ codepoints(searchChars) })
2852     *
2853     * <p>
2854     * A {@code null} CharSequence will return {@code -1}. A {@code null} or zero length search array will return {@code -1}.
2855     * </p>
2856     *
2857     * <pre>
2858     * StringUtils.indexOfAnyBut(null, *)                              = -1
2859     * StringUtils.indexOfAnyBut("", *)                                = -1
2860     * StringUtils.indexOfAnyBut(*, null)                              = -1
2861     * StringUtils.indexOfAnyBut(*, [])                                = -1
2862     * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
2863     * StringUtils.indexOfAnyBut("aba", new char[] {'z'} )             = 0
2864     * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} )        = -1
2865     * </pre>
2866     *
2867     * @param cs          the CharSequence to check, may be null.
2868     * @param searchChars the chars to search for, may be null.
2869     * @return the index of any of the chars, -1 if no match or null input.
2870     * @since 2.0
2871     * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...)
2872     */
2873    public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) {
2874        if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
2875            return INDEX_NOT_FOUND;
2876        }
2877        return indexOfAnyBut(cs, CharBuffer.wrap(searchChars));
2878    }
2879
2880    /**
2881     * Search a CharSequence to find the first index of any character not in the given set of characters, i.e., find index i of first char in seq such that
2882     * (seq.codePointAt(i) ∉ { x ∈ codepoints(searchChars) })
2883     *
2884     * <p>
2885     * A {@code null} CharSequence will return {@code -1}. A {@code null} or empty search string will return {@code -1}.
2886     * </p>
2887     *
2888     * <pre>
2889     * StringUtils.indexOfAnyBut(null, *)            = -1
2890     * StringUtils.indexOfAnyBut("", *)              = -1
2891     * StringUtils.indexOfAnyBut(*, null)            = -1
2892     * StringUtils.indexOfAnyBut(*, "")              = -1
2893     * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
2894     * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = -1
2895     * StringUtils.indexOfAnyBut("aba", "ab")        = -1
2896     * </pre>
2897     *
2898     * @param seq         the CharSequence to check, may be null.
2899     * @param searchChars the chars to search for, may be null.
2900     * @return the index of any of the chars, -1 if no match or null input.
2901     * @since 2.0
2902     * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence)
2903     */
2904    public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) {
2905        if (isEmpty(seq) || isEmpty(searchChars)) {
2906            return INDEX_NOT_FOUND;
2907        }
2908        final Set<Integer> searchSetCodePoints = searchChars.codePoints()
2909                .boxed().collect(Collectors.toSet());
2910        // advance character index from one interpreted codepoint to the next
2911        for (int curSeqCharIdx = 0; curSeqCharIdx < seq.length();) {
2912            final int curSeqCodePoint = Character.codePointAt(seq, curSeqCharIdx);
2913            if (!searchSetCodePoints.contains(curSeqCodePoint)) {
2914                return curSeqCharIdx;
2915            }
2916            curSeqCharIdx += Character.charCount(curSeqCodePoint); // skip indices to paired low-surrogates
2917        }
2918        return INDEX_NOT_FOUND;
2919    }
2920
2921    /**
2922     * Compares all CharSequences in an array and returns the index at which the CharSequences begin to differ.
2923     *
2924     * <p>
2925     * For example, {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}
2926     * </p>
2927     *
2928     * <pre>
2929     * StringUtils.indexOfDifference(null)                             = -1
2930     * StringUtils.indexOfDifference(new String[] {})                  = -1
2931     * StringUtils.indexOfDifference(new String[] {"abc"})             = -1
2932     * StringUtils.indexOfDifference(new String[] {null, null})        = -1
2933     * StringUtils.indexOfDifference(new String[] {"", ""})            = -1
2934     * StringUtils.indexOfDifference(new String[] {"", null})          = 0
2935     * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
2936     * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
2937     * StringUtils.indexOfDifference(new String[] {"", "abc"})         = 0
2938     * StringUtils.indexOfDifference(new String[] {"abc", ""})         = 0
2939     * StringUtils.indexOfDifference(new String[] {"abc", "abc"})      = -1
2940     * StringUtils.indexOfDifference(new String[] {"abc", "a"})        = 1
2941     * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"})     = 2
2942     * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"})  = 2
2943     * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"})    = 0
2944     * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"})    = 0
2945     * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
2946     * </pre>
2947     *
2948     * @param css array of CharSequences, entries may be null.
2949     * @return the index where the strings begin to differ; -1 if they are all equal.
2950     * @since 2.4
2951     * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...)
2952     */
2953    public static int indexOfDifference(final CharSequence... css) {
2954        if (ArrayUtils.getLength(css) <= 1) {
2955            return INDEX_NOT_FOUND;
2956        }
2957        boolean anyStringNull = false;
2958        boolean allStringsNull = true;
2959        final int arrayLen = css.length;
2960        int shortestStrLen = Integer.MAX_VALUE;
2961        int longestStrLen = 0;
2962        // find the min and max string lengths; this avoids checking to make
2963        // sure we are not exceeding the length of the string each time through
2964        // the bottom loop.
2965        for (final CharSequence cs : css) {
2966            if (cs == null) {
2967                anyStringNull = true;
2968                shortestStrLen = 0;
2969            } else {
2970                allStringsNull = false;
2971                shortestStrLen = Math.min(cs.length(), shortestStrLen);
2972                longestStrLen = Math.max(cs.length(), longestStrLen);
2973            }
2974        }
2975        // handle lists containing all nulls or all empty strings
2976        if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
2977            return INDEX_NOT_FOUND;
2978        }
2979        // handle lists containing some nulls or some empty strings
2980        if (shortestStrLen == 0) {
2981            return 0;
2982        }
2983        // find the position with the first difference across all strings
2984        int firstDiff = -1;
2985        for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
2986            final char comparisonChar = css[0].charAt(stringPos);
2987            for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
2988                if (css[arrayPos].charAt(stringPos) != comparisonChar) {
2989                    firstDiff = stringPos;
2990                    break;
2991                }
2992            }
2993            if (firstDiff != -1) {
2994                break;
2995            }
2996        }
2997        if (firstDiff == -1 && shortestStrLen != longestStrLen) {
2998            // we compared all of the characters up to the length of the
2999            // shortest string and didn't find a match, but the string lengths
3000            // vary, so return the length of the shortest string.
3001            return shortestStrLen;
3002        }
3003        return firstDiff;
3004    }
3005
3006    /**
3007     * Compares two CharSequences, and returns the index at which the CharSequences begin to differ.
3008     *
3009     * <p>
3010     * For example, {@code indexOfDifference("i am a machine", "i am a robot") -> 7}
3011     * </p>
3012     *
3013     * <pre>
3014     * StringUtils.indexOfDifference(null, null)       = -1
3015     * StringUtils.indexOfDifference("", "")           = -1
3016     * StringUtils.indexOfDifference("", "abc")        = 0
3017     * StringUtils.indexOfDifference("abc", "")        = 0
3018     * StringUtils.indexOfDifference("abc", "abc")     = -1
3019     * StringUtils.indexOfDifference("ab", "abxyz")    = 2
3020     * StringUtils.indexOfDifference("abcde", "abxyz") = 2
3021     * StringUtils.indexOfDifference("abcde", "xyz")   = 0
3022     * </pre>
3023     *
3024     * @param cs1 the first CharSequence, may be null.
3025     * @param cs2 the second CharSequence, may be null.
3026     * @return the index where cs1 and cs2 begin to differ; -1 if they are equal.
3027     * @since 2.0
3028     * @since 3.0 Changed signature from indexOfDifference(String, String) to indexOfDifference(CharSequence, CharSequence)
3029     */
3030    public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) {
3031        if (cs1 == cs2) {
3032            return INDEX_NOT_FOUND;
3033        }
3034        if (cs1 == null || cs2 == null) {
3035            return 0;
3036        }
3037        int i;
3038        for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
3039            if (cs1.charAt(i) != cs2.charAt(i)) {
3040                break;
3041            }
3042        }
3043        if (i < cs2.length() || i < cs1.length()) {
3044            return i;
3045        }
3046        return INDEX_NOT_FOUND;
3047    }
3048
3049    /**
3050     * Case in-sensitive find of the first index within a CharSequence.
3051     *
3052     * <p>
3053     * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A
3054     * start position greater than the string length only matches an empty search CharSequence.
3055     * </p>
3056     *
3057     * <pre>
3058     * StringUtils.indexOfIgnoreCase(null, *)          = -1
3059     * StringUtils.indexOfIgnoreCase(*, null)          = -1
3060     * StringUtils.indexOfIgnoreCase("", "")           = 0
3061     * StringUtils.indexOfIgnoreCase(" ", " ")         = 0
3062     * StringUtils.indexOfIgnoreCase("aabaabaa", "a")  = 0
3063     * StringUtils.indexOfIgnoreCase("aabaabaa", "b")  = 2
3064     * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
3065     * </pre>
3066     *
3067     * @param str       the CharSequence to check, may be null.
3068     * @param searchStr the CharSequence to find, may be null.
3069     * @return the first index of the search CharSequence, -1 if no match or {@code null} string input.
3070     * @since 2.5
3071     * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence)
3072     * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence) Strings.CI.indexOf(CharSequence, CharSequence)}.
3073     */
3074    @Deprecated
3075    public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
3076        return Strings.CI.indexOf(str, searchStr);
3077    }
3078
3079    /**
3080     * Case in-sensitive find of the first index within a CharSequence from the specified position.
3081     *
3082     * <p>
3083     * A {@code null} CharSequence will return {@code -1}. A negative start position is treated as zero. An empty ("") search CharSequence always matches. A
3084     * start position greater than the string length only matches an empty search CharSequence.
3085     * </p>
3086     *
3087     * <pre>
3088     * StringUtils.indexOfIgnoreCase(null, *, *)          = -1
3089     * StringUtils.indexOfIgnoreCase(*, null, *)          = -1
3090     * StringUtils.indexOfIgnoreCase("", "", 0)           = 0
3091     * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
3092     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
3093     * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
3094     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
3095     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
3096     * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
3097     * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
3098     * StringUtils.indexOfIgnoreCase("abc", "", 9)        = -1
3099     * </pre>
3100     *
3101     * @param str       the CharSequence to check, may be null.
3102     * @param searchStr the CharSequence to find, may be null.
3103     * @param startPos  the start position, negative treated as zero.
3104     * @return the first index of the search CharSequence (always &ge; startPos), -1 if no match or {@code null} string input.
3105     * @since 2.5
3106     * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int)
3107     * @deprecated Use {@link Strings#indexOf(CharSequence, CharSequence, int) Strings.CI.indexOf(CharSequence, CharSequence, int)}.
3108     */
3109    @Deprecated
3110    public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) {
3111        return Strings.CI.indexOf(str, searchStr, startPos);
3112    }
3113
3114    /**
3115     * Tests if all of the CharSequences are empty (""), null or whitespace only.
3116     *
3117     * <p>
3118     * Whitespace is defined by {@link Character#isWhitespace(char)}.
3119     * </p>
3120     *
3121     * <pre>
3122     * StringUtils.isAllBlank(null)             = true
3123     * StringUtils.isAllBlank(null, "foo")      = false
3124     * StringUtils.isAllBlank(null, null)       = true
3125     * StringUtils.isAllBlank("", "bar")        = false
3126     * StringUtils.isAllBlank("bob", "")        = false
3127     * StringUtils.isAllBlank("  bob  ", null)  = false
3128     * StringUtils.isAllBlank(" ", "bar")       = false
3129     * StringUtils.isAllBlank("foo", "bar")     = false
3130     * StringUtils.isAllBlank(new String[] {})  = true
3131     * </pre>
3132     *
3133     * @param css the CharSequences to check, may be null or empty.
3134     * @return {@code true} if all of the CharSequences are empty or null or whitespace only.
3135     * @since 3.6
3136     */
3137    public static boolean isAllBlank(final CharSequence... css) {
3138        if (ArrayUtils.isEmpty(css)) {
3139            return true;
3140        }
3141        for (final CharSequence cs : css) {
3142            if (isNotBlank(cs)) {
3143                return false;
3144            }
3145        }
3146        return true;
3147    }
3148
3149    /**
3150     * Tests if all of the CharSequences are empty ("") or null.
3151     *
3152     * <pre>
3153     * StringUtils.isAllEmpty(null)             = true
3154     * StringUtils.isAllEmpty(null, "")         = true
3155     * StringUtils.isAllEmpty(new String[] {})  = true
3156     * StringUtils.isAllEmpty(null, "foo")      = false
3157     * StringUtils.isAllEmpty("", "bar")        = false
3158     * StringUtils.isAllEmpty("bob", "")        = false
3159     * StringUtils.isAllEmpty("  bob  ", null)  = false
3160     * StringUtils.isAllEmpty(" ", "bar")       = false
3161     * StringUtils.isAllEmpty("foo", "bar")     = false
3162     * </pre>
3163     *
3164     * @param css the CharSequences to check, may be null or empty.
3165     * @return {@code true} if all of the CharSequences are empty or null.
3166     * @since 3.6
3167     */
3168    public static boolean isAllEmpty(final CharSequence... css) {
3169        if (ArrayUtils.isEmpty(css)) {
3170            return true;
3171        }
3172        for (final CharSequence cs : css) {
3173            if (isNotEmpty(cs)) {
3174                return false;
3175            }
3176        }
3177        return true;
3178    }
3179
3180    /**
3181     * Tests if the CharSequence contains only lowercase characters.
3182     *
3183     * <p>
3184     * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}.
3185     * </p>
3186     *
3187     * <pre>
3188     * StringUtils.isAllLowerCase(null)   = false
3189     * StringUtils.isAllLowerCase("")     = false
3190     * StringUtils.isAllLowerCase("  ")   = false
3191     * StringUtils.isAllLowerCase("abc")  = true
3192     * StringUtils.isAllLowerCase("abC")  = false
3193     * StringUtils.isAllLowerCase("ab c") = false
3194     * StringUtils.isAllLowerCase("ab1c") = false
3195     * StringUtils.isAllLowerCase("ab/c") = false
3196     * </pre>
3197     *
3198     * @param cs the CharSequence to check, may be null.
3199     * @return {@code true} if only contains lowercase characters, and is non-null.
3200     * @since 2.5
3201     * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence)
3202     */
3203    public static boolean isAllLowerCase(final CharSequence cs) {
3204        if (isEmpty(cs)) {
3205            return false;
3206        }
3207        final int sz = cs.length();
3208        for (int i = 0; i < sz; i++) {
3209            if (!Character.isLowerCase(cs.charAt(i))) {
3210                return false;
3211            }
3212        }
3213        return true;
3214    }
3215
3216    /**
3217     * Tests if the CharSequence contains only uppercase characters.
3218     *
3219     * <p>{@code null} will return {@code false}.
3220     * An empty String (length()=0) will return {@code false}.</p>
3221     *
3222     * <pre>
3223     * StringUtils.isAllUpperCase(null)   = false
3224     * StringUtils.isAllUpperCase("")     = false
3225     * StringUtils.isAllUpperCase("  ")   = false
3226     * StringUtils.isAllUpperCase("ABC")  = true
3227     * StringUtils.isAllUpperCase("aBC")  = false
3228     * StringUtils.isAllUpperCase("A C")  = false
3229     * StringUtils.isAllUpperCase("A1C")  = false
3230     * StringUtils.isAllUpperCase("A/C")  = false
3231     * </pre>
3232     *
3233     * @param cs the CharSequence to check, may be null.
3234     * @return {@code true} if only contains uppercase characters, and is non-null.
3235     * @since 2.5
3236     * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence)
3237     */
3238    public static boolean isAllUpperCase(final CharSequence cs) {
3239        if (isEmpty(cs)) {
3240            return false;
3241        }
3242        final int sz = cs.length();
3243        for (int i = 0; i < sz; i++) {
3244            if (!Character.isUpperCase(cs.charAt(i))) {
3245                return false;
3246            }
3247        }
3248        return true;
3249    }
3250
3251    /**
3252     * Tests if the CharSequence contains only Unicode letters.
3253     *
3254     * <p>
3255     * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}.
3256     * </p>
3257     *
3258     * <pre>
3259     * StringUtils.isAlpha(null)   = false
3260     * StringUtils.isAlpha("")     = false
3261     * StringUtils.isAlpha("  ")   = false
3262     * StringUtils.isAlpha("abc")  = true
3263     * StringUtils.isAlpha("ab2c") = false
3264     * StringUtils.isAlpha("ab-c") = false
3265     * </pre>
3266     *
3267     * @param cs the CharSequence to check, may be null.
3268     * @return {@code true} if only contains letters, and is non-null.
3269     * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence)
3270     * @since 3.0 Changed "" to return false and not true
3271     */
3272    public static boolean isAlpha(final CharSequence cs) {
3273        if (isEmpty(cs)) {
3274            return false;
3275        }
3276        final int sz = cs.length();
3277        for (int i = 0; i < sz; i++) {
3278            if (!Character.isLetter(cs.charAt(i))) {
3279                return false;
3280            }
3281        }
3282        return true;
3283    }
3284
3285    /**
3286     * Tests if the CharSequence contains only Unicode letters or digits.
3287     *
3288     * <p>
3289     * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}.
3290     * </p>
3291     *
3292     * <pre>
3293     * StringUtils.isAlphanumeric(null)   = false
3294     * StringUtils.isAlphanumeric("")     = false
3295     * StringUtils.isAlphanumeric("  ")   = false
3296     * StringUtils.isAlphanumeric("abc")  = true
3297     * StringUtils.isAlphanumeric("ab c") = false
3298     * StringUtils.isAlphanumeric("ab2c") = true
3299     * StringUtils.isAlphanumeric("ab-c") = false
3300     * </pre>
3301     *
3302     * @param cs the CharSequence to check, may be null.
3303     * @return {@code true} if only contains letters or digits, and is non-null.
3304     * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence)
3305     * @since 3.0 Changed "" to return false and not true
3306     */
3307    public static boolean isAlphanumeric(final CharSequence cs) {
3308        if (isEmpty(cs)) {
3309            return false;
3310        }
3311        final int sz = cs.length();
3312        for (int i = 0; i < sz; i++) {
3313            if (!Character.isLetterOrDigit(cs.charAt(i))) {
3314                return false;
3315            }
3316        }
3317        return true;
3318    }
3319
3320    /**
3321     * Tests if the CharSequence contains only Unicode letters, digits or space ({@code ' '}).
3322     *
3323     * <p>
3324     * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}.
3325     * </p>
3326     *
3327     * <pre>
3328     * StringUtils.isAlphanumericSpace(null)   = false
3329     * StringUtils.isAlphanumericSpace("")     = true
3330     * StringUtils.isAlphanumericSpace("  ")   = true
3331     * StringUtils.isAlphanumericSpace("abc")  = true
3332     * StringUtils.isAlphanumericSpace("ab c") = true
3333     * StringUtils.isAlphanumericSpace("ab2c") = true
3334     * StringUtils.isAlphanumericSpace("ab-c") = false
3335     * </pre>
3336     *
3337     * @param cs the CharSequence to check, may be null.
3338     * @return {@code true} if only contains letters, digits or space, and is non-null.
3339     * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence)
3340     */
3341    public static boolean isAlphanumericSpace(final CharSequence cs) {
3342        if (cs == null) {
3343            return false;
3344        }
3345        final int sz = cs.length();
3346        for (int i = 0; i < sz; i++) {
3347            final char nowChar = cs.charAt(i);
3348            if (nowChar != ' ' && !Character.isLetterOrDigit(nowChar)) {
3349                return false;
3350            }
3351        }
3352        return true;
3353    }
3354
3355    /**
3356     * Tests if the CharSequence contains only Unicode letters and space (' ').
3357     *
3358     * <p>
3359     * {@code null} will return {@code false} An empty CharSequence (length()=0) will return {@code true}.
3360     * </p>
3361     *
3362     * <pre>
3363     * StringUtils.isAlphaSpace(null)   = false
3364     * StringUtils.isAlphaSpace("")     = true
3365     * StringUtils.isAlphaSpace("  ")   = true
3366     * StringUtils.isAlphaSpace("abc")  = true
3367     * StringUtils.isAlphaSpace("ab c") = true
3368     * StringUtils.isAlphaSpace("ab2c") = false
3369     * StringUtils.isAlphaSpace("ab-c") = false
3370     * </pre>
3371     *
3372     * @param cs the CharSequence to check, may be null.
3373     * @return {@code true} if only contains letters and space, and is non-null.
3374     * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence)
3375     */
3376    public static boolean isAlphaSpace(final CharSequence cs) {
3377        if (cs == null) {
3378            return false;
3379        }
3380        final int sz = cs.length();
3381        for (int i = 0; i < sz; i++) {
3382            final char nowChar = cs.charAt(i);
3383            if (nowChar != ' ' && !Character.isLetter(nowChar)) {
3384                return false;
3385            }
3386        }
3387        return true;
3388    }
3389
3390    /**
3391     * Tests if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}).
3392     *
3393     * <p>
3394     * Whitespace is defined by {@link Character#isWhitespace(char)}.
3395     * </p>
3396     *
3397     * <pre>
3398     * StringUtils.isAnyBlank((String) null)    = true
3399     * StringUtils.isAnyBlank((String[]) null)  = false
3400     * StringUtils.isAnyBlank(null, "foo")      = true
3401     * StringUtils.isAnyBlank(null, null)       = true
3402     * StringUtils.isAnyBlank("", "bar")        = true
3403     * StringUtils.isAnyBlank("bob", "")        = true
3404     * StringUtils.isAnyBlank("  bob  ", null)  = true
3405     * StringUtils.isAnyBlank(" ", "bar")       = true
3406     * StringUtils.isAnyBlank(new String[] {})  = false
3407     * StringUtils.isAnyBlank(new String[]{""}) = true
3408     * StringUtils.isAnyBlank("foo", "bar")     = false
3409     * </pre>
3410     *
3411     * @param css the CharSequences to check, may be null or empty.
3412     * @return {@code true} if any of the CharSequences are {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}).
3413     * @see #isBlank(CharSequence)
3414     * @since 3.2
3415     */
3416    public static boolean isAnyBlank(final CharSequence... css) {
3417        if (ArrayUtils.isEmpty(css)) {
3418            return false;
3419        }
3420        for (final CharSequence cs : css) {
3421            if (isBlank(cs)) {
3422                return true;
3423            }
3424        }
3425        return false;
3426    }
3427
3428    /**
3429     * Tests if any of the CharSequences are empty ("") or null.
3430     *
3431     * <pre>
3432     * StringUtils.isAnyEmpty((String) null)    = true
3433     * StringUtils.isAnyEmpty((String[]) null)  = false
3434     * StringUtils.isAnyEmpty(null, "foo")      = true
3435     * StringUtils.isAnyEmpty("", "bar")        = true
3436     * StringUtils.isAnyEmpty("bob", "")        = true
3437     * StringUtils.isAnyEmpty("  bob  ", null)  = true
3438     * StringUtils.isAnyEmpty(" ", "bar")       = false
3439     * StringUtils.isAnyEmpty("foo", "bar")     = false
3440     * StringUtils.isAnyEmpty(new String[]{})   = false
3441     * StringUtils.isAnyEmpty(new String[]{""}) = true
3442     * </pre>
3443     *
3444     * @param css  the CharSequences to check, may be null or empty.
3445     * @return {@code true} if any of the CharSequences are empty or null.
3446     * @since 3.2
3447     */
3448    public static boolean isAnyEmpty(final CharSequence... css) {
3449        if (ArrayUtils.isEmpty(css)) {
3450            return false;
3451        }
3452        for (final CharSequence cs : css) {
3453            if (isEmpty(cs)) {
3454                return true;
3455            }
3456        }
3457        return false;
3458    }
3459
3460    /**
3461     * Tests if the CharSequence contains only ASCII printable characters.
3462     *
3463     * <p>
3464     * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}.
3465     * </p>
3466     *
3467     * <pre>
3468     * StringUtils.isAsciiPrintable(null)     = false
3469     * StringUtils.isAsciiPrintable("")       = true
3470     * StringUtils.isAsciiPrintable(" ")      = true
3471     * StringUtils.isAsciiPrintable("Ceki")   = true
3472     * StringUtils.isAsciiPrintable("ab2c")   = true
3473     * StringUtils.isAsciiPrintable("!ab-c~") = true
3474     * StringUtils.isAsciiPrintable("\u0020") = true
3475     * StringUtils.isAsciiPrintable("\u0021") = true
3476     * StringUtils.isAsciiPrintable("\u007e") = true
3477     * StringUtils.isAsciiPrintable("\u007f") = false
3478     * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
3479     * </pre>
3480     *
3481     * @param cs the CharSequence to check, may be null.
3482     * @return {@code true} if every character is in the range 32 through 126.
3483     * @since 2.1
3484     * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence)
3485     */
3486    public static boolean isAsciiPrintable(final CharSequence cs) {
3487        if (cs == null) {
3488            return false;
3489        }
3490        final int sz = cs.length();
3491        for (int i = 0; i < sz; i++) {
3492            if (!CharUtils.isAsciiPrintable(cs.charAt(i))) {
3493                return false;
3494            }
3495        }
3496        return true;
3497    }
3498
3499    /**
3500     * Tests if a CharSequence is empty ({@code "")}, null, or contains only whitespace as defined by {@link Character#isWhitespace(char)}.
3501     *
3502     * <pre>
3503     * StringUtils.isBlank(null)      = true
3504     * StringUtils.isBlank("")        = true
3505     * StringUtils.isBlank(" ")       = true
3506     * StringUtils.isBlank("bob")     = false
3507     * StringUtils.isBlank("  bob  ") = false
3508     * </pre>
3509     *
3510     * @param cs the CharSequence to check, may be null.
3511     * @return {@code true} if the CharSequence is null, empty or whitespace only.
3512     * @since 2.0
3513     * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
3514     */
3515    public static boolean isBlank(final CharSequence cs) {
3516        final int strLen = length(cs);
3517        for (int i = 0; i < strLen; i++) {
3518            if (!Character.isWhitespace(cs.charAt(i))) {
3519                return false;
3520            }
3521        }
3522        return true;
3523    }
3524
3525    /**
3526     * Tests if a CharSequence is empty ("") or null.
3527     *
3528     * <pre>
3529     * StringUtils.isEmpty(null)      = true
3530     * StringUtils.isEmpty("")        = true
3531     * StringUtils.isEmpty(" ")       = false
3532     * StringUtils.isEmpty("bob")     = false
3533     * StringUtils.isEmpty("  bob  ") = false
3534     * </pre>
3535     *
3536     * <p>
3537     * NOTE: This method changed in Lang version 2.0. It no longer trims the CharSequence. That functionality is available in isBlank().
3538     * </p>
3539     *
3540     * @param cs the CharSequence to check, may be null.
3541     * @return {@code true} if the CharSequence is empty or null.
3542     * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
3543     */
3544    public static boolean isEmpty(final CharSequence cs) {
3545        return cs == null || cs.length() == 0;
3546    }
3547
3548    /**
3549     * Tests if the CharSequence contains mixed casing of both uppercase and lowercase characters.
3550     *
3551     * <p>
3552     * {@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return {@code false}.
3553     * </p>
3554     *
3555     * <pre>
3556     * StringUtils.isMixedCase(null)    = false
3557     * StringUtils.isMixedCase("")      = false
3558     * StringUtils.isMixedCase(" ")     = false
3559     * StringUtils.isMixedCase("ABC")   = false
3560     * StringUtils.isMixedCase("abc")   = false
3561     * StringUtils.isMixedCase("aBc")   = true
3562     * StringUtils.isMixedCase("A c")   = true
3563     * StringUtils.isMixedCase("A1c")   = true
3564     * StringUtils.isMixedCase("a/C")   = true
3565     * StringUtils.isMixedCase("aC\t")  = true
3566     * </pre>
3567     *
3568     * @param cs the CharSequence to check, may be null.
3569     * @return {@code true} if the CharSequence contains both uppercase and lowercase characters.
3570     * @since 3.5
3571     */
3572    public static boolean isMixedCase(final CharSequence cs) {
3573        if (isEmpty(cs) || cs.length() == 1) {
3574            return false;
3575        }
3576        boolean containsUppercase = false;
3577        boolean containsLowercase = false;
3578        final int sz = cs.length();
3579        for (int i = 0; i < sz; i++) {
3580            final char nowChar = cs.charAt(i);
3581            if (Character.isUpperCase(nowChar)) {
3582                containsUppercase = true;
3583            } else if (Character.isLowerCase(nowChar)) {
3584                containsLowercase = true;
3585            }
3586            if (containsUppercase && containsLowercase) {
3587                return true;
3588            }
3589        }
3590        return false;
3591    }
3592
3593    /**
3594     * Tests if none of the CharSequences are empty (""), null or whitespace only.
3595     *
3596     * <p>
3597     * Whitespace is defined by {@link Character#isWhitespace(char)}.
3598     * </p>
3599     *
3600     * <pre>
3601     * StringUtils.isNoneBlank((String) null)    = false
3602     * StringUtils.isNoneBlank((String[]) null)  = true
3603     * StringUtils.isNoneBlank(null, "foo")      = false
3604     * StringUtils.isNoneBlank(null, null)       = false
3605     * StringUtils.isNoneBlank("", "bar")        = false
3606     * StringUtils.isNoneBlank("bob", "")        = false
3607     * StringUtils.isNoneBlank("  bob  ", null)  = false
3608     * StringUtils.isNoneBlank(" ", "bar")       = false
3609     * StringUtils.isNoneBlank(new String[] {})  = true
3610     * StringUtils.isNoneBlank(new String[]{""}) = false
3611     * StringUtils.isNoneBlank("foo", "bar")     = true
3612     * </pre>
3613     *
3614     * @param css the CharSequences to check, may be null or empty.
3615     * @return {@code true} if none of the CharSequences are empty or null or whitespace only.
3616     * @since 3.2
3617     */
3618    public static boolean isNoneBlank(final CharSequence... css) {
3619        return !isAnyBlank(css);
3620    }
3621
3622    /**
3623     * Tests if none of the CharSequences are empty ("") or null.
3624     *
3625     * <pre>
3626     * StringUtils.isNoneEmpty((String) null)    = false
3627     * StringUtils.isNoneEmpty((String[]) null)  = true
3628     * StringUtils.isNoneEmpty(null, "foo")      = false
3629     * StringUtils.isNoneEmpty("", "bar")        = false
3630     * StringUtils.isNoneEmpty("bob", "")        = false
3631     * StringUtils.isNoneEmpty("  bob  ", null)  = false
3632     * StringUtils.isNoneEmpty(new String[] {})  = true
3633     * StringUtils.isNoneEmpty(new String[]{""}) = false
3634     * StringUtils.isNoneEmpty(" ", "bar")       = true
3635     * StringUtils.isNoneEmpty("foo", "bar")     = true
3636     * </pre>
3637     *
3638     * @param css  the CharSequences to check, may be null or empty.
3639     * @return {@code true} if none of the CharSequences are empty or null.
3640     * @since 3.2
3641     */
3642    public static boolean isNoneEmpty(final CharSequence... css) {
3643        return !isAnyEmpty(css);
3644    }
3645
3646    /**
3647     * Tests if a CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}).
3648     *
3649     * <p>
3650     * Whitespace is defined by {@link Character#isWhitespace(char)}.
3651     * </p>
3652     *
3653     * <pre>
3654     * StringUtils.isNotBlank(null)      = false
3655     * StringUtils.isNotBlank("")        = false
3656     * StringUtils.isNotBlank(" ")       = false
3657     * StringUtils.isNotBlank("bob")     = true
3658     * StringUtils.isNotBlank("  bob  ") = true
3659     * </pre>
3660     *
3661     * @param cs the CharSequence to check, may be null.
3662     * @return {@code true} if the CharSequence is not {@link #isBlank(CharSequence) blank} (whitespaces, empty ({@code ""}), or {@code null}).
3663     * @see #isBlank(CharSequence)
3664     * @since 2.0
3665     * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
3666     */
3667    public static boolean isNotBlank(final CharSequence cs) {
3668        return !isBlank(cs);
3669    }
3670
3671    /**
3672     * Tests if a CharSequence is not empty ("") and not null.
3673     *
3674     * <pre>
3675     * StringUtils.isNotEmpty(null)      = false
3676     * StringUtils.isNotEmpty("")        = false
3677     * StringUtils.isNotEmpty(" ")       = true
3678     * StringUtils.isNotEmpty("bob")     = true
3679     * StringUtils.isNotEmpty("  bob  ") = true
3680     * </pre>
3681     *
3682     * @param cs  the CharSequence to check, may be null.
3683     * @return {@code true} if the CharSequence is not empty and not null.
3684     * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
3685     */
3686    public static boolean isNotEmpty(final CharSequence cs) {
3687        return !isEmpty(cs);
3688    }
3689
3690    /**
3691     * Tests if the CharSequence contains only Unicode digits. A decimal point is not a Unicode digit and returns false.
3692     *
3693     * <p>
3694     * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code false}.
3695     * </p>
3696     *
3697     * <p>
3698     * Note that the method does not allow for a leading sign, either positive or negative. Also, if a String passes the numeric test, it may still generate a
3699     * NumberFormatException when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range for int or long respectively.
3700     * </p>
3701     *
3702     * <pre>
3703     * StringUtils.isNumeric(null)   = false
3704     * StringUtils.isNumeric("")     = false
3705     * StringUtils.isNumeric("  ")   = false
3706     * StringUtils.isNumeric("123")  = true
3707     * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
3708     * StringUtils.isNumeric("12 3") = false
3709     * StringUtils.isNumeric("ab2c") = false
3710     * StringUtils.isNumeric("12-3") = false
3711     * StringUtils.isNumeric("12.3") = false
3712     * StringUtils.isNumeric("-123") = false
3713     * StringUtils.isNumeric("+123") = false
3714     * </pre>
3715     *
3716     * @param cs the CharSequence to check, may be null.
3717     * @return {@code true} if only contains digits, and is non-null.
3718     * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
3719     * @since 3.0 Changed "" to return false and not true
3720     */
3721    public static boolean isNumeric(final CharSequence cs) {
3722        if (isEmpty(cs)) {
3723            return false;
3724        }
3725        final int sz = cs.length();
3726        for (int i = 0; i < sz; i++) {
3727            if (!Character.isDigit(cs.charAt(i))) {
3728                return false;
3729            }
3730        }
3731        return true;
3732    }
3733
3734    /**
3735     * Tests if the CharSequence contains only Unicode digits or space ({@code ' '}). A decimal point is not a Unicode digit and returns false.
3736     *
3737     * <p>
3738     * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}.
3739     * </p>
3740     *
3741     * <pre>
3742     * StringUtils.isNumericSpace(null)   = false
3743     * StringUtils.isNumericSpace("")     = true
3744     * StringUtils.isNumericSpace("  ")   = true
3745     * StringUtils.isNumericSpace("123")  = true
3746     * StringUtils.isNumericSpace("12 3") = true
3747     * StringUtils.isNumericSpace("\u0967\u0968\u0969")   = true
3748     * StringUtils.isNumericSpace("\u0967\u0968 \u0969")  = true
3749     * StringUtils.isNumericSpace("ab2c") = false
3750     * StringUtils.isNumericSpace("12-3") = false
3751     * StringUtils.isNumericSpace("12.3") = false
3752     * </pre>
3753     *
3754     * @param cs the CharSequence to check, may be null.
3755     * @return {@code true} if only contains digits or space, and is non-null.
3756     * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence)
3757     */
3758    public static boolean isNumericSpace(final CharSequence cs) {
3759        if (cs == null) {
3760            return false;
3761        }
3762        final int sz = cs.length();
3763        for (int i = 0; i < sz; i++) {
3764            final char nowChar = cs.charAt(i);
3765            if (nowChar != ' ' && !Character.isDigit(nowChar)) {
3766                return false;
3767            }
3768        }
3769        return true;
3770    }
3771
3772    /**
3773     * Tests if the CharSequence contains only whitespace.
3774     *
3775     * <p>
3776     * Whitespace is defined by {@link Character#isWhitespace(char)}.
3777     * </p>
3778     *
3779     * <p>
3780     * {@code null} will return {@code false}. An empty CharSequence (length()=0) will return {@code true}.
3781     * </p>
3782     *
3783     * <pre>
3784     * StringUtils.isWhitespace(null)   = false
3785     * StringUtils.isWhitespace("")     = true
3786     * StringUtils.isWhitespace("  ")   = true
3787     * StringUtils.isWhitespace("abc")  = false
3788     * StringUtils.isWhitespace("ab2c") = false
3789     * StringUtils.isWhitespace("ab-c") = false
3790     * </pre>
3791     *
3792     * @param cs the CharSequence to check, may be null.
3793     * @return {@code true} if only contains whitespace, and is non-null.
3794     * @since 2.0
3795     * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence)
3796     */
3797    public static boolean isWhitespace(final CharSequence cs) {
3798        if (cs == null) {
3799            return false;
3800        }
3801        final int sz = cs.length();
3802        for (int i = 0; i < sz; i++) {
3803            if (!Character.isWhitespace(cs.charAt(i))) {
3804                return false;
3805            }
3806        }
3807        return true;
3808    }
3809
3810    /**
3811     * Joins the elements of the provided array into a single String containing the provided list of elements.
3812     *
3813     * <p>
3814     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
3815     * </p>
3816     *
3817     * <pre>
3818     * StringUtils.join(null, *)             = null
3819     * StringUtils.join([], *)               = ""
3820     * StringUtils.join([null], *)           = ""
3821     * StringUtils.join([false, false], ';') = "false;false"
3822     * </pre>
3823     *
3824     * @param array     the array of values to join together, may be null.
3825     * @param delimiter the separator character to use.
3826     * @return the joined String, {@code null} if null array input.
3827     * @since 3.12.0
3828     */
3829    public static String join(final boolean[] array, final char delimiter) {
3830        if (array == null) {
3831            return null;
3832        }
3833        return join(array, delimiter, 0, array.length);
3834    }
3835
3836    /**
3837     * Joins the elements of the provided array into a single String containing the provided list of elements.
3838     *
3839     * <p>
3840     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
3841     * by empty strings.
3842     * </p>
3843     *
3844     * <pre>
3845     * StringUtils.join(null, *)                  = null
3846     * StringUtils.join([], *)                    = ""
3847     * StringUtils.join([null], *)                = ""
3848     * StringUtils.join([true, false, true], ';') = "true;false;true"
3849     * </pre>
3850     *
3851     * @param array
3852     *            the array of values to join together, may be null.
3853     * @param delimiter
3854     *            the separator character to use.
3855     * @param startIndex
3856     *            the first index to start joining from. It is an error to pass in a start index past the end of the
3857     *            array.
3858     * @param endIndex
3859     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
3860     *            the array.
3861     * @return the joined String, {@code null} if null array input.
3862     * @since 3.12.0
3863     */
3864    public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) {
3865        // See StringUtilsJoinBenchmark
3866        if (array == null) {
3867            return null;
3868        }
3869        final int count = endIndex - startIndex;
3870        if (count <= 0) {
3871            return EMPTY;
3872        }
3873        final byte maxElementChars = 5; // "false"
3874        final StringBuilder stringBuilder = capacity(count, maxElementChars);
3875        stringBuilder.append(array[startIndex]);
3876        for (int i = startIndex + 1; i < endIndex; i++) {
3877            stringBuilder.append(delimiter).append(array[i]);
3878        }
3879        return stringBuilder.toString();
3880    }
3881
3882    /**
3883     * Joins the elements of the provided array into a single String containing the provided list of elements.
3884     *
3885     * <p>
3886     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
3887     * by empty strings.
3888     * </p>
3889     *
3890     * <pre>
3891     * StringUtils.join(null, *)         = null
3892     * StringUtils.join([], *)           = ""
3893     * StringUtils.join([null], *)       = ""
3894     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
3895     * StringUtils.join([1, 2, 3], null) = "123"
3896     * </pre>
3897     *
3898     * @param array
3899     *            the array of values to join together, may be null.
3900     * @param delimiter
3901     *            the separator character to use.
3902     * @return the joined String, {@code null} if null array input.
3903     * @since 3.2
3904     */
3905    public static String join(final byte[] array, final char delimiter) {
3906        if (array == null) {
3907            return null;
3908        }
3909        return join(array, delimiter, 0, array.length);
3910    }
3911
3912    /**
3913     * Joins the elements of the provided array into a single String containing the provided list of elements.
3914     *
3915     * <p>
3916     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
3917     * by empty strings.
3918     * </p>
3919     *
3920     * <pre>
3921     * StringUtils.join(null, *)         = null
3922     * StringUtils.join([], *)           = ""
3923     * StringUtils.join([null], *)       = ""
3924     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
3925     * StringUtils.join([1, 2, 3], null) = "123"
3926     * </pre>
3927     *
3928     * @param array
3929     *            the array of values to join together, may be null.
3930     * @param delimiter
3931     *            the separator character to use.
3932     * @param startIndex
3933     *            the first index to start joining from. It is an error to pass in a start index past the end of the
3934     *            array.
3935     * @param endIndex
3936     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
3937     *            the array.
3938     * @return the joined String, {@code null} if null array input.
3939     * @since 3.2
3940     */
3941    public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) {
3942        // See StringUtilsJoinBenchmark
3943        if (array == null) {
3944            return null;
3945        }
3946        final int count = endIndex - startIndex;
3947        if (count <= 0) {
3948            return EMPTY;
3949        }
3950        final byte maxElementChars = 4; // "-128"
3951        final StringBuilder stringBuilder = capacity(count, maxElementChars);
3952        stringBuilder.append(array[startIndex]);
3953        for (int i = startIndex + 1; i < endIndex; i++) {
3954            stringBuilder.append(delimiter).append(array[i]);
3955        }
3956        return stringBuilder.toString();
3957    }
3958
3959    /**
3960     * Joins the elements of the provided array into a single String containing the provided list of elements.
3961     *
3962     * <p>
3963     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
3964     * by empty strings.
3965     * </p>
3966     *
3967     * <pre>
3968     * StringUtils.join(null, *)         = null
3969     * StringUtils.join([], *)           = ""
3970     * StringUtils.join([null], *)       = ""
3971     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
3972     * StringUtils.join([1, 2, 3], null) = "123"
3973     * </pre>
3974     *
3975     * @param array
3976     *            the array of values to join together, may be null.
3977     * @param delimiter
3978     *            the separator character to use.
3979     * @return the joined String, {@code null} if null array input.
3980     * @since 3.2
3981     */
3982    public static String join(final char[] array, final char delimiter) {
3983        if (array == null) {
3984            return null;
3985        }
3986        return join(array, delimiter, 0, array.length);
3987    }
3988
3989    /**
3990     * Joins the elements of the provided array into a single String containing the provided list of elements.
3991     *
3992     * <p>
3993     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
3994     * by empty strings.
3995     * </p>
3996     *
3997     * <pre>
3998     * StringUtils.join(null, *)         = null
3999     * StringUtils.join([], *)           = ""
4000     * StringUtils.join([null], *)       = ""
4001     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
4002     * StringUtils.join([1, 2, 3], null) = "123"
4003     * </pre>
4004     *
4005     * @param array
4006     *            the array of values to join together, may be null.
4007     * @param delimiter
4008     *            the separator character to use.
4009     * @param startIndex
4010     *            the first index to start joining from. It is an error to pass in a start index past the end of the
4011     *            array.
4012     * @param endIndex
4013     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4014     *            the array.
4015     * @return the joined String, {@code null} if null array input.
4016     * @since 3.2
4017     */
4018    public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) {
4019        // See StringUtilsJoinBenchmark
4020        if (array == null) {
4021            return null;
4022        }
4023        final int count = endIndex - startIndex;
4024        if (count <= 0) {
4025            return EMPTY;
4026        }
4027        final byte maxElementChars = 1;
4028        final StringBuilder stringBuilder = capacity(count, maxElementChars);
4029        stringBuilder.append(array[startIndex]);
4030        for (int i = startIndex + 1; i < endIndex; i++) {
4031            stringBuilder.append(delimiter).append(array[i]);
4032        }
4033        return stringBuilder.toString();
4034    }
4035
4036    /**
4037     * Joins the elements of the provided array into a single String containing the provided list of elements.
4038     *
4039     * <p>
4040     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4041     * by empty strings.
4042     * </p>
4043     *
4044     * <pre>
4045     * StringUtils.join(null, *)          = null
4046     * StringUtils.join([], *)            = ""
4047     * StringUtils.join([null], *)        = ""
4048     * StringUtils.join([1, 2, 3], ';')   = "1;2;3"
4049     * StringUtils.join([1, 2, 3], null)  = "123"
4050     * </pre>
4051     *
4052     * @param array
4053     *            the array of values to join together, may be null.
4054     * @param delimiter
4055     *            the separator character to use.
4056     * @return the joined String, {@code null} if null array input.
4057     * @since 3.2
4058     */
4059    public static String join(final double[] array, final char delimiter) {
4060        if (array == null) {
4061            return null;
4062        }
4063        return join(array, delimiter, 0, array.length);
4064    }
4065
4066    /**
4067     * Joins the elements of the provided array into a single String containing the provided list of elements.
4068     *
4069     * <p>
4070     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4071     * by empty strings.
4072     * </p>
4073     *
4074     * <pre>
4075     * StringUtils.join(null, *)          = null
4076     * StringUtils.join([], *)            = ""
4077     * StringUtils.join([null], *)        = ""
4078     * StringUtils.join([1, 2, 3], ';')   = "1;2;3"
4079     * StringUtils.join([1, 2, 3], null)  = "123"
4080     * </pre>
4081     *
4082     * @param array
4083     *            the array of values to join together, may be null.
4084     * @param delimiter
4085     *            the separator character to use.
4086     * @param startIndex
4087     *            the first index to start joining from. It is an error to pass in a start index past the end of the
4088     *            array.
4089     * @param endIndex
4090     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4091     *            the array.
4092     * @return the joined String, {@code null} if null array input.
4093     * @since 3.2
4094     */
4095    public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) {
4096        // See StringUtilsJoinBenchmark
4097        if (array == null) {
4098            return null;
4099        }
4100        final int count = endIndex - startIndex;
4101        if (count <= 0) {
4102            return EMPTY;
4103        }
4104        final byte maxElementChars = 22; // "1.7976931348623157E308"
4105        final StringBuilder stringBuilder = capacity(count, maxElementChars);
4106        stringBuilder.append(array[startIndex]);
4107        for (int i = startIndex + 1; i < endIndex; i++) {
4108            stringBuilder.append(delimiter).append(array[i]);
4109        }
4110        return stringBuilder.toString();
4111    }
4112
4113    /**
4114     * Joins the elements of the provided array into a single String containing the provided list of elements.
4115     *
4116     * <p>
4117     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4118     * by empty strings.
4119     * </p>
4120     *
4121     * <pre>
4122     * StringUtils.join(null, *)          = null
4123     * StringUtils.join([], *)            = ""
4124     * StringUtils.join([null], *)        = ""
4125     * StringUtils.join([1, 2, 3], ';')   = "1;2;3"
4126     * StringUtils.join([1, 2, 3], null)  = "123"
4127     * </pre>
4128     *
4129     * @param array
4130     *            the array of values to join together, may be null.
4131     * @param delimiter
4132     *            the separator character to use.
4133     * @return the joined String, {@code null} if null array input
4134     * @since 3.2
4135     */
4136    public static String join(final float[] array, final char delimiter) {
4137        if (array == null) {
4138            return null;
4139        }
4140        return join(array, delimiter, 0, array.length);
4141    }
4142
4143    /**
4144     * Joins the elements of the provided array into a single String containing the provided list of elements.
4145     *
4146     * <p>
4147     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4148     * by empty strings.
4149     * </p>
4150     *
4151     * <pre>
4152     * StringUtils.join(null, *)          = null
4153     * StringUtils.join([], *)            = ""
4154     * StringUtils.join([null], *)        = ""
4155     * StringUtils.join([1, 2, 3], ';')   = "1;2;3"
4156     * StringUtils.join([1, 2, 3], null)  = "123"
4157     * </pre>
4158     *
4159     * @param array
4160     *            the array of values to join together, may be null.
4161     * @param delimiter
4162     *            the separator character to use.
4163     * @param startIndex
4164     *            the first index to start joining from. It is an error to pass in a start index past the end of the
4165     *            array.
4166     * @param endIndex
4167     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4168     *            the array.
4169     * @return the joined String, {@code null} if null array input.
4170     * @since 3.2
4171     */
4172    public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) {
4173        // See StringUtilsJoinBenchmark
4174        if (array == null) {
4175            return null;
4176        }
4177        final int count = endIndex - startIndex;
4178        if (count <= 0) {
4179            return EMPTY;
4180        }
4181        final byte maxElementChars = 12; // "3.4028235E38"
4182        final StringBuilder stringBuilder = capacity(count, maxElementChars);
4183        stringBuilder.append(array[startIndex]);
4184        for (int i = startIndex + 1; i < endIndex; i++) {
4185            stringBuilder.append(delimiter).append(array[i]);
4186        }
4187        return stringBuilder.toString();
4188    }
4189
4190    /**
4191     * Joins the elements of the provided array into a single String containing the provided list of elements.
4192     *
4193     * <p>
4194     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4195     * by empty strings.
4196     * </p>
4197     *
4198     * <pre>
4199     * StringUtils.join(null, *)          = null
4200     * StringUtils.join([], *)            = ""
4201     * StringUtils.join([null], *)        = ""
4202     * StringUtils.join([1, 2, 3], ';')   = "1;2;3"
4203     * StringUtils.join([1, 2, 3], null)  = "123"
4204     * </pre>
4205     *
4206     * @param array
4207     *            the array of values to join together, may be null.
4208     * @param separator
4209     *            the separator character to use.
4210     * @return the joined String, {@code null} if null array input.
4211     * @since 3.2
4212     */
4213    public static String join(final int[] array, final char separator) {
4214        if (array == null) {
4215            return null;
4216        }
4217        return join(array, separator, 0, array.length);
4218    }
4219
4220    /**
4221     * Joins the elements of the provided array into a single String containing the provided list of elements.
4222     *
4223     * <p>
4224     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4225     * by empty strings.
4226     * </p>
4227     *
4228     * <pre>
4229     * StringUtils.join(null, *)          = null
4230     * StringUtils.join([], *)            = ""
4231     * StringUtils.join([null], *)        = ""
4232     * StringUtils.join([1, 2, 3], ';')   = "1;2;3"
4233     * StringUtils.join([1, 2, 3], null)  = "123"
4234     * </pre>
4235     *
4236     * @param array
4237     *            the array of values to join together, may be null.
4238     * @param delimiter
4239     *            the separator character to use.
4240     * @param startIndex
4241     *            the first index to start joining from. It is an error to pass in a start index past the end of the
4242     *            array.
4243     * @param endIndex
4244     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4245     *            the array.
4246     * @return the joined String, {@code null} if null array input.
4247     * @since 3.2
4248     */
4249    public static String join(final int[] array, final char delimiter, final int startIndex, final int endIndex) {
4250        // See StringUtilsJoinBenchmark
4251        if (array == null) {
4252            return null;
4253        }
4254        final int count = endIndex - startIndex;
4255        if (count <= 0) {
4256            return EMPTY;
4257        }
4258        final byte maxElementChars = 11; // "-2147483648"
4259        final StringBuilder stringBuilder = capacity(count, maxElementChars);
4260        stringBuilder.append(array[startIndex]);
4261        for (int i = startIndex + 1; i < endIndex; i++) {
4262            stringBuilder.append(delimiter).append(array[i]);
4263        }
4264        return stringBuilder.toString();
4265    }
4266
4267    /**
4268     * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements.
4269     *
4270     * <p>
4271     * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings.
4272     * </p>
4273     *
4274     * <p>
4275     * See the examples here: {@link #join(Object[],char)}.
4276     * </p>
4277     *
4278     * @param iterable  the {@link Iterable} providing the values to join together, may be null.
4279     * @param separator the separator character to use.
4280     * @return the joined String, {@code null} if null iterator input.
4281     * @since 2.3
4282     */
4283    public static String join(final Iterable<?> iterable, final char separator) {
4284        return iterable != null ? join(iterable.iterator(), separator) : null;
4285    }
4286
4287    /**
4288     * Joins the elements of the provided {@link Iterable} into a single String containing the provided elements.
4289     *
4290     * <p>
4291     * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String ("").
4292     * </p>
4293     *
4294     * <p>
4295     * See the examples here: {@link #join(Object[],String)}.
4296     * </p>
4297     *
4298     * @param iterable  the {@link Iterable} providing the values to join together, may be null.
4299     * @param separator the separator character to use, null treated as "".
4300     * @return the joined String, {@code null} if null iterator input.
4301     * @since 2.3
4302     */
4303    public static String join(final Iterable<?> iterable, final String separator) {
4304        return iterable != null ? join(iterable.iterator(), separator) : null;
4305    }
4306
4307    /**
4308     * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements.
4309     *
4310     * <p>
4311     * No delimiter is added before or after the list. Null objects or empty strings within the iteration are represented by empty strings.
4312     * </p>
4313     *
4314     * <p>
4315     * See the examples here: {@link #join(Object[],char)}.
4316     * </p>
4317     *
4318     * @param iterator  the {@link Iterator} of values to join together, may be null.
4319     * @param separator the separator character to use.
4320     * @return the joined String, {@code null} if null iterator input.
4321     * @since 2.0
4322     */
4323    public static String join(final Iterator<?> iterator, final char separator) {
4324        // handle null, zero and one elements before building a buffer
4325        if (iterator == null) {
4326            return null;
4327        }
4328        if (!iterator.hasNext()) {
4329            return EMPTY;
4330        }
4331        return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(String.valueOf(separator)), EMPTY, EMPTY, ObjectUtils::toString));
4332    }
4333
4334    /**
4335     * Joins the elements of the provided {@link Iterator} into a single String containing the provided elements.
4336     *
4337     * <p>
4338     * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String ("").
4339     * </p>
4340     *
4341     * <p>
4342     * See the examples here: {@link #join(Object[],String)}.
4343     * </p>
4344     *
4345     * @param iterator  the {@link Iterator} of values to join together, may be null.
4346     * @param separator the separator character to use, null treated as "".
4347     * @return the joined String, {@code null} if null iterator input.
4348     */
4349    public static String join(final Iterator<?> iterator, final String separator) {
4350        // handle null, zero and one elements before building a buffer
4351        if (iterator == null) {
4352            return null;
4353        }
4354        if (!iterator.hasNext()) {
4355            return EMPTY;
4356        }
4357        return Streams.of(iterator).collect(LangCollectors.joining(ObjectUtils.toString(separator), EMPTY, EMPTY, ObjectUtils::toString));
4358    }
4359
4360    /**
4361     * Joins the elements of the provided {@link List} into a single String containing the provided list of elements.
4362     *
4363     * <p>
4364     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
4365     * </p>
4366     *
4367     * <pre>
4368     * StringUtils.join(null, *)               = null
4369     * StringUtils.join([], *)                 = ""
4370     * StringUtils.join([null], *)             = ""
4371     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
4372     * StringUtils.join(["a", "b", "c"], null) = "abc"
4373     * StringUtils.join([null, "", "a"], ';')  = ";;a"
4374     * </pre>
4375     *
4376     * @param list       the {@link List} of values to join together, may be null.
4377     * @param separator  the separator character to use.
4378     * @param startIndex the first index to start joining from. It is an error to pass in a start index past the end of the list.
4379     * @param endIndex   the index to stop joining from (exclusive). It is an error to pass in an end index past the end of the list.
4380     * @return the joined String, {@code null} if null list input.
4381     * @since 3.8
4382     */
4383    public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) {
4384        if (list == null) {
4385            return null;
4386        }
4387        final int noOfItems = endIndex - startIndex;
4388        if (noOfItems <= 0) {
4389            return EMPTY;
4390        }
4391        final List<?> subList = list.subList(startIndex, endIndex);
4392        return join(subList.iterator(), separator);
4393    }
4394
4395    /**
4396     * Joins the elements of the provided {@link List} into a single String containing the provided list of elements.
4397     *
4398     * <p>
4399     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
4400     * </p>
4401     *
4402     * <pre>
4403     * StringUtils.join(null, *)               = null
4404     * StringUtils.join([], *)                 = ""
4405     * StringUtils.join([null], *)             = ""
4406     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
4407     * StringUtils.join(["a", "b", "c"], null) = "abc"
4408     * StringUtils.join([null, "", "a"], ';')  = ";;a"
4409     * </pre>
4410     *
4411     * @param list       the {@link List} of values to join together, may be null.
4412     * @param separator  the separator character to use.
4413     * @param startIndex the first index to start joining from. It is an error to pass in a start index past the end of the list.
4414     * @param endIndex   the index to stop joining from (exclusive). It is an error to pass in an end index past the end of the list.
4415     * @return the joined String, {@code null} if null list input.
4416     * @since 3.8
4417     */
4418    public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) {
4419        if (list == null) {
4420            return null;
4421        }
4422        final int noOfItems = endIndex - startIndex;
4423        if (noOfItems <= 0) {
4424            return EMPTY;
4425        }
4426        final List<?> subList = list.subList(startIndex, endIndex);
4427        return join(subList.iterator(), separator);
4428    }
4429
4430    /**
4431     * Joins the elements of the provided array into a single String containing the provided list of elements.
4432     *
4433     * <p>
4434     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4435     * by empty strings.
4436     * </p>
4437     *
4438     * <pre>
4439     * StringUtils.join(null, *)               = null
4440     * StringUtils.join([], *)                 = ""
4441     * StringUtils.join([null], *)             = ""
4442     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
4443     * StringUtils.join([1, 2, 3], null) = "123"
4444     * </pre>
4445     *
4446     * @param array
4447     *            the array of values to join together, may be null.
4448     * @param separator
4449     *            the separator character to use.
4450     * @return the joined String, {@code null} if null array input.
4451     * @since 3.2
4452     */
4453    public static String join(final long[] array, final char separator) {
4454        if (array == null) {
4455            return null;
4456        }
4457        return join(array, separator, 0, array.length);
4458    }
4459
4460    /**
4461     * Joins the elements of the provided array into a single String containing the provided list of elements.
4462     *
4463     * <p>
4464     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4465     * by empty strings.
4466     * </p>
4467     *
4468     * <pre>
4469     * StringUtils.join(null, *)               = null
4470     * StringUtils.join([], *)                 = ""
4471     * StringUtils.join([null], *)             = ""
4472     * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
4473     * StringUtils.join([1, 2, 3], null) = "123"
4474     * </pre>
4475     *
4476     * @param array
4477     *            the array of values to join together, may be null.
4478     * @param delimiter
4479     *            the separator character to use.
4480     * @param startIndex
4481     *            the first index to start joining from. It is an error to pass in a start index past the end of the
4482     *            array.
4483     * @param endIndex
4484     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4485     *            the array.
4486     * @return the joined String, {@code null} if null array input.
4487     * @since 3.2
4488     */
4489    public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) {
4490        // See StringUtilsJoinBenchmark
4491        if (array == null) {
4492            return null;
4493        }
4494        final int count = endIndex - startIndex;
4495        if (count <= 0) {
4496            return EMPTY;
4497        }
4498        final byte maxElementChars = 20; // "-9223372036854775808"
4499        final StringBuilder stringBuilder = capacity(count, maxElementChars);
4500        stringBuilder.append(array[startIndex]);
4501        for (int i = startIndex + 1; i < endIndex; i++) {
4502            stringBuilder.append(delimiter).append(array[i]);
4503        }
4504        return stringBuilder.toString();
4505    }
4506
4507    /**
4508     * Joins the elements of the provided array into a single String containing the provided list of elements.
4509     *
4510     * <p>
4511     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
4512     * </p>
4513     *
4514     * <pre>
4515     * StringUtils.join(null, *)               = null
4516     * StringUtils.join([], *)                 = ""
4517     * StringUtils.join([null], *)             = ""
4518     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
4519     * StringUtils.join(["a", "b", "c"], null) = "abc"
4520     * StringUtils.join([null, "", "a"], ';')  = ";;a"
4521     * </pre>
4522     *
4523     * @param array     the array of values to join together, may be null.
4524     * @param delimiter the separator character to use.
4525     * @return the joined String, {@code null} if null array input.
4526     * @since 2.0
4527     */
4528    public static String join(final Object[] array, final char delimiter) {
4529        if (array == null) {
4530            return null;
4531        }
4532        return join(array, delimiter, 0, array.length);
4533    }
4534
4535    /**
4536     * Joins the elements of the provided array into a single String containing the provided list of elements.
4537     *
4538     * <p>
4539     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented by empty strings.
4540     * </p>
4541     *
4542     * <pre>
4543     * StringUtils.join(null, *)               = null
4544     * StringUtils.join([], *)                 = ""
4545     * StringUtils.join([null], *)             = ""
4546     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
4547     * StringUtils.join(["a", "b", "c"], null) = "abc"
4548     * StringUtils.join([null, "", "a"], ';')  = ";;a"
4549     * </pre>
4550     *
4551     * @param array      the array of values to join together, may be null.
4552     * @param delimiter  the separator character to use.
4553     * @param startIndex the first index to start joining from. It is an error to pass in a start index past the end of the array.
4554     * @param endIndex   the index to stop joining from (exclusive). It is an error to pass in an end index past the end of the array.
4555     * @return the joined String, {@code null} if null array input.
4556     * @since 2.0
4557     */
4558    public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) {
4559        return join(array, String.valueOf(delimiter), startIndex, endIndex);
4560    }
4561
4562    /**
4563     * Joins the elements of the provided array into a single String containing the provided list of elements.
4564     *
4565     * <p>
4566     * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). Null objects or empty strings within the
4567     * array are represented by empty strings.
4568     * </p>
4569     *
4570     * <pre>
4571     * StringUtils.join(null, *)                = null
4572     * StringUtils.join([], *)                  = ""
4573     * StringUtils.join([null], *)              = ""
4574     * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
4575     * StringUtils.join(["a", "b", "c"], null)  = "abc"
4576     * StringUtils.join(["a", "b", "c"], "")    = "abc"
4577     * StringUtils.join([null, "", "a"], ',')   = ",,a"
4578     * </pre>
4579     *
4580     * @param array     the array of values to join together, may be null.
4581     * @param delimiter the separator character to use, null treated as "".
4582     * @return the joined String, {@code null} if null array input.
4583     */
4584    public static String join(final Object[] array, final String delimiter) {
4585        return array != null ? join(array, ObjectUtils.toString(delimiter), 0, array.length) : null;
4586    }
4587
4588    /**
4589     * Joins the elements of the provided array into a single String containing the provided list of elements.
4590     *
4591     * <p>
4592     * No delimiter is added before or after the list. A {@code null} separator is the same as an empty String (""). Null objects or empty strings within the
4593     * array are represented by empty strings.
4594     * </p>
4595     *
4596     * <pre>
4597     * StringUtils.join(null, *, *, *)                = null
4598     * StringUtils.join([], *, *, *)                  = ""
4599     * StringUtils.join([null], *, *, *)              = ""
4600     * StringUtils.join(["a", "b", "c"], "--", 0, 3)  = "a--b--c"
4601     * StringUtils.join(["a", "b", "c"], "--", 1, 3)  = "b--c"
4602     * StringUtils.join(["a", "b", "c"], "--", 2, 3)  = "c"
4603     * StringUtils.join(["a", "b", "c"], "--", 2, 2)  = ""
4604     * StringUtils.join(["a", "b", "c"], null, 0, 3)  = "abc"
4605     * StringUtils.join(["a", "b", "c"], "", 0, 3)    = "abc"
4606     * StringUtils.join([null, "", "a"], ',', 0, 3)   = ",,a"
4607     * </pre>
4608     *
4609     * @param array      the array of values to join together, may be null.
4610     * @param delimiter  the separator character to use, null treated as "".
4611     * @param startIndex the first index to start joining from.
4612     * @param endIndex   the index to stop joining from (exclusive).
4613     * @return the joined String, {@code null} if null array input; or the empty string if {@code endIndex - startIndex <= 0}. The number of joined entries is
4614     *         given by {@code endIndex - startIndex}.
4615     * @throws ArrayIndexOutOfBoundsException ife<br>
4616     *                                        {@code startIndex < 0} or <br>
4617     *                                        {@code startIndex >= array.length()} or <br>
4618     *                                        {@code endIndex < 0} or <br>
4619     *                                        {@code endIndex > array.length()}
4620     */
4621    public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) {
4622        return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex))
4623                .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, ObjectUtils::toString)) : null;
4624    }
4625
4626    /**
4627     * Joins the elements of the provided array into a single String containing the provided list of elements.
4628     *
4629     * <p>
4630     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4631     * by empty strings.
4632     * </p>
4633     *
4634     * <pre>
4635     * StringUtils.join(null, *)          = null
4636     * StringUtils.join([], *)            = ""
4637     * StringUtils.join([null], *)        = ""
4638     * StringUtils.join([1, 2, 3], ';')   = "1;2;3"
4639     * StringUtils.join([1, 2, 3], null)  = "123"
4640     * </pre>
4641     *
4642     * @param array
4643     *            the array of values to join together, may be null.
4644     * @param delimiter
4645     *            the separator character to use.
4646     * @return the joined String, {@code null} if null array input.
4647     * @since 3.2
4648     */
4649    public static String join(final short[] array, final char delimiter) {
4650        if (array == null) {
4651            return null;
4652        }
4653        return join(array, delimiter, 0, array.length);
4654    }
4655
4656    /**
4657     * Joins the elements of the provided array into a single String containing the provided list of elements.
4658     *
4659     * <p>
4660     * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
4661     * by empty strings.
4662     * </p>
4663     *
4664     * <pre>
4665     * StringUtils.join(null, *)          = null
4666     * StringUtils.join([], *)            = ""
4667     * StringUtils.join([null], *)        = ""
4668     * StringUtils.join([1, 2, 3], ';')   = "1;2;3"
4669     * StringUtils.join([1, 2, 3], null)  = "123"
4670     * </pre>
4671     *
4672     * @param array
4673     *            the array of values to join together, may be null.
4674     * @param delimiter
4675     *            the separator character to use.
4676     * @param startIndex
4677     *            the first index to start joining from. It is an error to pass in a start index past the end of the
4678     *            array.
4679     * @param endIndex
4680     *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
4681     *            the array.
4682     * @return the joined String, {@code null} if null array input.
4683     * @since 3.2
4684     */
4685    public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) {
4686        // See StringUtilsJoinBenchmark
4687        if (array == null) {
4688            return null;
4689        }
4690        final int count = endIndex - startIndex;
4691        if (count <= 0) {
4692            return EMPTY;
4693        }
4694        final byte maxElementChars = 6; // "-32768"
4695        final StringBuilder stringBuilder = capacity(count, maxElementChars);
4696        stringBuilder.append(array[startIndex]);
4697        for (int i = startIndex + 1; i < endIndex; i++) {
4698            stringBuilder.append(delimiter).append(array[i]);
4699        }
4700        return stringBuilder.toString();
4701    }
4702
4703    /**
4704     * Joins the elements of the provided array into a single String containing the provided list of elements.
4705     *
4706     * <p>
4707     * No separator is added to the joined String. Null objects or empty strings within the array are represented by empty strings.
4708     * </p>
4709     *
4710     * <pre>
4711     * StringUtils.join(null)            = null
4712     * StringUtils.join([])              = ""
4713     * StringUtils.join([null])          = ""
4714     * StringUtils.join("a", "b", "c")   = "abc"
4715     * StringUtils.join(null, "", "a")   = "a"
4716     * </pre>
4717     *
4718     * @param <T>      the specific type of values to join together.
4719     * @param elements the values to join together, may be null.
4720     * @return the joined String, {@code null} if null array input.
4721     * @since 2.0
4722     * @since 3.0 Changed signature to use varargs
4723     */
4724    @SafeVarargs
4725    public static <T> String join(final T... elements) {
4726        return join(elements, null);
4727    }
4728
4729    /**
4730     * Joins the elements of the provided varargs into a single String containing the provided elements.
4731     *
4732     * <p>
4733     * No delimiter is added before or after the list. {@code null} elements and separator are treated as empty Strings ("").
4734     * </p>
4735     *
4736     * <pre>
4737     * StringUtils.joinWith(",", "a", "b")        = "a,b"
4738     * StringUtils.joinWith(",", "a", "b","")     = "a,b,"
4739     * StringUtils.joinWith(",", "a", null, "b")  = "a,,b"
4740     * StringUtils.joinWith(null, "a", "b")       = "ab"
4741     * </pre>
4742     *
4743     * @param delimiter the separator character to use, null treated as "".
4744     * @param array     the varargs providing the values to join together. {@code null} elements are treated as "".
4745     * @return the joined String.
4746     * @throws IllegalArgumentException if a null varargs is provided.
4747     * @since 3.5
4748     */
4749    public static String joinWith(final String delimiter, final Object... array) {
4750        if (array == null) {
4751            throw new IllegalArgumentException("Object varargs must not be null");
4752        }
4753        return join(array, delimiter);
4754    }
4755
4756    /**
4757     * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String)} if possible.
4758     *
4759     * <p>
4760     * A {@code null} CharSequence will return {@code -1}.
4761     * </p>
4762     *
4763     * <pre>
4764     * StringUtils.lastIndexOf(null, *)          = -1
4765     * StringUtils.lastIndexOf(*, null)          = -1
4766     * StringUtils.lastIndexOf("", "")           = 0
4767     * StringUtils.lastIndexOf("aabaabaa", "a")  = 7
4768     * StringUtils.lastIndexOf("aabaabaa", "b")  = 5
4769     * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
4770     * StringUtils.lastIndexOf("aabaabaa", "")   = 8
4771     * </pre>
4772     *
4773     * @param seq       the CharSequence to check, may be null.
4774     * @param searchSeq the CharSequence to find, may be null.
4775     * @return the last index of the search String, -1 if no match or {@code null} string input.
4776     * @since 2.0
4777     * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence)
4778     * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CS.lastIndexOf(CharSequence, CharSequence)}.
4779     */
4780    @Deprecated
4781    public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) {
4782        return Strings.CS.lastIndexOf(seq, searchSeq);
4783    }
4784
4785    /**
4786     * Finds the last index within a CharSequence, handling {@code null}. This method uses {@link String#lastIndexOf(String, int)} if possible.
4787     *
4788     * <p>
4789     * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless
4790     * the start position is negative. A start position greater than the string length searches the whole string. The search starts at the startPos and works
4791     * backwards; matches starting after the start position are ignored.
4792     * </p>
4793     *
4794     * <pre>
4795     * StringUtils.lastIndexOf(null, *, *)          = -1
4796     * StringUtils.lastIndexOf(*, null, *)          = -1
4797     * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7
4798     * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5
4799     * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
4800     * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5
4801     * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
4802     * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0
4803     * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1
4804     * StringUtils.lastIndexOf("aabaabaa", "b", 1)  = -1
4805     * StringUtils.lastIndexOf("aabaabaa", "b", 2)  = 2
4806     * StringUtils.lastIndexOf("aabaabaa", "ba", 2)  = 2
4807     * </pre>
4808     *
4809     * @param seq       the CharSequence to check, may be null.
4810     * @param searchSeq the CharSequence to find, may be null.
4811     * @param startPos  the start position, negative treated as zero.
4812     * @return the last index of the search CharSequence (always &le; startPos), -1 if no match or {@code null} string input.
4813     * @since 2.0
4814     * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int)
4815     * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CS.lastIndexOf(CharSequence, CharSequence, int)}.
4816     */
4817    @Deprecated
4818    public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
4819        return Strings.CS.lastIndexOf(seq, searchSeq, startPos);
4820    }
4821
4822    /**
4823     * Returns the index within {@code seq} of the last occurrence of the specified character. For values of {@code searchChar} in the range from 0 to 0xFFFF
4824     * (inclusive), the index (in Unicode code units) returned is the largest value <em>k</em> such that:
4825     *
4826     * <pre>
4827     * this.charAt(<em>k</em>) == searchChar
4828     * </pre>
4829     *
4830     * <p>
4831     * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that:
4832     * </p>
4833     *
4834     * <pre>
4835     * this.codePointAt(<em>k</em>) == searchChar
4836     * </pre>
4837     *
4838     * <p>
4839     * is true. In either case, if no such character occurs in this string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("")
4840     * {@link CharSequence} will return {@code -1}. The {@code seq} {@link CharSequence} object is searched backwards starting at the last character.
4841     * </p>
4842     *
4843     * <pre>
4844     * StringUtils.lastIndexOf(null, *)         = -1
4845     * StringUtils.lastIndexOf("", *)           = -1
4846     * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
4847     * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
4848     * </pre>
4849     *
4850     * @param seq        the {@link CharSequence} to check, may be null.
4851     * @param searchChar the character to find.
4852     * @return the last index of the search character, -1 if no match or {@code null} string input.
4853     * @since 2.0
4854     * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int)
4855     * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
4856     */
4857    public static int lastIndexOf(final CharSequence seq, final int searchChar) {
4858        if (isEmpty(seq)) {
4859            return INDEX_NOT_FOUND;
4860        }
4861        return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length());
4862    }
4863
4864    /**
4865     * Returns the index within {@code seq} of the last occurrence of the specified character, searching backward starting at the specified index. For values of
4866     * {@code searchChar} in the range from 0 to 0xFFFF (inclusive), the index returned is the largest value <em>k</em> such that:
4867     *
4868     * <pre>
4869     * (this.charAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &lt;= startPos)
4870     * </pre>
4871     *
4872     * <p>
4873     * is true. For other values of {@code searchChar}, it is the largest value <em>k</em> such that:
4874     * </p>
4875     *
4876     * <pre>
4877     * (this.codePointAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &lt;= startPos)
4878     * </pre>
4879     *
4880     * <p>
4881     * is true. In either case, if no such character occurs in {@code seq} at or before position {@code startPos}, then {@code -1} is returned. Furthermore, a
4882     * {@code null} or empty ("") {@link CharSequence} will return {@code -1}. A start position greater than the string length searches the whole string. The
4883     * search starts at the {@code startPos} and works backwards; matches starting after the start position are ignored.
4884     * </p>
4885     *
4886     * <p>
4887     * All indices are specified in {@code char} values (Unicode code units).
4888     * </p>
4889     *
4890     * <pre>
4891     * StringUtils.lastIndexOf(null, *, *)          = -1
4892     * StringUtils.lastIndexOf("", *,  *)           = -1
4893     * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5
4894     * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2
4895     * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1
4896     * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5
4897     * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
4898     * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0
4899     * </pre>
4900     *
4901     * @param seq        the CharSequence to check, may be null.
4902     * @param searchChar the character to find.
4903     * @param startPos   the start position.
4904     * @return the last index of the search character (always &le; startPos), -1 if no match or {@code null} string input.
4905     * @since 2.0
4906     * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int)
4907     */
4908    public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) {
4909        if (isEmpty(seq)) {
4910            return INDEX_NOT_FOUND;
4911        }
4912        return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos);
4913    }
4914
4915    /**
4916     * Finds the latest index of any substring in a set of potential substrings.
4917     *
4918     * <p>
4919     * A {@code null} CharSequence will return {@code -1}. A {@code null} search array will return {@code -1}. A {@code null} or zero length search array entry
4920     * will be ignored, but a search array containing "" will return the length of {@code str} if {@code str} is not null. This method uses
4921     * {@link String#indexOf(String)} if possible
4922     * </p>
4923     *
4924     * <pre>
4925     * StringUtils.lastIndexOfAny(null, *)                    = -1
4926     * StringUtils.lastIndexOfAny(*, null)                    = -1
4927     * StringUtils.lastIndexOfAny(*, [])                      = -1
4928     * StringUtils.lastIndexOfAny(*, [null])                  = -1
4929     * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6
4930     * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6
4931     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
4932     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
4933     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""])   = 10
4934     * </pre>
4935     *
4936     * @param str        the CharSequence to check, may be null.
4937     * @param searchStrs the CharSequences to search for, may be null.
4938     * @return the last index of any of the CharSequences, -1 if no match.
4939     * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence)
4940     */
4941    public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) {
4942        if (str == null || searchStrs == null) {
4943            return INDEX_NOT_FOUND;
4944        }
4945        int ret = INDEX_NOT_FOUND;
4946        int tmp;
4947        for (final CharSequence search : searchStrs) {
4948            if (search == null) {
4949                continue;
4950            }
4951            tmp = CharSequenceUtils.lastIndexOf(str, search, str.length());
4952            if (tmp > ret) {
4953                ret = tmp;
4954            }
4955        }
4956        return ret;
4957    }
4958
4959    /**
4960     * Case in-sensitive find of the last index within a CharSequence.
4961     *
4962     * <p>
4963     * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless
4964     * the start position is negative. A start position greater than the string length searches the whole string.
4965     * </p>
4966     *
4967     * <pre>
4968     * StringUtils.lastIndexOfIgnoreCase(null, *)          = -1
4969     * StringUtils.lastIndexOfIgnoreCase(*, null)          = -1
4970     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A")  = 7
4971     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B")  = 5
4972     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
4973     * </pre>
4974     *
4975     * @param str       the CharSequence to check, may be null.
4976     * @param searchStr the CharSequence to find, may be null.
4977     * @return the first index of the search CharSequence, -1 if no match or {@code null} string input.
4978     * @since 2.5
4979     * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence)
4980     * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence) Strings.CI.lastIndexOf(CharSequence, CharSequence)}.
4981     */
4982    @Deprecated
4983    public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
4984        return Strings.CI.lastIndexOf(str, searchStr);
4985    }
4986
4987    /**
4988     * Case in-sensitive find of the last index within a CharSequence from the specified position.
4989     *
4990     * <p>
4991     * A {@code null} CharSequence will return {@code -1}. A negative start position returns {@code -1}. An empty ("") search CharSequence always matches unless
4992     * the start position is negative. A start position greater than the string length searches the whole string. The search starts at the startPos and works
4993     * backwards; matches starting after the start position are ignored.
4994     * </p>
4995     *
4996     * <pre>
4997     * StringUtils.lastIndexOfIgnoreCase(null, *, *)          = -1
4998     * StringUtils.lastIndexOfIgnoreCase(*, null, *)          = -1
4999     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8)  = 7
5000     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8)  = 5
5001     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
5002     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9)  = 5
5003     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
5004     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0)  = 0
5005     * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0)  = -1
5006     * </pre>
5007     *
5008     * @param str       the CharSequence to check, may be null.
5009     * @param searchStr the CharSequence to find, may be null.
5010     * @param startPos  the start position.
5011     * @return the last index of the search CharSequence (always &le; startPos), -1 if no match or {@code null} input.
5012     * @since 2.5
5013     * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int)
5014     * @deprecated Use {@link Strings#lastIndexOf(CharSequence, CharSequence, int) Strings.CI.lastIndexOf(CharSequence, CharSequence, int)}.
5015     */
5016    @Deprecated
5017    public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, final int startPos) {
5018        return Strings.CI.lastIndexOf(str, searchStr, startPos);
5019    }
5020
5021    /**
5022     * Finds the n-th last index within a String, handling {@code null}. This method uses {@link String#lastIndexOf(String)}.
5023     *
5024     * <p>
5025     * A {@code null} String will return {@code -1}.
5026     * </p>
5027     *
5028     * <pre>
5029     * StringUtils.lastOrdinalIndexOf(null, *, *)          = -1
5030     * StringUtils.lastOrdinalIndexOf(*, null, *)          = -1
5031     * StringUtils.lastOrdinalIndexOf("", "", *)           = 0
5032     * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1)  = 7
5033     * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2)  = 6
5034     * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1)  = 5
5035     * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2)  = 2
5036     * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
5037     * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
5038     * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1)   = 8
5039     * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2)   = 8
5040     * </pre>
5041     *
5042     * <p>
5043     * Note that 'tail(CharSequence str, int n)' may be implemented as:
5044     * </p>
5045     *
5046     * <pre>
5047     * str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
5048     * </pre>
5049     *
5050     * @param str       the CharSequence to check, may be null.
5051     * @param searchStr the CharSequence to find, may be null.
5052     * @param ordinal   the n-th last {@code searchStr} to find.
5053     * @return the n-th last index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input.
5054     * @since 2.5
5055     * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int)
5056     */
5057    public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
5058        return ordinalIndexOf(str, searchStr, ordinal, true);
5059    }
5060
5061    /**
5062     * Gets the leftmost {@code len} characters of a String.
5063     *
5064     * <p>
5065     * If {@code len} characters are not available, or the String is {@code null}, the String will be returned without an exception. An empty String is returned
5066     * if len is negative.
5067     * </p>
5068     *
5069     * <pre>
5070     * StringUtils.left(null, *)    = null
5071     * StringUtils.left(*, -ve)     = ""
5072     * StringUtils.left("", *)      = ""
5073     * StringUtils.left("abc", 0)   = ""
5074     * StringUtils.left("abc", 2)   = "ab"
5075     * StringUtils.left("abc", 4)   = "abc"
5076     * </pre>
5077     *
5078     * @param str the String to get the leftmost characters from, may be null.
5079     * @param len the length of the required String.
5080     * @return the leftmost characters, {@code null} if null String input.
5081     */
5082    public static String left(final String str, final int len) {
5083        if (str == null) {
5084            return null;
5085        }
5086        if (len < 0) {
5087            return EMPTY;
5088        }
5089        if (str.length() <= len) {
5090            return str;
5091        }
5092        return str.substring(0, len);
5093    }
5094
5095    /**
5096     * Left pad a String with spaces (' ').
5097     *
5098     * <p>
5099     * The String is padded to the size of {@code size}.
5100     * </p>
5101     *
5102     * <pre>
5103     * StringUtils.leftPad(null, *)   = null
5104     * StringUtils.leftPad("", 3)     = "   "
5105     * StringUtils.leftPad("bat", 3)  = "bat"
5106     * StringUtils.leftPad("bat", 5)  = "  bat"
5107     * StringUtils.leftPad("bat", 1)  = "bat"
5108     * StringUtils.leftPad("bat", -1) = "bat"
5109     * </pre>
5110     *
5111     * @param str  the String to pad out, may be null.
5112     * @param size the size to pad to.
5113     * @return left padded String or original String if no padding is necessary, {@code null} if null String input.
5114     */
5115    public static String leftPad(final String str, final int size) {
5116        return leftPad(str, size, ' ');
5117    }
5118
5119    /**
5120     * Left pad a String with a specified character.
5121     *
5122     * <p>
5123     * Pad to a size of {@code size}.
5124     * </p>
5125     *
5126     * <pre>
5127     * StringUtils.leftPad(null, *, *)     = null
5128     * StringUtils.leftPad("", 3, 'z')     = "zzz"
5129     * StringUtils.leftPad("bat", 3, 'z')  = "bat"
5130     * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
5131     * StringUtils.leftPad("bat", 1, 'z')  = "bat"
5132     * StringUtils.leftPad("bat", -1, 'z') = "bat"
5133     * </pre>
5134     *
5135     * @param str     the String to pad out, may be null.
5136     * @param size    the size to pad to.
5137     * @param padChar the character to pad with.
5138     * @return left padded String or original String if no padding is necessary, {@code null} if null String input.
5139     * @since 2.0
5140     */
5141    public static String leftPad(final String str, final int size, final char padChar) {
5142        if (str == null) {
5143            return null;
5144        }
5145        final int pads = size - str.length();
5146        if (pads <= 0) {
5147            return str; // returns original String when possible
5148        }
5149        if (pads > PAD_LIMIT) {
5150            return leftPad(str, size, String.valueOf(padChar));
5151        }
5152        return repeat(padChar, pads).concat(str);
5153    }
5154
5155    /**
5156     * Left pad a String with a specified String.
5157     *
5158     * <p>
5159     * Pad to a size of {@code size}.
5160     * </p>
5161     *
5162     * <pre>
5163     * StringUtils.leftPad(null, *, *)      = null
5164     * StringUtils.leftPad("", 3, "z")      = "zzz"
5165     * StringUtils.leftPad("bat", 3, "yz")  = "bat"
5166     * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
5167     * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
5168     * StringUtils.leftPad("bat", 1, "yz")  = "bat"
5169     * StringUtils.leftPad("bat", -1, "yz") = "bat"
5170     * StringUtils.leftPad("bat", 5, null)  = "  bat"
5171     * StringUtils.leftPad("bat", 5, "")    = "  bat"
5172     * </pre>
5173     *
5174     * @param str    the String to pad out, may be null.
5175     * @param size   the size to pad to.
5176     * @param padStr the String to pad with, null or empty treated as single space.
5177     * @return left padded String or original String if no padding is necessary, {@code null} if null String input.
5178     */
5179    public static String leftPad(final String str, final int size, String padStr) {
5180        if (str == null) {
5181            return null;
5182        }
5183        if (isEmpty(padStr)) {
5184            padStr = SPACE;
5185        }
5186        final int padLen = padStr.length();
5187        final int strLen = str.length();
5188        final int pads = size - strLen;
5189        if (pads <= 0) {
5190            return str; // returns original String when possible
5191        }
5192        if (padLen == 1 && pads <= PAD_LIMIT) {
5193            return leftPad(str, size, padStr.charAt(0));
5194        }
5195        if (pads == padLen) {
5196            return padStr.concat(str);
5197        }
5198        if (pads < padLen) {
5199            return padStr.substring(0, pads).concat(str);
5200        }
5201        final char[] padding = new char[pads];
5202        final char[] padChars = padStr.toCharArray();
5203        for (int i = 0; i < pads; i++) {
5204            padding[i] = padChars[i % padLen];
5205        }
5206        return new String(padding).concat(str);
5207    }
5208
5209    /**
5210     * Gets a CharSequence length or {@code 0} if the CharSequence is {@code null}.
5211     *
5212     * @param cs a CharSequence or {@code null}.
5213     * @return CharSequence length or {@code 0} if the CharSequence is {@code null}.
5214     * @since 2.4
5215     * @since 3.0 Changed signature from length(String) to length(CharSequence)
5216     */
5217    public static int length(final CharSequence cs) {
5218        return cs == null ? 0 : cs.length();
5219    }
5220
5221    /**
5222     * Converts a String to lower case as per {@link String#toLowerCase()}.
5223     *
5224     * <p>
5225     * A {@code null} input String returns {@code null}.
5226     * </p>
5227     *
5228     * <pre>
5229     * StringUtils.lowerCase(null)  = null
5230     * StringUtils.lowerCase("")    = ""
5231     * StringUtils.lowerCase("aBc") = "abc"
5232     * </pre>
5233     *
5234     * <p>
5235     * <strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()}, the result of this method is affected by the current locale.
5236     * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)} should be used with a specific locale (e.g.
5237     * {@link Locale#ENGLISH}).
5238     * </p>
5239     *
5240     * @param str the String to lower case, may be null.
5241     * @return the lower cased String, {@code null} if null String input.
5242     */
5243    public static String lowerCase(final String str) {
5244        if (str == null) {
5245            return null;
5246        }
5247        return str.toLowerCase();
5248    }
5249
5250    /**
5251     * Converts a String to lower case as per {@link String#toLowerCase(Locale)}.
5252     *
5253     * <p>
5254     * A {@code null} input String returns {@code null}.
5255     * </p>
5256     *
5257     * <pre>
5258     * StringUtils.lowerCase(null, Locale.ENGLISH)  = null
5259     * StringUtils.lowerCase("", Locale.ENGLISH)    = ""
5260     * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
5261     * </pre>
5262     *
5263     * @param str    the String to lower case, may be null.
5264     * @param locale the locale that defines the case transformation rules, must not be null.
5265     * @return the lower cased String, {@code null} if null String input.
5266     * @since 2.5
5267     */
5268    public static String lowerCase(final String str, final Locale locale) {
5269        if (str == null) {
5270            return null;
5271        }
5272        return str.toLowerCase(LocaleUtils.toLocale(locale));
5273    }
5274
5275    private static int[] matches(final CharSequence first, final CharSequence second) {
5276        final CharSequence max;
5277        final CharSequence min;
5278        if (first.length() > second.length()) {
5279            max = first;
5280            min = second;
5281        } else {
5282            max = second;
5283            min = first;
5284        }
5285        final int range = Math.max(max.length() / 2 - 1, 0);
5286        final int[] matchIndexes = ArrayFill.fill(new int[min.length()], -1);
5287        final boolean[] matchFlags = new boolean[max.length()];
5288        int matches = 0;
5289        for (int mi = 0; mi < min.length(); mi++) {
5290            final char c1 = min.charAt(mi);
5291            for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) {
5292                if (!matchFlags[xi] && c1 == max.charAt(xi)) {
5293                    matchIndexes[mi] = xi;
5294                    matchFlags[xi] = true;
5295                    matches++;
5296                    break;
5297                }
5298            }
5299        }
5300        final char[] ms1 = new char[matches];
5301        final char[] ms2 = new char[matches];
5302        for (int i = 0, si = 0; i < min.length(); i++) {
5303            if (matchIndexes[i] != -1) {
5304                ms1[si] = min.charAt(i);
5305                si++;
5306            }
5307        }
5308        for (int i = 0, si = 0; i < max.length(); i++) {
5309            if (matchFlags[i]) {
5310                ms2[si] = max.charAt(i);
5311                si++;
5312            }
5313        }
5314        int transpositions = 0;
5315        for (int mi = 0; mi < ms1.length; mi++) {
5316            if (ms1[mi] != ms2[mi]) {
5317                transpositions++;
5318            }
5319        }
5320        int prefix = 0;
5321        for (int mi = 0; mi < min.length(); mi++) {
5322            if (first.charAt(mi) != second.charAt(mi)) {
5323                break;
5324            }
5325            prefix++;
5326        }
5327        return new int[] { matches, transpositions / 2, prefix, max.length() };
5328    }
5329
5330    /**
5331     * Gets {@code len} characters from the middle of a String.
5332     *
5333     * <p>
5334     * If {@code len} characters are not available, the remainder of the String will be returned without an exception. If the String is {@code null},
5335     * {@code null} will be returned. An empty String is returned if len is negative or exceeds the length of {@code str}.
5336     * </p>
5337     *
5338     * <pre>
5339     * StringUtils.mid(null, *, *)    = null
5340     * StringUtils.mid(*, *, -ve)     = ""
5341     * StringUtils.mid("", 0, *)      = ""
5342     * StringUtils.mid("abc", 0, 2)   = "ab"
5343     * StringUtils.mid("abc", 0, 4)   = "abc"
5344     * StringUtils.mid("abc", 2, 4)   = "c"
5345     * StringUtils.mid("abc", 4, 2)   = ""
5346     * StringUtils.mid("abc", -2, 2)  = "ab"
5347     * </pre>
5348     *
5349     * @param str the String to get the characters from, may be null.
5350     * @param pos the position to start from, negative treated as zero.
5351     * @param len the length of the required String.
5352     * @return the middle characters, {@code null} if null String input.
5353     */
5354    public static String mid(final String str, int pos, final int len) {
5355        if (str == null) {
5356            return null;
5357        }
5358        if (len < 0 || pos > str.length()) {
5359            return EMPTY;
5360        }
5361        if (pos < 0) {
5362            pos = 0;
5363        }
5364        if (str.length() <= pos + len) {
5365            return str.substring(pos);
5366        }
5367        return str.substring(pos, pos + len);
5368    }
5369
5370    /**
5371     * Similar to <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize -space</a>
5372     *
5373     * <p>
5374     * This function returns the argument string with whitespace normalized by using {@code {@link #trim(String)}} to remove leading and trailing whitespace and
5375     * then replacing sequences of whitespace characters by a single space.
5376     * </p>
5377     * In XML, whitespace characters are the same as those allowed by the <a href="https://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 |
5378     * #x9 | #xD | #xA)+
5379     * <p>
5380     * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r]
5381     * </p>
5382     * <p>
5383     * For reference:
5384     * </p>
5385     * <ul>
5386     * <li>\x0B = vertical tab</li>
5387     * <li>\f = #xC = form feed</li>
5388     * <li>#x20 = space</li>
5389     * <li>#x9 = \t</li>
5390     * <li>#xA = \n</li>
5391     * <li>#xD = \r</li>
5392     * </ul>
5393     *
5394     * <p>
5395     * The difference is that Java's whitespace includes vertical tab and form feed, which this function will also normalize. Additionally {@code {@link
5396     * #trim(String)}} removes control characters (char &lt;= 32) from both ends of this String.
5397     * </p>
5398     *
5399     * @param str the source String to normalize whitespaces from, may be null.
5400     * @return the modified string with whitespace normalized, {@code null} if null String input.
5401     * @see Pattern
5402     * @see #trim(String)
5403     * @see <a href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a>
5404     * @since 3.0
5405     */
5406    public static String normalizeSpace(final String str) {
5407        // LANG-1020: Improved performance significantly by normalizing manually instead of using regex
5408        // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test
5409        if (isEmpty(str)) {
5410            return str;
5411        }
5412        final int size = str.length();
5413        final char[] newChars = new char[size];
5414        int count = 0;
5415        int whitespacesCount = 0;
5416        boolean startWhitespaces = true;
5417        for (int i = 0; i < size; i++) {
5418            final char actualChar = str.charAt(i);
5419            final boolean isWhitespace = Character.isWhitespace(actualChar);
5420            if (isWhitespace) {
5421                if (whitespacesCount == 0 && !startWhitespaces) {
5422                    newChars[count++] = SPACE.charAt(0);
5423                }
5424                whitespacesCount++;
5425            } else {
5426                startWhitespaces = false;
5427                newChars[count++] = actualChar == 160 ? 32 : actualChar;
5428                whitespacesCount = 0;
5429            }
5430        }
5431        if (startWhitespaces) {
5432            return EMPTY;
5433        }
5434        return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim();
5435    }
5436
5437    /**
5438     * Finds the n-th index within a CharSequence, handling {@code null}. This method uses {@link String#indexOf(String)} if possible.
5439     * <p>
5440     * <strong>Note:</strong> The code starts looking for a match at the start of the target, incrementing the starting index by one after each successful match
5441     * (unless {@code searchStr} is an empty string, in which case the position is never incremented and {@code 0} is returned immediately). This means that
5442     * matches may overlap.
5443     * </p>
5444     * <p>
5445     * A {@code null} CharSequence will return {@code -1}.
5446     * </p>
5447     *
5448     * <pre>
5449     * StringUtils.ordinalIndexOf(null, *, *)          = -1
5450     * StringUtils.ordinalIndexOf(*, null, *)          = -1
5451     * StringUtils.ordinalIndexOf("", "", *)           = 0
5452     * StringUtils.ordinalIndexOf("aabaabaa", "a", 1)  = 0
5453     * StringUtils.ordinalIndexOf("aabaabaa", "a", 2)  = 1
5454     * StringUtils.ordinalIndexOf("aabaabaa", "b", 1)  = 2
5455     * StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  = 5
5456     * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
5457     * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
5458     * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0
5459     * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0
5460     * </pre>
5461     *
5462     * <p>
5463     * Matches may overlap:
5464     * </p>
5465     *
5466     * <pre>
5467     * StringUtils.ordinalIndexOf("ababab", "aba", 1)   = 0
5468     * StringUtils.ordinalIndexOf("ababab", "aba", 2)   = 2
5469     * StringUtils.ordinalIndexOf("ababab", "aba", 3)   = -1
5470     *
5471     * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0
5472     * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2
5473     * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4
5474     * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1
5475     * </pre>
5476     *
5477     * <p>
5478     * Note that 'head(CharSequence str, int n)' may be implemented as:
5479     * </p>
5480     *
5481     * <pre>
5482     * str.substring(0, lastOrdinalIndexOf(str, "\n", n))
5483     * </pre>
5484     *
5485     * @param str       the CharSequence to check, may be null.
5486     * @param searchStr the CharSequence to find, may be null.
5487     * @param ordinal   the n-th {@code searchStr} to find.
5488     * @return the n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input.
5489     * @since 2.1
5490     * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int)
5491     */
5492    public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
5493        return ordinalIndexOf(str, searchStr, ordinal, false);
5494    }
5495
5496    /**
5497     * Finds the n-th index within a String, handling {@code null}. This method uses {@link String#indexOf(String)} if possible.
5498     * <p>
5499     * Note that matches may overlap.
5500     * <p>
5501     *
5502     * <p>
5503     * A {@code null} CharSequence will return {@code -1}.
5504     * </p>
5505     *
5506     * @param str       the CharSequence to check, may be null.
5507     * @param searchStr the CharSequence to find, may be null.
5508     * @param ordinal   the n-th {@code searchStr} to find, overlapping matches are allowed.
5509     * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf().
5510     * @return the n-th index of the search CharSequence, {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input.
5511     */
5512    // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int)
5513    private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) {
5514        if (str == null || searchStr == null || ordinal <= 0) {
5515            return INDEX_NOT_FOUND;
5516        }
5517        if (searchStr.length() == 0) {
5518            return lastIndex ? str.length() : 0;
5519        }
5520        int found = 0;
5521        // set the initial index beyond the end of the string
5522        // this is to allow for the initial index decrement/increment
5523        int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
5524        do {
5525            if (lastIndex) {
5526                index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string
5527            } else {
5528                index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string
5529            }
5530            if (index < 0) {
5531                return index;
5532            }
5533            found++;
5534        } while (found < ordinal);
5535        return index;
5536    }
5537
5538    /**
5539     * Overlays part of a String with another String.
5540     *
5541     * <p>
5542     * A {@code null} string input returns {@code null}. A negative index is treated as zero. An index greater than the string length is treated as the string
5543     * length. The start index is always the smaller of the two indices.
5544     * </p>
5545     *
5546     * <pre>
5547     * StringUtils.overlay(null, *, *, *)            = null
5548     * StringUtils.overlay("", "abc", 0, 0)          = "abc"
5549     * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
5550     * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
5551     * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
5552     * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
5553     * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
5554     * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
5555     * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
5556     * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
5557     * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
5558     * </pre>
5559     *
5560     * @param str     the String to do overlaying in, may be null.
5561     * @param overlay the String to overlay, may be null.
5562     * @param start   the position to start overlaying at.
5563     * @param end     the position to stop overlaying before.
5564     * @return overlayed String, {@code null} if null String input.
5565     * @since 2.0
5566     */
5567    public static String overlay(final String str, String overlay, int start, int end) {
5568        if (str == null) {
5569            return null;
5570        }
5571        if (overlay == null) {
5572            overlay = EMPTY;
5573        }
5574        final int len = str.length();
5575        if (start < 0) {
5576            start = 0;
5577        }
5578        if (start > len) {
5579            start = len;
5580        }
5581        if (end < 0) {
5582            end = 0;
5583        }
5584        if (end > len) {
5585            end = len;
5586        }
5587        if (start > end) {
5588            final int temp = start;
5589            start = end;
5590            end = temp;
5591        }
5592        return str.substring(0, start) + overlay + str.substring(end);
5593    }
5594
5595    /**
5596     * Prepends the prefix to the start of the string if the string does not already start with any of the prefixes.
5597     *
5598     * <pre>
5599     * StringUtils.prependIfMissing(null, null) = null
5600     * StringUtils.prependIfMissing("abc", null) = "abc"
5601     * StringUtils.prependIfMissing("", "xyz") = "xyz"
5602     * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc"
5603     * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc"
5604     * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc"
5605     * </pre>
5606     * <p>
5607     * With additional prefixes,
5608     * </p>
5609     *
5610     * <pre>
5611     * StringUtils.prependIfMissing(null, null, null) = null
5612     * StringUtils.prependIfMissing("abc", null, null) = "abc"
5613     * StringUtils.prependIfMissing("", "xyz", null) = "xyz"
5614     * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
5615     * StringUtils.prependIfMissing("abc", "xyz", "") = "abc"
5616     * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc"
5617     * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc"
5618     * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc"
5619     * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc"
5620     * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc"
5621     * </pre>
5622     *
5623     * @param str      The string.
5624     * @param prefix   The prefix to prepend to the start of the string.
5625     * @param prefixes Additional prefixes that are valid.
5626     * @return A new String if prefix was prepended, the same string otherwise.
5627     * @since 3.2
5628     * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CS.prependIfMissing(String, CharSequence,
5629     *             CharSequence...)}.
5630     */
5631    @Deprecated
5632    public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) {
5633        return Strings.CS.prependIfMissing(str, prefix, prefixes);
5634    }
5635
5636    /**
5637     * Prepends the prefix to the start of the string if the string does not already start, case-insensitive, with any of the prefixes.
5638     *
5639     * <pre>
5640     * StringUtils.prependIfMissingIgnoreCase(null, null) = null
5641     * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc"
5642     * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz"
5643     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc"
5644     * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc"
5645     * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc"
5646     * </pre>
5647     * <p>
5648     * With additional prefixes,
5649     * </p>
5650     *
5651     * <pre>
5652     * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null
5653     * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc"
5654     * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz"
5655     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
5656     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc"
5657     * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc"
5658     * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc"
5659     * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc"
5660     * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc"
5661     * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc"
5662     * </pre>
5663     *
5664     * @param str      The string.
5665     * @param prefix   The prefix to prepend to the start of the string.
5666     * @param prefixes Additional prefixes that are valid (optional).
5667     * @return A new String if prefix was prepended, the same string otherwise.
5668     * @since 3.2
5669     * @deprecated Use {@link Strings#prependIfMissing(String, CharSequence, CharSequence...) Strings.CI.prependIfMissing(String, CharSequence,
5670     *             CharSequence...)}.
5671     */
5672    @Deprecated
5673    public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) {
5674        return Strings.CI.prependIfMissing(str, prefix, prefixes);
5675    }
5676
5677    /**
5678     * Removes all occurrences of a character from within the source string.
5679     *
5680     * <p>
5681     * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string.
5682     * </p>
5683     *
5684     * <pre>
5685     * StringUtils.remove(null, *)       = null
5686     * StringUtils.remove("", *)         = ""
5687     * StringUtils.remove("queued", 'u') = "qeed"
5688     * StringUtils.remove("queued", 'z') = "queued"
5689     * </pre>
5690     *
5691     * @param str    the source String to search, may be null.
5692     * @param remove the char to search for and remove, may be null.
5693     * @return the substring with the char removed if found, {@code null} if null String input.
5694     * @since 2.1
5695     */
5696    public static String remove(final String str, final char remove) {
5697        if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
5698            return str;
5699        }
5700        final char[] chars = str.toCharArray();
5701        int pos = 0;
5702        for (int i = 0; i < chars.length; i++) {
5703            if (chars[i] != remove) {
5704                chars[pos++] = chars[i];
5705            }
5706        }
5707        return new String(chars, 0, pos);
5708    }
5709
5710    /**
5711     * Removes all occurrences of a substring from within the source string.
5712     *
5713     * <p>
5714     * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} remove string will return
5715     * the source string. An empty ("") remove string will return the source string.
5716     * </p>
5717     *
5718     * <pre>
5719     * StringUtils.remove(null, *)        = null
5720     * StringUtils.remove("", *)          = ""
5721     * StringUtils.remove(*, null)        = *
5722     * StringUtils.remove(*, "")          = *
5723     * StringUtils.remove("queued", "ue") = "qd"
5724     * StringUtils.remove("queued", "zz") = "queued"
5725     * </pre>
5726     *
5727     * @param str    the source String to search, may be null.
5728     * @param remove the String to search for and remove, may be null.
5729     * @return the substring with the string removed if found, {@code null} if null String input.
5730     * @since 2.1
5731     * @deprecated Use {@link Strings#remove(String, String) Strings.CS.remove(String, String)}.
5732     */
5733    @Deprecated
5734    public static String remove(final String str, final String remove) {
5735        return Strings.CS.remove(str, remove);
5736    }
5737
5738    /**
5739     * Removes each substring of the text String that matches the given regular expression.
5740     *
5741     * This method is a {@code null} safe equivalent to:
5742     * <ul>
5743     * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li>
5744     * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
5745     * </ul>
5746     *
5747     * <p>
5748     * A {@code null} reference passed to this method is a no-op.
5749     * </p>
5750     *
5751     * <p>
5752     * Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option
5753     * prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl.
5754     * </p>
5755     *
5756     * <pre>{@code
5757     * StringUtils.removeAll(null, *)      = null
5758     * StringUtils.removeAll("any", (String) null)  = "any"
5759     * StringUtils.removeAll("any", "")    = "any"
5760     * StringUtils.removeAll("any", ".*")  = ""
5761     * StringUtils.removeAll("any", ".+")  = ""
5762     * StringUtils.removeAll("abc", ".?")  = ""
5763     * StringUtils.removeAll("A<__>\n<__>B", "<.*>")      = "A\nB"
5764     * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>")  = "AB"
5765     * StringUtils.removeAll("ABCabc123abc", "[a-z]")     = "ABC123"
5766     * }</pre>
5767     *
5768     * @param text  text to remove from, may be null.
5769     * @param regex the regular expression to which this string is to be matched.
5770     * @return the text with any removes processed, {@code null} if null String input.
5771     * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid.
5772     * @see #replaceAll(String, String, String)
5773     * @see #removePattern(String, String)
5774     * @see String#replaceAll(String, String)
5775     * @see java.util.regex.Pattern
5776     * @see java.util.regex.Pattern#DOTALL
5777     * @since 3.5
5778     * @deprecated Use {@link RegExUtils#removeAll(String, String)}.
5779     */
5780    @Deprecated
5781    public static String removeAll(final String text, final String regex) {
5782        return RegExUtils.removeAll(text, regex);
5783    }
5784
5785    /**
5786     * Removes a substring only if it is at the end of a source string, otherwise returns the source string.
5787     *
5788     * <p>
5789     * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return
5790     * the source string.
5791     * </p>
5792     *
5793     * <pre>
5794     * StringUtils.removeEnd(null, *)      = null
5795     * StringUtils.removeEnd("", *)        = ""
5796     * StringUtils.removeEnd(*, null)      = *
5797     * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
5798     * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
5799     * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
5800     * StringUtils.removeEnd("abc", "")    = "abc"
5801     * </pre>
5802     *
5803     * @param str    the source String to search, may be null.
5804     * @param remove the String to search for and remove, may be null.
5805     * @return the substring with the string removed if found, {@code null} if null String input.
5806     * @since 2.1
5807     * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CS.removeEnd(String, CharSequence)}.
5808     */
5809    @Deprecated
5810    public static String removeEnd(final String str, final String remove) {
5811        return Strings.CS.removeEnd(str, remove);
5812    }
5813
5814    /**
5815     * Case-insensitive removal of a substring if it is at the end of a source string, otherwise returns the source string.
5816     *
5817     * <p>
5818     * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return
5819     * the source string.
5820     * </p>
5821     *
5822     * <pre>
5823     * StringUtils.removeEndIgnoreCase(null, *)      = null
5824     * StringUtils.removeEndIgnoreCase("", *)        = ""
5825     * StringUtils.removeEndIgnoreCase(*, null)      = *
5826     * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
5827     * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
5828     * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
5829     * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
5830     * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain"
5831     * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain"
5832     * </pre>
5833     *
5834     * @param str    the source String to search, may be null.
5835     * @param remove the String to search for (case-insensitive) and remove, may be null.
5836     * @return the substring with the string removed if found, {@code null} if null String input.
5837     * @since 2.4
5838     * @deprecated Use {@link Strings#removeEnd(String, CharSequence) Strings.CI.removeEnd(String, CharSequence)}.
5839     */
5840    @Deprecated
5841    public static String removeEndIgnoreCase(final String str, final String remove) {
5842        return Strings.CI.removeEnd(str, remove);
5843    }
5844
5845    /**
5846     * Removes the first substring of the text string that matches the given regular expression.
5847     *
5848     * This method is a {@code null} safe equivalent to:
5849     * <ul>
5850     * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li>
5851     * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
5852     * </ul>
5853     *
5854     * <p>
5855     * A {@code null} reference passed to this method is a no-op.
5856     * </p>
5857     *
5858     * <p>
5859     * The {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option prepend {@code "(?s)"} to the regex. DOTALL is also known as
5860     * single-line mode in Perl.
5861     * </p>
5862     *
5863     * <pre>{@code
5864     * StringUtils.removeFirst(null, *)      = null
5865     * StringUtils.removeFirst("any", (String) null)  = "any"
5866     * StringUtils.removeFirst("any", "")    = "any"
5867     * StringUtils.removeFirst("any", ".*")  = ""
5868     * StringUtils.removeFirst("any", ".+")  = ""
5869     * StringUtils.removeFirst("abc", ".?")  = "bc"
5870     * StringUtils.removeFirst("A<__>\n<__>B", "<.*>")      = "A\n<__>B"
5871     * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>")  = "AB"
5872     * StringUtils.removeFirst("ABCabc123", "[a-z]")          = "ABCbc123"
5873     * StringUtils.removeFirst("ABCabc123abc", "[a-z]+")      = "ABC123abc"
5874     * }</pre>
5875     *
5876     * @param text  text to remove from, may be null.
5877     * @param regex the regular expression to which this string is to be matched.
5878     * @return the text with the first replacement processed, {@code null} if null String input.
5879     * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid.
5880     * @see #replaceFirst(String, String, String)
5881     * @see String#replaceFirst(String, String)
5882     * @see java.util.regex.Pattern
5883     * @see java.util.regex.Pattern#DOTALL
5884     * @since 3.5
5885     * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String) RegExUtils.replaceFirst(String, String, EMPTY)}.
5886     */
5887    @Deprecated
5888    public static String removeFirst(final String text, final String regex) {
5889        return replaceFirst(text, regex, EMPTY);
5890    }
5891
5892    /**
5893     * Case-insensitive removal of all occurrences of a substring from within the source string.
5894     *
5895     * <p>
5896     * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} remove string will return
5897     * the source string. An empty ("") remove string will return the source string.
5898     * </p>
5899     *
5900     * <pre>
5901     * StringUtils.removeIgnoreCase(null, *)        = null
5902     * StringUtils.removeIgnoreCase("", *)          = ""
5903     * StringUtils.removeIgnoreCase(*, null)        = *
5904     * StringUtils.removeIgnoreCase(*, "")          = *
5905     * StringUtils.removeIgnoreCase("queued", "ue") = "qd"
5906     * StringUtils.removeIgnoreCase("queued", "zz") = "queued"
5907     * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd"
5908     * StringUtils.removeIgnoreCase("queued", "zZ") = "queued"
5909     * </pre>
5910     *
5911     * @param str    the source String to search, may be null.
5912     * @param remove the String to search for (case-insensitive) and remove, may be null.
5913     * @return the substring with the string removed if found, {@code null} if null String input.
5914     * @since 3.5
5915     * @deprecated Use {@link Strings#remove(String, String) Strings.CI.remove(String, String)}.
5916     */
5917    @Deprecated
5918    public static String removeIgnoreCase(final String str, final String remove) {
5919        return Strings.CI.remove(str, remove);
5920    }
5921
5922    /**
5923     * Removes each substring of the source String that matches the given regular expression using the DOTALL option.
5924     *
5925     * This call is a {@code null} safe equivalent to:
5926     * <ul>
5927     * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, StringUtils.EMPTY)}</li>
5928     * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li>
5929     * </ul>
5930     *
5931     * <p>
5932     * A {@code null} reference passed to this method is a no-op.
5933     * </p>
5934     *
5935     * <pre>{@code
5936     * StringUtils.removePattern(null, *)       = null
5937     * StringUtils.removePattern("any", (String) null)   = "any"
5938     * StringUtils.removePattern("A<__>\n<__>B", "<.*>")  = "AB"
5939     * StringUtils.removePattern("ABCabc123", "[a-z]")    = "ABC123"
5940     * }</pre>
5941     *
5942     * @param source the source string.
5943     * @param regex  the regular expression to which this string is to be matched.
5944     * @return The resulting {@link String}.
5945     * @see #replacePattern(String, String, String)
5946     * @see String#replaceAll(String, String)
5947     * @see Pattern#DOTALL
5948     * @since 3.2
5949     * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
5950     * @deprecated Use {@link RegExUtils#removePattern(CharSequence, String)}.
5951     */
5952    @Deprecated
5953    public static String removePattern(final String source, final String regex) {
5954        return RegExUtils.removePattern(source, regex);
5955    }
5956
5957    /**
5958     * Removes a char only if it is at the beginning of a source string, otherwise returns the source string.
5959     *
5960     * <p>
5961     * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search char will return
5962     * the source string.
5963     * </p>
5964     *
5965     * <pre>
5966     * StringUtils.removeStart(null, *)      = null
5967     * StringUtils.removeStart("", *)        = ""
5968     * StringUtils.removeStart(*, null)      = *
5969     * StringUtils.removeStart("/path", '/') = "path"
5970     * StringUtils.removeStart("path", '/')  = "path"
5971     * StringUtils.removeStart("path", 0)    = "path"
5972     * </pre>
5973     *
5974     * @param str    the source String to search, may be null.
5975     * @param remove the char to search for and remove.
5976     * @return the substring with the char removed if found, {@code null} if null String input.
5977     * @since 3.13.0
5978     */
5979    public static String removeStart(final String str, final char remove) {
5980        if (isEmpty(str)) {
5981            return str;
5982        }
5983        return str.charAt(0) == remove ? str.substring(1) : str;
5984    }
5985
5986    /**
5987     * Removes a substring only if it is at the beginning of a source string, otherwise returns the source string.
5988     *
5989     * <p>
5990     * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return
5991     * the source string.
5992     * </p>
5993     *
5994     * <pre>
5995     * StringUtils.removeStart(null, *)                    = null
5996     * StringUtils.removeStart("", *)                      = ""
5997     * StringUtils.removeStart(*, null)                    = *
5998     * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
5999     * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
6000     * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
6001     * StringUtils.removeStart("abc", "")                  = "abc"
6002     * </pre>
6003     *
6004     * @param str    the source String to search, may be null.
6005     * @param remove the String to search for and remove, may be null.
6006     * @return the substring with the string removed if found, {@code null} if null String input.
6007     * @since 2.1
6008     * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CS.removeStart(String, CharSequence)}.
6009     */
6010    @Deprecated
6011    public static String removeStart(final String str, final String remove) {
6012        return Strings.CS.removeStart(str, remove);
6013    }
6014
6015    /**
6016     * Case-insensitive removal of a substring if it is at the beginning of a source string, otherwise returns the source string.
6017     *
6018     * <p>
6019     * A {@code null} source string will return {@code null}. An empty ("") source string will return the empty string. A {@code null} search string will return
6020     * the source string.
6021     * </p>
6022     *
6023     * <pre>
6024     * StringUtils.removeStartIgnoreCase(null, *)                    = null
6025     * StringUtils.removeStartIgnoreCase("", *)                      = ""
6026     * StringUtils.removeStartIgnoreCase(*, null)                    = *
6027     * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
6028     * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
6029     * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
6030     * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
6031     * StringUtils.removeStartIgnoreCase("abc", "")                  = "abc"
6032     * </pre>
6033     *
6034     * @param str    the source String to search, may be null.
6035     * @param remove the String to search for (case-insensitive) and remove, may be null.
6036     * @return the substring with the string removed if found, {@code null} if null String input.
6037     * @since 2.4
6038     * @deprecated Use {@link Strings#removeStart(String, CharSequence) Strings.CI.removeStart(String, CharSequence)}.
6039     */
6040    @Deprecated
6041    public static String removeStartIgnoreCase(final String str, final String remove) {
6042        return Strings.CI.removeStart(str, remove);
6043    }
6044
6045    /**
6046     * Returns padding using the specified delimiter repeated to a given length.
6047     *
6048     * <pre>
6049     * StringUtils.repeat('e', 0)  = ""
6050     * StringUtils.repeat('e', 3)  = "eee"
6051     * StringUtils.repeat('e', -2) = ""
6052     * </pre>
6053     *
6054     * <p>
6055     * Note: this method does not support padding with <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
6056     * as they require a pair of {@code char}s to be represented. If you are needing to support full I18N of your applications consider using
6057     * {@link #repeat(String, int)} instead.
6058     * </p>
6059     *
6060     * @param repeat character to repeat.
6061     * @param count  number of times to repeat char, negative treated as zero.
6062     * @return String with repeated character.
6063     * @see #repeat(String, int)
6064     */
6065    public static String repeat(final char repeat, final int count) {
6066        if (count <= 0) {
6067            return EMPTY;
6068        }
6069        return new String(ArrayFill.fill(new char[count], repeat));
6070    }
6071
6072    /**
6073     * Repeats a String {@code repeat} times to form a new String.
6074     *
6075     * <pre>
6076     * StringUtils.repeat(null, 2) = null
6077     * StringUtils.repeat("", 0)   = ""
6078     * StringUtils.repeat("", 2)   = ""
6079     * StringUtils.repeat("a", 3)  = "aaa"
6080     * StringUtils.repeat("ab", 2) = "abab"
6081     * StringUtils.repeat("a", -2) = ""
6082     * </pre>
6083     *
6084     * @param repeat the String to repeat, may be null.
6085     * @param count  number of times to repeat str, negative treated as zero.
6086     * @return a new String consisting of the original String repeated, {@code null} if null String input.
6087     */
6088    public static String repeat(final String repeat, final int count) {
6089        // Performance tuned for 2.0 (JDK1.4)
6090        if (repeat == null) {
6091            return null;
6092        }
6093        if (count <= 0) {
6094            return EMPTY;
6095        }
6096        final int inputLength = repeat.length();
6097        if (count == 1 || inputLength == 0) {
6098            return repeat;
6099        }
6100        if (inputLength == 1 && count <= PAD_LIMIT) {
6101            return repeat(repeat.charAt(0), count);
6102        }
6103        final int outputLength = inputLength * count;
6104        switch (inputLength) {
6105        case 1:
6106            return repeat(repeat.charAt(0), count);
6107        case 2:
6108            final char ch0 = repeat.charAt(0);
6109            final char ch1 = repeat.charAt(1);
6110            final char[] output2 = new char[outputLength];
6111            for (int i = count * 2 - 2; i >= 0; i--, i--) {
6112                output2[i] = ch0;
6113                output2[i + 1] = ch1;
6114            }
6115            return new String(output2);
6116        default:
6117            final StringBuilder buf = new StringBuilder(outputLength);
6118            for (int i = 0; i < count; i++) {
6119                buf.append(repeat);
6120            }
6121            return buf.toString();
6122        }
6123    }
6124
6125    /**
6126     * Repeats a String {@code repeat} times to form a new String, with a String separator injected each time.
6127     *
6128     * <pre>
6129     * StringUtils.repeat(null, null, 2) = null
6130     * StringUtils.repeat(null, "x", 2)  = null
6131     * StringUtils.repeat("", null, 0)   = ""
6132     * StringUtils.repeat("", "", 2)     = ""
6133     * StringUtils.repeat("", "x", 3)    = "xx"
6134     * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
6135     * </pre>
6136     *
6137     * @param repeat    the String to repeat, may be null.
6138     * @param separator the String to inject, may be null.
6139     * @param count     number of times to repeat str, negative treated as zero.
6140     * @return a new String consisting of the original String repeated, {@code null} if null String input.
6141     * @since 2.5
6142     */
6143    public static String repeat(final String repeat, final String separator, final int count) {
6144        if (repeat == null || separator == null) {
6145            return repeat(repeat, count);
6146        }
6147        // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
6148        final String result = repeat(repeat + separator, count);
6149        return Strings.CS.removeEnd(result, separator);
6150    }
6151
6152    /**
6153     * Replaces all occurrences of a String within another String.
6154     *
6155     * <p>
6156     * A {@code null} reference passed to this method is a no-op.
6157     * </p>
6158     *
6159     * <pre>
6160     * StringUtils.replace(null, *, *)        = null
6161     * StringUtils.replace("", *, *)          = ""
6162     * StringUtils.replace("any", null, *)    = "any"
6163     * StringUtils.replace("any", *, null)    = "any"
6164     * StringUtils.replace("any", "", *)      = "any"
6165     * StringUtils.replace("aba", "a", null)  = "aba"
6166     * StringUtils.replace("aba", "a", "")    = "b"
6167     * StringUtils.replace("aba", "a", "z")   = "zbz"
6168     * </pre>
6169     *
6170     * @param text         text to search and replace in, may be null.
6171     * @param searchString the String to search for, may be null.
6172     * @param replacement  the String to replace it with, may be null.
6173     * @return the text with any replacements processed, {@code null} if null String input.
6174     * @see #replace(String text, String searchString, String replacement, int max)
6175     * @deprecated Use {@link Strings#replace(String, String, String) Strings.CS.replace(String, String, String)}.
6176     */
6177    @Deprecated
6178    public static String replace(final String text, final String searchString, final String replacement) {
6179        return Strings.CS.replace(text, searchString, replacement);
6180    }
6181
6182    /**
6183     * Replaces a String with another String inside a larger String, for the first {@code max} values of the search String.
6184     *
6185     * <p>
6186     * A {@code null} reference passed to this method is a no-op.
6187     * </p>
6188     *
6189     * <pre>
6190     * StringUtils.replace(null, *, *, *)         = null
6191     * StringUtils.replace("", *, *, *)           = ""
6192     * StringUtils.replace("any", null, *, *)     = "any"
6193     * StringUtils.replace("any", *, null, *)     = "any"
6194     * StringUtils.replace("any", "", *, *)       = "any"
6195     * StringUtils.replace("any", *, *, 0)        = "any"
6196     * StringUtils.replace("abaa", "a", null, -1) = "abaa"
6197     * StringUtils.replace("abaa", "a", "", -1)   = "b"
6198     * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
6199     * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
6200     * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
6201     * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
6202     * </pre>
6203     *
6204     * @param text         text to search and replace in, may be null.
6205     * @param searchString the String to search for, may be null.
6206     * @param replacement  the String to replace it with, may be null.
6207     * @param max          maximum number of values to replace, or {@code -1} if no maximum.
6208     * @return the text with any replacements processed, {@code null} if null String input.
6209     * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CS.replace(String, String, String, int)}.
6210     */
6211    @Deprecated
6212    public static String replace(final String text, final String searchString, final String replacement, final int max) {
6213        return Strings.CS.replace(text, searchString, replacement, max);
6214    }
6215
6216    /**
6217     * Replaces each substring of the text String that matches the given regular expression with the given replacement.
6218     *
6219     * This method is a {@code null} safe equivalent to:
6220     * <ul>
6221     * <li>{@code text.replaceAll(regex, replacement)}</li>
6222     * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li>
6223     * </ul>
6224     *
6225     * <p>
6226     * A {@code null} reference passed to this method is a no-op.
6227     * </p>
6228     *
6229     * <p>
6230     * Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL
6231     * option prepend {@code "(?s)"} to the regex. DOTALL is also known as single-line mode in Perl.
6232     * </p>
6233     *
6234     * <pre>{@code
6235     * StringUtils.replaceAll(null, *, *)                                         = null
6236     * StringUtils.replaceAll("any", (String) null, *)                            = "any"
6237     * StringUtils.replaceAll("any", *, null)                                     = "any"
6238     * StringUtils.replaceAll("", "", "zzz")                                      = "zzz"
6239     * StringUtils.replaceAll("", ".*", "zzz")                                    = "zzz"
6240     * StringUtils.replaceAll("", ".+", "zzz")                                    = ""
6241     * StringUtils.replaceAll("abc", "", "ZZ")                                    = "ZZaZZbZZcZZ"
6242     * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z")                          = "z\nz"
6243     * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z")                      = "z"
6244     * StringUtils.replaceAll("ABCabc123", "[a-z]", "_")                          = "ABC___123"
6245     * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_")                     = "ABC_123"
6246     * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "")                      = "ABC123"
6247     * StringUtils.replaceAll("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
6248     * }</pre>
6249     *
6250     * @param text        text to search and replace in, may be null.
6251     * @param regex       the regular expression to which this string is to be matched.
6252     * @param replacement the string to be substituted for each match.
6253     * @return the text with any replacements processed, {@code null} if null String input.
6254     * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid.
6255     * @see #replacePattern(String, String, String)
6256     * @see String#replaceAll(String, String)
6257     * @see java.util.regex.Pattern
6258     * @see java.util.regex.Pattern#DOTALL
6259     * @since 3.5
6260     * @deprecated Use {@link RegExUtils#replaceAll(String, String, String)}.
6261     */
6262    @Deprecated
6263    public static String replaceAll(final String text, final String regex, final String replacement) {
6264        return RegExUtils.replaceAll(text, regex, replacement);
6265    }
6266
6267    /**
6268     * Replaces all occurrences of a character in a String with another. This is a null-safe version of {@link String#replace(char, char)}.
6269     *
6270     * <p>
6271     * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string.
6272     * </p>
6273     *
6274     * <pre>
6275     * StringUtils.replaceChars(null, *, *)        = null
6276     * StringUtils.replaceChars("", *, *)          = ""
6277     * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
6278     * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
6279     * </pre>
6280     *
6281     * @param str         String to replace characters in, may be null.
6282     * @param searchChar  the character to search for, may be null.
6283     * @param replaceChar the character to replace, may be null.
6284     * @return modified String, {@code null} if null string input.
6285     * @since 2.0
6286     */
6287    public static String replaceChars(final String str, final char searchChar, final char replaceChar) {
6288        if (str == null) {
6289            return null;
6290        }
6291        return str.replace(searchChar, replaceChar);
6292    }
6293
6294    /**
6295     * Replaces multiple characters in a String in one go. This method can also be used to delete characters.
6296     *
6297     * <p>
6298     * For example:
6299     * </p>
6300     * <pre>
6301     * replaceChars(&quot;hello&quot;, &quot;ho&quot;, &quot;jy&quot;) = jelly.
6302     * </pre>
6303     *
6304     * <p>
6305     * A {@code null} string input returns {@code null}. An empty ("") string input returns an empty string. A null or empty set of search characters returns
6306     * the input string.
6307     * </p>
6308     *
6309     * <p>
6310     * The length of the search characters should normally equal the length of the replace characters. If the search characters is longer, then the extra search
6311     * characters are deleted. If the search characters is shorter, then the extra replace characters are ignored.
6312     * </p>
6313     *
6314     * <pre>
6315     * StringUtils.replaceChars(null, *, *)           = null
6316     * StringUtils.replaceChars("", *, *)             = ""
6317     * StringUtils.replaceChars("abc", null, *)       = "abc"
6318     * StringUtils.replaceChars("abc", "", *)         = "abc"
6319     * StringUtils.replaceChars("abc", "b", null)     = "ac"
6320     * StringUtils.replaceChars("abc", "b", "")       = "ac"
6321     * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
6322     * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
6323     * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
6324     * </pre>
6325     *
6326     * @param str          String to replace characters in, may be null.
6327     * @param searchChars  a set of characters to search for, may be null.
6328     * @param replaceChars a set of characters to replace, may be null.
6329     * @return modified String, {@code null} if null string input.
6330     * @since 2.0
6331     */
6332    public static String replaceChars(final String str, final String searchChars, String replaceChars) {
6333        if (isEmpty(str) || isEmpty(searchChars)) {
6334            return str;
6335        }
6336        replaceChars = ObjectUtils.toString(replaceChars);
6337        boolean modified = false;
6338        final int replaceCharsLength = replaceChars.length();
6339        final int strLength = str.length();
6340        final StringBuilder buf = new StringBuilder(strLength);
6341        for (int i = 0; i < strLength; i++) {
6342            final char ch = str.charAt(i);
6343            final int index = searchChars.indexOf(ch);
6344            if (index >= 0) {
6345                modified = true;
6346                if (index < replaceCharsLength) {
6347                    buf.append(replaceChars.charAt(index));
6348                }
6349            } else {
6350                buf.append(ch);
6351            }
6352        }
6353        if (modified) {
6354            return buf.toString();
6355        }
6356        return str;
6357    }
6358
6359    /**
6360     * Replaces all occurrences of Strings within another String.
6361     *
6362     * <p>
6363     * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored. This
6364     * will not repeat. For repeating replaces, call the overloaded method.
6365     * </p>
6366     *
6367     * <pre>
6368     *  StringUtils.replaceEach(null, *, *)                                                = null
6369     *  StringUtils.replaceEach("", *, *)                                                  = ""
6370     *  StringUtils.replaceEach("aba", null, null)                                         = "aba"
6371     *  StringUtils.replaceEach("aba", new String[0], null)                                = "aba"
6372     *  StringUtils.replaceEach("aba", null, new String[0])                                = "aba"
6373     *  StringUtils.replaceEach("aba", new String[]{"a"}, null)                            = "aba"
6374     *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""})                = "b"
6375     *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"})              = "aba"
6376     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
6377     *  (example of how it does not repeat)
6378     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "dcte"
6379     * </pre>
6380     *
6381     * @param text            text to search and replace in, no-op if null.
6382     * @param searchList      the Strings to search for, no-op if null.
6383     * @param replacementList the Strings to replace them with, no-op if null.
6384     * @return the text with any replacements processed, {@code null} if null String input.
6385     * @throws IllegalArgumentException if the lengths of the arrays are not the same (null is ok, and/or size 0).
6386     * @since 2.4
6387     */
6388    public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) {
6389        return replaceEach(text, searchList, replacementList, false, 0);
6390    }
6391
6392    /**
6393     * Replace all occurrences of Strings within another String. This is a private recursive helper method for
6394     * {@link #replaceEachRepeatedly(String, String[], String[])} and {@link #replaceEach(String, String[], String[])}
6395     *
6396     * <p>
6397     * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored.
6398     * </p>
6399     *
6400     * <pre>
6401     *  StringUtils.replaceEach(null, *, *, *, *)                                                     = null
6402     *  StringUtils.replaceEach("", *, *, *, *)                                                       = ""
6403     *  StringUtils.replaceEach("aba", null, null, *, *)                                              = "aba"
6404     *  StringUtils.replaceEach("aba", new String[0], null, *, *)                                     = "aba"
6405     *  StringUtils.replaceEach("aba", null, new String[0], *, *)                                     = "aba"
6406     *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *)                                 = "aba"
6407     *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0)                   = "b"
6408     *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0)                 = "aba"
6409     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0)     = "wcte"
6410     *  (example of how it repeats)
6411     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte"
6412     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2)  = "tcte"
6413     *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *)      = Throws {@link IllegalStateException}
6414     * </pre>
6415     *
6416     * @param text            text to search and replace in, no-op if null.
6417     * @param searchList      the Strings to search for, no-op if null.
6418     * @param replacementList the Strings to replace them with, no-op if null.
6419     * @param repeat          if true, then replace repeatedly until there are no more possible replacements or timeToLive < 0.
6420     * @param timeToLive      if less than 0 then there is a circular reference and endless loop.
6421     * @return the text with any replacements processed, {@code null} if null String input.
6422     * @throws IllegalStateException    if the search is repeating and there is an endless loop due to outputs of one being inputs to another.
6423     * @throws IllegalArgumentException if the lengths of the arrays are not the same (null is ok, and/or size 0).
6424     * @since 2.4
6425     */
6426    private static String replaceEach(
6427            final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) {
6428
6429        // Performance note: This creates very few new objects (one major goal)
6430        // let me know if there are performance requests, we can create a harness to measure
6431        if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList)) {
6432            return text;
6433        }
6434
6435        // if recursing, this shouldn't be less than 0
6436        if (timeToLive < 0) {
6437            throw new IllegalStateException("Aborting to protect against StackOverflowError - " +
6438                "output of one loop is the input of another");
6439        }
6440
6441        final int searchLength = searchList.length;
6442        final int replacementLength = replacementList.length;
6443
6444        // make sure lengths are ok, these need to be equal
6445        if (searchLength != replacementLength) {
6446            throw new IllegalArgumentException("Search and Replace array lengths don't match: "
6447                + searchLength
6448                + " vs "
6449                + replacementLength);
6450        }
6451
6452        // keep track of which still have matches
6453        final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];
6454
6455        // index on index that the match was found
6456        int textIndex = -1;
6457        int replaceIndex = -1;
6458        int tempIndex;
6459
6460        // index of replace array that will replace the search string found
6461        // NOTE: logic duplicated below START
6462        for (int i = 0; i < searchLength; i++) {
6463            if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) {
6464                continue;
6465            }
6466            tempIndex = text.indexOf(searchList[i]);
6467
6468            // see if we need to keep searching for this
6469            if (tempIndex == -1) {
6470                noMoreMatchesForReplIndex[i] = true;
6471            } else if (textIndex == -1 || tempIndex < textIndex) {
6472                textIndex = tempIndex;
6473                replaceIndex = i;
6474            }
6475        }
6476        // NOTE: logic mostly below END
6477
6478        // no search strings found, we are done
6479        if (textIndex == -1) {
6480            return text;
6481        }
6482
6483        int start = 0;
6484
6485        // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit
6486        int increase = 0;
6487
6488        // count the replacement text elements that are larger than their corresponding text being replaced
6489        for (int i = 0; i < searchList.length; i++) {
6490            if (searchList[i] == null || replacementList[i] == null) {
6491                continue;
6492            }
6493            final int greater = replacementList[i].length() - searchList[i].length();
6494            if (greater > 0) {
6495                increase += 3 * greater; // assume 3 matches
6496            }
6497        }
6498        // have upper-bound at 20% increase, then let Java take over
6499        increase = Math.min(increase, text.length() / 5);
6500
6501        final StringBuilder buf = new StringBuilder(text.length() + increase);
6502
6503        while (textIndex != -1) {
6504
6505            for (int i = start; i < textIndex; i++) {
6506                buf.append(text.charAt(i));
6507            }
6508            buf.append(replacementList[replaceIndex]);
6509
6510            start = textIndex + searchList[replaceIndex].length();
6511
6512            textIndex = -1;
6513            replaceIndex = -1;
6514            // find the next earliest match
6515            // NOTE: logic mostly duplicated above START
6516            for (int i = 0; i < searchLength; i++) {
6517                if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) {
6518                    continue;
6519                }
6520                tempIndex = text.indexOf(searchList[i], start);
6521
6522                // see if we need to keep searching for this
6523                if (tempIndex == -1) {
6524                    noMoreMatchesForReplIndex[i] = true;
6525                } else if (textIndex == -1 || tempIndex < textIndex) {
6526                    textIndex = tempIndex;
6527                    replaceIndex = i;
6528                }
6529            }
6530            // NOTE: logic duplicated above END
6531
6532        }
6533        final int textLength = text.length();
6534        for (int i = start; i < textLength; i++) {
6535            buf.append(text.charAt(i));
6536        }
6537        final String result = buf.toString();
6538        if (!repeat) {
6539            return result;
6540        }
6541
6542        return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
6543    }
6544
6545    /**
6546     * Replaces all occurrences of Strings within another String.
6547     *
6548     * <p>
6549     * A {@code null} reference passed to this method is a no-op, or if any "search string" or "string to replace" is null, that replace will be ignored.
6550     * </p>
6551     *
6552     * <pre>
6553     *  StringUtils.replaceEachRepeatedly(null, *, *)                                                = null
6554     *  StringUtils.replaceEachRepeatedly("", *, *)                                                  = ""
6555     *  StringUtils.replaceEachRepeatedly("aba", null, null)                                         = "aba"
6556     *  StringUtils.replaceEachRepeatedly("aba", new String[0], null)                                = "aba"
6557     *  StringUtils.replaceEachRepeatedly("aba", null, new String[0])                                = "aba"
6558     *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, null)                            = "aba"
6559     *  StringUtils.replaceEachRepeatedly("aba", new String[]{"a"}, new String[]{""})                = "b"
6560     *  StringUtils.replaceEachRepeatedly("aba", new String[]{null}, new String[]{"a"})              = "aba"
6561     *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
6562     *  (example of how it repeats)
6563     *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "tcte"
6564     *  StringUtils.replaceEachRepeatedly("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}) = Throws {@link IllegalStateException}
6565     * </pre>
6566     *
6567     * @param text            text to search and replace in, no-op if null.
6568     * @param searchList      the Strings to search for, no-op if null.
6569     * @param replacementList the Strings to replace them with, no-op if null.
6570     * @return the text with any replacements processed, {@code null} if null String input.
6571     * @throws IllegalStateException    if the search is repeating and there is an endless loop due to outputs of one being inputs to another.
6572     * @throws IllegalArgumentException if the lengths of the arrays are not the same (null is ok, and/or size 0).
6573     * @since 2.4
6574     */
6575    public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) {
6576        final int timeToLive = Math.max(ArrayUtils.getLength(searchList), DEFAULT_TTL);
6577        return replaceEach(text, searchList, replacementList, true, timeToLive);
6578    }
6579
6580    /**
6581     * Replaces the first substring of the text string that matches the given regular expression with the given replacement.
6582     *
6583     * This method is a {@code null} safe equivalent to:
6584     * <ul>
6585     * <li>{@code text.replaceFirst(regex, replacement)}</li>
6586     * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>
6587     * </ul>
6588     *
6589     * <p>
6590     * A {@code null} reference passed to this method is a no-op.
6591     * </p>
6592     *
6593     * <p>
6594     * The {@link Pattern#DOTALL} option is NOT automatically added. To use the DOTALL option prepend {@code "(?s)"} to the regex. DOTALL is also known as
6595     * single-line mode in Perl.
6596     * </p>
6597     *
6598     * <pre>{@code
6599     * StringUtils.replaceFirst(null, *, *)       = null
6600     * StringUtils.replaceFirst("any", (String) null, *)   = "any"
6601     * StringUtils.replaceFirst("any", *, null)   = "any"
6602     * StringUtils.replaceFirst("", "", "zzz")    = "zzz"
6603     * StringUtils.replaceFirst("", ".*", "zzz")  = "zzz"
6604     * StringUtils.replaceFirst("", ".+", "zzz")  = ""
6605     * StringUtils.replaceFirst("abc", "", "ZZ")  = "ZZabc"
6606     * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z")      = "z\n<__>"
6607     * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z")  = "z"
6608     * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_")          = "ABC_bc123"
6609     * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_")  = "ABC_123abc"
6610     * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "")   = "ABC123abc"
6611     * StringUtils.replaceFirst("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum  dolor   sit"
6612     * }</pre>
6613     *
6614     * @param text        text to search and replace in, may be null.
6615     * @param regex       the regular expression to which this string is to be matched.
6616     * @param replacement the string to be substituted for the first match.
6617     * @return the text with the first replacement processed, {@code null} if null String input.
6618     * @throws java.util.regex.PatternSyntaxException if the regular expression's syntax is invalid.
6619     * @see String#replaceFirst(String, String)
6620     * @see java.util.regex.Pattern
6621     * @see java.util.regex.Pattern#DOTALL
6622     * @since 3.5
6623     * @deprecated Use {@link RegExUtils#replaceFirst(String, String, String)}.
6624     */
6625    @Deprecated
6626    public static String replaceFirst(final String text, final String regex, final String replacement) {
6627        return RegExUtils.replaceFirst(text, regex, replacement);
6628    }
6629
6630    /**
6631     * Case insensitively replaces all occurrences of a String within another String.
6632     *
6633     * <p>
6634     * A {@code null} reference passed to this method is a no-op.
6635     * </p>
6636     *
6637     * <pre>
6638     * StringUtils.replaceIgnoreCase(null, *, *)        = null
6639     * StringUtils.replaceIgnoreCase("", *, *)          = ""
6640     * StringUtils.replaceIgnoreCase("any", null, *)    = "any"
6641     * StringUtils.replaceIgnoreCase("any", *, null)    = "any"
6642     * StringUtils.replaceIgnoreCase("any", "", *)      = "any"
6643     * StringUtils.replaceIgnoreCase("aba", "a", null)  = "aba"
6644     * StringUtils.replaceIgnoreCase("abA", "A", "")    = "b"
6645     * StringUtils.replaceIgnoreCase("aba", "A", "z")   = "zbz"
6646     * </pre>
6647     *
6648     * @param text         text to search and replace in, may be null.
6649     * @param searchString the String to search for (case-insensitive), may be null.
6650     * @param replacement  the String to replace it with, may be null.
6651     * @return the text with any replacements processed, {@code null} if null String input.
6652     * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
6653     * @since 3.5
6654     * @deprecated Use {@link Strings#replace(String, String, String) Strings.CI.replace(String, String, String)}.
6655     */
6656    @Deprecated
6657    public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) {
6658        return Strings.CI.replace(text, searchString, replacement);
6659    }
6660
6661    /**
6662     * Case insensitively replaces a String with another String inside a larger String, for the first {@code max} values of the search String.
6663     *
6664     * <p>
6665     * A {@code null} reference passed to this method is a no-op.
6666     * </p>
6667     *
6668     * <pre>
6669     * StringUtils.replaceIgnoreCase(null, *, *, *)         = null
6670     * StringUtils.replaceIgnoreCase("", *, *, *)           = ""
6671     * StringUtils.replaceIgnoreCase("any", null, *, *)     = "any"
6672     * StringUtils.replaceIgnoreCase("any", *, null, *)     = "any"
6673     * StringUtils.replaceIgnoreCase("any", "", *, *)       = "any"
6674     * StringUtils.replaceIgnoreCase("any", *, *, 0)        = "any"
6675     * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa"
6676     * StringUtils.replaceIgnoreCase("abaa", "a", "", -1)   = "b"
6677     * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0)   = "abaa"
6678     * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1)   = "zbaa"
6679     * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2)   = "zbza"
6680     * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1)  = "zbzz"
6681     * </pre>
6682     *
6683     * @param text         text to search and replace in, may be null.
6684     * @param searchString the String to search for (case-insensitive), may be null.
6685     * @param replacement  the String to replace it with, may be null.
6686     * @param max          maximum number of values to replace, or {@code -1} if no maximum.
6687     * @return the text with any replacements processed, {@code null} if null String input.
6688     * @since 3.5
6689     * @deprecated Use {@link Strings#replace(String, String, String, int) Strings.CI.replace(String, String, String, int)}.
6690     */
6691    @Deprecated
6692    public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) {
6693        return Strings.CI.replace(text, searchString, replacement, max);
6694    }
6695
6696    /**
6697     * Replaces a String with another String inside a larger String, once.
6698     *
6699     * <p>
6700     * A {@code null} reference passed to this method is a no-op.
6701     * </p>
6702     *
6703     * <pre>
6704     * StringUtils.replaceOnce(null, *, *)        = null
6705     * StringUtils.replaceOnce("", *, *)          = ""
6706     * StringUtils.replaceOnce("any", null, *)    = "any"
6707     * StringUtils.replaceOnce("any", *, null)    = "any"
6708     * StringUtils.replaceOnce("any", "", *)      = "any"
6709     * StringUtils.replaceOnce("aba", "a", null)  = "aba"
6710     * StringUtils.replaceOnce("aba", "a", "")    = "ba"
6711     * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
6712     * </pre>
6713     *
6714     * @param text         text to search and replace in, may be null.
6715     * @param searchString the String to search for, may be null.
6716     * @param replacement  the String to replace with, may be null.
6717     * @return the text with any replacements processed, {@code null} if null String input.
6718     * @see #replace(String text, String searchString, String replacement, int max)
6719     * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CS.replaceOnce(String, String, String)}.
6720     */
6721    @Deprecated
6722    public static String replaceOnce(final String text, final String searchString, final String replacement) {
6723        return Strings.CS.replaceOnce(text, searchString, replacement);
6724    }
6725
6726    /**
6727     * Case insensitively replaces a String with another String inside a larger String, once.
6728     *
6729     * <p>
6730     * A {@code null} reference passed to this method is a no-op.
6731     * </p>
6732     *
6733     * <pre>
6734     * StringUtils.replaceOnceIgnoreCase(null, *, *)        = null
6735     * StringUtils.replaceOnceIgnoreCase("", *, *)          = ""
6736     * StringUtils.replaceOnceIgnoreCase("any", null, *)    = "any"
6737     * StringUtils.replaceOnceIgnoreCase("any", *, null)    = "any"
6738     * StringUtils.replaceOnceIgnoreCase("any", "", *)      = "any"
6739     * StringUtils.replaceOnceIgnoreCase("aba", "a", null)  = "aba"
6740     * StringUtils.replaceOnceIgnoreCase("aba", "a", "")    = "ba"
6741     * StringUtils.replaceOnceIgnoreCase("aba", "a", "z")   = "zba"
6742     * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo"
6743     * </pre>
6744     *
6745     * @param text         text to search and replace in, may be null.
6746     * @param searchString the String to search for (case-insensitive), may be null.
6747     * @param replacement  the String to replace with, may be null.
6748     * @return the text with any replacements processed, {@code null} if null String input.
6749     * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
6750     * @since 3.5
6751     * @deprecated Use {@link Strings#replaceOnce(String, String, String) Strings.CI.replaceOnce(String, String, String)}.
6752     */
6753    @Deprecated
6754    public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) {
6755        return Strings.CI.replaceOnce(text, searchString, replacement);
6756    }
6757
6758    /**
6759     * Replaces each substring of the source String that matches the given regular expression with the given replacement using the {@link Pattern#DOTALL}
6760     * option. DOTALL is also known as single-line mode in Perl.
6761     *
6762     * This call is a {@code null} safe equivalent to:
6763     * <ul>
6764     * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, replacement)}</li>
6765     * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li>
6766     * </ul>
6767     *
6768     * <p>
6769     * A {@code null} reference passed to this method is a no-op.
6770     * </p>
6771     *
6772     * <pre>{@code
6773     * StringUtils.replacePattern(null, *, *)                                         = null
6774     * StringUtils.replacePattern("any", (String) null, *)                            = "any"
6775     * StringUtils.replacePattern("any", *, null)                                     = "any"
6776     * StringUtils.replacePattern("", "", "zzz")                                      = "zzz"
6777     * StringUtils.replacePattern("", ".*", "zzz")                                    = "zzz"
6778     * StringUtils.replacePattern("", ".+", "zzz")                                    = ""
6779     * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z")                          = "z"
6780     * StringUtils.replacePattern("ABCabc123", "[a-z]", "_")                          = "ABC___123"
6781     * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_")                     = "ABC_123"
6782     * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "")                      = "ABC123"
6783     * StringUtils.replacePattern("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
6784     * }</pre>
6785     *
6786     * @param source      the source string.
6787     * @param regex       the regular expression to which this string is to be matched.
6788     * @param replacement the string to be substituted for each match.
6789     * @return The resulting {@link String}.
6790     * @see #replaceAll(String, String, String)
6791     * @see String#replaceAll(String, String)
6792     * @see Pattern#DOTALL
6793     * @since 3.2
6794     * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
6795     * @deprecated Use {@link RegExUtils#replacePattern(CharSequence, String, String)}.
6796     */
6797    @Deprecated
6798    public static String replacePattern(final String source, final String regex, final String replacement) {
6799        return RegExUtils.replacePattern(source, regex, replacement);
6800    }
6801
6802    /**
6803     * Reverses a String as per {@link StringBuilder#reverse()}.
6804     *
6805     * <p>
6806     * A {@code null} String returns {@code null}.
6807     * </p>
6808     *
6809     * <pre>
6810     * StringUtils.reverse(null)  = null
6811     * StringUtils.reverse("")    = ""
6812     * StringUtils.reverse("bat") = "tab"
6813     * </pre>
6814     *
6815     * @param str the String to reverse, may be null.
6816     * @return the reversed String, {@code null} if null String input.
6817     */
6818    public static String reverse(final String str) {
6819        if (str == null) {
6820            return null;
6821        }
6822        return new StringBuilder(str).reverse().toString();
6823    }
6824
6825    /**
6826     * Reverses a String that is delimited by a specific character.
6827     *
6828     * <p>
6829     * The Strings between the delimiters are not reversed. Thus java.lang.String becomes String.lang.java (if the delimiter is {@code '.'}).
6830     * </p>
6831     *
6832     * <pre>
6833     * StringUtils.reverseDelimited(null, *)      = null
6834     * StringUtils.reverseDelimited("", *)        = ""
6835     * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
6836     * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
6837     * </pre>
6838     *
6839     * @param str           the String to reverse, may be null.
6840     * @param separatorChar the separator character to use.
6841     * @return the reversed String, {@code null} if null String input.
6842     * @since 2.0
6843     */
6844    public static String reverseDelimited(final String str, final char separatorChar) {
6845        final String[] strs = split(str, separatorChar);
6846        ArrayUtils.reverse(strs);
6847        return join(strs, separatorChar);
6848    }
6849
6850    /**
6851     * Gets the rightmost {@code len} characters of a String.
6852     *
6853     * <p>
6854     * If {@code len} characters are not available, or the String is {@code null}, the String will be returned without an exception. An empty String is
6855     * returned if len is negative.
6856     * </p>
6857     *
6858     * <pre>
6859     * StringUtils.right(null, *)    = null
6860     * StringUtils.right(*, -ve)     = ""
6861     * StringUtils.right("", *)      = ""
6862     * StringUtils.right("abc", 0)   = ""
6863     * StringUtils.right("abc", 2)   = "bc"
6864     * StringUtils.right("abc", 4)   = "abc"
6865     * </pre>
6866     *
6867     * @param str the String to get the rightmost characters from, may be null.
6868     * @param len the length of the required String.
6869     * @return the rightmost characters, {@code null} if null String input.
6870     */
6871    public static String right(final String str, final int len) {
6872        if (str == null) {
6873            return null;
6874        }
6875        if (len < 0) {
6876            return EMPTY;
6877        }
6878        if (str.length() <= len) {
6879            return str;
6880        }
6881        return str.substring(str.length() - len);
6882    }
6883
6884    /**
6885     * Right pad a String with spaces (' ').
6886     *
6887     * <p>
6888     * The String is padded to the size of {@code size}.
6889     * </p>
6890     *
6891     * <pre>
6892     * StringUtils.rightPad(null, *)   = null
6893     * StringUtils.rightPad("", 3)     = "   "
6894     * StringUtils.rightPad("bat", 3)  = "bat"
6895     * StringUtils.rightPad("bat", 5)  = "bat  "
6896     * StringUtils.rightPad("bat", 1)  = "bat"
6897     * StringUtils.rightPad("bat", -1) = "bat"
6898     * </pre>
6899     *
6900     * @param str  the String to pad out, may be null.
6901     * @param size the size to pad to.
6902     * @return right padded String or original String if no padding is necessary, {@code null} if null String input.
6903     */
6904    public static String rightPad(final String str, final int size) {
6905        return rightPad(str, size, ' ');
6906    }
6907
6908    /**
6909     * Right pad a String with a specified character.
6910     *
6911     * <p>
6912     * The String is padded to the size of {@code size}.
6913     * </p>
6914     *
6915     * <pre>
6916     * StringUtils.rightPad(null, *, *)     = null
6917     * StringUtils.rightPad("", 3, 'z')     = "zzz"
6918     * StringUtils.rightPad("bat", 3, 'z')  = "bat"
6919     * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
6920     * StringUtils.rightPad("bat", 1, 'z')  = "bat"
6921     * StringUtils.rightPad("bat", -1, 'z') = "bat"
6922     * </pre>
6923     *
6924     * @param str     the String to pad out, may be null.
6925     * @param size    the size to pad to.
6926     * @param padChar the character to pad with.
6927     * @return right padded String or original String if no padding is necessary, {@code null} if null String input.
6928     * @since 2.0
6929     */
6930    public static String rightPad(final String str, final int size, final char padChar) {
6931        if (str == null) {
6932            return null;
6933        }
6934        final int pads = size - str.length();
6935        if (pads <= 0) {
6936            return str; // returns original String when possible
6937        }
6938        if (pads > PAD_LIMIT) {
6939            return rightPad(str, size, String.valueOf(padChar));
6940        }
6941        return str.concat(repeat(padChar, pads));
6942    }
6943
6944    /**
6945     * Right pad a String with a specified String.
6946     *
6947     * <p>
6948     * The String is padded to the size of {@code size}.
6949     * </p>
6950     *
6951     * <pre>
6952     * StringUtils.rightPad(null, *, *)      = null
6953     * StringUtils.rightPad("", 3, "z")      = "zzz"
6954     * StringUtils.rightPad("bat", 3, "yz")  = "bat"
6955     * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
6956     * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
6957     * StringUtils.rightPad("bat", 1, "yz")  = "bat"
6958     * StringUtils.rightPad("bat", -1, "yz") = "bat"
6959     * StringUtils.rightPad("bat", 5, null)  = "bat  "
6960     * StringUtils.rightPad("bat", 5, "")    = "bat  "
6961     * </pre>
6962     *
6963     * @param str    the String to pad out, may be null.
6964     * @param size   the size to pad to.
6965     * @param padStr the String to pad with, null or empty treated as single space.
6966     * @return right padded String or original String if no padding is necessary, {@code null} if null String input.
6967     */
6968    public static String rightPad(final String str, final int size, String padStr) {
6969        if (str == null) {
6970            return null;
6971        }
6972        if (isEmpty(padStr)) {
6973            padStr = SPACE;
6974        }
6975        final int padLen = padStr.length();
6976        final int strLen = str.length();
6977        final int pads = size - strLen;
6978        if (pads <= 0) {
6979            return str; // returns original String when possible
6980        }
6981        if (padLen == 1 && pads <= PAD_LIMIT) {
6982            return rightPad(str, size, padStr.charAt(0));
6983        }
6984        if (pads == padLen) {
6985            return str.concat(padStr);
6986        }
6987        if (pads < padLen) {
6988            return str.concat(padStr.substring(0, pads));
6989        }
6990        final char[] padding = new char[pads];
6991        final char[] padChars = padStr.toCharArray();
6992        for (int i = 0; i < pads; i++) {
6993            padding[i] = padChars[i % padLen];
6994        }
6995        return str.concat(new String(padding));
6996    }
6997
6998    /**
6999     * Rotate (circular shift) a String of {@code shift} characters.
7000     * <ul>
7001     * <li>If {@code shift > 0}, right circular shift (ex : ABCDEF =&gt; FABCDE)</li>
7002     * <li>If {@code shift < 0}, left circular shift (ex : ABCDEF =&gt; BCDEFA)</li>
7003     * </ul>
7004     *
7005     * <pre>
7006     * StringUtils.rotate(null, *)        = null
7007     * StringUtils.rotate("", *)          = ""
7008     * StringUtils.rotate("abcdefg", 0)   = "abcdefg"
7009     * StringUtils.rotate("abcdefg", 2)   = "fgabcde"
7010     * StringUtils.rotate("abcdefg", -2)  = "cdefgab"
7011     * StringUtils.rotate("abcdefg", 7)   = "abcdefg"
7012     * StringUtils.rotate("abcdefg", -7)  = "abcdefg"
7013     * StringUtils.rotate("abcdefg", 9)   = "fgabcde"
7014     * StringUtils.rotate("abcdefg", -9)  = "cdefgab"
7015     * </pre>
7016     *
7017     * @param str   the String to rotate, may be null.
7018     * @param shift number of time to shift (positive : right shift, negative : left shift).
7019     * @return the rotated String, or the original String if {@code shift == 0}, or {@code null} if null String input.
7020     * @since 3.5
7021     */
7022    public static String rotate(final String str, final int shift) {
7023        if (str == null) {
7024            return null;
7025        }
7026        final int strLen = str.length();
7027        if (shift == 0 || strLen == 0 || shift % strLen == 0) {
7028            return str;
7029        }
7030        final StringBuilder builder = new StringBuilder(strLen);
7031        final int offset = -(shift % strLen);
7032        builder.append(substring(str, offset));
7033        builder.append(substring(str, 0, offset));
7034        return builder.toString();
7035    }
7036
7037    /**
7038     * Splits the provided text into an array, using whitespace as the separator. Whitespace is defined by {@link Character#isWhitespace(char)}.
7039     *
7040     * <p>
7041     * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the
7042     * StrTokenizer class.
7043     * </p>
7044     *
7045     * <p>
7046     * A {@code null} input String returns {@code null}.
7047     * </p>
7048     *
7049     * <pre>
7050     * StringUtils.split(null)       = null
7051     * StringUtils.split("")         = []
7052     * StringUtils.split("abc def")  = ["abc", "def"]
7053     * StringUtils.split("abc  def") = ["abc", "def"]
7054     * StringUtils.split(" abc ")    = ["abc"]
7055     * </pre>
7056     *
7057     * @param str the String to parse, may be null.
7058     * @return an array of parsed Strings, {@code null} if null String input.
7059     */
7060    public static String[] split(final String str) {
7061        return split(str, null, -1);
7062    }
7063
7064    /**
7065     * Splits the provided text into an array, separator specified. This is an alternative to using StringTokenizer.
7066     *
7067     * <p>
7068     * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the
7069     * StrTokenizer class.
7070     * </p>
7071     *
7072     * <p>
7073     * A {@code null} input String returns {@code null}.
7074     * </p>
7075     *
7076     * <pre>
7077     * StringUtils.split(null, *)         = null
7078     * StringUtils.split("", *)           = []
7079     * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
7080     * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
7081     * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
7082     * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
7083     * </pre>
7084     *
7085     * @param str           the String to parse, may be null.
7086     * @param separatorChar the character used as the delimiter.
7087     * @return an array of parsed Strings, {@code null} if null String input.
7088     * @since 2.0
7089     */
7090    public static String[] split(final String str, final char separatorChar) {
7091        return splitWorker(str, separatorChar, false);
7092    }
7093
7094    /**
7095     * Splits the provided text into an array, separators specified. This is an alternative to using StringTokenizer.
7096     *
7097     * <p>
7098     * The separator is not included in the returned String array. Adjacent separators are treated as one separator. For more control over the split use the
7099     * StrTokenizer class.
7100     * </p>
7101     *
7102     * <p>
7103     * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace.
7104     * </p>
7105     *
7106     * <pre>
7107     * StringUtils.split(null, *)         = null
7108     * StringUtils.split("", *)           = []
7109     * StringUtils.split("abc def", null) = ["abc", "def"]
7110     * StringUtils.split("abc def", " ")  = ["abc", "def"]
7111     * StringUtils.split("abc  def", " ") = ["abc", "def"]
7112     * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
7113     * </pre>
7114     *
7115     * @param str            the String to parse, may be null.
7116     * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace.
7117     * @return an array of parsed Strings, {@code null} if null String input.
7118     */
7119    public static String[] split(final String str, final String separatorChars) {
7120        return splitWorker(str, separatorChars, -1, false);
7121    }
7122
7123    /**
7124     * Splits the provided text into an array with a maximum length, separators specified.
7125     *
7126     * <p>
7127     * The separator is not included in the returned String array. Adjacent separators are treated as one separator.
7128     * </p>
7129     *
7130     * <p>
7131     * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace.
7132     * </p>
7133     *
7134     * <p>
7135     * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned
7136     * strings (including separator characters).
7137     * </p>
7138     *
7139     * <pre>
7140     * StringUtils.split(null, *, *)            = null
7141     * StringUtils.split("", *, *)              = []
7142     * StringUtils.split("ab cd ef", null, 0)   = ["ab", "cd", "ef"]
7143     * StringUtils.split("ab   cd ef", null, 0) = ["ab", "cd", "ef"]
7144     * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
7145     * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
7146     * </pre>
7147     *
7148     * @param str            the String to parse, may be null.
7149     * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace.
7150     * @param max            the maximum number of elements to include in the array. A zero or negative value implies no limit.
7151     * @return an array of parsed Strings, {@code null} if null String input.
7152     */
7153    public static String[] split(final String str, final String separatorChars, final int max) {
7154        return splitWorker(str, separatorChars, max, false);
7155    }
7156
7157    /**
7158     * Splits a String by Character type as returned by {@code java.lang.Character.getType(char)}. Groups of contiguous characters of the same type are returned
7159     * as complete tokens.
7160     *
7161     * <pre>
7162     * StringUtils.splitByCharacterType(null)         = null
7163     * StringUtils.splitByCharacterType("")           = []
7164     * StringUtils.splitByCharacterType("ab de fg")   = ["ab", " ", "de", " ", "fg"]
7165     * StringUtils.splitByCharacterType("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
7166     * StringUtils.splitByCharacterType("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
7167     * StringUtils.splitByCharacterType("number5")    = ["number", "5"]
7168     * StringUtils.splitByCharacterType("fooBar")     = ["foo", "B", "ar"]
7169     * StringUtils.splitByCharacterType("foo200Bar")  = ["foo", "200", "B", "ar"]
7170     * StringUtils.splitByCharacterType("ASFRules")   = ["ASFR", "ules"]
7171     * </pre>
7172     *
7173     * @param str the String to split, may be {@code null}.
7174     * @return an array of parsed Strings, {@code null} if null String input.
7175     * @since 2.4
7176     */
7177    public static String[] splitByCharacterType(final String str) {
7178        return splitByCharacterType(str, false);
7179    }
7180
7181    /**
7182     * Splits a String by Character type as returned by {@code java.lang.Character.getType(char)}. Groups of contiguous characters of the same type are returned
7183     * as complete tokens, with the following exception: if {@code camelCase} is {@code true}, the character of type {@code Character.UPPERCASE_LETTER}, if any,
7184     * immediately preceding a token of type {@code Character.LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any,
7185     * {@code Character.UPPERCASE_LETTER} token.
7186     *
7187     * @param str       the String to split, may be {@code null}.
7188     * @param camelCase whether to use so-called "camel-case" for letter types.
7189     * @return an array of parsed Strings, {@code null} if null String input.
7190     * @since 2.4
7191     */
7192    private static String[] splitByCharacterType(final String str, final boolean camelCase) {
7193        if (str == null) {
7194            return null;
7195        }
7196        if (str.isEmpty()) {
7197            return ArrayUtils.EMPTY_STRING_ARRAY;
7198        }
7199        final char[] c = str.toCharArray();
7200        final List<String> list = new ArrayList<>();
7201        int tokenStart = 0;
7202        int currentType = Character.getType(c[tokenStart]);
7203        for (int pos = tokenStart + 1; pos < c.length; pos++) {
7204            final int type = Character.getType(c[pos]);
7205            if (type == currentType) {
7206                continue;
7207            }
7208            if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
7209                final int newTokenStart = pos - 1;
7210                if (newTokenStart != tokenStart) {
7211                    list.add(new String(c, tokenStart, newTokenStart - tokenStart));
7212                    tokenStart = newTokenStart;
7213                }
7214            } else {
7215                list.add(new String(c, tokenStart, pos - tokenStart));
7216                tokenStart = pos;
7217            }
7218            currentType = type;
7219        }
7220        list.add(new String(c, tokenStart, c.length - tokenStart));
7221        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
7222    }
7223
7224    /**
7225     * Splits a String by Character type as returned by {@code java.lang.Character.getType(char)}. Groups of contiguous characters of the same type are returned
7226     * as complete tokens, with the following exception: the character of type {@code Character.UPPERCASE_LETTER}, if any, immediately preceding a token of type
7227     * {@code Character.LOWERCASE_LETTER} will belong to the following token rather than to the preceding, if any, {@code Character.UPPERCASE_LETTER} token.
7228     *
7229     * <pre>
7230     * StringUtils.splitByCharacterTypeCamelCase(null)         = null
7231     * StringUtils.splitByCharacterTypeCamelCase("")           = []
7232     * StringUtils.splitByCharacterTypeCamelCase("ab de fg")   = ["ab", " ", "de", " ", "fg"]
7233     * StringUtils.splitByCharacterTypeCamelCase("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
7234     * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
7235     * StringUtils.splitByCharacterTypeCamelCase("number5")    = ["number", "5"]
7236     * StringUtils.splitByCharacterTypeCamelCase("fooBar")     = ["foo", "Bar"]
7237     * StringUtils.splitByCharacterTypeCamelCase("foo200Bar")  = ["foo", "200", "Bar"]
7238     * StringUtils.splitByCharacterTypeCamelCase("ASFRules")   = ["ASF", "Rules"]
7239     * </pre>
7240     *
7241     * @param str the String to split, may be {@code null}.
7242     * @return an array of parsed Strings, {@code null} if null String input.
7243     * @since 2.4
7244     */
7245    public static String[] splitByCharacterTypeCamelCase(final String str) {
7246        return splitByCharacterType(str, true);
7247    }
7248
7249    /**
7250     * Splits the provided text into an array, separator string specified.
7251     *
7252     * <p>
7253     * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator.
7254     * </p>
7255     *
7256     * <p>
7257     * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace.
7258     * </p>
7259     *
7260     * <pre>
7261     * StringUtils.splitByWholeSeparator(null, *)               = null
7262     * StringUtils.splitByWholeSeparator("", *)                 = []
7263     * StringUtils.splitByWholeSeparator("ab de fg", null)      = ["ab", "de", "fg"]
7264     * StringUtils.splitByWholeSeparator("ab   de fg", null)    = ["ab", "de", "fg"]
7265     * StringUtils.splitByWholeSeparator("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
7266     * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
7267     * </pre>
7268     *
7269     * @param str       the String to parse, may be null.
7270     * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7271     * @return an array of parsed Strings, {@code null} if null String was input.
7272     */
7273    public static String[] splitByWholeSeparator(final String str, final String separator) {
7274        return splitByWholeSeparatorWorker(str, separator, -1, false);
7275    }
7276
7277    /**
7278     * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings.
7279     *
7280     * <p>
7281     * The separator(s) will not be included in the returned String array. Adjacent separators are treated as one separator.
7282     * </p>
7283     *
7284     * <p>
7285     * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace.
7286     * </p>
7287     *
7288     * <pre>
7289     * StringUtils.splitByWholeSeparator(null, *, *)               = null
7290     * StringUtils.splitByWholeSeparator("", *, *)                 = []
7291     * StringUtils.splitByWholeSeparator("ab de fg", null, 0)      = ["ab", "de", "fg"]
7292     * StringUtils.splitByWholeSeparator("ab   de fg", null, 0)    = ["ab", "de", "fg"]
7293     * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
7294     * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
7295     * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
7296     * </pre>
7297     *
7298     * @param str       the String to parse, may be null.
7299     * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7300     * @param max       the maximum number of elements to include in the returned array. A zero or negative value implies no limit.
7301     * @return an array of parsed Strings, {@code null} if null String was input.
7302     */
7303    public static String[] splitByWholeSeparator(final String str, final String separator, final int max) {
7304        return splitByWholeSeparatorWorker(str, separator, max, false);
7305    }
7306
7307    /**
7308     * Splits the provided text into an array, separator string specified.
7309     *
7310     * <p>
7311     * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7312     * split use the StrTokenizer class.
7313     * </p>
7314     *
7315     * <p>
7316     * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace.
7317     * </p>
7318     *
7319     * <pre>
7320     * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *)               = null
7321     * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *)                 = []
7322     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null)      = ["ab", "de", "fg"]
7323     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null)    = ["ab", "", "", "de", "fg"]
7324     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
7325     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
7326     * </pre>
7327     *
7328     * @param str       the String to parse, may be null.
7329     * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7330     * @return an array of parsed Strings, {@code null} if null String was input.
7331     * @since 2.4
7332     */
7333    public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) {
7334        return splitByWholeSeparatorWorker(str, separator, -1, true);
7335    }
7336
7337    /**
7338     * Splits the provided text into an array, separator string specified. Returns a maximum of {@code max} substrings.
7339     *
7340     * <p>
7341     * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7342     * split use the StrTokenizer class.
7343     * </p>
7344     *
7345     * <p>
7346     * A {@code null} input String returns {@code null}. A {@code null} separator splits on whitespace.
7347     * </p>
7348     *
7349     * <pre>
7350     * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *)               = null
7351     * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *)                 = []
7352     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0)      = ["ab", "de", "fg"]
7353     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null, 0)    = ["ab", "", "", "de", "fg"]
7354     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
7355     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
7356     * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
7357     * </pre>
7358     *
7359     * @param str       the String to parse, may be null.
7360     * @param separator String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7361     * @param max       the maximum number of elements to include in the returned array. A zero or negative value implies no limit.
7362     * @return an array of parsed Strings, {@code null} if null String was input.
7363     * @since 2.4
7364     */
7365    public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) {
7366        return splitByWholeSeparatorWorker(str, separator, max, true);
7367    }
7368
7369    /**
7370     * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods.
7371     *
7372     * @param str               the String to parse, may be {@code null}.
7373     * @param separator         String containing the String to be used as a delimiter, {@code null} splits on whitespace.
7374     * @param max               the maximum number of elements to include in the returned array. A zero or negative value implies no limit.
7375     * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as
7376     *                          one separator.
7377     * @return an array of parsed Strings, {@code null} if null String input.
7378     * @since 2.4
7379     */
7380    private static String[] splitByWholeSeparatorWorker(final String str, final String separator, final int max, final boolean preserveAllTokens) {
7381        if (str == null) {
7382            return null;
7383        }
7384        final int len = str.length();
7385        if (len == 0) {
7386            return ArrayUtils.EMPTY_STRING_ARRAY;
7387        }
7388        if (separator == null || EMPTY.equals(separator)) {
7389            // Split on whitespace.
7390            return splitWorker(str, null, max, preserveAllTokens);
7391        }
7392        final int separatorLength = separator.length();
7393        final ArrayList<String> substrings = new ArrayList<>();
7394        int numberOfSubstrings = 0;
7395        int beg = 0;
7396        int end = 0;
7397        while (end < len) {
7398            end = str.indexOf(separator, beg);
7399            if (end > -1) {
7400                if (end > beg) {
7401                    numberOfSubstrings += 1;
7402                    if (numberOfSubstrings == max) {
7403                        end = len;
7404                        substrings.add(str.substring(beg));
7405                    } else {
7406                        // The following is OK, because String.substring( beg, end ) excludes
7407                        // the character at the position 'end'.
7408                        substrings.add(str.substring(beg, end));
7409                        // Set the starting point for the next search.
7410                        // The following is equivalent to beg = end + (separatorLength - 1) + 1,
7411                        // which is the right calculation:
7412                        beg = end + separatorLength;
7413                    }
7414                } else {
7415                    // We found a consecutive occurrence of the separator, so skip it.
7416                    if (preserveAllTokens) {
7417                        numberOfSubstrings += 1;
7418                        if (numberOfSubstrings == max) {
7419                            end = len;
7420                            substrings.add(str.substring(beg));
7421                        } else {
7422                            substrings.add(EMPTY);
7423                        }
7424                    }
7425                    beg = end + separatorLength;
7426                }
7427            } else {
7428                // String.substring( beg ) goes from 'beg' to the end of the String.
7429                substrings.add(str.substring(beg));
7430                end = len;
7431            }
7432        }
7433        return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
7434    }
7435
7436    /**
7437     * Splits the provided text into an array, using whitespace as the separator, preserving all tokens, including empty tokens created by adjacent separators.
7438     * This is an alternative to using StringTokenizer. Whitespace is defined by {@link Character#isWhitespace(char)}.
7439     *
7440     * <p>
7441     * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7442     * split use the StrTokenizer class.
7443     * </p>
7444     *
7445     * <p>
7446     * A {@code null} input String returns {@code null}.
7447     * </p>
7448     *
7449     * <pre>
7450     * StringUtils.splitPreserveAllTokens(null)       = null
7451     * StringUtils.splitPreserveAllTokens("")         = []
7452     * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]
7453     * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "", "def"]
7454     * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc", ""]
7455     * </pre>
7456     *
7457     * @param str the String to parse, may be {@code null}.
7458     * @return an array of parsed Strings, {@code null} if null String input.
7459     * @since 2.1
7460     */
7461    public static String[] splitPreserveAllTokens(final String str) {
7462        return splitWorker(str, null, -1, true);
7463    }
7464
7465    /**
7466     * Splits the provided text into an array, separator specified, preserving all tokens, including empty tokens created by adjacent separators. This is an
7467     * alternative to using StringTokenizer.
7468     *
7469     * <p>
7470     * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7471     * split use the StrTokenizer class.
7472     * </p>
7473     *
7474     * <p>
7475     * A {@code null} input String returns {@code null}.
7476     * </p>
7477     *
7478     * <pre>
7479     * StringUtils.splitPreserveAllTokens(null, *)         = null
7480     * StringUtils.splitPreserveAllTokens("", *)           = []
7481     * StringUtils.splitPreserveAllTokens("a.b.c", '.')    = ["a", "b", "c"]
7482     * StringUtils.splitPreserveAllTokens("a..b.c", '.')   = ["a", "", "b", "c"]
7483     * StringUtils.splitPreserveAllTokens("a:b:c", '.')    = ["a:b:c"]
7484     * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
7485     * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b", "c"]
7486     * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b", "c", ""]
7487     * StringUtils.splitPreserveAllTokens("a b c  ", ' ')  = ["a", "b", "c", "", ""]
7488     * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", "a", "b", "c"]
7489     * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", "a", "b", "c"]
7490     * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", "a", "b", "c", ""]
7491     * </pre>
7492     *
7493     * @param str           the String to parse, may be {@code null}.
7494     * @param separatorChar the character used as the delimiter, {@code null} splits on whitespace.
7495     * @return an array of parsed Strings, {@code null} if null String input.
7496     * @since 2.1
7497     */
7498    public static String[] splitPreserveAllTokens(final String str, final char separatorChar) {
7499        return splitWorker(str, separatorChar, true);
7500    }
7501
7502    /**
7503     * Splits the provided text into an array, separators specified, preserving all tokens, including empty tokens created by adjacent separators. This is an
7504     * alternative to using StringTokenizer.
7505     *
7506     * <p>
7507     * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. For more control over the
7508     * split use the StrTokenizer class.
7509     * </p>
7510     *
7511     * <p>
7512     * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace.
7513     * </p>
7514     *
7515     * <pre>
7516     * StringUtils.splitPreserveAllTokens(null, *)           = null
7517     * StringUtils.splitPreserveAllTokens("", *)             = []
7518     * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]
7519     * StringUtils.splitPreserveAllTokens("abc def", " ")    = ["abc", "def"]
7520     * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", "def"]
7521     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":")   = ["ab", "cd", "ef"]
7522     * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":")  = ["ab", "cd", "ef", ""]
7523     * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
7524     * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":")  = ["ab", "", "cd", "ef"]
7525     * StringUtils.splitPreserveAllTokens(":cd:ef", ":")     = ["", "cd", "ef"]
7526     * StringUtils.splitPreserveAllTokens("::cd:ef", ":")    = ["", "", "cd", "ef"]
7527     * StringUtils.splitPreserveAllTokens(":cd:ef:", ":")    = ["", "cd", "ef", ""]
7528     * </pre>
7529     *
7530     * @param str            the String to parse, may be {@code null}.
7531     * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace.
7532     * @return an array of parsed Strings, {@code null} if null String input.
7533     * @since 2.1
7534     */
7535    public static String[] splitPreserveAllTokens(final String str, final String separatorChars) {
7536        return splitWorker(str, separatorChars, -1, true);
7537    }
7538
7539    /**
7540     * Splits the provided text into an array with a maximum length, separators specified, preserving all tokens, including empty tokens created by adjacent
7541     * separators.
7542     *
7543     * <p>
7544     * The separator is not included in the returned String array. Adjacent separators are treated as separators for empty tokens. Adjacent separators are
7545     * treated as one separator.
7546     * </p>
7547     *
7548     * <p>
7549     * A {@code null} input String returns {@code null}. A {@code null} separatorChars splits on whitespace.
7550     * </p>
7551     *
7552     * <p>
7553     * If more than {@code max} delimited substrings are found, the last returned string includes all characters after the first {@code max - 1} returned
7554     * strings (including separator characters).
7555     * </p>
7556     *
7557     * <pre>
7558     * StringUtils.splitPreserveAllTokens(null, *, *)            = null
7559     * StringUtils.splitPreserveAllTokens("", *, *)              = []
7560     * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "de", "fg"]
7561     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab", "", "", "de", "fg"]
7562     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
7563     * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
7564     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab", "  de fg"]
7565     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab", "", " de fg"]
7566     * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab", "", "", "de fg"]
7567     * </pre>
7568     *
7569     * @param str            the String to parse, may be {@code null}.
7570     * @param separatorChars the characters used as the delimiters, {@code null} splits on whitespace.
7571     * @param max            the maximum number of elements to include in the array. A zero or negative value implies no limit.
7572     * @return an array of parsed Strings, {@code null} if null String input.
7573     * @since 2.1
7574     */
7575    public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) {
7576        return splitWorker(str, separatorChars, max, true);
7577    }
7578
7579    /**
7580     * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that do not return a maximum array length.
7581     *
7582     * @param str               the String to parse, may be {@code null}.
7583     * @param separatorChar     the separate character.
7584     * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as
7585     *                          one separator.
7586     * @return an array of parsed Strings, {@code null} if null String input.
7587     */
7588    private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) {
7589        // Performance tuned for 2.0 (JDK1.4)
7590        if (str == null) {
7591            return null;
7592        }
7593        final int len = str.length();
7594        if (len == 0) {
7595            return ArrayUtils.EMPTY_STRING_ARRAY;
7596        }
7597        final List<String> list = new ArrayList<>();
7598        int i = 0;
7599        int start = 0;
7600        boolean match = false;
7601        boolean lastMatch = false;
7602        while (i < len) {
7603            if (str.charAt(i) == separatorChar) {
7604                if (match || preserveAllTokens) {
7605                    list.add(str.substring(start, i));
7606                    match = false;
7607                    lastMatch = true;
7608                }
7609                start = ++i;
7610                continue;
7611            }
7612            lastMatch = false;
7613            match = true;
7614            i++;
7615        }
7616        if (match || preserveAllTokens && lastMatch) {
7617            list.add(str.substring(start, i));
7618        }
7619        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
7620    }
7621
7622    /**
7623     * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that return a maximum array length.
7624     *
7625     * @param str               the String to parse, may be {@code null}.
7626     * @param separatorChars    the separate character.
7627     * @param max               the maximum number of elements to include in the array. A zero or negative value implies no limit.
7628     * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as
7629     *                          one separator.
7630     * @return an array of parsed Strings, {@code null} if null String input.
7631     */
7632    private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
7633        // Performance tuned for 2.0 (JDK1.4)
7634        // Direct code is quicker than StringTokenizer.
7635        // Also, StringTokenizer uses isSpace() not isWhitespace()
7636        if (str == null) {
7637            return null;
7638        }
7639        final int len = str.length();
7640        if (len == 0) {
7641            return ArrayUtils.EMPTY_STRING_ARRAY;
7642        }
7643        final List<String> list = new ArrayList<>();
7644        int sizePlus1 = 1;
7645        int i = 0;
7646        int start = 0;
7647        boolean match = false;
7648        boolean lastMatch = false;
7649        if (separatorChars == null) {
7650            // Null separator means use whitespace
7651            while (i < len) {
7652                if (Character.isWhitespace(str.charAt(i))) {
7653                    if (match || preserveAllTokens) {
7654                        lastMatch = true;
7655                        if (sizePlus1++ == max) {
7656                            i = len;
7657                            lastMatch = false;
7658                        }
7659                        list.add(str.substring(start, i));
7660                        match = false;
7661                    }
7662                    start = ++i;
7663                    continue;
7664                }
7665                lastMatch = false;
7666                match = true;
7667                i++;
7668            }
7669        } else if (separatorChars.length() == 1) {
7670            // Optimize 1 character case
7671            final char sep = separatorChars.charAt(0);
7672            while (i < len) {
7673                if (str.charAt(i) == sep) {
7674                    if (match || preserveAllTokens) {
7675                        lastMatch = true;
7676                        if (sizePlus1++ == max) {
7677                            i = len;
7678                            lastMatch = false;
7679                        }
7680                        list.add(str.substring(start, i));
7681                        match = false;
7682                    }
7683                    start = ++i;
7684                    continue;
7685                }
7686                lastMatch = false;
7687                match = true;
7688                i++;
7689            }
7690        } else {
7691            // standard case
7692            while (i < len) {
7693                if (separatorChars.indexOf(str.charAt(i)) >= 0) {
7694                    if (match || preserveAllTokens) {
7695                        lastMatch = true;
7696                        if (sizePlus1++ == max) {
7697                            i = len;
7698                            lastMatch = false;
7699                        }
7700                        list.add(str.substring(start, i));
7701                        match = false;
7702                    }
7703                    start = ++i;
7704                    continue;
7705                }
7706                lastMatch = false;
7707                match = true;
7708                i++;
7709            }
7710        }
7711        if (match || preserveAllTokens && lastMatch) {
7712            list.add(str.substring(start, i));
7713        }
7714        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
7715    }
7716
7717    /**
7718     * Tests if a CharSequence starts with a specified prefix.
7719     *
7720     * <p>
7721     * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case-sensitive.
7722     * </p>
7723     *
7724     * <pre>
7725     * StringUtils.startsWith(null, null)      = true
7726     * StringUtils.startsWith(null, "abc")     = false
7727     * StringUtils.startsWith("abcdef", null)  = false
7728     * StringUtils.startsWith("abcdef", "abc") = true
7729     * StringUtils.startsWith("ABCDEF", "abc") = false
7730     * </pre>
7731     *
7732     * @param str    the CharSequence to check, may be null.
7733     * @param prefix the prefix to find, may be null.
7734     * @return {@code true} if the CharSequence starts with the prefix, case-sensitive, or both {@code null}.
7735     * @see String#startsWith(String)
7736     * @since 2.4
7737     * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
7738     * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CS.startsWith(CharSequence, CharSequence)}.
7739     */
7740    @Deprecated
7741    public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
7742        return Strings.CS.startsWith(str, prefix);
7743    }
7744
7745    /**
7746     * Tests if a CharSequence starts with any of the provided case-sensitive prefixes.
7747     *
7748     * <pre>
7749     * StringUtils.startsWithAny(null, null)      = false
7750     * StringUtils.startsWithAny(null, new String[] {"abc"})  = false
7751     * StringUtils.startsWithAny("abcxyz", null)     = false
7752     * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true
7753     * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
7754     * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
7755     * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false
7756     * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false
7757     * </pre>
7758     *
7759     * @param sequence      the CharSequence to check, may be null.
7760     * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null}.
7761     * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or the input {@code sequence} begins with
7762     *         any of the provided case-sensitive {@code searchStrings}.
7763     * @see StringUtils#startsWith(CharSequence, CharSequence)
7764     * @since 2.5
7765     * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...)
7766     * @deprecated Use {@link Strings#startsWithAny(CharSequence, CharSequence...) Strings.CS.startsWithAny(CharSequence, CharSequence...)}.
7767     */
7768    @Deprecated
7769    public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
7770        return Strings.CS.startsWithAny(sequence, searchStrings);
7771    }
7772
7773    /**
7774     * Case-insensitive check if a CharSequence starts with a specified prefix.
7775     *
7776     * <p>
7777     * {@code null}s are handled without exceptions. Two {@code null} references are considered to be equal. The comparison is case insensitive.
7778     * </p>
7779     *
7780     * <pre>
7781     * StringUtils.startsWithIgnoreCase(null, null)      = true
7782     * StringUtils.startsWithIgnoreCase(null, "abc")     = false
7783     * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
7784     * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
7785     * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
7786     * </pre>
7787     *
7788     * @param str    the CharSequence to check, may be null.
7789     * @param prefix the prefix to find, may be null.
7790     * @return {@code true} if the CharSequence starts with the prefix, case-insensitive, or both {@code null}.
7791     * @see String#startsWith(String)
7792     * @since 2.4
7793     * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
7794     * @deprecated Use {@link Strings#startsWith(CharSequence, CharSequence) Strings.CI.startsWith(CharSequence, CharSequence)}.
7795     */
7796    @Deprecated
7797    public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
7798        return Strings.CI.startsWith(str, prefix);
7799    }
7800
7801    /**
7802     * Strips whitespace from the start and end of a String.
7803     *
7804     * <p>
7805     * This is similar to {@link #trim(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}.
7806     * </p>
7807     *
7808     * <p>
7809     * A {@code null} input String returns {@code null}.
7810     * </p>
7811     *
7812     * <pre>
7813     * StringUtils.strip(null)     = null
7814     * StringUtils.strip("")       = ""
7815     * StringUtils.strip("   ")    = ""
7816     * StringUtils.strip("abc")    = "abc"
7817     * StringUtils.strip("  abc")  = "abc"
7818     * StringUtils.strip("abc  ")  = "abc"
7819     * StringUtils.strip(" abc ")  = "abc"
7820     * StringUtils.strip(" ab c ") = "ab c"
7821     * </pre>
7822     *
7823     * @param str the String to remove whitespace from, may be null.
7824     * @return the stripped String, {@code null} if null String input.
7825     */
7826    public static String strip(final String str) {
7827        return strip(str, null);
7828    }
7829
7830    /**
7831     * Strips any of a set of characters from the start and end of a String. This is similar to {@link String#trim()} but allows the characters to be stripped
7832     * to be controlled.
7833     *
7834     * <p>
7835     * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string.
7836     * </p>
7837     *
7838     * <p>
7839     * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}. Alternatively use
7840     * {@link #strip(String)}.
7841     * </p>
7842     *
7843     * <pre>
7844     * StringUtils.strip(null, *)          = null
7845     * StringUtils.strip("", *)            = ""
7846     * StringUtils.strip("abc", null)      = "abc"
7847     * StringUtils.strip("  abc", null)    = "abc"
7848     * StringUtils.strip("abc  ", null)    = "abc"
7849     * StringUtils.strip(" abc ", null)    = "abc"
7850     * StringUtils.strip("  abcyx", "xyz") = "  abc"
7851     * </pre>
7852     *
7853     * @param str        the String to remove characters from, may be null.
7854     * @param stripChars the characters to remove, null treated as whitespace.
7855     * @return the stripped String, {@code null} if null String input.
7856     */
7857    public static String strip(String str, final String stripChars) {
7858        str = stripStart(str, stripChars);
7859        return stripEnd(str, stripChars);
7860    }
7861
7862    /**
7863     * Removes diacritics (~= accents) from a string. The case will not be altered.
7864     * <p>
7865     * For instance, '&agrave;' will be replaced by 'a'.
7866     * </p>
7867     * <p>
7868     * Decomposes ligatures and digraphs per the KD column in the <a href = "https://www.unicode.org/charts/normalization/">Unicode Normalization Chart.</a>
7869     * </p>
7870     *
7871     * <pre>
7872     * StringUtils.stripAccents(null)         = null
7873     * StringUtils.stripAccents("")           = ""
7874     * StringUtils.stripAccents("control")    = "control"
7875     * StringUtils.stripAccents("&eacute;clair")     = "eclair"
7876     * StringUtils.stripAccents("\u1d43\u1d47\u1d9c\u00b9\u00b2\u00b3")     = "abc123"
7877     * StringUtils.stripAccents("\u00BC \u00BD \u00BE")      = "1⁄4 1⁄2 3⁄4"
7878     * </pre>
7879     * <p>
7880     * See also <a href="https://www.unicode.org/unicode/reports/tr15/tr15-23.html">Unicode Standard Annex #15 Unicode Normalization Forms</a>.
7881     * </p>
7882     *
7883     * @param input String to be stripped.
7884     * @return input text with diacritics removed.
7885     * @since 3.0
7886     */
7887    // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix:
7888    // https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907).
7889    public static String stripAccents(final String input) {
7890        if (isEmpty(input)) {
7891            return input;
7892        }
7893        final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFKD));
7894        convertRemainingAccentCharacters(decomposed);
7895        return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY);
7896    }
7897
7898    /**
7899     * Strips whitespace from the start and end of every String in an array. Whitespace is defined by {@link Character#isWhitespace(char)}.
7900     *
7901     * <p>
7902     * A new array is returned each time, except for length zero. A {@code null} array will return {@code null}. An empty array will return itself. A
7903     * {@code null} array entry will be ignored.
7904     * </p>
7905     *
7906     * <pre>
7907     * StringUtils.stripAll(null)             = null
7908     * StringUtils.stripAll([])               = []
7909     * StringUtils.stripAll(["abc", "  abc"]) = ["abc", "abc"]
7910     * StringUtils.stripAll(["abc  ", null])  = ["abc", null]
7911     * </pre>
7912     *
7913     * @param strs the array to remove whitespace from, may be null.
7914     * @return the stripped Strings, {@code null} if null array input.
7915     */
7916    public static String[] stripAll(final String... strs) {
7917        return stripAll(strs, null);
7918    }
7919
7920    /**
7921     * Strips any of a set of characters from the start and end of every String in an array.
7922     * <p>
7923     * Whitespace is defined by {@link Character#isWhitespace(char)}.
7924     * </p>
7925     *
7926     * <p>
7927     * A new array is returned each time, except for length zero. A {@code null} array will return {@code null}. An empty array will return itself. A
7928     * {@code null} array entry will be ignored. A {@code null} stripChars will strip whitespace as defined by {@link Character#isWhitespace(char)}.
7929     * </p>
7930     *
7931     * <pre>
7932     * StringUtils.stripAll(null, *)                = null
7933     * StringUtils.stripAll([], *)                  = []
7934     * StringUtils.stripAll(["abc", "  abc"], null) = ["abc", "abc"]
7935     * StringUtils.stripAll(["abc  ", null], null)  = ["abc", null]
7936     * StringUtils.stripAll(["abc  ", null], "yz")  = ["abc  ", null]
7937     * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]
7938     * </pre>
7939     *
7940     * @param strs       the array to remove characters from, may be null.
7941     * @param stripChars the characters to remove, null treated as whitespace.
7942     * @return the stripped Strings, {@code null} if null array input.
7943     */
7944    public static String[] stripAll(final String[] strs, final String stripChars) {
7945        final int strsLen = ArrayUtils.getLength(strs);
7946        if (strsLen == 0) {
7947            return strs;
7948        }
7949        return ArrayUtils.setAll(new String[strsLen], i -> strip(strs[i], stripChars));
7950    }
7951
7952    /**
7953     * Strips any of a set of characters from the end of a String.
7954     *
7955     * <p>
7956     * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string.
7957     * </p>
7958     *
7959     * <p>
7960     * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}.
7961     * </p>
7962     *
7963     * <pre>
7964     * StringUtils.stripEnd(null, *)          = null
7965     * StringUtils.stripEnd("", *)            = ""
7966     * StringUtils.stripEnd("abc", "")        = "abc"
7967     * StringUtils.stripEnd("abc", null)      = "abc"
7968     * StringUtils.stripEnd("  abc", null)    = "  abc"
7969     * StringUtils.stripEnd("abc  ", null)    = "abc"
7970     * StringUtils.stripEnd(" abc ", null)    = " abc"
7971     * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
7972     * StringUtils.stripEnd("120.00", ".0")   = "12"
7973     * </pre>
7974     *
7975     * @param str        the String to remove characters from, may be null.
7976     * @param stripChars the set of characters to remove, null treated as whitespace.
7977     * @return the stripped String, {@code null} if null String input.
7978     */
7979    public static String stripEnd(final String str, final String stripChars) {
7980        int end = length(str);
7981        if (end == 0) {
7982            return str;
7983        }
7984        if (stripChars == null) {
7985            while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
7986                end--;
7987            }
7988        } else if (stripChars.isEmpty()) {
7989            return str;
7990        } else {
7991            while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
7992                end--;
7993            }
7994        }
7995        return str.substring(0, end);
7996    }
7997
7998    /**
7999     * Strips any of a set of characters from the start of a String.
8000     *
8001     * <p>
8002     * A {@code null} input String returns {@code null}. An empty string ("") input returns the empty string.
8003     * </p>
8004     *
8005     * <p>
8006     * If the stripChars String is {@code null}, whitespace is stripped as defined by {@link Character#isWhitespace(char)}.
8007     * </p>
8008     *
8009     * <pre>
8010     * StringUtils.stripStart(null, *)          = null
8011     * StringUtils.stripStart("", *)            = ""
8012     * StringUtils.stripStart("abc", "")        = "abc"
8013     * StringUtils.stripStart("abc", null)      = "abc"
8014     * StringUtils.stripStart("  abc", null)    = "abc"
8015     * StringUtils.stripStart("abc  ", null)    = "abc  "
8016     * StringUtils.stripStart(" abc ", null)    = "abc "
8017     * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
8018     * </pre>
8019     *
8020     * @param str        the String to remove characters from, may be null.
8021     * @param stripChars the characters to remove, null treated as whitespace.
8022     * @return the stripped String, {@code null} if null String input.
8023     */
8024    public static String stripStart(final String str, final String stripChars) {
8025        final int strLen = length(str);
8026        if (strLen == 0) {
8027            return str;
8028        }
8029        int start = 0;
8030        if (stripChars == null) {
8031            while (start != strLen && Character.isWhitespace(str.charAt(start))) {
8032                start++;
8033            }
8034        } else if (stripChars.isEmpty()) {
8035            return str;
8036        } else {
8037            while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
8038                start++;
8039            }
8040        }
8041        return str.substring(start);
8042    }
8043
8044    /**
8045     * Strips whitespace from the start and end of a String returning an empty String if {@code null} input.
8046     *
8047     * <p>
8048     * This is similar to {@link #trimToEmpty(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}.
8049     * </p>
8050     *
8051     * <pre>
8052     * StringUtils.stripToEmpty(null)     = ""
8053     * StringUtils.stripToEmpty("")       = ""
8054     * StringUtils.stripToEmpty("   ")    = ""
8055     * StringUtils.stripToEmpty("abc")    = "abc"
8056     * StringUtils.stripToEmpty("  abc")  = "abc"
8057     * StringUtils.stripToEmpty("abc  ")  = "abc"
8058     * StringUtils.stripToEmpty(" abc ")  = "abc"
8059     * StringUtils.stripToEmpty(" ab c ") = "ab c"
8060     * </pre>
8061     *
8062     * @param str the String to be stripped, may be null.
8063     * @return the trimmed String, or an empty String if {@code null} input.
8064     * @since 2.0
8065     */
8066    public static String stripToEmpty(final String str) {
8067        return str == null ? EMPTY : strip(str, null);
8068    }
8069
8070    /**
8071     * Strips whitespace from the start and end of a String returning {@code null} if the String is empty ("") after the strip.
8072     *
8073     * <p>
8074     * This is similar to {@link #trimToNull(String)} but removes whitespace. Whitespace is defined by {@link Character#isWhitespace(char)}.
8075     * </p>
8076     *
8077     * <pre>
8078     * StringUtils.stripToNull(null)     = null
8079     * StringUtils.stripToNull("")       = null
8080     * StringUtils.stripToNull("   ")    = null
8081     * StringUtils.stripToNull("abc")    = "abc"
8082     * StringUtils.stripToNull("  abc")  = "abc"
8083     * StringUtils.stripToNull("abc  ")  = "abc"
8084     * StringUtils.stripToNull(" abc ")  = "abc"
8085     * StringUtils.stripToNull(" ab c ") = "ab c"
8086     * </pre>
8087     *
8088     * @param str the String to be stripped, may be null.
8089     * @return the stripped String, {@code null} if whitespace, empty or null String input.
8090     * @since 2.0
8091     */
8092    public static String stripToNull(String str) {
8093        if (str == null) {
8094            return null;
8095        }
8096        str = strip(str, null);
8097        return str.isEmpty() ? null : str; // NOSONARLINT str cannot be null here
8098    }
8099
8100    /**
8101     * Gets a substring from the specified String avoiding exceptions.
8102     *
8103     * <p>
8104     * A negative start position can be used to start {@code n} characters from the end of the String.
8105     * </p>
8106     *
8107     * <p>
8108     * A {@code null} String will return {@code null}. An empty ("") String will return "".
8109     * </p>
8110     *
8111     * <pre>
8112     * StringUtils.substring(null, *)   = null
8113     * StringUtils.substring("", *)     = ""
8114     * StringUtils.substring("abc", 0)  = "abc"
8115     * StringUtils.substring("abc", 2)  = "c"
8116     * StringUtils.substring("abc", 4)  = ""
8117     * StringUtils.substring("abc", -2) = "bc"
8118     * StringUtils.substring("abc", -4) = "abc"
8119     * </pre>
8120     *
8121     * @param str   the String to get the substring from, may be null.
8122     * @param start the position to start from, negative means count back from the end of the String by this many characters.
8123     * @return substring from start position, {@code null} if null String input.
8124     */
8125    public static String substring(final String str, int start) {
8126        if (str == null) {
8127            return null;
8128        }
8129        // handle negatives, which means last n characters
8130        if (start < 0) {
8131            start = str.length() + start; // remember start is negative
8132        }
8133        if (start < 0) {
8134            start = 0;
8135        }
8136        if (start > str.length()) {
8137            return EMPTY;
8138        }
8139        return str.substring(start);
8140    }
8141
8142    /**
8143     * Gets a substring from the specified String avoiding exceptions.
8144     *
8145     * <p>
8146     * A negative start position can be used to start/end {@code n} characters from the end of the String.
8147     * </p>
8148     *
8149     * <p>
8150     * The returned substring starts with the character in the {@code start} position and ends before the {@code end} position. All position counting is
8151     * zero-based -- i.e., to start at the beginning of the string use {@code start = 0}. Negative start and end positions can be used to specify offsets
8152     * relative to the end of the String.
8153     * </p>
8154     *
8155     * <p>
8156     * If {@code start} is not strictly to the left of {@code end}, "" is returned.
8157     * </p>
8158     *
8159     * <pre>
8160     * StringUtils.substring(null, *, *)    = null
8161     * StringUtils.substring("", * ,  *)    = "";
8162     * StringUtils.substring("abc", 0, 2)   = "ab"
8163     * StringUtils.substring("abc", 2, 0)   = ""
8164     * StringUtils.substring("abc", 2, 4)   = "c"
8165     * StringUtils.substring("abc", 4, 6)   = ""
8166     * StringUtils.substring("abc", 2, 2)   = ""
8167     * StringUtils.substring("abc", -2, -1) = "b"
8168     * StringUtils.substring("abc", -4, 2)  = "ab"
8169     * </pre>
8170     *
8171     * @param str   the String to get the substring from, may be null.
8172     * @param start the position to start from, negative means count back from the end of the String by this many characters.
8173     * @param end   the position to end at (exclusive), negative means count back from the end of the String by this many characters.
8174     * @return substring from start position to end position, {@code null} if null String input.
8175     */
8176    public static String substring(final String str, int start, int end) {
8177        if (str == null) {
8178            return null;
8179        }
8180        // handle negatives
8181        if (end < 0) {
8182            end = str.length() + end; // remember end is negative
8183        }
8184        if (start < 0) {
8185            start = str.length() + start; // remember start is negative
8186        }
8187        // check length next
8188        if (end > str.length()) {
8189            end = str.length();
8190        }
8191        // if start is greater than end, return ""
8192        if (start > end) {
8193            return EMPTY;
8194        }
8195        if (start < 0) {
8196            start = 0;
8197        }
8198        if (end < 0) {
8199            end = 0;
8200        }
8201        return str.substring(start, end);
8202    }
8203
8204    /**
8205     * Gets the substring after the first occurrence of a separator. The separator is not returned.
8206     *
8207     * <p>
8208     * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string.
8209     * </p>
8210     *
8211     * <p>
8212     * If nothing is found, the empty string is returned.
8213     * </p>
8214     *
8215     * <pre>
8216     * StringUtils.substringAfter(null, *)      = null
8217     * StringUtils.substringAfter("", *)        = ""
8218     * StringUtils.substringAfter("abc", 'a')   = "bc"
8219     * StringUtils.substringAfter("abcba", 'b') = "cba"
8220     * StringUtils.substringAfter("abc", 'c')   = ""
8221     * StringUtils.substringAfter("abc", 'd')   = ""
8222     * StringUtils.substringAfter(" abc", 32)   = "abc"
8223     * </pre>
8224     *
8225     * @param str       the String to get a substring from, may be null.
8226     * @param find the character (Unicode code point) to find.
8227     * @return the substring after the first occurrence of the specified character, {@code null} if null String input.
8228     * @since 3.11
8229     */
8230    public static String substringAfter(final String str, final int find) {
8231        if (isEmpty(str)) {
8232            return str;
8233        }
8234        final int pos = str.indexOf(find);
8235        if (pos == INDEX_NOT_FOUND) {
8236            return EMPTY;
8237        }
8238        return str.substring(pos + 1);
8239    }
8240
8241    /**
8242     * Gets the substring after the first occurrence of a separator. The separator is not returned.
8243     *
8244     * <p>
8245     * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A {@code null} separator will return the
8246     * empty string if the input string is not {@code null}.
8247     * </p>
8248     *
8249     * <p>
8250     * If nothing is found, the empty string is returned.
8251     * </p>
8252     *
8253     * <pre>
8254     * StringUtils.substringAfter(null, *)      = null
8255     * StringUtils.substringAfter("", *)        = ""
8256     * StringUtils.substringAfter(*, null)      = ""
8257     * StringUtils.substringAfter("abc", "a")   = "bc"
8258     * StringUtils.substringAfter("abcba", "b") = "cba"
8259     * StringUtils.substringAfter("abc", "c")   = ""
8260     * StringUtils.substringAfter("abc", "d")   = ""
8261     * StringUtils.substringAfter("abc", "")    = "abc"
8262     * </pre>
8263     *
8264     * @param str       the String to get a substring from, may be null.
8265     * @param find the String to find, may be null.
8266     * @return the substring after the first occurrence of the specified string, {@code null} if null String input.
8267     * @since 2.0
8268     */
8269    public static String substringAfter(final String str, final String find) {
8270        if (isEmpty(str)) {
8271            return str;
8272        }
8273        if (find == null) {
8274            return EMPTY;
8275        }
8276        final int pos = str.indexOf(find);
8277        if (pos == INDEX_NOT_FOUND) {
8278            return EMPTY;
8279        }
8280        return str.substring(pos + find.length());
8281    }
8282
8283    /**
8284     * Gets the substring after the last occurrence of a separator. The separator is not returned.
8285     *
8286     * <p>
8287     * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string.
8288     * </p>
8289     *
8290     * <p>
8291     * If nothing is found, the empty string is returned.
8292     * </p>
8293     *
8294     * <pre>
8295     * StringUtils.substringAfterLast(null, *)      = null
8296     * StringUtils.substringAfterLast("", *)        = ""
8297     * StringUtils.substringAfterLast("abc", 'a')   = "bc"
8298     * StringUtils.substringAfterLast(" bc", 32)    = "bc"
8299     * StringUtils.substringAfterLast("abcba", 'b') = "a"
8300     * StringUtils.substringAfterLast("abc", 'c')   = ""
8301     * StringUtils.substringAfterLast("a", 'a')     = ""
8302     * StringUtils.substringAfterLast("a", 'z')     = ""
8303     * </pre>
8304     *
8305     * @param str       the String to get a substring from, may be null.
8306     * @param find the character (Unicode code point) to find.
8307     * @return the substring after the last occurrence of the specified character, {@code null} if null String input.
8308     * @since 3.11
8309     */
8310    public static String substringAfterLast(final String str, final int find) {
8311        if (isEmpty(str)) {
8312            return str;
8313        }
8314        final int pos = str.lastIndexOf(find);
8315        if (pos == INDEX_NOT_FOUND || pos == str.length() - 1) {
8316            return EMPTY;
8317        }
8318        return str.substring(pos + 1);
8319    }
8320
8321    /**
8322     * Gets the substring after the last occurrence of a separator. The separator is not returned.
8323     *
8324     * <p>
8325     * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. An empty or {@code null} separator will
8326     * return the empty string if the input string is not {@code null}.
8327     * </p>
8328     *
8329     * <p>
8330     * If nothing is found, the empty string is returned.
8331     * </p>
8332     *
8333     * <pre>
8334     * StringUtils.substringAfterLast(null, *)      = null
8335     * StringUtils.substringAfterLast("", *)        = ""
8336     * StringUtils.substringAfterLast(*, "")        = ""
8337     * StringUtils.substringAfterLast(*, null)      = ""
8338     * StringUtils.substringAfterLast("abc", "a")   = "bc"
8339     * StringUtils.substringAfterLast("abcba", "b") = "a"
8340     * StringUtils.substringAfterLast("abc", "c")   = ""
8341     * StringUtils.substringAfterLast("a", "a")     = ""
8342     * StringUtils.substringAfterLast("a", "z")     = ""
8343     * </pre>
8344     *
8345     * @param str       the String to get a substring from, may be null.
8346     * @param find the String to find, may be null.
8347     * @return the substring after the last occurrence of the specified string, {@code null} if null String input.
8348     * @since 2.0
8349     */
8350    public static String substringAfterLast(final String str, final String find) {
8351        if (isEmpty(str)) {
8352            return str;
8353        }
8354        if (isEmpty(find)) {
8355            return EMPTY;
8356        }
8357        final int pos = str.lastIndexOf(find);
8358        if (pos == INDEX_NOT_FOUND || pos == str.length() - find.length()) {
8359            return EMPTY;
8360        }
8361        return str.substring(pos + find.length());
8362    }
8363
8364    /**
8365     * Gets the substring before the first occurrence of a separator. The separator is not returned.
8366     *
8367     * <p>
8368     * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string.
8369     * </p>
8370     *
8371     * <p>
8372     * If nothing is found, the string input is returned.
8373     * </p>
8374     *
8375     * <pre>
8376     * StringUtils.substringBefore(null, *)      = null
8377     * StringUtils.substringBefore("", *)        = ""
8378     * StringUtils.substringBefore("abc", 'a')   = ""
8379     * StringUtils.substringBefore("abcba", 'b') = "a"
8380     * StringUtils.substringBefore("abc", 'c')   = "ab"
8381     * StringUtils.substringBefore("abc", 'd')   = "abc"
8382     * </pre>
8383     *
8384     * @param str       the String to get a substring from, may be null.
8385     * @param find the character (Unicode code point) to find.
8386     * @return the substring before the first occurrence of the specified character, {@code null} if null String input.
8387     * @since 3.12.0
8388     */
8389    public static String substringBefore(final String str, final int find) {
8390        if (isEmpty(str)) {
8391            return str;
8392        }
8393        final int pos = str.indexOf(find);
8394        if (pos == INDEX_NOT_FOUND) {
8395            return str;
8396        }
8397        return str.substring(0, pos);
8398    }
8399
8400    /**
8401     * Gets the substring before the first occurrence of a separator. The separator is not returned.
8402     *
8403     * <p>
8404     * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. A {@code null} separator will return the
8405     * input string.
8406     * </p>
8407     *
8408     * <p>
8409     * If nothing is found, the string input is returned.
8410     * </p>
8411     *
8412     * <pre>
8413     * StringUtils.substringBefore(null, *)      = null
8414     * StringUtils.substringBefore("", *)        = ""
8415     * StringUtils.substringBefore("abc", "a")   = ""
8416     * StringUtils.substringBefore("abcba", "b") = "a"
8417     * StringUtils.substringBefore("abc", "c")   = "ab"
8418     * StringUtils.substringBefore("abc", "d")   = "abc"
8419     * StringUtils.substringBefore("abc", "")    = ""
8420     * StringUtils.substringBefore("abc", null)  = "abc"
8421     * </pre>
8422     *
8423     * @param str       the String to get a substring from, may be null.
8424     * @param find the String to find, may be null.
8425     * @return the substring before the first occurrence of the specified string, {@code null} if null String input.
8426     * @since 2.0
8427     */
8428    public static String substringBefore(final String str, final String find) {
8429        if (isEmpty(str) || find == null) {
8430            return str;
8431        }
8432        if (find.isEmpty()) {
8433            return EMPTY;
8434        }
8435        final int pos = str.indexOf(find);
8436        if (pos == INDEX_NOT_FOUND) {
8437            return str;
8438        }
8439        return str.substring(0, pos);
8440    }
8441
8442    /**
8443     * Gets the substring before the last occurrence of a separator. The separator is not returned.
8444     *
8445     * <p>
8446     * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string. An empty or {@code null} separator will
8447     * return the input string.
8448     * </p>
8449     *
8450     * <p>
8451     * If nothing is found, the string input is returned.
8452     * </p>
8453     *
8454     * <pre>
8455     * StringUtils.substringBeforeLast(null, *)      = null
8456     * StringUtils.substringBeforeLast("", *)        = ""
8457     * StringUtils.substringBeforeLast("abcba", "b") = "abc"
8458     * StringUtils.substringBeforeLast("abc", "c")   = "ab"
8459     * StringUtils.substringBeforeLast("a", "a")     = ""
8460     * StringUtils.substringBeforeLast("a", "z")     = "a"
8461     * StringUtils.substringBeforeLast("a", null)    = "a"
8462     * StringUtils.substringBeforeLast("a", "")      = "a"
8463     * </pre>
8464     *
8465     * @param str       the String to get a substring from, may be null.
8466     * @param find the String to find, may be null.
8467     * @return the substring before the last occurrence of the specified string, {@code null} if null String input.
8468     * @since 2.0
8469     */
8470    public static String substringBeforeLast(final String str, final String find) {
8471        if (isEmpty(str) || isEmpty(find)) {
8472            return str;
8473        }
8474        final int pos = str.lastIndexOf(find);
8475        if (pos == INDEX_NOT_FOUND) {
8476            return str;
8477        }
8478        return str.substring(0, pos);
8479    }
8480
8481    /**
8482     * Gets the String that is nested in between two instances of the same String.
8483     *
8484     * <p>
8485     * A {@code null} input String returns {@code null}. A {@code null} tag returns {@code null}.
8486     * </p>
8487     *
8488     * <pre>
8489     * StringUtils.substringBetween(null, *)            = null
8490     * StringUtils.substringBetween("", "")             = ""
8491     * StringUtils.substringBetween("", "tag")          = null
8492     * StringUtils.substringBetween("tagabctag", null)  = null
8493     * StringUtils.substringBetween("tagabctag", "")    = ""
8494     * StringUtils.substringBetween("tagabctag", "tag") = "abc"
8495     * </pre>
8496     *
8497     * @param str the String containing the substring, may be null.
8498     * @param tag the String before and after the substring, may be null.
8499     * @return the substring, {@code null} if no match.
8500     * @since 2.0
8501     */
8502    public static String substringBetween(final String str, final String tag) {
8503        return substringBetween(str, tag, tag);
8504    }
8505
8506    /**
8507     * Gets the String that is nested in between two Strings. Only the first match is returned.
8508     *
8509     * <p>
8510     * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open and close returns an
8511     * empty string.
8512     * </p>
8513     *
8514     * <pre>
8515     * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
8516     * StringUtils.substringBetween(null, *, *)          = null
8517     * StringUtils.substringBetween(*, null, *)          = null
8518     * StringUtils.substringBetween(*, *, null)          = null
8519     * StringUtils.substringBetween("", "", "")          = ""
8520     * StringUtils.substringBetween("", "", "]")         = null
8521     * StringUtils.substringBetween("", "[", "]")        = null
8522     * StringUtils.substringBetween("yabcz", "", "")     = ""
8523     * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
8524     * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
8525     * </pre>
8526     *
8527     * @param str   the String containing the substring, may be null.
8528     * @param open  the String before the substring, may be null.
8529     * @param close the String after the substring, may be null.
8530     * @return the substring, {@code null} if no match.
8531     * @since 2.0
8532     */
8533    public static String substringBetween(final String str, final String open, final String close) {
8534        if (!ObjectUtils.allNotNull(str, open, close)) {
8535            return null;
8536        }
8537        final int start = str.indexOf(open);
8538        if (start != INDEX_NOT_FOUND) {
8539            final int end = str.indexOf(close, start + open.length());
8540            if (end != INDEX_NOT_FOUND) {
8541                return str.substring(start + open.length(), end);
8542            }
8543        }
8544        return null;
8545    }
8546
8547    /**
8548     * Searches a String for substrings delimited by a start and end tag, returning all matching substrings in an array.
8549     *
8550     * <p>
8551     * A {@code null} input String returns {@code null}. A {@code null} open/close returns {@code null} (no match). An empty ("") open/close returns
8552     * {@code null} (no match).
8553     * </p>
8554     *
8555     * <pre>
8556     * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
8557     * StringUtils.substringsBetween(null, *, *)            = null
8558     * StringUtils.substringsBetween(*, null, *)            = null
8559     * StringUtils.substringsBetween(*, *, null)            = null
8560     * StringUtils.substringsBetween("", "[", "]")          = []
8561     * </pre>
8562     *
8563     * @param str   the String containing the substrings, null returns null, empty returns empty.
8564     * @param open  the String identifying the start of the substring, empty returns null.
8565     * @param close the String identifying the end of the substring, empty returns null.
8566     * @return a String Array of substrings, or {@code null} if no match.
8567     * @since 2.3
8568     */
8569    public static String[] substringsBetween(final String str, final String open, final String close) {
8570        if (str == null || isEmpty(open) || isEmpty(close)) {
8571            return null;
8572        }
8573        final int strLen = str.length();
8574        if (strLen == 0) {
8575            return ArrayUtils.EMPTY_STRING_ARRAY;
8576        }
8577        final int closeLen = close.length();
8578        final int openLen = open.length();
8579        final List<String> list = new ArrayList<>();
8580        int pos = 0;
8581        while (pos < strLen - closeLen) {
8582            int start = str.indexOf(open, pos);
8583            if (start < 0) {
8584                break;
8585            }
8586            start += openLen;
8587            final int end = str.indexOf(close, start);
8588            if (end < 0) {
8589                break;
8590            }
8591            list.add(str.substring(start, end));
8592            pos = end + closeLen;
8593        }
8594        if (list.isEmpty()) {
8595            return null;
8596        }
8597        return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
8598    }
8599
8600    /**
8601     * Swaps the case of a String changing upper and title case to lower case, and lower case to upper case.
8602     *
8603     * <ul>
8604     * <li>Upper case character converts to Lower case</li>
8605     * <li>Title case character converts to Lower case</li>
8606     * <li>Lower case character converts to Upper case</li>
8607     * </ul>
8608     *
8609     * <p>
8610     * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#swapCase(String)}. A {@code null} input String returns {@code null}.
8611     * </p>
8612     *
8613     * <pre>
8614     * StringUtils.swapCase(null)                 = null
8615     * StringUtils.swapCase("")                   = ""
8616     * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
8617     * </pre>
8618     *
8619     * <p>
8620     * NOTE: This method changed in Lang version 2.0. It no longer performs a word based algorithm. If you only use ASCII, you will notice no change. That
8621     * functionality is available in org.apache.commons.lang3.text.WordUtils.
8622     * </p>
8623     *
8624     * @param str the String to swap case, may be null.
8625     * @return the changed String, {@code null} if null String input.
8626     */
8627    public static String swapCase(final String str) {
8628        if (isEmpty(str)) {
8629            return str;
8630        }
8631        final int strLen = str.length();
8632        final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
8633        int outOffset = 0;
8634        for (int i = 0; i < strLen;) {
8635            final int oldCodepoint = str.codePointAt(i);
8636            final int newCodePoint;
8637            if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) {
8638                newCodePoint = Character.toLowerCase(oldCodepoint);
8639            } else if (Character.isLowerCase(oldCodepoint)) {
8640                newCodePoint = Character.toUpperCase(oldCodepoint);
8641            } else {
8642                newCodePoint = oldCodepoint;
8643            }
8644            newCodePoints[outOffset++] = newCodePoint;
8645            i += Character.charCount(newCodePoint);
8646        }
8647        return new String(newCodePoints, 0, outOffset);
8648    }
8649
8650    /**
8651     * Converts a {@link CharSequence} into an array of code points.
8652     *
8653     * <p>
8654     * Valid pairs of surrogate code units will be converted into a single supplementary code point. Isolated surrogate code units (i.e. a high surrogate not
8655     * followed by a low surrogate or a low surrogate not preceded by a high surrogate) will be returned as-is.
8656     * </p>
8657     *
8658     * <pre>
8659     * StringUtils.toCodePoints(null)   =  null
8660     * StringUtils.toCodePoints("")     =  []  // empty array
8661     * </pre>
8662     *
8663     * @param cs the character sequence to convert.
8664     * @return an array of code points.
8665     * @since 3.6
8666     */
8667    public static int[] toCodePoints(final CharSequence cs) {
8668        if (cs == null) {
8669            return null;
8670        }
8671        if (cs.length() == 0) {
8672            return ArrayUtils.EMPTY_INT_ARRAY;
8673        }
8674        return cs.toString().codePoints().toArray();
8675    }
8676
8677    /**
8678     * Converts a {@code byte[]} to a String using the specified character encoding.
8679     *
8680     * @param bytes   the byte array to read from.
8681     * @param charset the encoding to use, if null then use the platform default.
8682     * @return a new String.
8683     * @throws NullPointerException if {@code bytes} is null
8684     * @since 3.2
8685     * @since 3.3 No longer throws {@link UnsupportedEncodingException}.
8686     */
8687    public static String toEncodedString(final byte[] bytes, final Charset charset) {
8688        return new String(bytes, Charsets.toCharset(charset));
8689    }
8690
8691    /**
8692     * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner.
8693     *
8694     * @param source A source String or null.
8695     * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null.
8696     * @since 3.10
8697     */
8698    public static String toRootLowerCase(final String source) {
8699        return source == null ? null : source.toLowerCase(Locale.ROOT);
8700    }
8701
8702    /**
8703     * Converts the given source String as an upper-case using the {@link Locale#ROOT} locale in a null-safe manner.
8704     *
8705     * @param source A source String or null.
8706     * @return the given source String as an upper-case using the {@link Locale#ROOT} locale or null.
8707     * @since 3.10
8708     */
8709    public static String toRootUpperCase(final String source) {
8710        return source == null ? null : source.toUpperCase(Locale.ROOT);
8711    }
8712
8713    /**
8714     * Converts a {@code byte[]} to a String using the specified character encoding.
8715     *
8716     * @param bytes       the byte array to read from.
8717     * @param charsetName the encoding to use, if null then use the platform default.
8718     * @return a new String.
8719     * @throws NullPointerException if the input is null.
8720     * @since 3.1
8721     * @deprecated Use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code.
8722     */
8723    @Deprecated
8724    public static String toString(final byte[] bytes, final String charsetName) {
8725        return new String(bytes, Charsets.toCharset(charsetName));
8726    }
8727
8728    /**
8729     * Removes control characters (char &lt;= 32) from both ends of this String, handling {@code null} by returning {@code null}.
8730     *
8731     * <p>
8732     * The String is trimmed using {@link String#trim()}. Trim removes start and end characters &lt;= 32. To strip whitespace use {@link #strip(String)}.
8733     * </p>
8734     *
8735     * <p>
8736     * To trim your choice of characters, use the {@link #strip(String, String)} methods.
8737     * </p>
8738     *
8739     * <pre>
8740     * StringUtils.trim(null)          = null
8741     * StringUtils.trim("")            = ""
8742     * StringUtils.trim("     ")       = ""
8743     * StringUtils.trim("abc")         = "abc"
8744     * StringUtils.trim("    abc    ") = "abc"
8745     * </pre>
8746     *
8747     * @param str the String to be trimmed, may be null.
8748     * @return the trimmed string, {@code null} if null String input.
8749     */
8750    public static String trim(final String str) {
8751        return str == null ? null : str.trim();
8752    }
8753
8754    /**
8755     * Removes control characters (char &lt;= 32) from both ends of this String returning an empty String ("") if the String is empty ("") after the trim or if
8756     * it is {@code null}.
8757     *
8758     * <p>
8759     * The String is trimmed using {@link String#trim()}. Trim removes start and end characters &lt;= 32. To strip whitespace use {@link #stripToEmpty(String)}.
8760     * </p>
8761     *
8762     * <pre>
8763     * StringUtils.trimToEmpty(null)          = ""
8764     * StringUtils.trimToEmpty("")            = ""
8765     * StringUtils.trimToEmpty("     ")       = ""
8766     * StringUtils.trimToEmpty("abc")         = "abc"
8767     * StringUtils.trimToEmpty("    abc    ") = "abc"
8768     * </pre>
8769     *
8770     * @param str the String to be trimmed, may be null.
8771     * @return the trimmed String, or an empty String if {@code null} input.
8772     * @since 2.0
8773     */
8774    public static String trimToEmpty(final String str) {
8775        return str == null ? EMPTY : str.trim();
8776    }
8777
8778    /**
8779     * Removes control characters (char &lt;= 32) from both ends of this String returning {@code null} if the String is empty ("") after the trim or if it is
8780     * {@code null}.
8781     *
8782     * <p>
8783     * The String is trimmed using {@link String#trim()}. Trim removes start and end characters &lt;= 32. To strip whitespace use {@link #stripToNull(String)}.
8784     * </p>
8785     *
8786     * <pre>
8787     * StringUtils.trimToNull(null)          = null
8788     * StringUtils.trimToNull("")            = null
8789     * StringUtils.trimToNull("     ")       = null
8790     * StringUtils.trimToNull("abc")         = "abc"
8791     * StringUtils.trimToNull("    abc    ") = "abc"
8792     * </pre>
8793     *
8794     * @param str the String to be trimmed, may be null.
8795     * @return the trimmed String, {@code null} if only chars &lt;= 32, empty or null String input.
8796     * @since 2.0
8797     */
8798    public static String trimToNull(final String str) {
8799        final String ts = trim(str);
8800        return isEmpty(ts) ? null : ts;
8801    }
8802
8803    /**
8804     * Truncates a String. This will turn "Now is the time for all good men" into "Now is the time for".
8805     *
8806     * <p>
8807     * Specifically:
8808     * </p>
8809     * <ul>
8810     * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li>
8811     * <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li>
8812     * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li>
8813     * <li>In no case will it return a String of length greater than {@code maxWidth}.</li>
8814     * </ul>
8815     *
8816     * <pre>
8817     * StringUtils.truncate(null, 0)       = null
8818     * StringUtils.truncate(null, 2)       = null
8819     * StringUtils.truncate("", 4)         = ""
8820     * StringUtils.truncate("abcdefg", 4)  = "abcd"
8821     * StringUtils.truncate("abcdefg", 6)  = "abcdef"
8822     * StringUtils.truncate("abcdefg", 7)  = "abcdefg"
8823     * StringUtils.truncate("abcdefg", 8)  = "abcdefg"
8824     * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException
8825     * </pre>
8826     *
8827     * @param str      the String to truncate, may be null.
8828     * @param maxWidth maximum length of result String, must be non-negative.
8829     * @return truncated String, {@code null} if null String input.
8830     * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0}.
8831     * @since 3.5
8832     */
8833    public static String truncate(final String str, final int maxWidth) {
8834        return truncate(str, 0, maxWidth);
8835    }
8836
8837    /**
8838     * Truncates a String. This will turn "Now is the time for all good men" into "is the time for all".
8839     *
8840     * <p>
8841     * Works like {@code truncate(String, int)}, but allows you to specify a "left edge" offset.
8842     * </p>
8843     *
8844     * <p>
8845     * Specifically:
8846     * </p>
8847     * <ul>
8848     * <li>If {@code str} is less than {@code maxWidth} characters long, return it.</li>
8849     * <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li>
8850     * <li>If {@code maxWidth} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li>
8851     * <li>If {@code offset} is less than {@code 0}, throw an {@link IllegalArgumentException}.</li>
8852     * <li>In no case will it return a String of length greater than {@code maxWidth}.</li>
8853     * </ul>
8854     *
8855     * <pre>
8856     * StringUtils.truncate(null, 0, 0) = null
8857     * StringUtils.truncate(null, 2, 4) = null
8858     * StringUtils.truncate("", 0, 10) = ""
8859     * StringUtils.truncate("", 2, 10) = ""
8860     * StringUtils.truncate("abcdefghij", 0, 3) = "abc"
8861     * StringUtils.truncate("abcdefghij", 5, 6) = "fghij"
8862     * StringUtils.truncate("raspberry peach", 10, 15) = "peach"
8863     * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij"
8864     * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException
8865     * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException
8866     * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException
8867     * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno"
8868     * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk"
8869     * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl"
8870     * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm"
8871     * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn"
8872     * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno"
8873     * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij"
8874     * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh"
8875     * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm"
8876     * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno"
8877     * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n"
8878     * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no"
8879     * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o"
8880     * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o"
8881     * StringUtils.truncate("abcdefghijklmno", 15, 1) = ""
8882     * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = ""
8883     * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = ""
8884     * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException
8885     * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException
8886     * </pre>
8887     *
8888     * @param str      the String to truncate, may be null.
8889     * @param offset   left edge of source String.
8890     * @param maxWidth maximum length of result String, must be non-negative.
8891     * @return truncated String, {@code null} if null String input.
8892     * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0}.
8893     * @since 3.5
8894     */
8895    public static String truncate(final String str, final int offset, final int maxWidth) {
8896        if (offset < 0) {
8897            throw new IllegalArgumentException("offset cannot be negative");
8898        }
8899        if (maxWidth < 0) {
8900            throw new IllegalArgumentException("maxWidth cannot be negative");
8901        }
8902        if (str == null) {
8903            return null;
8904        }
8905        final int len = str.length();
8906        final int start = Math.min(offset, len);
8907        final int end = offset > len - maxWidth ? len : offset + maxWidth;
8908        return str.substring(start, Math.min(end, len));
8909    }
8910
8911    /**
8912     * Uncapitalizes a String, changing the first character to lower case as per {@link Character#toLowerCase(int)}. No other characters are changed.
8913     *
8914     * <p>
8915     * For a word based algorithm, see {@link org.apache.commons.text.WordUtils#uncapitalize(String)}. A {@code null} input String returns {@code null}.
8916     * </p>
8917     *
8918     * <pre>
8919     * StringUtils.uncapitalize(null)  = null
8920     * StringUtils.uncapitalize("")    = ""
8921     * StringUtils.uncapitalize("cat") = "cat"
8922     * StringUtils.uncapitalize("Cat") = "cat"
8923     * StringUtils.uncapitalize("CAT") = "cAT"
8924     * </pre>
8925     *
8926     * @param str the String to uncapitalize, may be null.
8927     * @return the uncapitalized String, {@code null} if null String input.
8928     * @see org.apache.commons.text.WordUtils#uncapitalize(String)
8929     * @see #capitalize(String)
8930     * @since 2.0
8931     */
8932    public static String uncapitalize(final String str) {
8933        final int strLen = length(str);
8934        if (strLen == 0) {
8935            return str;
8936        }
8937        final int firstCodePoint = str.codePointAt(0);
8938        final int newCodePoint = Character.toLowerCase(firstCodePoint);
8939        if (firstCodePoint == newCodePoint) {
8940            // already uncapitalized
8941            return str;
8942        }
8943        final int[] newCodePoints = str.codePoints().toArray();
8944        newCodePoints[0] = newCodePoint; // copy the first code point
8945        return new String(newCodePoints, 0, newCodePoints.length);
8946    }
8947
8948    /**
8949     * Unwraps a given string from a character.
8950     *
8951     * <pre>
8952     * StringUtils.unwrap(null, null)         = null
8953     * StringUtils.unwrap(null, '\0')         = null
8954     * StringUtils.unwrap(null, '1')          = null
8955     * StringUtils.unwrap("a", 'a')           = "a"
8956     * StringUtils.unwrap("aa", 'a')           = ""
8957     * StringUtils.unwrap("\'abc\'", '\'')    = "abc"
8958     * StringUtils.unwrap("AABabcBAA", 'A')   = "ABabcBA"
8959     * StringUtils.unwrap("A", '#')           = "A"
8960     * StringUtils.unwrap("#A", '#')          = "#A"
8961     * StringUtils.unwrap("A#", '#')          = "A#"
8962     * </pre>
8963     *
8964     * @param str      the String to be unwrapped, can be null.
8965     * @param wrapChar the character used to unwrap.
8966     * @return unwrapped String or the original string if it is not quoted properly with the wrapChar.
8967     * @since 3.6
8968     */
8969    public static String unwrap(final String str, final char wrapChar) {
8970        if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) {
8971            return str;
8972        }
8973        if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) {
8974            final int startIndex = 0;
8975            final int endIndex = str.length() - 1;
8976            return str.substring(startIndex + 1, endIndex);
8977        }
8978        return str;
8979    }
8980
8981    /**
8982     * Unwraps a given string from another string.
8983     *
8984     * <pre>
8985     * StringUtils.unwrap(null, null)         = null
8986     * StringUtils.unwrap(null, "")           = null
8987     * StringUtils.unwrap(null, "1")          = null
8988     * StringUtils.unwrap("a", "a")           = "a"
8989     * StringUtils.unwrap("aa", "a")          = ""
8990     * StringUtils.unwrap("\'abc\'", "\'")    = "abc"
8991     * StringUtils.unwrap("\"abc\"", "\"")    = "abc"
8992     * StringUtils.unwrap("AABabcBAA", "AA")  = "BabcB"
8993     * StringUtils.unwrap("A", "#")           = "A"
8994     * StringUtils.unwrap("#A", "#")          = "#A"
8995     * StringUtils.unwrap("A#", "#")          = "A#"
8996     * </pre>
8997     *
8998     * @param str       the String to be unwrapped, can be null.
8999     * @param wrapToken the String used to unwrap.
9000     * @return unwrapped String or the original string if it is not quoted properly with the wrapToken.
9001     * @since 3.6
9002     */
9003    public static String unwrap(final String str, final String wrapToken) {
9004        if (isEmpty(str) || isEmpty(wrapToken) || str.length() < 2 * wrapToken.length()) {
9005            return str;
9006        }
9007        if (Strings.CS.startsWith(str, wrapToken) && Strings.CS.endsWith(str, wrapToken)) {
9008            return str.substring(wrapToken.length(), str.lastIndexOf(wrapToken));
9009        }
9010        return str;
9011    }
9012
9013    /**
9014     * Converts a String to upper case as per {@link String#toUpperCase()}.
9015     *
9016     * <p>
9017     * A {@code null} input String returns {@code null}.
9018     * </p>
9019     *
9020     * <pre>
9021     * StringUtils.upperCase(null)  = null
9022     * StringUtils.upperCase("")    = ""
9023     * StringUtils.upperCase("aBc") = "ABC"
9024     * </pre>
9025     *
9026     * <p>
9027     * <strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()}, the result of this method is affected by the current locale.
9028     * For platform-independent case transformations, the method {@link #upperCase(String, Locale)} should be used with a specific locale (e.g.
9029     * {@link Locale#ENGLISH}).
9030     * </p>
9031     *
9032     * @param str the String to upper case, may be null.
9033     * @return the upper-cased String, {@code null} if null String input.
9034     */
9035    public static String upperCase(final String str) {
9036        if (str == null) {
9037            return null;
9038        }
9039        return str.toUpperCase();
9040    }
9041
9042    /**
9043     * Converts a String to upper case as per {@link String#toUpperCase(Locale)}.
9044     *
9045     * <p>
9046     * A {@code null} input String returns {@code null}.
9047     * </p>
9048     *
9049     * <pre>
9050     * StringUtils.upperCase(null, Locale.ENGLISH)  = null
9051     * StringUtils.upperCase("", Locale.ENGLISH)    = ""
9052     * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
9053     * </pre>
9054     *
9055     * @param str    the String to upper case, may be null.
9056     * @param locale the locale that defines the case transformation rules, must not be null.
9057     * @return the upper-cased String, {@code null} if null String input.
9058     * @since 2.5
9059     */
9060    public static String upperCase(final String str, final Locale locale) {
9061        if (str == null) {
9062            return null;
9063        }
9064        return str.toUpperCase(LocaleUtils.toLocale(locale));
9065    }
9066
9067    /**
9068     * Returns the string representation of the {@code char} array or null.
9069     *
9070     * @param value the character array.
9071     * @return a String or null.
9072     * @see String#valueOf(char[])
9073     * @since 3.9
9074     */
9075    public static String valueOf(final char[] value) {
9076        return value == null ? null : String.valueOf(value);
9077    }
9078
9079    /**
9080     * Wraps a string with a char.
9081     *
9082     * <pre>
9083     * StringUtils.wrap(null, *)        = null
9084     * StringUtils.wrap("", *)          = ""
9085     * StringUtils.wrap("ab", '\0')     = "ab"
9086     * StringUtils.wrap("ab", 'x')      = "xabx"
9087     * StringUtils.wrap("ab", '\'')     = "'ab'"
9088     * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\""
9089     * </pre>
9090     *
9091     * @param str      the string to be wrapped, may be {@code null}.
9092     * @param wrapWith the char that will wrap {@code str}.
9093     * @return the wrapped string, or {@code null} if {@code str == null}.
9094     * @since 3.4
9095     */
9096    public static String wrap(final String str, final char wrapWith) {
9097        if (isEmpty(str) || wrapWith == CharUtils.NUL) {
9098            return str;
9099        }
9100        return wrapWith + str + wrapWith;
9101    }
9102
9103    /**
9104     * Wraps a String with another String.
9105     *
9106     * <p>
9107     * A {@code null} input String returns {@code null}.
9108     * </p>
9109     *
9110     * <pre>
9111     * StringUtils.wrap(null, *)         = null
9112     * StringUtils.wrap("", *)           = ""
9113     * StringUtils.wrap("ab", null)      = "ab"
9114     * StringUtils.wrap("ab", "x")       = "xabx"
9115     * StringUtils.wrap("ab", "\"")      = "\"ab\""
9116     * StringUtils.wrap("\"ab\"", "\"")  = "\"\"ab\"\""
9117     * StringUtils.wrap("ab", "'")       = "'ab'"
9118     * StringUtils.wrap("'abcd'", "'")   = "''abcd''"
9119     * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
9120     * StringUtils.wrap("'abcd'", "\"")  = "\"'abcd'\""
9121     * </pre>
9122     *
9123     * @param str      the String to be wrapper, may be null.
9124     * @param wrapWith the String that will wrap str.
9125     * @return wrapped String, {@code null} if null String input.
9126     * @since 3.4
9127     */
9128    public static String wrap(final String str, final String wrapWith) {
9129        if (isEmpty(str) || isEmpty(wrapWith)) {
9130            return str;
9131        }
9132        return wrapWith.concat(str).concat(wrapWith);
9133    }
9134
9135    /**
9136     * Wraps a string with a char if that char is missing from the start or end of the given string.
9137     *
9138     * <p>
9139     * A new {@link String} will not be created if {@code str} is already wrapped.
9140     * </p>
9141     *
9142     * <pre>
9143     * StringUtils.wrapIfMissing(null, *)        = null
9144     * StringUtils.wrapIfMissing("", *)          = ""
9145     * StringUtils.wrapIfMissing("ab", '\0')     = "ab"
9146     * StringUtils.wrapIfMissing("ab", 'x')      = "xabx"
9147     * StringUtils.wrapIfMissing("ab", '\'')     = "'ab'"
9148     * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\""
9149     * StringUtils.wrapIfMissing("/", '/')  = "/"
9150     * StringUtils.wrapIfMissing("a/b/c", '/')  = "/a/b/c/"
9151     * StringUtils.wrapIfMissing("/a/b/c", '/')  = "/a/b/c/"
9152     * StringUtils.wrapIfMissing("a/b/c/", '/')  = "/a/b/c/"
9153     * </pre>
9154     *
9155     * @param str      the string to be wrapped, may be {@code null}.
9156     * @param wrapWith the char that will wrap {@code str}.
9157     * @return the wrapped string, or {@code null} if {@code str == null}.
9158     * @since 3.5
9159     */
9160    public static String wrapIfMissing(final String str, final char wrapWith) {
9161        if (isEmpty(str) || wrapWith == CharUtils.NUL) {
9162            return str;
9163        }
9164        final boolean wrapStart = str.charAt(0) != wrapWith;
9165        final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith;
9166        if (!wrapStart && !wrapEnd) {
9167            return str;
9168        }
9169        final StringBuilder builder = new StringBuilder(str.length() + 2);
9170        if (wrapStart) {
9171            builder.append(wrapWith);
9172        }
9173        builder.append(str);
9174        if (wrapEnd) {
9175            builder.append(wrapWith);
9176        }
9177        return builder.toString();
9178    }
9179
9180    /**
9181     * Wraps a string with a string if that string is missing from the start or end of the given string.
9182     *
9183     * <p>
9184     * A new {@link String} will not be created if {@code str} is already wrapped.
9185     * </p>
9186     *
9187     * <pre>
9188     * StringUtils.wrapIfMissing(null, *)         = null
9189     * StringUtils.wrapIfMissing("", *)           = ""
9190     * StringUtils.wrapIfMissing("ab", null)      = "ab"
9191     * StringUtils.wrapIfMissing("ab", "x")       = "xabx"
9192     * StringUtils.wrapIfMissing("ab", "\"")      = "\"ab\""
9193     * StringUtils.wrapIfMissing("\"ab\"", "\"")  = "\"ab\""
9194     * StringUtils.wrapIfMissing("ab", "'")       = "'ab'"
9195     * StringUtils.wrapIfMissing("'abcd'", "'")   = "'abcd'"
9196     * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'"
9197     * StringUtils.wrapIfMissing("'abcd'", "\"")  = "\"'abcd'\""
9198     * StringUtils.wrapIfMissing("/", "/")  = "/"
9199     * StringUtils.wrapIfMissing("a/b/c", "/")  = "/a/b/c/"
9200     * StringUtils.wrapIfMissing("/a/b/c", "/")  = "/a/b/c/"
9201     * StringUtils.wrapIfMissing("a/b/c/", "/")  = "/a/b/c/"
9202     * </pre>
9203     *
9204     * @param str      the string to be wrapped, may be {@code null}.
9205     * @param wrapWith the string that will wrap {@code str}.
9206     * @return the wrapped string, or {@code null} if {@code str == null}.
9207     * @since 3.5
9208     */
9209    public static String wrapIfMissing(final String str, final String wrapWith) {
9210        if (isEmpty(str) || isEmpty(wrapWith)) {
9211            return str;
9212        }
9213        final boolean wrapStart = !str.startsWith(wrapWith);
9214        final boolean wrapEnd = !str.endsWith(wrapWith);
9215        if (!wrapStart && !wrapEnd) {
9216            return str;
9217        }
9218        final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length());
9219        if (wrapStart) {
9220            builder.append(wrapWith);
9221        }
9222        builder.append(str);
9223        if (wrapEnd) {
9224            builder.append(wrapWith);
9225        }
9226        return builder.toString();
9227    }
9228
9229    /**
9230     * {@link StringUtils} instances should NOT be constructed in standard programming. Instead, the class should be used as {@code StringUtils.trim(" foo ");}.
9231     *
9232     * <p>
9233     * This constructor is public to permit tools that require a JavaBean instance to operate.
9234     * </p>
9235     *
9236     * @deprecated TODO Make private in 4.0.
9237     */
9238    @Deprecated
9239    public StringUtils() {
9240        // empty
9241    }
9242
9243}