View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.lang3;
18  
19  import java.io.UnsupportedEncodingException;
20  import java.nio.CharBuffer;
21  import java.nio.charset.Charset;
22  import java.text.Normalizer;
23  import java.util.ArrayList;
24  import java.util.Arrays;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Locale;
28  import java.util.Objects;
29  import java.util.Set;
30  import java.util.function.Supplier;
31  import java.util.regex.Pattern;
32  import java.util.stream.Collectors;
33  
34  import org.apache.commons.lang3.function.Suppliers;
35  import org.apache.commons.lang3.stream.LangCollectors;
36  import org.apache.commons.lang3.stream.Streams;
37  
38  /**
39   * Operations on {@link String} that are
40   * {@code null} safe.
41   *
42   * <ul>
43   *  <li><strong>IsEmpty/IsBlank</strong>
44   *      - checks if a String contains text</li>
45   *  <li><strong>Trim/Strip</strong>
46   *      - removes leading and trailing whitespace</li>
47   *  <li><strong>Equals/Compare</strong>
48   *      - compares two strings in a null-safe manner</li>
49   *  <li><strong>startsWith</strong>
50   *      - check if a String starts with a prefix in a null-safe manner</li>
51   *  <li><strong>endsWith</strong>
52   *      - check if a String ends with a suffix in a null-safe manner</li>
53   *  <li><strong>IndexOf/LastIndexOf/Contains</strong>
54   *      - null-safe index-of checks</li>
55   *  <li><strong>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</strong>
56   *      - index-of any of a set of Strings</li>
57   *  <li><strong>ContainsOnly/ContainsNone/ContainsAny</strong>
58   *      - checks if String contains only/none/any of these characters</li>
59   *  <li><strong>Substring/Left/Right/Mid</strong>
60   *      - null-safe substring extractions</li>
61   *  <li><strong>SubstringBefore/SubstringAfter/SubstringBetween</strong>
62   *      - substring extraction relative to other strings</li>
63   *  <li><strong>Split/Join</strong>
64   *      - splits a String into an array of substrings and vice versa</li>
65   *  <li><strong>Remove/Delete</strong>
66   *      - removes part of a String</li>
67   *  <li><strong>Replace/Overlay</strong>
68   *      - Searches a String and replaces one String with another</li>
69   *  <li><strong>Chomp/Chop</strong>
70   *      - removes the last part of a String</li>
71   *  <li><strong>AppendIfMissing</strong>
72   *      - appends a suffix to the end of the String if not present</li>
73   *  <li><strong>PrependIfMissing</strong>
74   *      - prepends a prefix to the start of the String if not present</li>
75   *  <li><strong>LeftPad/RightPad/Center/Repeat</strong>
76   *      - pads a String</li>
77   *  <li><strong>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</strong>
78   *      - changes the case of a String</li>
79   *  <li><strong>CountMatches</strong>
80   *      - counts the number of occurrences of one String in another</li>
81   *  <li><strong>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</strong>
82   *      - checks the characters in a String</li>
83   *  <li><strong>DefaultString</strong>
84   *      - protects against a null input String</li>
85   *  <li><strong>Rotate</strong>
86   *      - rotate (circular shift) a String</li>
87   *  <li><strong>Reverse/ReverseDelimited</strong>
88   *      - reverses a String</li>
89   *  <li><strong>Abbreviate</strong>
90   *      - abbreviates a string using ellipses or another given String</li>
91   *  <li><strong>Difference</strong>
92   *      - compares Strings and reports on their differences</li>
93   *  <li><strong>LevenshteinDistance</strong>
94   *      - the number of changes needed to change one String into another</li>
95   * </ul>
96   *
97   * <p>The {@link StringUtils} class defines certain words related to
98   * String handling.</p>
99   *
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
126 public 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 }