StringUtils.java

  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.  *      http://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. import java.io.UnsupportedEncodingException;
  19. import java.nio.charset.Charset;
  20. import java.text.Normalizer;
  21. import java.util.ArrayList;
  22. import java.util.Arrays;
  23. import java.util.HashSet;
  24. import java.util.Iterator;
  25. import java.util.List;
  26. import java.util.Locale;
  27. import java.util.Objects;
  28. import java.util.Set;
  29. import java.util.function.Supplier;
  30. import java.util.regex.Pattern;

  31. import org.apache.commons.lang3.function.Suppliers;
  32. import org.apache.commons.lang3.function.ToBooleanBiFunction;
  33. import org.apache.commons.lang3.stream.LangCollectors;
  34. import org.apache.commons.lang3.stream.Streams;

  35. /**
  36.  * Operations on {@link String} that are
  37.  * {@code null} safe.
  38.  *
  39.  * <ul>
  40.  *  <li><b>IsEmpty/IsBlank</b>
  41.  *      - checks if a String contains text</li>
  42.  *  <li><b>Trim/Strip</b>
  43.  *      - removes leading and trailing whitespace</li>
  44.  *  <li><b>Equals/Compare</b>
  45.  *      - compares two strings in a null-safe manner</li>
  46.  *  <li><b>startsWith</b>
  47.  *      - check if a String starts with a prefix in a null-safe manner</li>
  48.  *  <li><b>endsWith</b>
  49.  *      - check if a String ends with a suffix in a null-safe manner</li>
  50.  *  <li><b>IndexOf/LastIndexOf/Contains</b>
  51.  *      - null-safe index-of checks
  52.  *  <li><b>IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut</b>
  53.  *      - index-of any of a set of Strings</li>
  54.  *  <li><b>ContainsOnly/ContainsNone/ContainsAny</b>
  55.  *      - checks if String contains only/none/any of these characters</li>
  56.  *  <li><b>Substring/Left/Right/Mid</b>
  57.  *      - null-safe substring extractions</li>
  58.  *  <li><b>SubstringBefore/SubstringAfter/SubstringBetween</b>
  59.  *      - substring extraction relative to other strings</li>
  60.  *  <li><b>Split/Join</b>
  61.  *      - splits a String into an array of substrings and vice versa</li>
  62.  *  <li><b>Remove/Delete</b>
  63.  *      - removes part of a String</li>
  64.  *  <li><b>Replace/Overlay</b>
  65.  *      - Searches a String and replaces one String with another</li>
  66.  *  <li><b>Chomp/Chop</b>
  67.  *      - removes the last part of a String</li>
  68.  *  <li><b>AppendIfMissing</b>
  69.  *      - appends a suffix to the end of the String if not present</li>
  70.  *  <li><b>PrependIfMissing</b>
  71.  *      - prepends a prefix to the start of the String if not present</li>
  72.  *  <li><b>LeftPad/RightPad/Center/Repeat</b>
  73.  *      - pads a String</li>
  74.  *  <li><b>UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize</b>
  75.  *      - changes the case of a String</li>
  76.  *  <li><b>CountMatches</b>
  77.  *      - counts the number of occurrences of one String in another</li>
  78.  *  <li><b>IsAlpha/IsNumeric/IsWhitespace/IsAsciiPrintable</b>
  79.  *      - checks the characters in a String</li>
  80.  *  <li><b>DefaultString</b>
  81.  *      - protects against a null input String</li>
  82.  *  <li><b>Rotate</b>
  83.  *      - rotate (circular shift) a String</li>
  84.  *  <li><b>Reverse/ReverseDelimited</b>
  85.  *      - reverses a String</li>
  86.  *  <li><b>Abbreviate</b>
  87.  *      - abbreviates a string using ellipses or another given String</li>
  88.  *  <li><b>Difference</b>
  89.  *      - compares Strings and reports on their differences</li>
  90.  *  <li><b>LevenshteinDistance</b>
  91.  *      - the number of changes needed to change one String into another</li>
  92.  * </ul>
  93.  *
  94.  * <p>The {@link StringUtils} class defines certain words related to
  95.  * String handling.</p>
  96.  *
  97.  * <ul>
  98.  *  <li>null - {@code null}</li>
  99.  *  <li>empty - a zero-length string ({@code ""})</li>
  100.  *  <li>space - the space character ({@code ' '}, char 32)</li>
  101.  *  <li>whitespace - the characters defined by {@link Character#isWhitespace(char)}</li>
  102.  *  <li>trim - the characters &lt;= 32 as in {@link String#trim()}</li>
  103.  * </ul>
  104.  *
  105.  * <p>{@link StringUtils} handles {@code null} input Strings quietly.
  106.  * That is to say that a {@code null} input will return {@code null}.
  107.  * Where a {@code boolean} or {@code int} is being returned
  108.  * details vary by method.</p>
  109.  *
  110.  * <p>A side effect of the {@code null} handling is that a
  111.  * {@link NullPointerException} should be considered a bug in
  112.  * {@link StringUtils}.</p>
  113.  *
  114.  * <p>Methods in this class include sample code in their Javadoc comments to explain their operation.
  115.  * The symbol {@code *} is used to indicate any input including {@code null}.</p>
  116.  *
  117.  * <p>#ThreadSafe#</p>
  118.  * @see String
  119.  * @since 1.0
  120.  */
  121. //@Immutable
  122. public class StringUtils {

  123.     // Performance testing notes (JDK 1.4, Jul03, scolebourne)
  124.     // Whitespace:
  125.     // Character.isWhitespace() is faster than WHITESPACE.indexOf()
  126.     // where WHITESPACE is a string of all whitespace characters
  127.     //
  128.     // Character access:
  129.     // String.charAt(n) versus toCharArray(), then array[n]
  130.     // String.charAt(n) is about 15% worse for a 10K string
  131.     // They are about equal for a length 50 string
  132.     // String.charAt(n) is about 4 times better for a length 3 string
  133.     // String.charAt(n) is best bet overall
  134.     //
  135.     // Append:
  136.     // String.concat about twice as fast as StringBuffer.append
  137.     // (not sure who tested this)

  138.     /**
  139.      * A String for a space character.
  140.      *
  141.      * @since 3.2
  142.      */
  143.     public static final String SPACE = " ";

  144.     /**
  145.      * The empty String {@code ""}.
  146.      * @since 2.0
  147.      */
  148.     public static final String EMPTY = "";

  149.     /**
  150.      * A String for linefeed LF ("\n").
  151.      *
  152.      * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
  153.      *      for Character and String Literals</a>
  154.      * @since 3.2
  155.      */
  156.     public static final String LF = "\n";

  157.     /**
  158.      * A String for carriage return CR ("\r").
  159.      *
  160.      * @see <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.6">JLF: Escape Sequences
  161.      *      for Character and String Literals</a>
  162.      * @since 3.2
  163.      */
  164.     public static final String CR = "\r";

  165.     /**
  166.      * Represents a failed index search.
  167.      * @since 2.1
  168.      */
  169.     public static final int INDEX_NOT_FOUND = -1;

  170.     /**
  171.      * The maximum size to which the padding constant(s) can expand.
  172.      */
  173.     private static final int PAD_LIMIT = 8192;

  174.     /**
  175.      * Pattern used in {@link #stripAccents(String)}.
  176.      */
  177.     private static final Pattern STRIP_ACCENTS_PATTERN = Pattern.compile("\\p{InCombiningDiacriticalMarks}+"); //$NON-NLS-1$

  178.     /**
  179.      * Abbreviates a String using ellipses. This will turn
  180.      * "Now is the time for all good men" into "Now is the time for..."
  181.      *
  182.      * <p>Specifically:</p>
  183.      * <ul>
  184.      *   <li>If the number of characters in {@code str} is less than or equal to
  185.      *       {@code maxWidth}, return {@code str}.</li>
  186.      *   <li>Else abbreviate it to {@code (substring(str, 0, max-3) + "...")}.</li>
  187.      *   <li>If {@code maxWidth} is less than {@code 4}, throw an
  188.      *       {@link IllegalArgumentException}.</li>
  189.      *   <li>In no case will it return a String of length greater than
  190.      *       {@code maxWidth}.</li>
  191.      * </ul>
  192.      *
  193.      * <pre>
  194.      * StringUtils.abbreviate(null, *)      = null
  195.      * StringUtils.abbreviate("", 4)        = ""
  196.      * StringUtils.abbreviate("abcdefg", 6) = "abc..."
  197.      * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
  198.      * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
  199.      * StringUtils.abbreviate("abcdefg", 4) = "a..."
  200.      * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
  201.      * </pre>
  202.      *
  203.      * @param str  the String to check, may be null
  204.      * @param maxWidth  maximum length of result String, must be at least 4
  205.      * @return abbreviated String, {@code null} if null String input
  206.      * @throws IllegalArgumentException if the width is too small
  207.      * @since 2.0
  208.      */
  209.     public static String abbreviate(final String str, final int maxWidth) {
  210.         return abbreviate(str, "...", 0, maxWidth);
  211.     }

  212.     /**
  213.      * Abbreviates a String using ellipses. This will turn
  214.      * "Now is the time for all good men" into "...is the time for..."
  215.      *
  216.      * <p>Works like {@code abbreviate(String, int)}, but allows you to specify
  217.      * a "left edge" offset.  Note that this left edge is not necessarily going to
  218.      * be the leftmost character in the result, or the first character following the
  219.      * ellipses, but it will appear somewhere in the result.
  220.      *
  221.      * <p>In no case will it return a String of length greater than
  222.      * {@code maxWidth}.</p>
  223.      *
  224.      * <pre>
  225.      * StringUtils.abbreviate(null, *, *)                = null
  226.      * StringUtils.abbreviate("", 0, 4)                  = ""
  227.      * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
  228.      * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
  229.      * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
  230.      * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
  231.      * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
  232.      * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
  233.      * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
  234.      * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
  235.      * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
  236.      * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
  237.      * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
  238.      * </pre>
  239.      *
  240.      * @param str  the String to check, may be null
  241.      * @param offset  left edge of source String
  242.      * @param maxWidth  maximum length of result String, must be at least 4
  243.      * @return abbreviated String, {@code null} if null String input
  244.      * @throws IllegalArgumentException if the width is too small
  245.      * @since 2.0
  246.      */
  247.     public static String abbreviate(final String str, final int offset, final int maxWidth) {
  248.         return abbreviate(str, "...", offset, maxWidth);
  249.     }

  250.     /**
  251.      * Abbreviates a String using another given String as replacement marker. This will turn
  252.      * "Now is the time for all good men" into "Now is the time for..." if "..." was defined
  253.      * as the replacement marker.
  254.      *
  255.      * <p>Specifically:</p>
  256.      * <ul>
  257.      *   <li>If the number of characters in {@code str} is less than or equal to
  258.      *       {@code maxWidth}, return {@code str}.</li>
  259.      *   <li>Else abbreviate it to {@code (substring(str, 0, max-abbrevMarker.length) + abbrevMarker)}.</li>
  260.      *   <li>If {@code maxWidth} is less than {@code abbrevMarker.length + 1}, throw an
  261.      *       {@link IllegalArgumentException}.</li>
  262.      *   <li>In no case will it return a String of length greater than
  263.      *       {@code maxWidth}.</li>
  264.      * </ul>
  265.      *
  266.      * <pre>
  267.      * StringUtils.abbreviate(null, "...", *)      = null
  268.      * StringUtils.abbreviate("abcdefg", null, *)  = "abcdefg"
  269.      * StringUtils.abbreviate("", "...", 4)        = ""
  270.      * StringUtils.abbreviate("abcdefg", ".", 5)   = "abcd."
  271.      * StringUtils.abbreviate("abcdefg", ".", 7)   = "abcdefg"
  272.      * StringUtils.abbreviate("abcdefg", ".", 8)   = "abcdefg"
  273.      * StringUtils.abbreviate("abcdefg", "..", 4)  = "ab.."
  274.      * StringUtils.abbreviate("abcdefg", "..", 3)  = "a.."
  275.      * StringUtils.abbreviate("abcdefg", "..", 2)  = IllegalArgumentException
  276.      * StringUtils.abbreviate("abcdefg", "...", 3) = IllegalArgumentException
  277.      * </pre>
  278.      *
  279.      * @param str  the String to check, may be null
  280.      * @param abbrevMarker  the String used as replacement marker
  281.      * @param maxWidth  maximum length of result String, must be at least {@code abbrevMarker.length + 1}
  282.      * @return abbreviated String, {@code null} if null String input
  283.      * @throws IllegalArgumentException if the width is too small
  284.      * @since 3.6
  285.      */
  286.     public static String abbreviate(final String str, final String abbrevMarker, final int maxWidth) {
  287.         return abbreviate(str, abbrevMarker, 0, maxWidth);
  288.     }
  289.     /**
  290.      * Abbreviates a String using a given replacement marker. This will turn
  291.      * "Now is the time for all good men" into "...is the time for..." if "..." was defined
  292.      * as the replacement marker.
  293.      *
  294.      * <p>Works like {@code abbreviate(String, String, int)}, but allows you to specify
  295.      * a "left edge" offset.  Note that this left edge is not necessarily going to
  296.      * be the leftmost character in the result, or the first character following the
  297.      * replacement marker, but it will appear somewhere in the result.
  298.      *
  299.      * <p>In no case will it return a String of length greater than {@code maxWidth}.</p>
  300.      *
  301.      * <pre>
  302.      * StringUtils.abbreviate(null, null, *, *)                 = null
  303.      * StringUtils.abbreviate("abcdefghijklmno", null, *, *)    = "abcdefghijklmno"
  304.      * StringUtils.abbreviate("", "...", 0, 4)                  = ""
  305.      * StringUtils.abbreviate("abcdefghijklmno", "---", -1, 10) = "abcdefg---"
  306.      * StringUtils.abbreviate("abcdefghijklmno", ",", 0, 10)    = "abcdefghi,"
  307.      * StringUtils.abbreviate("abcdefghijklmno", ",", 1, 10)    = "abcdefghi,"
  308.      * StringUtils.abbreviate("abcdefghijklmno", ",", 2, 10)    = "abcdefghi,"
  309.      * StringUtils.abbreviate("abcdefghijklmno", "::", 4, 10)   = "::efghij::"
  310.      * StringUtils.abbreviate("abcdefghijklmno", "...", 6, 10)  = "...ghij..."
  311.      * StringUtils.abbreviate("abcdefghijklmno", "*", 9, 10)    = "*ghijklmno"
  312.      * StringUtils.abbreviate("abcdefghijklmno", "'", 10, 10)   = "'ghijklmno"
  313.      * StringUtils.abbreviate("abcdefghijklmno", "!", 12, 10)   = "!ghijklmno"
  314.      * StringUtils.abbreviate("abcdefghij", "abra", 0, 4)       = IllegalArgumentException
  315.      * StringUtils.abbreviate("abcdefghij", "...", 5, 6)        = IllegalArgumentException
  316.      * </pre>
  317.      *
  318.      * @param str  the String to check, may be null
  319.      * @param abbrevMarker  the String used as replacement marker
  320.      * @param offset  left edge of source String
  321.      * @param maxWidth  maximum length of result String, must be at least 4
  322.      * @return abbreviated String, {@code null} if null String input
  323.      * @throws IllegalArgumentException if the width is too small
  324.      * @since 3.6
  325.      */
  326.     public static String abbreviate(final String str, final String abbrevMarker, int offset, final int maxWidth) {
  327.         if (isNotEmpty(str) && EMPTY.equals(abbrevMarker) && maxWidth > 0) {
  328.             return substring(str, 0, maxWidth);
  329.         }
  330.         if (isAnyEmpty(str, abbrevMarker)) {
  331.             return str;
  332.         }
  333.         final int abbrevMarkerLength = abbrevMarker.length();
  334.         final int minAbbrevWidth = abbrevMarkerLength + 1;
  335.         final int minAbbrevWidthOffset = abbrevMarkerLength + abbrevMarkerLength + 1;

  336.         if (maxWidth < minAbbrevWidth) {
  337.             throw new IllegalArgumentException(String.format("Minimum abbreviation width is %d", minAbbrevWidth));
  338.         }
  339.         final int strLen = str.length();
  340.         if (strLen <= maxWidth) {
  341.             return str;
  342.         }
  343.         if (offset > strLen) {
  344.             offset = strLen;
  345.         }
  346.         if (strLen - offset < maxWidth - abbrevMarkerLength) {
  347.             offset = strLen - (maxWidth - abbrevMarkerLength);
  348.         }
  349.         if (offset <= abbrevMarkerLength + 1) {
  350.             return str.substring(0, maxWidth - abbrevMarkerLength) + abbrevMarker;
  351.         }
  352.         if (maxWidth < minAbbrevWidthOffset) {
  353.             throw new IllegalArgumentException(String.format("Minimum abbreviation width with offset is %d", minAbbrevWidthOffset));
  354.         }
  355.         if (offset + maxWidth - abbrevMarkerLength < strLen) {
  356.             return abbrevMarker + abbreviate(str.substring(offset), abbrevMarker, maxWidth - abbrevMarkerLength);
  357.         }
  358.         return abbrevMarker + str.substring(strLen - (maxWidth - abbrevMarkerLength));
  359.     }

  360.     /**
  361.      * Abbreviates a String to the length passed, replacing the middle characters with the supplied
  362.      * replacement String.
  363.      *
  364.      * <p>This abbreviation only occurs if the following criteria is met:</p>
  365.      * <ul>
  366.      * <li>Neither the String for abbreviation nor the replacement String are null or empty </li>
  367.      * <li>The length to truncate to is less than the length of the supplied String</li>
  368.      * <li>The length to truncate to is greater than 0</li>
  369.      * <li>The abbreviated String will have enough room for the length supplied replacement String
  370.      * and the first and last characters of the supplied String for abbreviation</li>
  371.      * </ul>
  372.      * <p>Otherwise, the returned String will be the same as the supplied String for abbreviation.
  373.      * </p>
  374.      *
  375.      * <pre>
  376.      * StringUtils.abbreviateMiddle(null, null, 0)    = null
  377.      * StringUtils.abbreviateMiddle("abc", null, 0)   = "abc"
  378.      * StringUtils.abbreviateMiddle("abc", ".", 0)    = "abc"
  379.      * StringUtils.abbreviateMiddle("abc", ".", 3)    = "abc"
  380.      * StringUtils.abbreviateMiddle("abcdef", ".", 4) = "ab.f"
  381.      * </pre>
  382.      *
  383.      * @param str  the String to abbreviate, may be null
  384.      * @param middle the String to replace the middle characters with, may be null
  385.      * @param length the length to abbreviate {@code str} to.
  386.      * @return the abbreviated String if the above criteria is met, or the original String supplied for abbreviation.
  387.      * @since 2.5
  388.      */
  389.     public static String abbreviateMiddle(final String str, final String middle, final int length) {
  390.         if (isAnyEmpty(str, middle) || length >= str.length() || length < middle.length() + 2) {
  391.             return str;
  392.         }
  393.         final int targetSting = length - middle.length();
  394.         final int startOffset = targetSting / 2 + targetSting % 2;
  395.         final int endOffset = str.length() - targetSting / 2;
  396.         return str.substring(0, startOffset) + middle + str.substring(endOffset);
  397.     }

  398.     /**
  399.      * Appends the suffix to the end of the string if the string does not
  400.      * already end with the suffix.
  401.      *
  402.      * @param str The string.
  403.      * @param suffix The suffix to append to the end of the string.
  404.      * @param ignoreCase Indicates whether the compare should ignore case.
  405.      * @param suffixes Additional suffixes that are valid terminators (optional).
  406.      *
  407.      * @return A new String if suffix was appended, the same string otherwise.
  408.      */
  409.     private static String appendIfMissing(final String str, final CharSequence suffix, final boolean ignoreCase, final CharSequence... suffixes) {
  410.         if (str == null || isEmpty(suffix) || endsWith(str, suffix, ignoreCase)) {
  411.             return str;
  412.         }
  413.         if (ArrayUtils.isNotEmpty(suffixes)) {
  414.             for (final CharSequence s : suffixes) {
  415.                 if (endsWith(str, s, ignoreCase)) {
  416.                     return str;
  417.                 }
  418.             }
  419.         }
  420.         return str + suffix;
  421.     }

  422.     /**
  423.      * Appends the suffix to the end of the string if the string does not
  424.      * already end with any of the suffixes.
  425.      *
  426.      * <pre>
  427.      * StringUtils.appendIfMissing(null, null)      = null
  428.      * StringUtils.appendIfMissing("abc", null)     = "abc"
  429.      * StringUtils.appendIfMissing("", "xyz"        = "xyz"
  430.      * StringUtils.appendIfMissing("abc", "xyz")    = "abcxyz"
  431.      * StringUtils.appendIfMissing("abcxyz", "xyz") = "abcxyz"
  432.      * StringUtils.appendIfMissing("abcXYZ", "xyz") = "abcXYZxyz"
  433.      * </pre>
  434.      * <p>With additional suffixes,</p>
  435.      * <pre>
  436.      * StringUtils.appendIfMissing(null, null, null)       = null
  437.      * StringUtils.appendIfMissing("abc", null, null)      = "abc"
  438.      * StringUtils.appendIfMissing("", "xyz", null)        = "xyz"
  439.      * StringUtils.appendIfMissing("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
  440.      * StringUtils.appendIfMissing("abc", "xyz", "")       = "abc"
  441.      * StringUtils.appendIfMissing("abc", "xyz", "mno")    = "abcxyz"
  442.      * StringUtils.appendIfMissing("abcxyz", "xyz", "mno") = "abcxyz"
  443.      * StringUtils.appendIfMissing("abcmno", "xyz", "mno") = "abcmno"
  444.      * StringUtils.appendIfMissing("abcXYZ", "xyz", "mno") = "abcXYZxyz"
  445.      * StringUtils.appendIfMissing("abcMNO", "xyz", "mno") = "abcMNOxyz"
  446.      * </pre>
  447.      *
  448.      * @param str The string.
  449.      * @param suffix The suffix to append to the end of the string.
  450.      * @param suffixes Additional suffixes that are valid terminators.
  451.      *
  452.      * @return A new String if suffix was appended, the same string otherwise.
  453.      *
  454.      * @since 3.2
  455.      */
  456.     public static String appendIfMissing(final String str, final CharSequence suffix, final CharSequence... suffixes) {
  457.         return appendIfMissing(str, suffix, false, suffixes);
  458.     }

  459.     /**
  460.      * Appends the suffix to the end of the string if the string does not
  461.      * already end, case-insensitive, with any of the suffixes.
  462.      *
  463.      * <pre>
  464.      * StringUtils.appendIfMissingIgnoreCase(null, null)      = null
  465.      * StringUtils.appendIfMissingIgnoreCase("abc", null)     = "abc"
  466.      * StringUtils.appendIfMissingIgnoreCase("", "xyz")       = "xyz"
  467.      * StringUtils.appendIfMissingIgnoreCase("abc", "xyz")    = "abcxyz"
  468.      * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz") = "abcxyz"
  469.      * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz") = "abcXYZ"
  470.      * </pre>
  471.      * <p>With additional suffixes,</p>
  472.      * <pre>
  473.      * StringUtils.appendIfMissingIgnoreCase(null, null, null)       = null
  474.      * StringUtils.appendIfMissingIgnoreCase("abc", null, null)      = "abc"
  475.      * StringUtils.appendIfMissingIgnoreCase("", "xyz", null)        = "xyz"
  476.      * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "abcxyz"
  477.      * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "")       = "abc"
  478.      * StringUtils.appendIfMissingIgnoreCase("abc", "xyz", "mno")    = "abcxyz"
  479.      * StringUtils.appendIfMissingIgnoreCase("abcxyz", "xyz", "mno") = "abcxyz"
  480.      * StringUtils.appendIfMissingIgnoreCase("abcmno", "xyz", "mno") = "abcmno"
  481.      * StringUtils.appendIfMissingIgnoreCase("abcXYZ", "xyz", "mno") = "abcXYZ"
  482.      * StringUtils.appendIfMissingIgnoreCase("abcMNO", "xyz", "mno") = "abcMNO"
  483.      * </pre>
  484.      *
  485.      * @param str The string.
  486.      * @param suffix The suffix to append to the end of the string.
  487.      * @param suffixes Additional suffixes that are valid terminators.
  488.      *
  489.      * @return A new String if suffix was appended, the same string otherwise.
  490.      *
  491.      * @since 3.2
  492.      */
  493.     public static String appendIfMissingIgnoreCase(final String str, final CharSequence suffix, final CharSequence... suffixes) {
  494.         return appendIfMissing(str, suffix, true, suffixes);
  495.     }

  496.     /**
  497.      * Capitalizes a String changing the first character to title case as
  498.      * per {@link Character#toTitleCase(int)}. No other characters are changed.
  499.      *
  500.      * <p>For a word based algorithm, see {@link org.apache.commons.text.WordUtils#capitalize(String)}.
  501.      * A {@code null} input String returns {@code null}.</p>
  502.      *
  503.      * <pre>
  504.      * StringUtils.capitalize(null)    = null
  505.      * StringUtils.capitalize("")      = ""
  506.      * StringUtils.capitalize("cat")   = "Cat"
  507.      * StringUtils.capitalize("cAt")   = "CAt"
  508.      * StringUtils.capitalize("'cat'") = "'cat'"
  509.      * </pre>
  510.      *
  511.      * @param str the String to capitalize, may be null
  512.      * @return the capitalized String, {@code null} if null String input
  513.      * @see org.apache.commons.text.WordUtils#capitalize(String)
  514.      * @see #uncapitalize(String)
  515.      * @since 2.0
  516.      */
  517.     public static String capitalize(final String str) {
  518.         final int strLen = length(str);
  519.         if (strLen == 0) {
  520.             return str;
  521.         }

  522.         final int firstCodepoint = str.codePointAt(0);
  523.         final int newCodePoint = Character.toTitleCase(firstCodepoint);
  524.         if (firstCodepoint == newCodePoint) {
  525.             // already capitalized
  526.             return str;
  527.         }

  528.         final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
  529.         int outOffset = 0;
  530.         newCodePoints[outOffset++] = newCodePoint; // copy the first code point
  531.         for (int inOffset = Character.charCount(firstCodepoint); inOffset < strLen; ) {
  532.             final int codePoint = str.codePointAt(inOffset);
  533.             newCodePoints[outOffset++] = codePoint; // copy the remaining ones
  534.             inOffset += Character.charCount(codePoint);
  535.          }
  536.         return new String(newCodePoints, 0, outOffset);
  537.     }

  538.     /**
  539.      * Centers a String in a larger String of size {@code size}
  540.      * using the space character (' ').
  541.      *
  542.      * <p>If the size is less than the String length, the original String is returned.
  543.      * A {@code null} String returns {@code null}.
  544.      * A negative size is treated as zero.</p>
  545.      *
  546.      * <p>Equivalent to {@code center(str, size, " ")}.</p>
  547.      *
  548.      * <pre>
  549.      * StringUtils.center(null, *)   = null
  550.      * StringUtils.center("", 4)     = "    "
  551.      * StringUtils.center("ab", -1)  = "ab"
  552.      * StringUtils.center("ab", 4)   = " ab "
  553.      * StringUtils.center("abcd", 2) = "abcd"
  554.      * StringUtils.center("a", 4)    = " a  "
  555.      * </pre>
  556.      *
  557.      * @param str  the String to center, may be null
  558.      * @param size  the int size of new String, negative treated as zero
  559.      * @return centered String, {@code null} if null String input
  560.      */
  561.     public static String center(final String str, final int size) {
  562.         return center(str, size, ' ');
  563.     }

  564.     /**
  565.      * Centers a String in a larger String of size {@code size}.
  566.      * Uses a supplied character as the value to pad the String with.
  567.      *
  568.      * <p>If the size is less than the String length, the String is returned.
  569.      * A {@code null} String returns {@code null}.
  570.      * A negative size is treated as zero.</p>
  571.      *
  572.      * <pre>
  573.      * StringUtils.center(null, *, *)     = null
  574.      * StringUtils.center("", 4, ' ')     = "    "
  575.      * StringUtils.center("ab", -1, ' ')  = "ab"
  576.      * StringUtils.center("ab", 4, ' ')   = " ab "
  577.      * StringUtils.center("abcd", 2, ' ') = "abcd"
  578.      * StringUtils.center("a", 4, ' ')    = " a  "
  579.      * StringUtils.center("a", 4, 'y')    = "yayy"
  580.      * </pre>
  581.      *
  582.      * @param str  the String to center, may be null
  583.      * @param size  the int size of new String, negative treated as zero
  584.      * @param padChar  the character to pad the new String with
  585.      * @return centered String, {@code null} if null String input
  586.      * @since 2.0
  587.      */
  588.     public static String center(String str, final int size, final char padChar) {
  589.         if (str == null || size <= 0) {
  590.             return str;
  591.         }
  592.         final int strLen = str.length();
  593.         final int pads = size - strLen;
  594.         if (pads <= 0) {
  595.             return str;
  596.         }
  597.         str = leftPad(str, strLen + pads / 2, padChar);
  598.         return rightPad(str, size, padChar);
  599.     }

  600.     /**
  601.      * Centers a String in a larger String of size {@code size}.
  602.      * Uses a supplied String as the value to pad the String with.
  603.      *
  604.      * <p>If the size is less than the String length, the String is returned.
  605.      * A {@code null} String returns {@code null}.
  606.      * A negative size is treated as zero.</p>
  607.      *
  608.      * <pre>
  609.      * StringUtils.center(null, *, *)     = null
  610.      * StringUtils.center("", 4, " ")     = "    "
  611.      * StringUtils.center("ab", -1, " ")  = "ab"
  612.      * StringUtils.center("ab", 4, " ")   = " ab "
  613.      * StringUtils.center("abcd", 2, " ") = "abcd"
  614.      * StringUtils.center("a", 4, " ")    = " a  "
  615.      * StringUtils.center("a", 4, "yz")   = "yayz"
  616.      * StringUtils.center("abc", 7, null) = "  abc  "
  617.      * StringUtils.center("abc", 7, "")   = "  abc  "
  618.      * </pre>
  619.      *
  620.      * @param str  the String to center, may be null
  621.      * @param size  the int size of new String, negative treated as zero
  622.      * @param padStr  the String to pad the new String with, must not be null or empty
  623.      * @return centered String, {@code null} if null String input
  624.      * @throws IllegalArgumentException if padStr is {@code null} or empty
  625.      */
  626.     public static String center(String str, final int size, String padStr) {
  627.         if (str == null || size <= 0) {
  628.             return str;
  629.         }
  630.         if (isEmpty(padStr)) {
  631.             padStr = SPACE;
  632.         }
  633.         final int strLen = str.length();
  634.         final int pads = size - strLen;
  635.         if (pads <= 0) {
  636.             return str;
  637.         }
  638.         str = leftPad(str, strLen + pads / 2, padStr);
  639.         return rightPad(str, size, padStr);
  640.     }

  641.     /**
  642.      * Removes one newline from end of a String if it's there,
  643.      * otherwise leave it alone.  A newline is &quot;{@code \n}&quot;,
  644.      * &quot;{@code \r}&quot;, or &quot;{@code \r\n}&quot;.
  645.      *
  646.      * <p>NOTE: This method changed in 2.0.
  647.      * It now more closely matches Perl chomp.</p>
  648.      *
  649.      * <pre>
  650.      * StringUtils.chomp(null)          = null
  651.      * StringUtils.chomp("")            = ""
  652.      * StringUtils.chomp("abc \r")      = "abc "
  653.      * StringUtils.chomp("abc\n")       = "abc"
  654.      * StringUtils.chomp("abc\r\n")     = "abc"
  655.      * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
  656.      * StringUtils.chomp("abc\n\r")     = "abc\n"
  657.      * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
  658.      * StringUtils.chomp("\r")          = ""
  659.      * StringUtils.chomp("\n")          = ""
  660.      * StringUtils.chomp("\r\n")        = ""
  661.      * </pre>
  662.      *
  663.      * @param str  the String to chomp a newline from, may be null
  664.      * @return String without newline, {@code null} if null String input
  665.      */
  666.     public static String chomp(final String str) {
  667.         if (isEmpty(str)) {
  668.             return str;
  669.         }

  670.         if (str.length() == 1) {
  671.             final char ch = str.charAt(0);
  672.             if (ch == CharUtils.CR || ch == CharUtils.LF) {
  673.                 return EMPTY;
  674.             }
  675.             return str;
  676.         }

  677.         int lastIdx = str.length() - 1;
  678.         final char last = str.charAt(lastIdx);

  679.         if (last == CharUtils.LF) {
  680.             if (str.charAt(lastIdx - 1) == CharUtils.CR) {
  681.                 lastIdx--;
  682.             }
  683.         } else if (last != CharUtils.CR) {
  684.             lastIdx++;
  685.         }
  686.         return str.substring(0, lastIdx);
  687.     }

  688.     /**
  689.      * Removes {@code separator} from the end of
  690.      * {@code str} if it's there, otherwise leave it alone.
  691.      *
  692.      * <p>NOTE: This method changed in version 2.0.
  693.      * It now more closely matches Perl chomp.
  694.      * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
  695.      * This method uses {@link String#endsWith(String)}.</p>
  696.      *
  697.      * <pre>
  698.      * StringUtils.chomp(null, *)         = null
  699.      * StringUtils.chomp("", *)           = ""
  700.      * StringUtils.chomp("foobar", "bar") = "foo"
  701.      * StringUtils.chomp("foobar", "baz") = "foobar"
  702.      * StringUtils.chomp("foo", "foo")    = ""
  703.      * StringUtils.chomp("foo ", "foo")   = "foo "
  704.      * StringUtils.chomp(" foo", "foo")   = " "
  705.      * StringUtils.chomp("foo", "foooo")  = "foo"
  706.      * StringUtils.chomp("foo", "")       = "foo"
  707.      * StringUtils.chomp("foo", null)     = "foo"
  708.      * </pre>
  709.      *
  710.      * @param str  the String to chomp from, may be null
  711.      * @param separator  separator String, may be null
  712.      * @return String without trailing separator, {@code null} if null String input
  713.      * @deprecated This feature will be removed in Lang 4, use {@link StringUtils#removeEnd(String, String)} instead
  714.      */
  715.     @Deprecated
  716.     public static String chomp(final String str, final String separator) {
  717.         return removeEnd(str, separator);
  718.     }

  719.     /**
  720.      * Remove the last character from a String.
  721.      *
  722.      * <p>If the String ends in {@code \r\n}, then remove both
  723.      * of them.</p>
  724.      *
  725.      * <pre>
  726.      * StringUtils.chop(null)          = null
  727.      * StringUtils.chop("")            = ""
  728.      * StringUtils.chop("abc \r")      = "abc "
  729.      * StringUtils.chop("abc\n")       = "abc"
  730.      * StringUtils.chop("abc\r\n")     = "abc"
  731.      * StringUtils.chop("abc")         = "ab"
  732.      * StringUtils.chop("abc\nabc")    = "abc\nab"
  733.      * StringUtils.chop("a")           = ""
  734.      * StringUtils.chop("\r")          = ""
  735.      * StringUtils.chop("\n")          = ""
  736.      * StringUtils.chop("\r\n")        = ""
  737.      * </pre>
  738.      *
  739.      * @param str  the String to chop last character from, may be null
  740.      * @return String without last character, {@code null} if null String input
  741.      */
  742.     public static String chop(final String str) {
  743.         if (str == null) {
  744.             return null;
  745.         }
  746.         final int strLen = str.length();
  747.         if (strLen < 2) {
  748.             return EMPTY;
  749.         }
  750.         final int lastIdx = strLen - 1;
  751.         final String ret = str.substring(0, lastIdx);
  752.         final char last = str.charAt(lastIdx);
  753.         if (last == CharUtils.LF && ret.charAt(lastIdx - 1) == CharUtils.CR) {
  754.             return ret.substring(0, lastIdx - 1);
  755.         }
  756.         return ret;
  757.     }

  758.     /**
  759.      * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
  760.      * <ul>
  761.      *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
  762.      *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
  763.      *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
  764.      * </ul>
  765.      *
  766.      * <p>This is a {@code null} safe version of :</p>
  767.      * <blockquote><pre>str1.compareTo(str2)</pre></blockquote>
  768.      *
  769.      * <p>{@code null} value is considered less than non-{@code null} value.
  770.      * Two {@code null} references are considered equal.</p>
  771.      *
  772.      * <pre>{@code
  773.      * StringUtils.compare(null, null)   = 0
  774.      * StringUtils.compare(null , "a")   < 0
  775.      * StringUtils.compare("a", null)   > 0
  776.      * StringUtils.compare("abc", "abc") = 0
  777.      * StringUtils.compare("a", "b")     < 0
  778.      * StringUtils.compare("b", "a")     > 0
  779.      * StringUtils.compare("a", "B")     > 0
  780.      * StringUtils.compare("ab", "abc")  < 0
  781.      * }</pre>
  782.      *
  783.      * @see #compare(String, String, boolean)
  784.      * @see String#compareTo(String)
  785.      * @param str1  the String to compare from
  786.      * @param str2  the String to compare to
  787.      * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal or greater than {@code str2}
  788.      * @since 3.5
  789.      */
  790.     public static int compare(final String str1, final String str2) {
  791.         return compare(str1, str2, true);
  792.     }

  793.     /**
  794.      * Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :
  795.      * <ul>
  796.      *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
  797.      *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
  798.      *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
  799.      * </ul>
  800.      *
  801.      * <p>This is a {@code null} safe version of :</p>
  802.      * <blockquote><pre>str1.compareTo(str2)</pre></blockquote>
  803.      *
  804.      * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter.
  805.      * Two {@code null} references are considered equal.</p>
  806.      *
  807.      * <pre>{@code
  808.      * StringUtils.compare(null, null, *)     = 0
  809.      * StringUtils.compare(null , "a", true)  < 0
  810.      * StringUtils.compare(null , "a", false) > 0
  811.      * StringUtils.compare("a", null, true)   > 0
  812.      * StringUtils.compare("a", null, false)  < 0
  813.      * StringUtils.compare("abc", "abc", *)   = 0
  814.      * StringUtils.compare("a", "b", *)       < 0
  815.      * StringUtils.compare("b", "a", *)       > 0
  816.      * StringUtils.compare("a", "B", *)       > 0
  817.      * StringUtils.compare("ab", "abc", *)    < 0
  818.      * }</pre>
  819.      *
  820.      * @see String#compareTo(String)
  821.      * @param str1  the String to compare from
  822.      * @param str2  the String to compare to
  823.      * @param nullIsLess  whether consider {@code null} value less than non-{@code null} value
  824.      * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2}
  825.      * @since 3.5
  826.      */
  827.     public static int compare(final String str1, final String str2, final boolean nullIsLess) {
  828.         if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null
  829.             return 0;
  830.         }
  831.         if (str1 == null) {
  832.             return nullIsLess ? -1 : 1;
  833.         }
  834.         if (str2 == null) {
  835.             return nullIsLess ? 1 : - 1;
  836.         }
  837.         return str1.compareTo(str2);
  838.     }

  839.     /**
  840.      * Compare two Strings lexicographically, ignoring case differences,
  841.      * as per {@link String#compareToIgnoreCase(String)}, returning :
  842.      * <ul>
  843.      *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
  844.      *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
  845.      *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
  846.      * </ul>
  847.      *
  848.      * <p>This is a {@code null} safe version of :</p>
  849.      * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>
  850.      *
  851.      * <p>{@code null} value is considered less than non-{@code null} value.
  852.      * Two {@code null} references are considered equal.
  853.      * Comparison is case insensitive.</p>
  854.      *
  855.      * <pre>{@code
  856.      * StringUtils.compareIgnoreCase(null, null)   = 0
  857.      * StringUtils.compareIgnoreCase(null , "a")   < 0
  858.      * StringUtils.compareIgnoreCase("a", null)    > 0
  859.      * StringUtils.compareIgnoreCase("abc", "abc") = 0
  860.      * StringUtils.compareIgnoreCase("abc", "ABC") = 0
  861.      * StringUtils.compareIgnoreCase("a", "b")     < 0
  862.      * StringUtils.compareIgnoreCase("b", "a")     > 0
  863.      * StringUtils.compareIgnoreCase("a", "B")     < 0
  864.      * StringUtils.compareIgnoreCase("A", "b")     < 0
  865.      * StringUtils.compareIgnoreCase("ab", "ABC")  < 0
  866.      * }</pre>
  867.      *
  868.      * @see #compareIgnoreCase(String, String, boolean)
  869.      * @see String#compareToIgnoreCase(String)
  870.      * @param str1  the String to compare from
  871.      * @param str2  the String to compare to
  872.      * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
  873.      *          ignoring case differences.
  874.      * @since 3.5
  875.      */
  876.     public static int compareIgnoreCase(final String str1, final String str2) {
  877.         return compareIgnoreCase(str1, str2, true);
  878.     }

  879.     /**
  880.      * Compare two Strings lexicographically, ignoring case differences,
  881.      * as per {@link String#compareToIgnoreCase(String)}, returning :
  882.      * <ul>
  883.      *  <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li>
  884.      *  <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li>
  885.      *  <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li>
  886.      * </ul>
  887.      *
  888.      * <p>This is a {@code null} safe version of :</p>
  889.      * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote>
  890.      *
  891.      * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter.
  892.      * Two {@code null} references are considered equal.
  893.      * Comparison is case insensitive.</p>
  894.      *
  895.      * <pre>{@code
  896.      * StringUtils.compareIgnoreCase(null, null, *)     = 0
  897.      * StringUtils.compareIgnoreCase(null , "a", true)  < 0
  898.      * StringUtils.compareIgnoreCase(null , "a", false) > 0
  899.      * StringUtils.compareIgnoreCase("a", null, true)   > 0
  900.      * StringUtils.compareIgnoreCase("a", null, false)  < 0
  901.      * StringUtils.compareIgnoreCase("abc", "abc", *)   = 0
  902.      * StringUtils.compareIgnoreCase("abc", "ABC", *)   = 0
  903.      * StringUtils.compareIgnoreCase("a", "b", *)       < 0
  904.      * StringUtils.compareIgnoreCase("b", "a", *)       > 0
  905.      * StringUtils.compareIgnoreCase("a", "B", *)       < 0
  906.      * StringUtils.compareIgnoreCase("A", "b", *)       < 0
  907.      * StringUtils.compareIgnoreCase("ab", "abc", *)    < 0
  908.      * }</pre>
  909.      *
  910.      * @see String#compareToIgnoreCase(String)
  911.      * @param str1  the String to compare from
  912.      * @param str2  the String to compare to
  913.      * @param nullIsLess  whether consider {@code null} value less than non-{@code null} value
  914.      * @return &lt; 0, 0, &gt; 0, if {@code str1} is respectively less, equal ou greater than {@code str2},
  915.      *          ignoring case differences.
  916.      * @since 3.5
  917.      */
  918.     public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) {
  919.         if (str1 == str2) { // NOSONARLINT this intentionally uses == to allow for both null
  920.             return 0;
  921.         }
  922.         if (str1 == null) {
  923.             return nullIsLess ? -1 : 1;
  924.         }
  925.         if (str2 == null) {
  926.             return nullIsLess ? 1 : - 1;
  927.         }
  928.         return str1.compareToIgnoreCase(str2);
  929.     }

  930.     /**
  931.      * Checks if CharSequence contains a search CharSequence, handling {@code null}.
  932.      * This method uses {@link String#indexOf(String)} if possible.
  933.      *
  934.      * <p>A {@code null} CharSequence will return {@code false}.</p>
  935.      *
  936.      * <pre>
  937.      * StringUtils.contains(null, *)     = false
  938.      * StringUtils.contains(*, null)     = false
  939.      * StringUtils.contains("", "")      = true
  940.      * StringUtils.contains("abc", "")   = true
  941.      * StringUtils.contains("abc", "a")  = true
  942.      * StringUtils.contains("abc", "z")  = false
  943.      * </pre>
  944.      *
  945.      * @param seq  the CharSequence to check, may be null
  946.      * @param searchSeq  the CharSequence to find, may be null
  947.      * @return true if the CharSequence contains the search CharSequence,
  948.      *  false if not or {@code null} string input
  949.      * @since 2.0
  950.      * @since 3.0 Changed signature from contains(String, String) to contains(CharSequence, CharSequence)
  951.      */
  952.     public static boolean contains(final CharSequence seq, final CharSequence searchSeq) {
  953.         if (seq == null || searchSeq == null) {
  954.             return false;
  955.         }
  956.         return CharSequenceUtils.indexOf(seq, searchSeq, 0) >= 0;
  957.     }

  958.     /**
  959.      * Checks if CharSequence contains a search character, handling {@code null}.
  960.      * This method uses {@link String#indexOf(int)} if possible.
  961.      *
  962.      * <p>A {@code null} or empty ("") CharSequence will return {@code false}.</p>
  963.      *
  964.      * <pre>
  965.      * StringUtils.contains(null, *)    = false
  966.      * StringUtils.contains("", *)      = false
  967.      * StringUtils.contains("abc", 'a') = true
  968.      * StringUtils.contains("abc", 'z') = false
  969.      * </pre>
  970.      *
  971.      * @param seq  the CharSequence to check, may be null
  972.      * @param searchChar  the character to find
  973.      * @return true if the CharSequence contains the search character,
  974.      *  false if not or {@code null} string input
  975.      * @since 2.0
  976.      * @since 3.0 Changed signature from contains(String, int) to contains(CharSequence, int)
  977.      */
  978.     public static boolean contains(final CharSequence seq, final int searchChar) {
  979.         if (isEmpty(seq)) {
  980.             return false;
  981.         }
  982.         return CharSequenceUtils.indexOf(seq, searchChar, 0) >= 0;
  983.     }

  984.     /**
  985.      * Checks if the CharSequence contains any character in the given
  986.      * set of characters.
  987.      *
  988.      * <p>A {@code null} CharSequence will return {@code false}.
  989.      * A {@code null} or zero length search array will return {@code false}.</p>
  990.      *
  991.      * <pre>
  992.      * StringUtils.containsAny(null, *)                  = false
  993.      * StringUtils.containsAny("", *)                    = false
  994.      * StringUtils.containsAny(*, null)                  = false
  995.      * StringUtils.containsAny(*, [])                    = false
  996.      * StringUtils.containsAny("zzabyycdxx", ['z', 'a']) = true
  997.      * StringUtils.containsAny("zzabyycdxx", ['b', 'y']) = true
  998.      * StringUtils.containsAny("zzabyycdxx", ['z', 'y']) = true
  999.      * StringUtils.containsAny("aba", ['z'])             = false
  1000.      * </pre>
  1001.      *
  1002.      * @param cs  the CharSequence to check, may be null
  1003.      * @param searchChars  the chars to search for, may be null
  1004.      * @return the {@code true} if any of the chars are found,
  1005.      * {@code false} if no match or null input
  1006.      * @since 2.4
  1007.      * @since 3.0 Changed signature from containsAny(String, char[]) to containsAny(CharSequence, char...)
  1008.      */
  1009.     public static boolean containsAny(final CharSequence cs, final char... searchChars) {
  1010.         if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
  1011.             return false;
  1012.         }
  1013.         final int csLength = cs.length();
  1014.         final int searchLength = searchChars.length;
  1015.         final int csLast = csLength - 1;
  1016.         final int searchLast = searchLength - 1;
  1017.         for (int i = 0; i < csLength; i++) {
  1018.             final char ch = cs.charAt(i);
  1019.             for (int j = 0; j < searchLength; j++) {
  1020.                 if (searchChars[j] == ch) {
  1021.                     if (!Character.isHighSurrogate(ch)) {
  1022.                         // ch is in the Basic Multilingual Plane
  1023.                         return true;
  1024.                     }
  1025.                     if (j == searchLast) {
  1026.                         // missing low surrogate, fine, like String.indexOf(String)
  1027.                         return true;
  1028.                     }
  1029.                     if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
  1030.                         return true;
  1031.                     }
  1032.                 }
  1033.             }
  1034.         }
  1035.         return false;
  1036.     }

  1037.     /**
  1038.      * Checks if the CharSequence contains any character in the given set of characters.
  1039.      *
  1040.      * <p>
  1041.      * A {@code null} CharSequence will return {@code false}. A {@code null} search CharSequence will return
  1042.      * {@code false}.
  1043.      * </p>
  1044.      *
  1045.      * <pre>
  1046.      * StringUtils.containsAny(null, *)               = false
  1047.      * StringUtils.containsAny("", *)                 = false
  1048.      * StringUtils.containsAny(*, null)               = false
  1049.      * StringUtils.containsAny(*, "")                 = false
  1050.      * StringUtils.containsAny("zzabyycdxx", "za")    = true
  1051.      * StringUtils.containsAny("zzabyycdxx", "by")    = true
  1052.      * StringUtils.containsAny("zzabyycdxx", "zy")    = true
  1053.      * StringUtils.containsAny("zzabyycdxx", "\tx")   = true
  1054.      * StringUtils.containsAny("zzabyycdxx", "$.#yF") = true
  1055.      * StringUtils.containsAny("aba", "z")            = false
  1056.      * </pre>
  1057.      *
  1058.      * @param cs
  1059.      *            the CharSequence to check, may be null
  1060.      * @param searchChars
  1061.      *            the chars to search for, may be null
  1062.      * @return the {@code true} if any of the chars are found, {@code false} if no match or null input
  1063.      * @since 2.4
  1064.      * @since 3.0 Changed signature from containsAny(String, String) to containsAny(CharSequence, CharSequence)
  1065.      */
  1066.     public static boolean containsAny(final CharSequence cs, final CharSequence searchChars) {
  1067.         if (searchChars == null) {
  1068.             return false;
  1069.         }
  1070.         return containsAny(cs, CharSequenceUtils.toCharArray(searchChars));
  1071.     }

  1072.     /**
  1073.      * Checks if the CharSequence contains any of the CharSequences in the given array.
  1074.      *
  1075.      * <p>
  1076.      * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will
  1077.      * return {@code false}.
  1078.      * </p>
  1079.      *
  1080.      * <pre>
  1081.      * StringUtils.containsAny(null, *)            = false
  1082.      * StringUtils.containsAny("", *)              = false
  1083.      * StringUtils.containsAny(*, null)            = false
  1084.      * StringUtils.containsAny(*, [])              = false
  1085.      * StringUtils.containsAny("abcd", "ab", null) = true
  1086.      * StringUtils.containsAny("abcd", "ab", "cd") = true
  1087.      * StringUtils.containsAny("abc", "d", "abc")  = true
  1088.      * </pre>
  1089.      *
  1090.      * @param cs The CharSequence to check, may be null
  1091.      * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be
  1092.      *        null as well.
  1093.      * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
  1094.      * @since 3.4
  1095.      */
  1096.     public static boolean containsAny(final CharSequence cs, final CharSequence... searchCharSequences) {
  1097.         return containsAny(StringUtils::contains, cs, searchCharSequences);
  1098.     }

  1099.     /**
  1100.      * Checks if the CharSequence contains any of the CharSequences in the given array.
  1101.      *
  1102.      * <p>
  1103.      * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will
  1104.      * return {@code false}.
  1105.      * </p>
  1106.      *
  1107.      * @param cs The CharSequence to check, may be null
  1108.      * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be
  1109.      *        null as well.
  1110.      * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
  1111.      * @since 3.12.0
  1112.      */
  1113.     private static boolean containsAny(final ToBooleanBiFunction<CharSequence, CharSequence> test,
  1114.         final CharSequence cs, final CharSequence... searchCharSequences) {
  1115.         if (isEmpty(cs) || ArrayUtils.isEmpty(searchCharSequences)) {
  1116.             return false;
  1117.         }
  1118.         for (final CharSequence searchCharSequence : searchCharSequences) {
  1119.             if (test.applyAsBoolean(cs, searchCharSequence)) {
  1120.                 return true;
  1121.             }
  1122.         }
  1123.         return false;
  1124.     }

  1125.     /**
  1126.      * Checks if the CharSequence contains any of the CharSequences in the given array, ignoring case.
  1127.      *
  1128.      * <p>
  1129.      * A {@code null} {@code cs} CharSequence will return {@code false}. A {@code null} or zero length search array will
  1130.      * return {@code false}.
  1131.      * </p>
  1132.      *
  1133.      * <pre>
  1134.      * StringUtils.containsAny(null, *)            = false
  1135.      * StringUtils.containsAny("", *)              = false
  1136.      * StringUtils.containsAny(*, null)            = false
  1137.      * StringUtils.containsAny(*, [])              = false
  1138.      * StringUtils.containsAny("abcd", "ab", null) = true
  1139.      * StringUtils.containsAny("abcd", "ab", "cd") = true
  1140.      * StringUtils.containsAny("abc", "d", "abc")  = true
  1141.      * StringUtils.containsAny("abc", "D", "ABC")  = true
  1142.      * StringUtils.containsAny("ABC", "d", "abc")  = true
  1143.      * </pre>
  1144.      *
  1145.      * @param cs The CharSequence to check, may be null
  1146.      * @param searchCharSequences The array of CharSequences to search for, may be null. Individual CharSequences may be
  1147.      *        null as well.
  1148.      * @return {@code true} if any of the search CharSequences are found, {@code false} otherwise
  1149.      * @since 3.12.0
  1150.      */
  1151.     public static boolean containsAnyIgnoreCase(final CharSequence cs, final CharSequence... searchCharSequences) {
  1152.         return containsAny(StringUtils::containsIgnoreCase, cs, searchCharSequences);
  1153.     }

  1154.     /**
  1155.      * Checks if CharSequence contains a search CharSequence irrespective of case,
  1156.      * handling {@code null}. Case-insensitivity is defined as by
  1157.      * {@link String#equalsIgnoreCase(String)}.
  1158.      *
  1159.      * <p>A {@code null} CharSequence will return {@code false}.
  1160.      *
  1161.      * <pre>
  1162.      * StringUtils.containsIgnoreCase(null, *)    = false
  1163.      * StringUtils.containsIgnoreCase(*, null)    = false
  1164.      * StringUtils.containsIgnoreCase("", "")     = true
  1165.      * StringUtils.containsIgnoreCase("abc", "")  = true
  1166.      * StringUtils.containsIgnoreCase("abc", "a") = true
  1167.      * StringUtils.containsIgnoreCase("abc", "z") = false
  1168.      * StringUtils.containsIgnoreCase("abc", "A") = true
  1169.      * StringUtils.containsIgnoreCase("abc", "Z") = false
  1170.      * </pre>
  1171.      *
  1172.      * @param str  the CharSequence to check, may be null
  1173.      * @param searchStr  the CharSequence to find, may be null
  1174.      * @return true if the CharSequence contains the search CharSequence irrespective of
  1175.      * case or false if not or {@code null} string input
  1176.      * @since 3.0 Changed signature from containsIgnoreCase(String, String) to containsIgnoreCase(CharSequence, CharSequence)
  1177.      */
  1178.     public static boolean containsIgnoreCase(final CharSequence str, final CharSequence searchStr) {
  1179.         if (str == null || searchStr == null) {
  1180.             return false;
  1181.         }
  1182.         final int len = searchStr.length();
  1183.         final int max = str.length() - len;
  1184.         for (int i = 0; i <= max; i++) {
  1185.             if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, len)) {
  1186.                 return true;
  1187.             }
  1188.         }
  1189.         return false;
  1190.     }

  1191.     /**
  1192.      * Checks that the CharSequence does not contain certain characters.
  1193.      *
  1194.      * <p>A {@code null} CharSequence will return {@code true}.
  1195.      * A {@code null} invalid character array will return {@code true}.
  1196.      * An empty CharSequence (length()=0) always returns true.</p>
  1197.      *
  1198.      * <pre>
  1199.      * StringUtils.containsNone(null, *)       = true
  1200.      * StringUtils.containsNone(*, null)       = true
  1201.      * StringUtils.containsNone("", *)         = true
  1202.      * StringUtils.containsNone("ab", '')      = true
  1203.      * StringUtils.containsNone("abab", 'xyz') = true
  1204.      * StringUtils.containsNone("ab1", 'xyz')  = true
  1205.      * StringUtils.containsNone("abz", 'xyz')  = false
  1206.      * </pre>
  1207.      *
  1208.      * @param cs  the CharSequence to check, may be null
  1209.      * @param searchChars  an array of invalid chars, may be null
  1210.      * @return true if it contains none of the invalid chars, or is null
  1211.      * @since 2.0
  1212.      * @since 3.0 Changed signature from containsNone(String, char[]) to containsNone(CharSequence, char...)
  1213.      */
  1214.     public static boolean containsNone(final CharSequence cs, final char... searchChars) {
  1215.         if (cs == null || searchChars == null) {
  1216.             return true;
  1217.         }
  1218.         final int csLen = cs.length();
  1219.         final int csLast = csLen - 1;
  1220.         final int searchLen = searchChars.length;
  1221.         final int searchLast = searchLen - 1;
  1222.         for (int i = 0; i < csLen; i++) {
  1223.             final char ch = cs.charAt(i);
  1224.             for (int j = 0; j < searchLen; j++) {
  1225.                 if (searchChars[j] == ch) {
  1226.                     if (!Character.isHighSurrogate(ch)) {
  1227.                         // ch is in the Basic Multilingual Plane
  1228.                         return false;
  1229.                     }
  1230.                     if (j == searchLast) {
  1231.                         // missing low surrogate, fine, like String.indexOf(String)
  1232.                         return false;
  1233.                     }
  1234.                     if (i < csLast && searchChars[j + 1] == cs.charAt(i + 1)) {
  1235.                         return false;
  1236.                     }
  1237.                 }
  1238.             }
  1239.         }
  1240.         return true;
  1241.     }

  1242.     /**
  1243.      * Checks that the CharSequence does not contain certain characters.
  1244.      *
  1245.      * <p>A {@code null} CharSequence will return {@code true}.
  1246.      * A {@code null} invalid character array will return {@code true}.
  1247.      * An empty String ("") always returns true.</p>
  1248.      *
  1249.      * <pre>
  1250.      * StringUtils.containsNone(null, *)       = true
  1251.      * StringUtils.containsNone(*, null)       = true
  1252.      * StringUtils.containsNone("", *)         = true
  1253.      * StringUtils.containsNone("ab", "")      = true
  1254.      * StringUtils.containsNone("abab", "xyz") = true
  1255.      * StringUtils.containsNone("ab1", "xyz")  = true
  1256.      * StringUtils.containsNone("abz", "xyz")  = false
  1257.      * </pre>
  1258.      *
  1259.      * @param cs  the CharSequence to check, may be null
  1260.      * @param invalidChars  a String of invalid chars, may be null
  1261.      * @return true if it contains none of the invalid chars, or is null
  1262.      * @since 2.0
  1263.      * @since 3.0 Changed signature from containsNone(String, String) to containsNone(CharSequence, String)
  1264.      */
  1265.     public static boolean containsNone(final CharSequence cs, final String invalidChars) {
  1266.         if (invalidChars == null) {
  1267.             return true;
  1268.         }
  1269.         return containsNone(cs, invalidChars.toCharArray());
  1270.     }

  1271.     /**
  1272.      * Checks if the CharSequence contains only certain characters.
  1273.      *
  1274.      * <p>A {@code null} CharSequence will return {@code false}.
  1275.      * A {@code null} valid character array will return {@code false}.
  1276.      * An empty CharSequence (length()=0) always returns {@code true}.</p>
  1277.      *
  1278.      * <pre>
  1279.      * StringUtils.containsOnly(null, *)       = false
  1280.      * StringUtils.containsOnly(*, null)       = false
  1281.      * StringUtils.containsOnly("", *)         = true
  1282.      * StringUtils.containsOnly("ab", '')      = false
  1283.      * StringUtils.containsOnly("abab", 'abc') = true
  1284.      * StringUtils.containsOnly("ab1", 'abc')  = false
  1285.      * StringUtils.containsOnly("abz", 'abc')  = false
  1286.      * </pre>
  1287.      *
  1288.      * @param cs  the String to check, may be null
  1289.      * @param valid  an array of valid chars, may be null
  1290.      * @return true if it only contains valid chars and is non-null
  1291.      * @since 3.0 Changed signature from containsOnly(String, char[]) to containsOnly(CharSequence, char...)
  1292.      */
  1293.     public static boolean containsOnly(final CharSequence cs, final char... valid) {
  1294.         // All these pre-checks are to maintain API with an older version
  1295.         if (valid == null || cs == null) {
  1296.             return false;
  1297.         }
  1298.         if (cs.length() == 0) {
  1299.             return true;
  1300.         }
  1301.         if (valid.length == 0) {
  1302.             return false;
  1303.         }
  1304.         return indexOfAnyBut(cs, valid) == INDEX_NOT_FOUND;
  1305.     }

  1306.     /**
  1307.      * Checks if the CharSequence contains only certain characters.
  1308.      *
  1309.      * <p>A {@code null} CharSequence will return {@code false}.
  1310.      * A {@code null} valid character String will return {@code false}.
  1311.      * An empty String (length()=0) always returns {@code true}.</p>
  1312.      *
  1313.      * <pre>
  1314.      * StringUtils.containsOnly(null, *)       = false
  1315.      * StringUtils.containsOnly(*, null)       = false
  1316.      * StringUtils.containsOnly("", *)         = true
  1317.      * StringUtils.containsOnly("ab", "")      = false
  1318.      * StringUtils.containsOnly("abab", "abc") = true
  1319.      * StringUtils.containsOnly("ab1", "abc")  = false
  1320.      * StringUtils.containsOnly("abz", "abc")  = false
  1321.      * </pre>
  1322.      *
  1323.      * @param cs  the CharSequence to check, may be null
  1324.      * @param validChars  a String of valid chars, may be null
  1325.      * @return true if it only contains valid chars and is non-null
  1326.      * @since 2.0
  1327.      * @since 3.0 Changed signature from containsOnly(String, String) to containsOnly(CharSequence, String)
  1328.      */
  1329.     public static boolean containsOnly(final CharSequence cs, final String validChars) {
  1330.         if (cs == null || validChars == null) {
  1331.             return false;
  1332.         }
  1333.         return containsOnly(cs, validChars.toCharArray());
  1334.     }

  1335.     /**
  1336.      * Check whether the given CharSequence contains any whitespace characters.
  1337.      *
  1338.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  1339.      *
  1340.      * @param seq the CharSequence to check (may be {@code null})
  1341.      * @return {@code true} if the CharSequence is not empty and
  1342.      * contains at least 1 (breaking) whitespace character
  1343.      * @since 3.0
  1344.      */
  1345.     // From org.springframework.util.StringUtils, under Apache License 2.0
  1346.     public static boolean containsWhitespace(final CharSequence seq) {
  1347.         if (isEmpty(seq)) {
  1348.             return false;
  1349.         }
  1350.         final int strLen = seq.length();
  1351.         for (int i = 0; i < strLen; i++) {
  1352.             if (Character.isWhitespace(seq.charAt(i))) {
  1353.                 return true;
  1354.             }
  1355.         }
  1356.         return false;
  1357.     }

  1358.     private static void convertRemainingAccentCharacters(final StringBuilder decomposed) {
  1359.         for (int i = 0; i < decomposed.length(); i++) {
  1360.             final char charAt = decomposed.charAt(i);
  1361.             switch (charAt) {
  1362.             case '\u0141':
  1363.                 decomposed.setCharAt(i, 'L');
  1364.                 break;
  1365.             case '\u0142':
  1366.                 decomposed.setCharAt(i, 'l');
  1367.                 break;
  1368.             // D with stroke
  1369.             case '\u0110':
  1370.                 // LATIN CAPITAL LETTER D WITH STROKE
  1371.                 decomposed.setCharAt(i, 'D');
  1372.                 break;
  1373.             case '\u0111':
  1374.                 // LATIN SMALL LETTER D WITH STROKE
  1375.                 decomposed.setCharAt(i, 'd');
  1376.                 break;
  1377.             // I with bar
  1378.             case '\u0197':
  1379.                 decomposed.setCharAt(i, 'I');
  1380.                 break;
  1381.             case '\u0268':
  1382.                 decomposed.setCharAt(i, 'i');
  1383.                 break;
  1384.             case '\u1D7B':
  1385.                 decomposed.setCharAt(i, 'I');
  1386.                 break;
  1387.             case '\u1DA4':
  1388.                 decomposed.setCharAt(i, 'i');
  1389.                 break;
  1390.             case '\u1DA7':
  1391.                 decomposed.setCharAt(i, 'I');
  1392.                 break;
  1393.             // U with bar
  1394.             case '\u0244':
  1395.                 // LATIN CAPITAL LETTER U BAR
  1396.                 decomposed.setCharAt(i, 'U');
  1397.                 break;
  1398.             case '\u0289':
  1399.                 // LATIN SMALL LETTER U BAR
  1400.                 decomposed.setCharAt(i, 'u');
  1401.                 break;
  1402.             case '\u1D7E':
  1403.                 // LATIN SMALL CAPITAL LETTER U WITH STROKE
  1404.                 decomposed.setCharAt(i, 'U');
  1405.                 break;
  1406.             case '\u1DB6':
  1407.                 // MODIFIER LETTER SMALL U BAR
  1408.                 decomposed.setCharAt(i, 'u');
  1409.                 break;
  1410.             // T with stroke
  1411.             case '\u0166':
  1412.                 // LATIN CAPITAL LETTER T WITH STROKE
  1413.                 decomposed.setCharAt(i, 'T');
  1414.                 break;
  1415.             case '\u0167':
  1416.                 // LATIN SMALL LETTER T WITH STROKE
  1417.                 decomposed.setCharAt(i, 't');
  1418.                 break;
  1419.             default:
  1420.                 break;
  1421.             }
  1422.         }
  1423.     }

  1424.     /**
  1425.      * Counts how many times the char appears in the given string.
  1426.      *
  1427.      * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
  1428.      *
  1429.      * <pre>
  1430.      * StringUtils.countMatches(null, *)     = 0
  1431.      * StringUtils.countMatches("", *)       = 0
  1432.      * StringUtils.countMatches("abba", 0)   = 0
  1433.      * StringUtils.countMatches("abba", 'a') = 2
  1434.      * StringUtils.countMatches("abba", 'b') = 2
  1435.      * StringUtils.countMatches("abba", 'x') = 0
  1436.      * </pre>
  1437.      *
  1438.      * @param str  the CharSequence to check, may be null
  1439.      * @param ch  the char to count
  1440.      * @return the number of occurrences, 0 if the CharSequence is {@code null}
  1441.      * @since 3.4
  1442.      */
  1443.     public static int countMatches(final CharSequence str, final char ch) {
  1444.         if (isEmpty(str)) {
  1445.             return 0;
  1446.         }
  1447.         int count = 0;
  1448.         // We could also call str.toCharArray() for faster lookups but that would generate more garbage.
  1449.         for (int i = 0; i < str.length(); i++) {
  1450.             if (ch == str.charAt(i)) {
  1451.                 count++;
  1452.             }
  1453.         }
  1454.         return count;
  1455.     }

  1456.     /**
  1457.      * Counts how many times the substring appears in the larger string.
  1458.      * Note that the code only counts non-overlapping matches.
  1459.      *
  1460.      * <p>A {@code null} or empty ("") String input returns {@code 0}.</p>
  1461.      *
  1462.      * <pre>
  1463.      * StringUtils.countMatches(null, *)        = 0
  1464.      * StringUtils.countMatches("", *)          = 0
  1465.      * StringUtils.countMatches("abba", null)   = 0
  1466.      * StringUtils.countMatches("abba", "")     = 0
  1467.      * StringUtils.countMatches("abba", "a")    = 2
  1468.      * StringUtils.countMatches("abba", "ab")   = 1
  1469.      * StringUtils.countMatches("abba", "xxx")  = 0
  1470.      * StringUtils.countMatches("ababa", "aba") = 1
  1471.      * </pre>
  1472.      *
  1473.      * @param str  the CharSequence to check, may be null
  1474.      * @param sub  the substring to count, may be null
  1475.      * @return the number of occurrences, 0 if either CharSequence is {@code null}
  1476.      * @since 3.0 Changed signature from countMatches(String, String) to countMatches(CharSequence, CharSequence)
  1477.      */
  1478.     public static int countMatches(final CharSequence str, final CharSequence sub) {
  1479.         if (isEmpty(str) || isEmpty(sub)) {
  1480.             return 0;
  1481.         }
  1482.         int count = 0;
  1483.         int idx = 0;
  1484.         while ((idx = CharSequenceUtils.indexOf(str, sub, idx)) != INDEX_NOT_FOUND) {
  1485.             count++;
  1486.             idx += sub.length();
  1487.         }
  1488.         return count;
  1489.     }

  1490.     /**
  1491.      * Returns either the passed in CharSequence, or if the CharSequence is
  1492.      * whitespace, empty ("") or {@code null}, the value of {@code defaultStr}.
  1493.      *
  1494.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  1495.      *
  1496.      * <pre>
  1497.      * StringUtils.defaultIfBlank(null, "NULL")  = "NULL"
  1498.      * StringUtils.defaultIfBlank("", "NULL")    = "NULL"
  1499.      * StringUtils.defaultIfBlank(" ", "NULL")   = "NULL"
  1500.      * StringUtils.defaultIfBlank("bat", "NULL") = "bat"
  1501.      * StringUtils.defaultIfBlank("", null)      = null
  1502.      * </pre>
  1503.      * @param <T> the specific kind of CharSequence
  1504.      * @param str the CharSequence to check, may be null
  1505.      * @param defaultStr  the default CharSequence to return
  1506.      *  if the input is whitespace, empty ("") or {@code null}, may be null
  1507.      * @return the passed in CharSequence, or the default
  1508.      * @see StringUtils#defaultString(String, String)
  1509.      */
  1510.     public static <T extends CharSequence> T defaultIfBlank(final T str, final T defaultStr) {
  1511.         return isBlank(str) ? defaultStr : str;
  1512.     }

  1513.     /**
  1514.      * Returns either the passed in CharSequence, or if the CharSequence is
  1515.      * empty or {@code null}, the value of {@code defaultStr}.
  1516.      *
  1517.      * <pre>
  1518.      * StringUtils.defaultIfEmpty(null, "NULL")  = "NULL"
  1519.      * StringUtils.defaultIfEmpty("", "NULL")    = "NULL"
  1520.      * StringUtils.defaultIfEmpty(" ", "NULL")   = " "
  1521.      * StringUtils.defaultIfEmpty("bat", "NULL") = "bat"
  1522.      * StringUtils.defaultIfEmpty("", null)      = null
  1523.      * </pre>
  1524.      * @param <T> the specific kind of CharSequence
  1525.      * @param str  the CharSequence to check, may be null
  1526.      * @param defaultStr  the default CharSequence to return
  1527.      *  if the input is empty ("") or {@code null}, may be null
  1528.      * @return the passed in CharSequence, or the default
  1529.      * @see StringUtils#defaultString(String, String)
  1530.      */
  1531.     public static <T extends CharSequence> T defaultIfEmpty(final T str, final T defaultStr) {
  1532.         return isEmpty(str) ? defaultStr : str;
  1533.     }

  1534.     /**
  1535.      * Returns either the passed in String,
  1536.      * or if the String is {@code null}, an empty String ("").
  1537.      *
  1538.      * <pre>
  1539.      * StringUtils.defaultString(null)  = ""
  1540.      * StringUtils.defaultString("")    = ""
  1541.      * StringUtils.defaultString("bat") = "bat"
  1542.      * </pre>
  1543.      *
  1544.      * @see Objects#toString(Object, String)
  1545.      * @see String#valueOf(Object)
  1546.      * @param str  the String to check, may be null
  1547.      * @return the passed in String, or the empty String if it
  1548.      *  was {@code null}
  1549.      */
  1550.     public static String defaultString(final String str) {
  1551.         return Objects.toString(str, EMPTY);
  1552.     }

  1553.     /**
  1554.      * Returns either the given String, or if the String is
  1555.      * {@code null}, {@code nullDefault}.
  1556.      *
  1557.      * <pre>
  1558.      * StringUtils.defaultString(null, "NULL")  = "NULL"
  1559.      * StringUtils.defaultString("", "NULL")    = ""
  1560.      * StringUtils.defaultString("bat", "NULL") = "bat"
  1561.      * </pre>
  1562.      * <p>
  1563.      * Since this is now provided by Java, instead call {@link Objects#toString(Object, String)}:
  1564.      * </p>
  1565.      * <pre>
  1566.      * Objects.toString(null, "NULL")  = "NULL"
  1567.      * Objects.toString("", "NULL")    = ""
  1568.      * Objects.toString("bat", "NULL") = "bat"
  1569.      * </pre>
  1570.      *
  1571.      * @see Objects#toString(Object, String)
  1572.      * @see String#valueOf(Object)
  1573.      * @param str  the String to check, may be null
  1574.      * @param nullDefault  the default String to return
  1575.      *  if the input is {@code null}, may be null
  1576.      * @return the passed in String, or the default if it was {@code null}
  1577.      * @deprecated Use {@link Objects#toString(Object, String)}
  1578.      */
  1579.     @Deprecated
  1580.     public static String defaultString(final String str, final String nullDefault) {
  1581.         return Objects.toString(str, nullDefault);
  1582.     }

  1583.     /**
  1584.      * Deletes all whitespaces from a String as defined by
  1585.      * {@link Character#isWhitespace(char)}.
  1586.      *
  1587.      * <pre>
  1588.      * StringUtils.deleteWhitespace(null)         = null
  1589.      * StringUtils.deleteWhitespace("")           = ""
  1590.      * StringUtils.deleteWhitespace("abc")        = "abc"
  1591.      * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
  1592.      * </pre>
  1593.      *
  1594.      * @param str  the String to delete whitespace from, may be null
  1595.      * @return the String without whitespaces, {@code null} if null String input
  1596.      */
  1597.     public static String deleteWhitespace(final String str) {
  1598.         if (isEmpty(str)) {
  1599.             return str;
  1600.         }
  1601.         final int sz = str.length();
  1602.         final char[] chs = new char[sz];
  1603.         int count = 0;
  1604.         for (int i = 0; i < sz; i++) {
  1605.             if (!Character.isWhitespace(str.charAt(i))) {
  1606.                 chs[count++] = str.charAt(i);
  1607.             }
  1608.         }
  1609.         if (count == sz) {
  1610.             return str;
  1611.         }
  1612.         if (count == 0) {
  1613.             return EMPTY;
  1614.         }
  1615.         return new String(chs, 0, count);
  1616.     }

  1617.     /**
  1618.      * Compares two Strings, and returns the portion where they differ.
  1619.      * More precisely, return the remainder of the second String,
  1620.      * starting from where it's different from the first. This means that
  1621.      * the difference between "abc" and "ab" is the empty String and not "c".
  1622.      *
  1623.      * <p>For example,
  1624.      * {@code difference("i am a machine", "i am a robot") -> "robot"}.</p>
  1625.      *
  1626.      * <pre>
  1627.      * StringUtils.difference(null, null)       = null
  1628.      * StringUtils.difference("", "")           = ""
  1629.      * StringUtils.difference("", "abc")        = "abc"
  1630.      * StringUtils.difference("abc", "")        = ""
  1631.      * StringUtils.difference("abc", "abc")     = ""
  1632.      * StringUtils.difference("abc", "ab")      = ""
  1633.      * StringUtils.difference("ab", "abxyz")    = "xyz"
  1634.      * StringUtils.difference("abcde", "abxyz") = "xyz"
  1635.      * StringUtils.difference("abcde", "xyz")   = "xyz"
  1636.      * </pre>
  1637.      *
  1638.      * @param str1  the first String, may be null
  1639.      * @param str2  the second String, may be null
  1640.      * @return the portion of str2 where it differs from str1; returns the
  1641.      * empty String if they are equal
  1642.      * @see #indexOfDifference(CharSequence,CharSequence)
  1643.      * @since 2.0
  1644.      */
  1645.     public static String difference(final String str1, final String str2) {
  1646.         if (str1 == null) {
  1647.             return str2;
  1648.         }
  1649.         if (str2 == null) {
  1650.             return str1;
  1651.         }
  1652.         final int at = indexOfDifference(str1, str2);
  1653.         if (at == INDEX_NOT_FOUND) {
  1654.             return EMPTY;
  1655.         }
  1656.         return str2.substring(at);
  1657.     }

  1658.     /**
  1659.      * Check if a CharSequence ends with a specified suffix.
  1660.      *
  1661.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  1662.      * references are considered to be equal. The comparison is case-sensitive.</p>
  1663.      *
  1664.      * <pre>
  1665.      * StringUtils.endsWith(null, null)      = true
  1666.      * StringUtils.endsWith(null, "def")     = false
  1667.      * StringUtils.endsWith("abcdef", null)  = false
  1668.      * StringUtils.endsWith("abcdef", "def") = true
  1669.      * StringUtils.endsWith("ABCDEF", "def") = false
  1670.      * StringUtils.endsWith("ABCDEF", "cde") = false
  1671.      * StringUtils.endsWith("ABCDEF", "")    = true
  1672.      * </pre>
  1673.      *
  1674.      * @see String#endsWith(String)
  1675.      * @param str  the CharSequence to check, may be null
  1676.      * @param suffix the suffix to find, may be null
  1677.      * @return {@code true} if the CharSequence ends with the suffix, case-sensitive, or
  1678.      *  both {@code null}
  1679.      * @since 2.4
  1680.      * @since 3.0 Changed signature from endsWith(String, String) to endsWith(CharSequence, CharSequence)
  1681.      */
  1682.     public static boolean endsWith(final CharSequence str, final CharSequence suffix) {
  1683.         return endsWith(str, suffix, false);
  1684.     }

  1685.     /**
  1686.      * Check if a CharSequence ends with a specified suffix (optionally case-insensitive).
  1687.      *
  1688.      * @see String#endsWith(String)
  1689.      * @param str  the CharSequence to check, may be null
  1690.      * @param suffix the suffix to find, may be null
  1691.      * @param ignoreCase indicates whether the compare should ignore case
  1692.      *  (case-insensitive) or not.
  1693.      * @return {@code true} if the CharSequence starts with the prefix or
  1694.      *  both {@code null}
  1695.      */
  1696.     private static boolean endsWith(final CharSequence str, final CharSequence suffix, final boolean ignoreCase) {
  1697.         if (str == null || suffix == null) {
  1698.             return str == suffix;
  1699.         }
  1700.         if (suffix.length() > str.length()) {
  1701.             return false;
  1702.         }
  1703.         final int strOffset = str.length() - suffix.length();
  1704.         return CharSequenceUtils.regionMatches(str, ignoreCase, strOffset, suffix, 0, suffix.length());
  1705.     }

  1706.     /**
  1707.      * Check if a CharSequence ends with any of the provided case-sensitive suffixes.
  1708.      *
  1709.      * <pre>
  1710.      * StringUtils.endsWithAny(null, null)                  = false
  1711.      * StringUtils.endsWithAny(null, new String[] {"abc"})  = false
  1712.      * StringUtils.endsWithAny("abcxyz", null)              = false
  1713.      * StringUtils.endsWithAny("abcxyz", new String[] {""}) = true
  1714.      * StringUtils.endsWithAny("abcxyz", new String[] {"xyz"}) = true
  1715.      * StringUtils.endsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
  1716.      * StringUtils.endsWithAny("abcXYZ", "def", "XYZ")      = true
  1717.      * StringUtils.endsWithAny("abcXYZ", "def", "xyz")      = false
  1718.      * </pre>
  1719.      *
  1720.      * @param sequence  the CharSequence to check, may be null
  1721.      * @param searchStrings the case-sensitive CharSequences to find, may be empty or contain {@code null}
  1722.      * @see StringUtils#endsWith(CharSequence, CharSequence)
  1723.      * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
  1724.      *   the input {@code sequence} ends in any of the provided case-sensitive {@code searchStrings}.
  1725.      * @since 3.0
  1726.      */
  1727.     public static boolean endsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
  1728.         if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
  1729.             return false;
  1730.         }
  1731.         for (final CharSequence searchString : searchStrings) {
  1732.             if (endsWith(sequence, searchString)) {
  1733.                 return true;
  1734.             }
  1735.         }
  1736.         return false;
  1737.     }

  1738.     /**
  1739.      * Case-insensitive check if a CharSequence ends with a specified suffix.
  1740.      *
  1741.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  1742.      * references are considered to be equal. The comparison is case insensitive.</p>
  1743.      *
  1744.      * <pre>
  1745.      * StringUtils.endsWithIgnoreCase(null, null)      = true
  1746.      * StringUtils.endsWithIgnoreCase(null, "def")     = false
  1747.      * StringUtils.endsWithIgnoreCase("abcdef", null)  = false
  1748.      * StringUtils.endsWithIgnoreCase("abcdef", "def") = true
  1749.      * StringUtils.endsWithIgnoreCase("ABCDEF", "def") = true
  1750.      * StringUtils.endsWithIgnoreCase("ABCDEF", "cde") = false
  1751.      * </pre>
  1752.      *
  1753.      * @see String#endsWith(String)
  1754.      * @param str  the CharSequence to check, may be null
  1755.      * @param suffix the suffix to find, may be null
  1756.      * @return {@code true} if the CharSequence ends with the suffix, case-insensitive, or
  1757.      *  both {@code null}
  1758.      * @since 2.4
  1759.      * @since 3.0 Changed signature from endsWithIgnoreCase(String, String) to endsWithIgnoreCase(CharSequence, CharSequence)
  1760.      */
  1761.     public static boolean endsWithIgnoreCase(final CharSequence str, final CharSequence suffix) {
  1762.         return endsWith(str, suffix, true);
  1763.     }

  1764.     /**
  1765.      * Compares two CharSequences, returning {@code true} if they represent
  1766.      * equal sequences of characters.
  1767.      *
  1768.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  1769.      * references are considered to be equal. The comparison is <strong>case-sensitive</strong>.</p>
  1770.      *
  1771.      * <pre>
  1772.      * StringUtils.equals(null, null)   = true
  1773.      * StringUtils.equals(null, "abc")  = false
  1774.      * StringUtils.equals("abc", null)  = false
  1775.      * StringUtils.equals("abc", "abc") = true
  1776.      * StringUtils.equals("abc", "ABC") = false
  1777.      * </pre>
  1778.      *
  1779.      * @param cs1  the first CharSequence, may be {@code null}
  1780.      * @param cs2  the second CharSequence, may be {@code null}
  1781.      * @return {@code true} if the CharSequences are equal (case-sensitive), or both {@code null}
  1782.      * @since 3.0 Changed signature from equals(String, String) to equals(CharSequence, CharSequence)
  1783.      * @see Object#equals(Object)
  1784.      * @see #equalsIgnoreCase(CharSequence, CharSequence)
  1785.      */
  1786.     public static boolean equals(final CharSequence cs1, final CharSequence cs2) {
  1787.         if (cs1 == cs2) {
  1788.             return true;
  1789.         }
  1790.         if (cs1 == null || cs2 == null) {
  1791.             return false;
  1792.         }
  1793.         if (cs1.length() != cs2.length()) {
  1794.             return false;
  1795.         }
  1796.         if (cs1 instanceof String && cs2 instanceof String) {
  1797.             return cs1.equals(cs2);
  1798.         }
  1799.         // Step-wise comparison
  1800.         final int length = cs1.length();
  1801.         for (int i = 0; i < length; i++) {
  1802.             if (cs1.charAt(i) != cs2.charAt(i)) {
  1803.                 return false;
  1804.             }
  1805.         }
  1806.         return true;
  1807.     }

  1808.     /**
  1809.      * Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
  1810.      * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}.
  1811.      *
  1812.      * <pre>
  1813.      * StringUtils.equalsAny(null, (CharSequence[]) null) = false
  1814.      * StringUtils.equalsAny(null, null, null)    = true
  1815.      * StringUtils.equalsAny(null, "abc", "def")  = false
  1816.      * StringUtils.equalsAny("abc", null, "def")  = false
  1817.      * StringUtils.equalsAny("abc", "abc", "def") = true
  1818.      * StringUtils.equalsAny("abc", "ABC", "DEF") = false
  1819.      * </pre>
  1820.      *
  1821.      * @param string to compare, may be {@code null}.
  1822.      * @param searchStrings a vararg of strings, may be {@code null}.
  1823.      * @return {@code true} if the string is equal (case-sensitive) to any other element of {@code searchStrings};
  1824.      * {@code false} if {@code searchStrings} is null or contains no matches.
  1825.      * @since 3.5
  1826.      */
  1827.     public static boolean equalsAny(final CharSequence string, final CharSequence... searchStrings) {
  1828.         if (ArrayUtils.isNotEmpty(searchStrings)) {
  1829.             for (final CharSequence next : searchStrings) {
  1830.                 if (equals(string, next)) {
  1831.                     return true;
  1832.                 }
  1833.             }
  1834.         }
  1835.         return false;
  1836.     }

  1837.     /**
  1838.      * Compares given {@code string} to a CharSequences vararg of {@code searchStrings},
  1839.      * returning {@code true} if the {@code string} is equal to any of the {@code searchStrings}, ignoring case.
  1840.      *
  1841.      * <pre>
  1842.      * StringUtils.equalsAnyIgnoreCase(null, (CharSequence[]) null) = false
  1843.      * StringUtils.equalsAnyIgnoreCase(null, null, null)    = true
  1844.      * StringUtils.equalsAnyIgnoreCase(null, "abc", "def")  = false
  1845.      * StringUtils.equalsAnyIgnoreCase("abc", null, "def")  = false
  1846.      * StringUtils.equalsAnyIgnoreCase("abc", "abc", "def") = true
  1847.      * StringUtils.equalsAnyIgnoreCase("abc", "ABC", "DEF") = true
  1848.      * </pre>
  1849.      *
  1850.      * @param string to compare, may be {@code null}.
  1851.      * @param searchStrings a vararg of strings, may be {@code null}.
  1852.      * @return {@code true} if the string is equal (case-insensitive) to any other element of {@code searchStrings};
  1853.      * {@code false} if {@code searchStrings} is null or contains no matches.
  1854.      * @since 3.5
  1855.      */
  1856.     public static boolean equalsAnyIgnoreCase(final CharSequence string, final CharSequence... searchStrings) {
  1857.         if (ArrayUtils.isNotEmpty(searchStrings)) {
  1858.             for (final CharSequence next : searchStrings) {
  1859.                 if (equalsIgnoreCase(string, next)) {
  1860.                     return true;
  1861.                 }
  1862.             }
  1863.         }
  1864.         return false;
  1865.     }

  1866.     /**
  1867.      * Compares two CharSequences, returning {@code true} if they represent
  1868.      * equal sequences of characters, ignoring case.
  1869.      *
  1870.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  1871.      * references are considered equal. The comparison is <strong>case insensitive</strong>.</p>
  1872.      *
  1873.      * <pre>
  1874.      * StringUtils.equalsIgnoreCase(null, null)   = true
  1875.      * StringUtils.equalsIgnoreCase(null, "abc")  = false
  1876.      * StringUtils.equalsIgnoreCase("abc", null)  = false
  1877.      * StringUtils.equalsIgnoreCase("abc", "abc") = true
  1878.      * StringUtils.equalsIgnoreCase("abc", "ABC") = true
  1879.      * </pre>
  1880.      *
  1881.      * @param cs1  the first CharSequence, may be {@code null}
  1882.      * @param cs2  the second CharSequence, may be {@code null}
  1883.      * @return {@code true} if the CharSequences are equal (case-insensitive), or both {@code null}
  1884.      * @since 3.0 Changed signature from equalsIgnoreCase(String, String) to equalsIgnoreCase(CharSequence, CharSequence)
  1885.      * @see #equals(CharSequence, CharSequence)
  1886.      */
  1887.     public static boolean equalsIgnoreCase(final CharSequence cs1, final CharSequence cs2) {
  1888.         if (cs1 == cs2) {
  1889.             return true;
  1890.         }
  1891.         if (cs1 == null || cs2 == null) {
  1892.             return false;
  1893.         }
  1894.         if (cs1.length() != cs2.length()) {
  1895.             return false;
  1896.         }
  1897.         return CharSequenceUtils.regionMatches(cs1, true, 0, cs2, 0, cs1.length());
  1898.     }

  1899.     /**
  1900.      * Returns the first value in the array which is not empty (""),
  1901.      * {@code null} or whitespace only.
  1902.      *
  1903.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  1904.      *
  1905.      * <p>If all values are blank or the array is {@code null}
  1906.      * or empty then {@code null} is returned.</p>
  1907.      *
  1908.      * <pre>
  1909.      * StringUtils.firstNonBlank(null, null, null)     = null
  1910.      * StringUtils.firstNonBlank(null, "", " ")        = null
  1911.      * StringUtils.firstNonBlank("abc")                = "abc"
  1912.      * StringUtils.firstNonBlank(null, "xyz")          = "xyz"
  1913.      * StringUtils.firstNonBlank(null, "", " ", "xyz") = "xyz"
  1914.      * StringUtils.firstNonBlank(null, "xyz", "abc")   = "xyz"
  1915.      * StringUtils.firstNonBlank()                     = null
  1916.      * </pre>
  1917.      *
  1918.      * @param <T> the specific kind of CharSequence
  1919.      * @param values  the values to test, may be {@code null} or empty
  1920.      * @return the first value from {@code values} which is not blank,
  1921.      *  or {@code null} if there are no non-blank values
  1922.      * @since 3.8
  1923.      */
  1924.     @SafeVarargs
  1925.     public static <T extends CharSequence> T firstNonBlank(final T... values) {
  1926.         if (values != null) {
  1927.             for (final T val : values) {
  1928.                 if (isNotBlank(val)) {
  1929.                     return val;
  1930.                 }
  1931.             }
  1932.         }
  1933.         return null;
  1934.     }

  1935.     /**
  1936.      * Returns the first value in the array which is not empty.
  1937.      *
  1938.      * <p>If all values are empty or the array is {@code null}
  1939.      * or empty then {@code null} is returned.</p>
  1940.      *
  1941.      * <pre>
  1942.      * StringUtils.firstNonEmpty(null, null, null)   = null
  1943.      * StringUtils.firstNonEmpty(null, null, "")     = null
  1944.      * StringUtils.firstNonEmpty(null, "", " ")      = " "
  1945.      * StringUtils.firstNonEmpty("abc")              = "abc"
  1946.      * StringUtils.firstNonEmpty(null, "xyz")        = "xyz"
  1947.      * StringUtils.firstNonEmpty("", "xyz")          = "xyz"
  1948.      * StringUtils.firstNonEmpty(null, "xyz", "abc") = "xyz"
  1949.      * StringUtils.firstNonEmpty()                   = null
  1950.      * </pre>
  1951.      *
  1952.      * @param <T> the specific kind of CharSequence
  1953.      * @param values  the values to test, may be {@code null} or empty
  1954.      * @return the first value from {@code values} which is not empty,
  1955.      *  or {@code null} if there are no non-empty values
  1956.      * @since 3.8
  1957.      */
  1958.     @SafeVarargs
  1959.     public static <T extends CharSequence> T firstNonEmpty(final T... values) {
  1960.         if (values != null) {
  1961.             for (final T val : values) {
  1962.                 if (isNotEmpty(val)) {
  1963.                     return val;
  1964.                 }
  1965.             }
  1966.         }
  1967.         return null;
  1968.     }

  1969.     /**
  1970.      * Calls {@link String#getBytes(Charset)} in a null-safe manner.
  1971.      *
  1972.      * @param string input string
  1973.      * @param charset The {@link Charset} to encode the {@link String}. If null, then use the default Charset.
  1974.      * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(Charset)} otherwise.
  1975.      * @see String#getBytes(Charset)
  1976.      * @since 3.10
  1977.      */
  1978.     public static byte[] getBytes(final String string, final Charset charset) {
  1979.         return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharset(charset));
  1980.     }

  1981.     /**
  1982.      * Calls {@link String#getBytes(String)} in a null-safe manner.
  1983.      *
  1984.      * @param string input string
  1985.      * @param charset The {@link Charset} name to encode the {@link String}. If null, then use the default Charset.
  1986.      * @return The empty byte[] if {@code string} is null, the result of {@link String#getBytes(String)} otherwise.
  1987.      * @throws UnsupportedEncodingException Thrown when the named charset is not supported.
  1988.      * @see String#getBytes(String)
  1989.      * @since 3.10
  1990.      */
  1991.     public static byte[] getBytes(final String string, final String charset) throws UnsupportedEncodingException {
  1992.         return string == null ? ArrayUtils.EMPTY_BYTE_ARRAY : string.getBytes(Charsets.toCharsetName(charset));
  1993.     }

  1994.     /**
  1995.      * Compares all Strings in an array and returns the initial sequence of
  1996.      * characters that is common to all of them.
  1997.      *
  1998.      * <p>For example,
  1999.      * {@code getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) -&gt; "i am a "}</p>
  2000.      *
  2001.      * <pre>
  2002.      * StringUtils.getCommonPrefix(null)                             = ""
  2003.      * StringUtils.getCommonPrefix(new String[] {})                  = ""
  2004.      * StringUtils.getCommonPrefix(new String[] {"abc"})             = "abc"
  2005.      * StringUtils.getCommonPrefix(new String[] {null, null})        = ""
  2006.      * StringUtils.getCommonPrefix(new String[] {"", ""})            = ""
  2007.      * StringUtils.getCommonPrefix(new String[] {"", null})          = ""
  2008.      * StringUtils.getCommonPrefix(new String[] {"abc", null, null}) = ""
  2009.      * StringUtils.getCommonPrefix(new String[] {null, null, "abc"}) = ""
  2010.      * StringUtils.getCommonPrefix(new String[] {"", "abc"})         = ""
  2011.      * StringUtils.getCommonPrefix(new String[] {"abc", ""})         = ""
  2012.      * StringUtils.getCommonPrefix(new String[] {"abc", "abc"})      = "abc"
  2013.      * StringUtils.getCommonPrefix(new String[] {"abc", "a"})        = "a"
  2014.      * StringUtils.getCommonPrefix(new String[] {"ab", "abxyz"})     = "ab"
  2015.      * StringUtils.getCommonPrefix(new String[] {"abcde", "abxyz"})  = "ab"
  2016.      * StringUtils.getCommonPrefix(new String[] {"abcde", "xyz"})    = ""
  2017.      * StringUtils.getCommonPrefix(new String[] {"xyz", "abcde"})    = ""
  2018.      * StringUtils.getCommonPrefix(new String[] {"i am a machine", "i am a robot"}) = "i am a "
  2019.      * </pre>
  2020.      *
  2021.      * @param strs  array of String objects, entries may be null
  2022.      * @return the initial sequence of characters that are common to all Strings
  2023.      * in the array; empty String if the array is null, the elements are all null
  2024.      * or if there is no common prefix.
  2025.      * @since 2.4
  2026.      */
  2027.     public static String getCommonPrefix(final String... strs) {
  2028.         if (ArrayUtils.isEmpty(strs)) {
  2029.             return EMPTY;
  2030.         }
  2031.         final int smallestIndexOfDiff = indexOfDifference(strs);
  2032.         if (smallestIndexOfDiff == INDEX_NOT_FOUND) {
  2033.             // all strings were identical
  2034.             if (strs[0] == null) {
  2035.                 return EMPTY;
  2036.             }
  2037.             return strs[0];
  2038.         }
  2039.         if (smallestIndexOfDiff == 0) {
  2040.             // there were no common initial characters
  2041.             return EMPTY;
  2042.         }
  2043.         // we found a common initial character sequence
  2044.         return strs[0].substring(0, smallestIndexOfDiff);
  2045.     }

  2046.     /**
  2047.      * Checks if a String {@code str} contains Unicode digits,
  2048.      * if yes then concatenate all the digits in {@code str} and return it as a String.
  2049.      *
  2050.      * <p>An empty ("") String will be returned if no digits found in {@code str}.</p>
  2051.      *
  2052.      * <pre>
  2053.      * StringUtils.getDigits(null)                 = null
  2054.      * StringUtils.getDigits("")                   = ""
  2055.      * StringUtils.getDigits("abc")                = ""
  2056.      * StringUtils.getDigits("1000$")              = "1000"
  2057.      * StringUtils.getDigits("1123~45")            = "112345"
  2058.      * StringUtils.getDigits("(541) 754-3010")     = "5417543010"
  2059.      * StringUtils.getDigits("\u0967\u0968\u0969") = "\u0967\u0968\u0969"
  2060.      * </pre>
  2061.      *
  2062.      * @param str the String to extract digits from, may be null
  2063.      * @return String with only digits,
  2064.      *           or an empty ("") String if no digits found,
  2065.      *           or {@code null} String if {@code str} is null
  2066.      * @since 3.6
  2067.      */
  2068.     public static String getDigits(final String str) {
  2069.         if (isEmpty(str)) {
  2070.             return str;
  2071.         }
  2072.         final int sz = str.length();
  2073.         final StringBuilder strDigits = new StringBuilder(sz);
  2074.         for (int i = 0; i < sz; i++) {
  2075.             final char tempChar = str.charAt(i);
  2076.             if (Character.isDigit(tempChar)) {
  2077.                 strDigits.append(tempChar);
  2078.             }
  2079.         }
  2080.         return strDigits.toString();
  2081.     }

  2082.     /**
  2083.      * Find the Fuzzy Distance which indicates the similarity score between two Strings.
  2084.      *
  2085.      * <p>This string matching algorithm is similar to the algorithms of editors such as Sublime Text,
  2086.      * TextMate, Atom and others. One point is given for every matched character. Subsequent
  2087.      * matches yield two bonus points. A higher score indicates a higher similarity.</p>
  2088.      *
  2089.      * <pre>
  2090.      * StringUtils.getFuzzyDistance(null, null, null)                                    = IllegalArgumentException
  2091.      * StringUtils.getFuzzyDistance("", "", Locale.ENGLISH)                              = 0
  2092.      * StringUtils.getFuzzyDistance("Workshop", "b", Locale.ENGLISH)                     = 0
  2093.      * StringUtils.getFuzzyDistance("Room", "o", Locale.ENGLISH)                         = 1
  2094.      * StringUtils.getFuzzyDistance("Workshop", "w", Locale.ENGLISH)                     = 1
  2095.      * StringUtils.getFuzzyDistance("Workshop", "ws", Locale.ENGLISH)                    = 2
  2096.      * StringUtils.getFuzzyDistance("Workshop", "wo", Locale.ENGLISH)                    = 4
  2097.      * StringUtils.getFuzzyDistance("Apache Software Foundation", "asf", Locale.ENGLISH) = 3
  2098.      * </pre>
  2099.      *
  2100.      * @param term a full term that should be matched against, must not be null
  2101.      * @param query the query that will be matched against a term, must not be null
  2102.      * @param locale This string matching logic is case-insensitive. A locale is necessary to normalize
  2103.      *  both Strings to lower case.
  2104.      * @return result score
  2105.      * @throws IllegalArgumentException if either String input {@code null} or Locale input {@code null}
  2106.      * @since 3.4
  2107.      * @deprecated As of 3.6, use Apache Commons Text
  2108.      * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/FuzzyScore.html">
  2109.      * FuzzyScore</a> instead
  2110.      */
  2111.     @Deprecated
  2112.     public static int getFuzzyDistance(final CharSequence term, final CharSequence query, final Locale locale) {
  2113.         if (term == null || query == null) {
  2114.             throw new IllegalArgumentException("Strings must not be null");
  2115.         }
  2116.         if (locale == null) {
  2117.             throw new IllegalArgumentException("Locale must not be null");
  2118.         }

  2119.         // fuzzy logic is case-insensitive. We normalize the Strings to lower
  2120.         // case right from the start. Turning characters to lower case
  2121.         // via Character.toLowerCase(char) is unfortunately insufficient
  2122.         // as it does not accept a locale.
  2123.         final String termLowerCase = term.toString().toLowerCase(locale);
  2124.         final String queryLowerCase = query.toString().toLowerCase(locale);

  2125.         // the resulting score
  2126.         int score = 0;

  2127.         // the position in the term which will be scanned next for potential
  2128.         // query character matches
  2129.         int termIndex = 0;

  2130.         // index of the previously matched character in the term
  2131.         int previousMatchingCharacterIndex = Integer.MIN_VALUE;

  2132.         for (int queryIndex = 0; queryIndex < queryLowerCase.length(); queryIndex++) {
  2133.             final char queryChar = queryLowerCase.charAt(queryIndex);

  2134.             boolean termCharacterMatchFound = false;
  2135.             for (; termIndex < termLowerCase.length() && !termCharacterMatchFound; termIndex++) {
  2136.                 final char termChar = termLowerCase.charAt(termIndex);

  2137.                 if (queryChar == termChar) {
  2138.                     // simple character matches result in one point
  2139.                     score++;

  2140.                     // subsequent character matches further improve
  2141.                     // the score.
  2142.                     if (previousMatchingCharacterIndex + 1 == termIndex) {
  2143.                         score += 2;
  2144.                     }

  2145.                     previousMatchingCharacterIndex = termIndex;

  2146.                     // we can leave the nested loop. Every character in the
  2147.                     // query can match at most one character in the term.
  2148.                     termCharacterMatchFound = true;
  2149.                 }
  2150.             }
  2151.         }

  2152.         return score;
  2153.     }

  2154.     /**
  2155.      * Returns either the passed in CharSequence, or if the CharSequence is
  2156.      * whitespace, empty ("") or {@code null}, the value supplied by {@code defaultStrSupplier}.
  2157.      *
  2158.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  2159.      *
  2160.      * <p>Caller responsible for thread-safety and exception handling of default value supplier</p>
  2161.      *
  2162.      * <pre>
  2163.      * {@code
  2164.      * StringUtils.getIfBlank(null, () -> "NULL")   = "NULL"
  2165.      * StringUtils.getIfBlank("", () -> "NULL")     = "NULL"
  2166.      * StringUtils.getIfBlank(" ", () -> "NULL")    = "NULL"
  2167.      * StringUtils.getIfBlank("bat", () -> "NULL")  = "bat"
  2168.      * StringUtils.getIfBlank("", () -> null)       = null
  2169.      * StringUtils.getIfBlank("", null)             = null
  2170.      * }</pre>
  2171.      * @param <T> the specific kind of CharSequence
  2172.      * @param str the CharSequence to check, may be null
  2173.      * @param defaultSupplier the supplier of default CharSequence to return
  2174.      *  if the input is whitespace, empty ("") or {@code null}, may be null
  2175.      * @return the passed in CharSequence, or the default
  2176.      * @see StringUtils#defaultString(String, String)
  2177.      * @since 3.10
  2178.      */
  2179.     public static <T extends CharSequence> T getIfBlank(final T str, final Supplier<T> defaultSupplier) {
  2180.         return isBlank(str) ? Suppliers.get(defaultSupplier) : str;
  2181.     }

  2182.     /**
  2183.      * Returns either the passed in CharSequence, or if the CharSequence is
  2184.      * empty or {@code null}, the value supplied by {@code defaultStrSupplier}.
  2185.      *
  2186.      * <p>Caller responsible for thread-safety and exception handling of default value supplier</p>
  2187.      *
  2188.      * <pre>
  2189.      * {@code
  2190.      * StringUtils.getIfEmpty(null, () -> "NULL")    = "NULL"
  2191.      * StringUtils.getIfEmpty("", () -> "NULL")      = "NULL"
  2192.      * StringUtils.getIfEmpty(" ", () -> "NULL")     = " "
  2193.      * StringUtils.getIfEmpty("bat", () -> "NULL")   = "bat"
  2194.      * StringUtils.getIfEmpty("", () -> null)        = null
  2195.      * StringUtils.getIfEmpty("", null)              = null
  2196.      * }
  2197.      * </pre>
  2198.      * @param <T> the specific kind of CharSequence
  2199.      * @param str  the CharSequence to check, may be null
  2200.      * @param defaultSupplier  the supplier of default CharSequence to return
  2201.      *  if the input is empty ("") or {@code null}, may be null
  2202.      * @return the passed in CharSequence, or the default
  2203.      * @see StringUtils#defaultString(String, String)
  2204.      * @since 3.10
  2205.      */
  2206.     public static <T extends CharSequence> T getIfEmpty(final T str, final Supplier<T> defaultSupplier) {
  2207.         return isEmpty(str) ? Suppliers.get(defaultSupplier) : str;
  2208.     }

  2209.     /**
  2210.      * Find the Jaro Winkler Distance which indicates the similarity score between two Strings.
  2211.      *
  2212.      * <p>The Jaro measure is the weighted sum of percentage of matched characters from each file and transposed characters.
  2213.      * Winkler increased this measure for matching initial characters.</p>
  2214.      *
  2215.      * <p>This implementation is based on the Jaro Winkler similarity algorithm
  2216.      * from <a href="https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance">https://en.wikipedia.org/wiki/Jaro%E2%80%93Winkler_distance</a>.</p>
  2217.      *
  2218.      * <pre>
  2219.      * StringUtils.getJaroWinklerDistance(null, null)          = IllegalArgumentException
  2220.      * StringUtils.getJaroWinklerDistance("", "")              = 0.0
  2221.      * StringUtils.getJaroWinklerDistance("", "a")             = 0.0
  2222.      * StringUtils.getJaroWinklerDistance("aaapppp", "")       = 0.0
  2223.      * StringUtils.getJaroWinklerDistance("frog", "fog")       = 0.93
  2224.      * StringUtils.getJaroWinklerDistance("fly", "ant")        = 0.0
  2225.      * StringUtils.getJaroWinklerDistance("elephant", "hippo") = 0.44
  2226.      * StringUtils.getJaroWinklerDistance("hippo", "elephant") = 0.44
  2227.      * StringUtils.getJaroWinklerDistance("hippo", "zzzzzzzz") = 0.0
  2228.      * StringUtils.getJaroWinklerDistance("hello", "hallo")    = 0.88
  2229.      * StringUtils.getJaroWinklerDistance("ABC Corporation", "ABC Corp") = 0.93
  2230.      * StringUtils.getJaroWinklerDistance("D N H Enterprises Inc", "D &amp; H Enterprises, Inc.") = 0.95
  2231.      * StringUtils.getJaroWinklerDistance("My Gym Children's Fitness Center", "My Gym. Childrens Fitness") = 0.92
  2232.      * StringUtils.getJaroWinklerDistance("PENNSYLVANIA", "PENNCISYLVNIA") = 0.88
  2233.      * </pre>
  2234.      *
  2235.      * @param first the first String, must not be null
  2236.      * @param second the second String, must not be null
  2237.      * @return result distance
  2238.      * @throws IllegalArgumentException if either String input {@code null}
  2239.      * @since 3.3
  2240.      * @deprecated As of 3.6, use Apache Commons Text
  2241.      * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/JaroWinklerDistance.html">
  2242.      * JaroWinklerDistance</a> instead
  2243.      */
  2244.     @Deprecated
  2245.     public static double getJaroWinklerDistance(final CharSequence first, final CharSequence second) {
  2246.         final double DEFAULT_SCALING_FACTOR = 0.1;

  2247.         if (first == null || second == null) {
  2248.             throw new IllegalArgumentException("Strings must not be null");
  2249.         }

  2250.         final int[] mtp = matches(first, second);
  2251.         final double m = mtp[0];
  2252.         if (m == 0) {
  2253.             return 0D;
  2254.         }
  2255.         final double j = (m / first.length() + m / second.length() + (m - mtp[1]) / m) / 3;
  2256.         final double jw = j < 0.7D ? j : j + Math.min(DEFAULT_SCALING_FACTOR, 1D / mtp[3]) * mtp[2] * (1D - j);
  2257.         return Math.round(jw * 100.0D) / 100.0D;
  2258.     }

  2259.     /**
  2260.      * Find the Levenshtein distance between two Strings.
  2261.      *
  2262.      * <p>This is the number of changes needed to change one String into
  2263.      * another, where each change is a single character modification (deletion,
  2264.      * insertion or substitution).</p>
  2265.      *
  2266.      * <p>The implementation uses a single-dimensional array of length s.length() + 1. See
  2267.      * <a href="https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html">
  2268.      * https://blog.softwx.net/2014/12/optimizing-levenshtein-algorithm-in-c.html</a> for details.</p>
  2269.      *
  2270.      * <pre>
  2271.      * StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException
  2272.      * StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException
  2273.      * StringUtils.getLevenshteinDistance("", "")              = 0
  2274.      * StringUtils.getLevenshteinDistance("", "a")             = 1
  2275.      * StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
  2276.      * StringUtils.getLevenshteinDistance("frog", "fog")       = 1
  2277.      * StringUtils.getLevenshteinDistance("fly", "ant")        = 3
  2278.      * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
  2279.      * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
  2280.      * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
  2281.      * StringUtils.getLevenshteinDistance("hello", "hallo")    = 1
  2282.      * </pre>
  2283.      *
  2284.      * @param s  the first String, must not be null
  2285.      * @param t  the second String, must not be null
  2286.      * @return result distance
  2287.      * @throws IllegalArgumentException if either String input {@code null}
  2288.      * @since 3.0 Changed signature from getLevenshteinDistance(String, String) to
  2289.      * getLevenshteinDistance(CharSequence, CharSequence)
  2290.      * @deprecated As of 3.6, use Apache Commons Text
  2291.      * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
  2292.      * LevenshteinDistance</a> instead
  2293.      */
  2294.     @Deprecated
  2295.     public static int getLevenshteinDistance(CharSequence s, CharSequence t) {
  2296.         if (s == null || t == null) {
  2297.             throw new IllegalArgumentException("Strings must not be null");
  2298.         }

  2299.         int n = s.length();
  2300.         int m = t.length();

  2301.         if (n == 0) {
  2302.             return m;
  2303.         }
  2304.         if (m == 0) {
  2305.             return n;
  2306.         }

  2307.         if (n > m) {
  2308.             // swap the input strings to consume less memory
  2309.             final CharSequence tmp = s;
  2310.             s = t;
  2311.             t = tmp;
  2312.             n = m;
  2313.             m = t.length();
  2314.         }

  2315.         final int[] p = new int[n + 1];
  2316.         // indexes into strings s and t
  2317.         int i; // iterates through s
  2318.         int j; // iterates through t
  2319.         int upperleft;
  2320.         int upper;

  2321.         char jOfT; // jth character of t
  2322.         int cost;

  2323.         for (i = 0; i <= n; i++) {
  2324.             p[i] = i;
  2325.         }

  2326.         for (j = 1; j <= m; j++) {
  2327.             upperleft = p[0];
  2328.             jOfT = t.charAt(j - 1);
  2329.             p[0] = j;

  2330.             for (i = 1; i <= n; i++) {
  2331.                 upper = p[i];
  2332.                 cost = s.charAt(i - 1) == jOfT ? 0 : 1;
  2333.                 // minimum of cell to the left+1, to the top+1, diagonally left and up +cost
  2334.                 p[i] = Math.min(Math.min(p[i - 1] + 1, p[i] + 1), upperleft + cost);
  2335.                 upperleft = upper;
  2336.             }
  2337.         }

  2338.         return p[n];
  2339.     }

  2340.     /**
  2341.      * Find the Levenshtein distance between two Strings if it's less than or equal to a given
  2342.      * threshold.
  2343.      *
  2344.      * <p>This is the number of changes needed to change one String into
  2345.      * another, where each change is a single character modification (deletion,
  2346.      * insertion or substitution).</p>
  2347.      *
  2348.      * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield
  2349.      * and Chas Emerick's implementation of the Levenshtein distance algorithm from
  2350.      * <a href="https://web.archive.org/web/20120212021906/http%3A//www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p>
  2351.      *
  2352.      * <pre>
  2353.      * StringUtils.getLevenshteinDistance(null, *, *)             = IllegalArgumentException
  2354.      * StringUtils.getLevenshteinDistance(*, null, *)             = IllegalArgumentException
  2355.      * StringUtils.getLevenshteinDistance(*, *, -1)               = IllegalArgumentException
  2356.      * StringUtils.getLevenshteinDistance("", "", 0)              = 0
  2357.      * StringUtils.getLevenshteinDistance("aaapppp", "", 8)       = 7
  2358.      * StringUtils.getLevenshteinDistance("aaapppp", "", 7)       = 7
  2359.      * StringUtils.getLevenshteinDistance("aaapppp", "", 6))      = -1
  2360.      * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7
  2361.      * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1
  2362.      * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7
  2363.      * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1
  2364.      * </pre>
  2365.      *
  2366.      * @param s  the first String, must not be null
  2367.      * @param t  the second String, must not be null
  2368.      * @param threshold the target threshold, must not be negative
  2369.      * @return result distance, or {@code -1} if the distance would be greater than the threshold
  2370.      * @throws IllegalArgumentException if either String input {@code null} or negative threshold
  2371.      * @deprecated As of 3.6, use Apache Commons Text
  2372.      * <a href="https://commons.apache.org/proper/commons-text/javadocs/api-release/org/apache/commons/text/similarity/LevenshteinDistance.html">
  2373.      * LevenshteinDistance</a> instead
  2374.      */
  2375.     @Deprecated
  2376.     public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) {
  2377.         if (s == null || t == null) {
  2378.             throw new IllegalArgumentException("Strings must not be null");
  2379.         }
  2380.         if (threshold < 0) {
  2381.             throw new IllegalArgumentException("Threshold must not be negative");
  2382.         }

  2383.         /*
  2384.         This implementation only computes the distance if it's less than or equal to the
  2385.         threshold value, returning -1 if it's greater.  The advantage is performance: unbounded
  2386.         distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only
  2387.         computing a diagonal stripe of width 2k + 1 of the cost table.
  2388.         It is also possible to use this to compute the unbounded Levenshtein distance by starting
  2389.         the threshold at 1 and doubling each time until the distance is found; this is O(dm), where
  2390.         d is the distance.

  2391.         One subtlety comes from needing to ignore entries on the border of our stripe
  2392.         eg.
  2393.         p[] = |#|#|#|*
  2394.         d[] =  *|#|#|#|
  2395.         We must ignore the entry to the left of the leftmost member
  2396.         We must ignore the entry above the rightmost member

  2397.         Another subtlety comes from our stripe running off the matrix if the strings aren't
  2398.         of the same size.  Since string s is always swapped to be the shorter of the two,
  2399.         the stripe will always run off to the upper right instead of the lower left of the matrix.

  2400.         As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1.
  2401.         In this case we're going to walk a stripe of length 3.  The matrix would look like so:

  2402.            1 2 3 4 5
  2403.         1 |#|#| | | |
  2404.         2 |#|#|#| | |
  2405.         3 | |#|#|#| |
  2406.         4 | | |#|#|#|
  2407.         5 | | | |#|#|
  2408.         6 | | | | |#|
  2409.         7 | | | | | |

  2410.         Note how the stripe leads off the table as there is no possible way to turn a string of length 5
  2411.         into one of length 7 in edit distance of 1.

  2412.         Additionally, this implementation decreases memory usage by using two
  2413.         single-dimensional arrays and swapping them back and forth instead of allocating
  2414.         an entire n by m matrix.  This requires a few minor changes, such as immediately returning
  2415.         when it's detected that the stripe has run off the matrix and initially filling the arrays with
  2416.         large values so that entries we don't compute are ignored.

  2417.         See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion.
  2418.          */

  2419.         int n = s.length(); // length of s
  2420.         int m = t.length(); // length of t

  2421.         // if one string is empty, the edit distance is necessarily the length of the other
  2422.         if (n == 0) {
  2423.             return m <= threshold ? m : -1;
  2424.         }
  2425.         if (m == 0) {
  2426.             return n <= threshold ? n : -1;
  2427.         }
  2428.         if (Math.abs(n - m) > threshold) {
  2429.             // no need to calculate the distance if the length difference is greater than the threshold
  2430.             return -1;
  2431.         }

  2432.         if (n > m) {
  2433.             // swap the two strings to consume less memory
  2434.             final CharSequence tmp = s;
  2435.             s = t;
  2436.             t = tmp;
  2437.             n = m;
  2438.             m = t.length();
  2439.         }

  2440.         int[] p = new int[n + 1]; // 'previous' cost array, horizontally
  2441.         int[] d = new int[n + 1]; // cost array, horizontally
  2442.         int[] tmp; // placeholder to assist in swapping p and d

  2443.         // fill in starting table values
  2444.         final int boundary = Math.min(n, threshold) + 1;
  2445.         for (int i = 0; i < boundary; i++) {
  2446.             p[i] = i;
  2447.         }
  2448.         // these fills ensure that the value above the rightmost entry of our
  2449.         // stripe will be ignored in following loop iterations
  2450.         Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE);
  2451.         Arrays.fill(d, Integer.MAX_VALUE);

  2452.         // iterates through t
  2453.         for (int j = 1; j <= m; j++) {
  2454.             final char jOfT = t.charAt(j - 1); // jth character of t
  2455.             d[0] = j;

  2456.             // compute stripe indices, constrain to array size
  2457.             final int min = Math.max(1, j - threshold);
  2458.             final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold);

  2459.             // the stripe may lead off of the table if s and t are of different sizes
  2460.             if (min > max) {
  2461.                 return -1;
  2462.             }

  2463.             // ignore entry left of leftmost
  2464.             if (min > 1) {
  2465.                 d[min - 1] = Integer.MAX_VALUE;
  2466.             }

  2467.             // iterates through [min, max] in s
  2468.             for (int i = min; i <= max; i++) {
  2469.                 if (s.charAt(i - 1) == jOfT) {
  2470.                     // diagonally left and up
  2471.                     d[i] = p[i - 1];
  2472.                 } else {
  2473.                     // 1 + minimum of cell to the left, to the top, diagonally left and up
  2474.                     d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]);
  2475.                 }
  2476.             }

  2477.             // copy current distance counts to 'previous row' distance counts
  2478.             tmp = p;
  2479.             p = d;
  2480.             d = tmp;
  2481.         }

  2482.         // if p[n] is greater than the threshold, there's no guarantee on it being the correct
  2483.         // distance
  2484.         if (p[n] <= threshold) {
  2485.             return p[n];
  2486.         }
  2487.         return -1;
  2488.     }

  2489.     /**
  2490.      * Finds the first index within a CharSequence, handling {@code null}.
  2491.      * This method uses {@link String#indexOf(String, int)} if possible.
  2492.      *
  2493.      * <p>A {@code null} CharSequence will return {@code -1}.</p>
  2494.      *
  2495.      * <pre>
  2496.      * StringUtils.indexOf(null, *)          = -1
  2497.      * StringUtils.indexOf(*, null)          = -1
  2498.      * StringUtils.indexOf("", "")           = 0
  2499.      * StringUtils.indexOf("", *)            = -1 (except when * = "")
  2500.      * StringUtils.indexOf("aabaabaa", "a")  = 0
  2501.      * StringUtils.indexOf("aabaabaa", "b")  = 2
  2502.      * StringUtils.indexOf("aabaabaa", "ab") = 1
  2503.      * StringUtils.indexOf("aabaabaa", "")   = 0
  2504.      * </pre>
  2505.      *
  2506.      * @param seq  the CharSequence to check, may be null
  2507.      * @param searchSeq  the CharSequence to find, may be null
  2508.      * @return the first index of the search CharSequence,
  2509.      *  -1 if no match or {@code null} string input
  2510.      * @since 2.0
  2511.      * @since 3.0 Changed signature from indexOf(String, String) to indexOf(CharSequence, CharSequence)
  2512.      */
  2513.     public static int indexOf(final CharSequence seq, final CharSequence searchSeq) {
  2514.         if (seq == null || searchSeq == null) {
  2515.             return INDEX_NOT_FOUND;
  2516.         }
  2517.         return CharSequenceUtils.indexOf(seq, searchSeq, 0);
  2518.     }

  2519.     /**
  2520.      * Finds the first index within a CharSequence, handling {@code null}.
  2521.      * This method uses {@link String#indexOf(String, int)} if possible.
  2522.      *
  2523.      * <p>A {@code null} CharSequence will return {@code -1}.
  2524.      * A negative start position is treated as zero.
  2525.      * An empty ("") search CharSequence always matches.
  2526.      * A start position greater than the string length only matches
  2527.      * an empty search CharSequence.</p>
  2528.      *
  2529.      * <pre>
  2530.      * StringUtils.indexOf(null, *, *)          = -1
  2531.      * StringUtils.indexOf(*, null, *)          = -1
  2532.      * StringUtils.indexOf("", "", 0)           = 0
  2533.      * StringUtils.indexOf("", *, 0)            = -1 (except when * = "")
  2534.      * StringUtils.indexOf("aabaabaa", "a", 0)  = 0
  2535.      * StringUtils.indexOf("aabaabaa", "b", 0)  = 2
  2536.      * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
  2537.      * StringUtils.indexOf("aabaabaa", "b", 3)  = 5
  2538.      * StringUtils.indexOf("aabaabaa", "b", 9)  = -1
  2539.      * StringUtils.indexOf("aabaabaa", "b", -1) = 2
  2540.      * StringUtils.indexOf("aabaabaa", "", 2)   = 2
  2541.      * StringUtils.indexOf("abc", "", 9)        = 3
  2542.      * </pre>
  2543.      *
  2544.      * @param seq  the CharSequence to check, may be null
  2545.      * @param searchSeq  the CharSequence to find, may be null
  2546.      * @param startPos  the start position, negative treated as zero
  2547.      * @return the first index of the search CharSequence (always &ge; startPos),
  2548.      *  -1 if no match or {@code null} string input
  2549.      * @since 2.0
  2550.      * @since 3.0 Changed signature from indexOf(String, String, int) to indexOf(CharSequence, CharSequence, int)
  2551.      */
  2552.     public static int indexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
  2553.         if (seq == null || searchSeq == null) {
  2554.             return INDEX_NOT_FOUND;
  2555.         }
  2556.         return CharSequenceUtils.indexOf(seq, searchSeq, startPos);
  2557.     }

  2558.     /**
  2559.      * Returns the index within {@code seq} of the first occurrence of
  2560.      * the specified character. If a character with value
  2561.      * {@code searchChar} occurs in the character sequence represented by
  2562.      * {@code seq} {@link CharSequence} object, then the index (in Unicode
  2563.      * code units) of the first such occurrence is returned. For
  2564.      * values of {@code searchChar} in the range from 0 to 0xFFFF
  2565.      * (inclusive), this is the smallest value <em>k</em> such that:
  2566.      * <blockquote><pre>
  2567.      * this.charAt(<em>k</em>) == searchChar
  2568.      * </pre></blockquote>
  2569.      * is true. For other values of {@code searchChar}, it is the
  2570.      * smallest value <em>k</em> such that:
  2571.      * <blockquote><pre>
  2572.      * this.codePointAt(<em>k</em>) == searchChar
  2573.      * </pre></blockquote>
  2574.      * is true. In either case, if no such character occurs in {@code seq},
  2575.      * then {@code INDEX_NOT_FOUND (-1)} is returned.
  2576.      *
  2577.      * <p>Furthermore, a {@code null} or empty ("") CharSequence will
  2578.      * return {@code INDEX_NOT_FOUND (-1)}.</p>
  2579.      *
  2580.      * <pre>
  2581.      * StringUtils.indexOf(null, *)         = -1
  2582.      * StringUtils.indexOf("", *)           = -1
  2583.      * StringUtils.indexOf("aabaabaa", 'a') = 0
  2584.      * StringUtils.indexOf("aabaabaa", 'b') = 2
  2585.      * </pre>
  2586.      *
  2587.      * @param seq  the CharSequence to check, may be null
  2588.      * @param searchChar  the character to find
  2589.      * @return the first index of the search character,
  2590.      *  -1 if no match or {@code null} string input
  2591.      * @since 2.0
  2592.      * @since 3.0 Changed signature from indexOf(String, int) to indexOf(CharSequence, int)
  2593.      * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
  2594.      */
  2595.     public static int indexOf(final CharSequence seq, final int searchChar) {
  2596.         if (isEmpty(seq)) {
  2597.             return INDEX_NOT_FOUND;
  2598.         }
  2599.         return CharSequenceUtils.indexOf(seq, searchChar, 0);
  2600.     }

  2601.     /**
  2602.      * Returns the index within {@code seq} of the first occurrence of the
  2603.      * specified character, starting the search at the specified index.
  2604.      * <p>
  2605.      * If a character with value {@code searchChar} occurs in the
  2606.      * character sequence represented by the {@code seq} {@link CharSequence}
  2607.      * object at an index no smaller than {@code startPos}, then
  2608.      * the index of the first such occurrence is returned. For values
  2609.      * of {@code searchChar} in the range from 0 to 0xFFFF (inclusive),
  2610.      * this is the smallest value <em>k</em> such that:
  2611.      * <blockquote><pre>
  2612.      * (this.charAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &gt;= startPos)
  2613.      * </pre></blockquote>
  2614.      * is true. For other values of {@code searchChar}, it is the
  2615.      * smallest value <em>k</em> such that:
  2616.      * <blockquote><pre>
  2617.      * (this.codePointAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &gt;= startPos)
  2618.      * </pre></blockquote>
  2619.      * is true. In either case, if no such character occurs in {@code seq}
  2620.      * at or after position {@code startPos}, then
  2621.      * {@code -1} is returned.
  2622.      *
  2623.      * <p>
  2624.      * There is no restriction on the value of {@code startPos}. If it
  2625.      * is negative, it has the same effect as if it were zero: this entire
  2626.      * string may be searched. If it is greater than the length of this
  2627.      * string, it has the same effect as if it were equal to the length of
  2628.      * this string: {@code (INDEX_NOT_FOUND) -1} is returned. Furthermore, a
  2629.      * {@code null} or empty ("") CharSequence will
  2630.      * return {@code (INDEX_NOT_FOUND) -1}.
  2631.      *
  2632.      * <p>All indices are specified in {@code char} values
  2633.      * (Unicode code units).
  2634.      *
  2635.      * <pre>
  2636.      * StringUtils.indexOf(null, *, *)          = -1
  2637.      * StringUtils.indexOf("", *, *)            = -1
  2638.      * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2
  2639.      * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5
  2640.      * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1
  2641.      * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
  2642.      * </pre>
  2643.      *
  2644.      * @param seq  the CharSequence to check, may be null
  2645.      * @param searchChar  the character to find
  2646.      * @param startPos  the start position, negative treated as zero
  2647.      * @return the first index of the search character (always &ge; startPos),
  2648.      *  -1 if no match or {@code null} string input
  2649.      * @since 2.0
  2650.      * @since 3.0 Changed signature from indexOf(String, int, int) to indexOf(CharSequence, int, int)
  2651.      * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
  2652.      */
  2653.     public static int indexOf(final CharSequence seq, final int searchChar, final int startPos) {
  2654.         if (isEmpty(seq)) {
  2655.             return INDEX_NOT_FOUND;
  2656.         }
  2657.         return CharSequenceUtils.indexOf(seq, searchChar, startPos);
  2658.     }

  2659.     /**
  2660.      * Search a CharSequence to find the first index of any
  2661.      * character in the given set of characters.
  2662.      *
  2663.      * <p>A {@code null} String will return {@code -1}.
  2664.      * A {@code null} or zero length search array will return {@code -1}.</p>
  2665.      *
  2666.      * <pre>
  2667.      * StringUtils.indexOfAny(null, *)                  = -1
  2668.      * StringUtils.indexOfAny("", *)                    = -1
  2669.      * StringUtils.indexOfAny(*, null)                  = -1
  2670.      * StringUtils.indexOfAny(*, [])                    = -1
  2671.      * StringUtils.indexOfAny("zzabyycdxx", ['z', 'a']) = 0
  2672.      * StringUtils.indexOfAny("zzabyycdxx", ['b', 'y']) = 3
  2673.      * StringUtils.indexOfAny("aba", ['z'])             = -1
  2674.      * </pre>
  2675.      *
  2676.      * @param cs  the CharSequence to check, may be null
  2677.      * @param searchChars  the chars to search for, may be null
  2678.      * @return the index of any of the chars, -1 if no match or null input
  2679.      * @since 2.0
  2680.      * @since 3.0 Changed signature from indexOfAny(String, char[]) to indexOfAny(CharSequence, char...)
  2681.      */
  2682.     public static int indexOfAny(final CharSequence cs, final char... searchChars) {
  2683.         if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
  2684.             return INDEX_NOT_FOUND;
  2685.         }
  2686.         final int csLen = cs.length();
  2687.         final int csLast = csLen - 1;
  2688.         final int searchLen = searchChars.length;
  2689.         final int searchLast = searchLen - 1;
  2690.         for (int i = 0; i < csLen; i++) {
  2691.             final char ch = cs.charAt(i);
  2692.             for (int j = 0; j < searchLen; j++) {
  2693.                 if (searchChars[j] == ch) {
  2694.                     if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch)) {
  2695.                         return i;
  2696.                     }
  2697.                     // ch is a supplementary character
  2698.                     if (searchChars[j + 1] == cs.charAt(i + 1)) {
  2699.                         return i;
  2700.                     }
  2701.                 }
  2702.             }
  2703.         }
  2704.         return INDEX_NOT_FOUND;
  2705.     }

  2706.     /**
  2707.      * Find the first index of any of a set of potential substrings.
  2708.      *
  2709.      * <p>A {@code null} CharSequence will return {@code -1}.
  2710.      * A {@code null} or zero length search array will return {@code -1}.
  2711.      * A {@code null} search array entry will be ignored, but a search
  2712.      * array containing "" will return {@code 0} if {@code str} is not
  2713.      * null. This method uses {@link String#indexOf(String)} if possible.</p>
  2714.      *
  2715.      * <pre>
  2716.      * StringUtils.indexOfAny(null, *)                      = -1
  2717.      * StringUtils.indexOfAny(*, null)                      = -1
  2718.      * StringUtils.indexOfAny(*, [])                        = -1
  2719.      * StringUtils.indexOfAny("zzabyycdxx", ["ab", "cd"])   = 2
  2720.      * StringUtils.indexOfAny("zzabyycdxx", ["cd", "ab"])   = 2
  2721.      * StringUtils.indexOfAny("zzabyycdxx", ["mn", "op"])   = -1
  2722.      * StringUtils.indexOfAny("zzabyycdxx", ["zab", "aby"]) = 1
  2723.      * StringUtils.indexOfAny("zzabyycdxx", [""])           = 0
  2724.      * StringUtils.indexOfAny("", [""])                     = 0
  2725.      * StringUtils.indexOfAny("", ["a"])                    = -1
  2726.      * </pre>
  2727.      *
  2728.      * @param str  the CharSequence to check, may be null
  2729.      * @param searchStrs  the CharSequences to search for, may be null
  2730.      * @return the first index of any of the searchStrs in str, -1 if no match
  2731.      * @since 3.0 Changed signature from indexOfAny(String, String[]) to indexOfAny(CharSequence, CharSequence...)
  2732.      */
  2733.     public static int indexOfAny(final CharSequence str, final CharSequence... searchStrs) {
  2734.         if (str == null || searchStrs == null) {
  2735.             return INDEX_NOT_FOUND;
  2736.         }

  2737.         // String's can't have a MAX_VALUEth index.
  2738.         int ret = Integer.MAX_VALUE;

  2739.         int tmp;
  2740.         for (final CharSequence search : searchStrs) {
  2741.             if (search == null) {
  2742.                 continue;
  2743.             }
  2744.             tmp = CharSequenceUtils.indexOf(str, search, 0);
  2745.             if (tmp == INDEX_NOT_FOUND) {
  2746.                 continue;
  2747.             }

  2748.             if (tmp < ret) {
  2749.                 ret = tmp;
  2750.             }
  2751.         }

  2752.         return ret == Integer.MAX_VALUE ? INDEX_NOT_FOUND : ret;
  2753.     }

  2754.     /**
  2755.      * Search a CharSequence to find the first index of any
  2756.      * character in the given set of characters.
  2757.      *
  2758.      * <p>A {@code null} String will return {@code -1}.
  2759.      * A {@code null} search string will return {@code -1}.</p>
  2760.      *
  2761.      * <pre>
  2762.      * StringUtils.indexOfAny(null, *)            = -1
  2763.      * StringUtils.indexOfAny("", *)              = -1
  2764.      * StringUtils.indexOfAny(*, null)            = -1
  2765.      * StringUtils.indexOfAny(*, "")              = -1
  2766.      * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
  2767.      * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
  2768.      * StringUtils.indexOfAny("aba", "z")         = -1
  2769.      * </pre>
  2770.      *
  2771.      * @param cs  the CharSequence to check, may be null
  2772.      * @param searchChars  the chars to search for, may be null
  2773.      * @return the index of any of the chars, -1 if no match or null input
  2774.      * @since 2.0
  2775.      * @since 3.0 Changed signature from indexOfAny(String, String) to indexOfAny(CharSequence, String)
  2776.      */
  2777.     public static int indexOfAny(final CharSequence cs, final String searchChars) {
  2778.         if (isEmpty(cs) || isEmpty(searchChars)) {
  2779.             return INDEX_NOT_FOUND;
  2780.         }
  2781.         return indexOfAny(cs, searchChars.toCharArray());
  2782.     }

  2783.     /**
  2784.      * Searches a CharSequence to find the first index of any
  2785.      * character not in the given set of characters.
  2786.      *
  2787.      * <p>A {@code null} CharSequence will return {@code -1}.
  2788.      * A {@code null} or zero length search array will return {@code -1}.</p>
  2789.      *
  2790.      * <pre>
  2791.      * StringUtils.indexOfAnyBut(null, *)                              = -1
  2792.      * StringUtils.indexOfAnyBut("", *)                                = -1
  2793.      * StringUtils.indexOfAnyBut(*, null)                              = -1
  2794.      * StringUtils.indexOfAnyBut(*, [])                                = -1
  2795.      * StringUtils.indexOfAnyBut("zzabyycdxx", new char[] {'z', 'a'} ) = 3
  2796.      * StringUtils.indexOfAnyBut("aba", new char[] {'z'} )             = 0
  2797.      * StringUtils.indexOfAnyBut("aba", new char[] {'a', 'b'} )        = -1

  2798.      * </pre>
  2799.      *
  2800.      * @param cs  the CharSequence to check, may be null
  2801.      * @param searchChars  the chars to search for, may be null
  2802.      * @return the index of any of the chars, -1 if no match or null input
  2803.      * @since 2.0
  2804.      * @since 3.0 Changed signature from indexOfAnyBut(String, char[]) to indexOfAnyBut(CharSequence, char...)
  2805.      */
  2806.     public static int indexOfAnyBut(final CharSequence cs, final char... searchChars) {
  2807.         if (isEmpty(cs) || ArrayUtils.isEmpty(searchChars)) {
  2808.             return INDEX_NOT_FOUND;
  2809.         }
  2810.         final int csLen = cs.length();
  2811.         final int csLast = csLen - 1;
  2812.         final int searchLen = searchChars.length;
  2813.         final int searchLast = searchLen - 1;
  2814.         outer:
  2815.         for (int i = 0; i < csLen; i++) {
  2816.             final char ch = cs.charAt(i);
  2817.             for (int j = 0; j < searchLen; j++) {
  2818.                 if (searchChars[j] == ch) {
  2819.                     if (i >= csLast || j >= searchLast || !Character.isHighSurrogate(ch)) {
  2820.                         continue outer;
  2821.                     }
  2822.                     if (searchChars[j + 1] == cs.charAt(i + 1)) {
  2823.                         continue outer;
  2824.                     }
  2825.                 }
  2826.             }
  2827.             return i;
  2828.         }
  2829.         return INDEX_NOT_FOUND;
  2830.     }

  2831.     /**
  2832.      * Search a CharSequence to find the first index of any
  2833.      * character not in the given set of characters.
  2834.      *
  2835.      * <p>A {@code null} CharSequence will return {@code -1}.
  2836.      * A {@code null} or empty search string will return {@code -1}.</p>
  2837.      *
  2838.      * <pre>
  2839.      * StringUtils.indexOfAnyBut(null, *)            = -1
  2840.      * StringUtils.indexOfAnyBut("", *)              = -1
  2841.      * StringUtils.indexOfAnyBut(*, null)            = -1
  2842.      * StringUtils.indexOfAnyBut(*, "")              = -1
  2843.      * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
  2844.      * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = -1
  2845.      * StringUtils.indexOfAnyBut("aba", "ab")        = -1
  2846.      * </pre>
  2847.      *
  2848.      * @param seq  the CharSequence to check, may be null
  2849.      * @param searchChars  the chars to search for, may be null
  2850.      * @return the index of any of the chars, -1 if no match or null input
  2851.      * @since 2.0
  2852.      * @since 3.0 Changed signature from indexOfAnyBut(String, String) to indexOfAnyBut(CharSequence, CharSequence)
  2853.      */
  2854.     public static int indexOfAnyBut(final CharSequence seq, final CharSequence searchChars) {
  2855.         if (isEmpty(seq) || isEmpty(searchChars)) {
  2856.             return INDEX_NOT_FOUND;
  2857.         }
  2858.         final int strLen = seq.length();
  2859.         for (int i = 0; i < strLen; i++) {
  2860.             final char ch = seq.charAt(i);
  2861.             final boolean chFound = CharSequenceUtils.indexOf(searchChars, ch, 0) >= 0;
  2862.             if (i + 1 < strLen && Character.isHighSurrogate(ch)) {
  2863.                 final char ch2 = seq.charAt(i + 1);
  2864.                 if (chFound && CharSequenceUtils.indexOf(searchChars, ch2, 0) < 0) {
  2865.                     return i;
  2866.                 }
  2867.             } else if (!chFound) {
  2868.                 return i;
  2869.             }
  2870.         }
  2871.         return INDEX_NOT_FOUND;
  2872.     }

  2873.     /**
  2874.      * Compares all CharSequences in an array and returns the index at which the
  2875.      * CharSequences begin to differ.
  2876.      *
  2877.      * <p>For example,
  2878.      * {@code indexOfDifference(new String[] {"i am a machine", "i am a robot"}) -> 7}</p>
  2879.      *
  2880.      * <pre>
  2881.      * StringUtils.indexOfDifference(null)                             = -1
  2882.      * StringUtils.indexOfDifference(new String[] {})                  = -1
  2883.      * StringUtils.indexOfDifference(new String[] {"abc"})             = -1
  2884.      * StringUtils.indexOfDifference(new String[] {null, null})        = -1
  2885.      * StringUtils.indexOfDifference(new String[] {"", ""})            = -1
  2886.      * StringUtils.indexOfDifference(new String[] {"", null})          = 0
  2887.      * StringUtils.indexOfDifference(new String[] {"abc", null, null}) = 0
  2888.      * StringUtils.indexOfDifference(new String[] {null, null, "abc"}) = 0
  2889.      * StringUtils.indexOfDifference(new String[] {"", "abc"})         = 0
  2890.      * StringUtils.indexOfDifference(new String[] {"abc", ""})         = 0
  2891.      * StringUtils.indexOfDifference(new String[] {"abc", "abc"})      = -1
  2892.      * StringUtils.indexOfDifference(new String[] {"abc", "a"})        = 1
  2893.      * StringUtils.indexOfDifference(new String[] {"ab", "abxyz"})     = 2
  2894.      * StringUtils.indexOfDifference(new String[] {"abcde", "abxyz"})  = 2
  2895.      * StringUtils.indexOfDifference(new String[] {"abcde", "xyz"})    = 0
  2896.      * StringUtils.indexOfDifference(new String[] {"xyz", "abcde"})    = 0
  2897.      * StringUtils.indexOfDifference(new String[] {"i am a machine", "i am a robot"}) = 7
  2898.      * </pre>
  2899.      *
  2900.      * @param css  array of CharSequences, entries may be null
  2901.      * @return the index where the strings begin to differ; -1 if they are all equal
  2902.      * @since 2.4
  2903.      * @since 3.0 Changed signature from indexOfDifference(String...) to indexOfDifference(CharSequence...)
  2904.      */
  2905.     public static int indexOfDifference(final CharSequence... css) {
  2906.         if (ArrayUtils.getLength(css) <= 1) {
  2907.             return INDEX_NOT_FOUND;
  2908.         }
  2909.         boolean anyStringNull = false;
  2910.         boolean allStringsNull = true;
  2911.         final int arrayLen = css.length;
  2912.         int shortestStrLen = Integer.MAX_VALUE;
  2913.         int longestStrLen = 0;

  2914.         // find the min and max string lengths; this avoids checking to make
  2915.         // sure we are not exceeding the length of the string each time through
  2916.         // the bottom loop.
  2917.         for (final CharSequence cs : css) {
  2918.             if (cs == null) {
  2919.                 anyStringNull = true;
  2920.                 shortestStrLen = 0;
  2921.             } else {
  2922.                 allStringsNull = false;
  2923.                 shortestStrLen = Math.min(cs.length(), shortestStrLen);
  2924.                 longestStrLen = Math.max(cs.length(), longestStrLen);
  2925.             }
  2926.         }

  2927.         // handle lists containing all nulls or all empty strings
  2928.         if (allStringsNull || longestStrLen == 0 && !anyStringNull) {
  2929.             return INDEX_NOT_FOUND;
  2930.         }

  2931.         // handle lists containing some nulls or some empty strings
  2932.         if (shortestStrLen == 0) {
  2933.             return 0;
  2934.         }

  2935.         // find the position with the first difference across all strings
  2936.         int firstDiff = -1;
  2937.         for (int stringPos = 0; stringPos < shortestStrLen; stringPos++) {
  2938.             final char comparisonChar = css[0].charAt(stringPos);
  2939.             for (int arrayPos = 1; arrayPos < arrayLen; arrayPos++) {
  2940.                 if (css[arrayPos].charAt(stringPos) != comparisonChar) {
  2941.                     firstDiff = stringPos;
  2942.                     break;
  2943.                 }
  2944.             }
  2945.             if (firstDiff != -1) {
  2946.                 break;
  2947.             }
  2948.         }

  2949.         if (firstDiff == -1 && shortestStrLen != longestStrLen) {
  2950.             // we compared all of the characters up to the length of the
  2951.             // shortest string and didn't find a match, but the string lengths
  2952.             // vary, so return the length of the shortest string.
  2953.             return shortestStrLen;
  2954.         }
  2955.         return firstDiff;
  2956.     }

  2957.     /**
  2958.      * Compares two CharSequences, and returns the index at which the
  2959.      * CharSequences begin to differ.
  2960.      *
  2961.      * <p>For example,
  2962.      * {@code indexOfDifference("i am a machine", "i am a robot") -> 7}</p>
  2963.      *
  2964.      * <pre>
  2965.      * StringUtils.indexOfDifference(null, null)       = -1
  2966.      * StringUtils.indexOfDifference("", "")           = -1
  2967.      * StringUtils.indexOfDifference("", "abc")        = 0
  2968.      * StringUtils.indexOfDifference("abc", "")        = 0
  2969.      * StringUtils.indexOfDifference("abc", "abc")     = -1
  2970.      * StringUtils.indexOfDifference("ab", "abxyz")    = 2
  2971.      * StringUtils.indexOfDifference("abcde", "abxyz") = 2
  2972.      * StringUtils.indexOfDifference("abcde", "xyz")   = 0
  2973.      * </pre>
  2974.      *
  2975.      * @param cs1  the first CharSequence, may be null
  2976.      * @param cs2  the second CharSequence, may be null
  2977.      * @return the index where cs1 and cs2 begin to differ; -1 if they are equal
  2978.      * @since 2.0
  2979.      * @since 3.0 Changed signature from indexOfDifference(String, String) to
  2980.      * indexOfDifference(CharSequence, CharSequence)
  2981.      */
  2982.     public static int indexOfDifference(final CharSequence cs1, final CharSequence cs2) {
  2983.         if (cs1 == cs2) {
  2984.             return INDEX_NOT_FOUND;
  2985.         }
  2986.         if (cs1 == null || cs2 == null) {
  2987.             return 0;
  2988.         }
  2989.         int i;
  2990.         for (i = 0; i < cs1.length() && i < cs2.length(); ++i) {
  2991.             if (cs1.charAt(i) != cs2.charAt(i)) {
  2992.                 break;
  2993.             }
  2994.         }
  2995.         if (i < cs2.length() || i < cs1.length()) {
  2996.             return i;
  2997.         }
  2998.         return INDEX_NOT_FOUND;
  2999.     }

  3000.     /**
  3001.      * Case in-sensitive find of the first index within a CharSequence.
  3002.      *
  3003.      * <p>A {@code null} CharSequence will return {@code -1}.
  3004.      * A negative start position is treated as zero.
  3005.      * An empty ("") search CharSequence always matches.
  3006.      * A start position greater than the string length only matches
  3007.      * an empty search CharSequence.</p>
  3008.      *
  3009.      * <pre>
  3010.      * StringUtils.indexOfIgnoreCase(null, *)          = -1
  3011.      * StringUtils.indexOfIgnoreCase(*, null)          = -1
  3012.      * StringUtils.indexOfIgnoreCase("", "")           = 0
  3013.      * StringUtils.indexOfIgnoreCase(" ", " ")         = 0
  3014.      * StringUtils.indexOfIgnoreCase("aabaabaa", "a")  = 0
  3015.      * StringUtils.indexOfIgnoreCase("aabaabaa", "b")  = 2
  3016.      * StringUtils.indexOfIgnoreCase("aabaabaa", "ab") = 1
  3017.      * </pre>
  3018.      *
  3019.      * @param str  the CharSequence to check, may be null
  3020.      * @param searchStr  the CharSequence to find, may be null
  3021.      * @return the first index of the search CharSequence,
  3022.      *  -1 if no match or {@code null} string input
  3023.      * @since 2.5
  3024.      * @since 3.0 Changed signature from indexOfIgnoreCase(String, String) to indexOfIgnoreCase(CharSequence, CharSequence)
  3025.      */
  3026.     public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
  3027.         return indexOfIgnoreCase(str, searchStr, 0);
  3028.     }

  3029.     /**
  3030.      * Case in-sensitive find of the first index within a CharSequence
  3031.      * from the specified position.
  3032.      *
  3033.      * <p>A {@code null} CharSequence will return {@code -1}.
  3034.      * A negative start position is treated as zero.
  3035.      * An empty ("") search CharSequence always matches.
  3036.      * A start position greater than the string length only matches
  3037.      * an empty search CharSequence.</p>
  3038.      *
  3039.      * <pre>
  3040.      * StringUtils.indexOfIgnoreCase(null, *, *)          = -1
  3041.      * StringUtils.indexOfIgnoreCase(*, null, *)          = -1
  3042.      * StringUtils.indexOfIgnoreCase("", "", 0)           = 0
  3043.      * StringUtils.indexOfIgnoreCase("aabaabaa", "A", 0)  = 0
  3044.      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 0)  = 2
  3045.      * StringUtils.indexOfIgnoreCase("aabaabaa", "AB", 0) = 1
  3046.      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 3)  = 5
  3047.      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", 9)  = -1
  3048.      * StringUtils.indexOfIgnoreCase("aabaabaa", "B", -1) = 2
  3049.      * StringUtils.indexOfIgnoreCase("aabaabaa", "", 2)   = 2
  3050.      * StringUtils.indexOfIgnoreCase("abc", "", 9)        = -1
  3051.      * </pre>
  3052.      *
  3053.      * @param str  the CharSequence to check, may be null
  3054.      * @param searchStr  the CharSequence to find, may be null
  3055.      * @param startPos  the start position, negative treated as zero
  3056.      * @return the first index of the search CharSequence (always &ge; startPos),
  3057.      *  -1 if no match or {@code null} string input
  3058.      * @since 2.5
  3059.      * @since 3.0 Changed signature from indexOfIgnoreCase(String, String, int) to indexOfIgnoreCase(CharSequence, CharSequence, int)
  3060.      */
  3061.     public static int indexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
  3062.         if (str == null || searchStr == null) {
  3063.             return INDEX_NOT_FOUND;
  3064.         }
  3065.         if (startPos < 0) {
  3066.             startPos = 0;
  3067.         }
  3068.         final int endLimit = str.length() - searchStr.length() + 1;
  3069.         if (startPos > endLimit) {
  3070.             return INDEX_NOT_FOUND;
  3071.         }
  3072.         if (searchStr.length() == 0) {
  3073.             return startPos;
  3074.         }
  3075.         for (int i = startPos; i < endLimit; i++) {
  3076.             if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStr.length())) {
  3077.                 return i;
  3078.             }
  3079.         }
  3080.         return INDEX_NOT_FOUND;
  3081.     }

  3082.     /**
  3083.      * Checks if all of the CharSequences are empty (""), null or whitespace only.
  3084.      *
  3085.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  3086.      *
  3087.      * <pre>
  3088.      * StringUtils.isAllBlank(null)             = true
  3089.      * StringUtils.isAllBlank(null, "foo")      = false
  3090.      * StringUtils.isAllBlank(null, null)       = true
  3091.      * StringUtils.isAllBlank("", "bar")        = false
  3092.      * StringUtils.isAllBlank("bob", "")        = false
  3093.      * StringUtils.isAllBlank("  bob  ", null)  = false
  3094.      * StringUtils.isAllBlank(" ", "bar")       = false
  3095.      * StringUtils.isAllBlank("foo", "bar")     = false
  3096.      * StringUtils.isAllBlank(new String[] {})  = true
  3097.      * </pre>
  3098.      *
  3099.      * @param css  the CharSequences to check, may be null or empty
  3100.      * @return {@code true} if all of the CharSequences are empty or null or whitespace only
  3101.      * @since 3.6
  3102.      */
  3103.     public static boolean isAllBlank(final CharSequence... css) {
  3104.         if (ArrayUtils.isEmpty(css)) {
  3105.             return true;
  3106.         }
  3107.         for (final CharSequence cs : css) {
  3108.             if (isNotBlank(cs)) {
  3109.                return false;
  3110.             }
  3111.         }
  3112.         return true;
  3113.     }

  3114.     /**
  3115.      * Checks if all of the CharSequences are empty ("") or null.
  3116.      *
  3117.      * <pre>
  3118.      * StringUtils.isAllEmpty(null)             = true
  3119.      * StringUtils.isAllEmpty(null, "")         = true
  3120.      * StringUtils.isAllEmpty(new String[] {})  = true
  3121.      * StringUtils.isAllEmpty(null, "foo")      = false
  3122.      * StringUtils.isAllEmpty("", "bar")        = false
  3123.      * StringUtils.isAllEmpty("bob", "")        = false
  3124.      * StringUtils.isAllEmpty("  bob  ", null)  = false
  3125.      * StringUtils.isAllEmpty(" ", "bar")       = false
  3126.      * StringUtils.isAllEmpty("foo", "bar")     = false
  3127.      * </pre>
  3128.      *
  3129.      * @param css  the CharSequences to check, may be null or empty
  3130.      * @return {@code true} if all of the CharSequences are empty or null
  3131.      * @since 3.6
  3132.      */
  3133.     public static boolean isAllEmpty(final CharSequence... css) {
  3134.         if (ArrayUtils.isEmpty(css)) {
  3135.             return true;
  3136.         }
  3137.         for (final CharSequence cs : css) {
  3138.             if (isNotEmpty(cs)) {
  3139.                 return false;
  3140.             }
  3141.         }
  3142.         return true;
  3143.     }

  3144.     /**
  3145.      * Checks if the CharSequence contains only lowercase characters.
  3146.      *
  3147.      * <p>{@code null} will return {@code false}.
  3148.      * An empty CharSequence (length()=0) will return {@code false}.</p>
  3149.      *
  3150.      * <pre>
  3151.      * StringUtils.isAllLowerCase(null)   = false
  3152.      * StringUtils.isAllLowerCase("")     = false
  3153.      * StringUtils.isAllLowerCase("  ")   = false
  3154.      * StringUtils.isAllLowerCase("abc")  = true
  3155.      * StringUtils.isAllLowerCase("abC")  = false
  3156.      * StringUtils.isAllLowerCase("ab c") = false
  3157.      * StringUtils.isAllLowerCase("ab1c") = false
  3158.      * StringUtils.isAllLowerCase("ab/c") = false
  3159.      * </pre>
  3160.      *
  3161.      * @param cs  the CharSequence to check, may be null
  3162.      * @return {@code true} if only contains lowercase characters, and is non-null
  3163.      * @since 2.5
  3164.      * @since 3.0 Changed signature from isAllLowerCase(String) to isAllLowerCase(CharSequence)
  3165.      */
  3166.     public static boolean isAllLowerCase(final CharSequence cs) {
  3167.         if (isEmpty(cs)) {
  3168.             return false;
  3169.         }
  3170.         final int sz = cs.length();
  3171.         for (int i = 0; i < sz; i++) {
  3172.             if (!Character.isLowerCase(cs.charAt(i))) {
  3173.                 return false;
  3174.             }
  3175.         }
  3176.         return true;
  3177.     }

  3178.     /**
  3179.      * Checks if the CharSequence contains only uppercase characters.
  3180.      *
  3181.      * <p>{@code null} will return {@code false}.
  3182.      * An empty String (length()=0) will return {@code false}.</p>
  3183.      *
  3184.      * <pre>
  3185.      * StringUtils.isAllUpperCase(null)   = false
  3186.      * StringUtils.isAllUpperCase("")     = false
  3187.      * StringUtils.isAllUpperCase("  ")   = false
  3188.      * StringUtils.isAllUpperCase("ABC")  = true
  3189.      * StringUtils.isAllUpperCase("aBC")  = false
  3190.      * StringUtils.isAllUpperCase("A C")  = false
  3191.      * StringUtils.isAllUpperCase("A1C")  = false
  3192.      * StringUtils.isAllUpperCase("A/C")  = false
  3193.      * </pre>
  3194.      *
  3195.      * @param cs the CharSequence to check, may be null
  3196.      * @return {@code true} if only contains uppercase characters, and is non-null
  3197.      * @since 2.5
  3198.      * @since 3.0 Changed signature from isAllUpperCase(String) to isAllUpperCase(CharSequence)
  3199.      */
  3200.     public static boolean isAllUpperCase(final CharSequence cs) {
  3201.         if (isEmpty(cs)) {
  3202.             return false;
  3203.         }
  3204.         final int sz = cs.length();
  3205.         for (int i = 0; i < sz; i++) {
  3206.             if (!Character.isUpperCase(cs.charAt(i))) {
  3207.                 return false;
  3208.             }
  3209.         }
  3210.         return true;
  3211.     }

  3212.     /**
  3213.      * Checks if the CharSequence contains only Unicode letters.
  3214.      *
  3215.      * <p>{@code null} will return {@code false}.
  3216.      * An empty CharSequence (length()=0) will return {@code false}.</p>
  3217.      *
  3218.      * <pre>
  3219.      * StringUtils.isAlpha(null)   = false
  3220.      * StringUtils.isAlpha("")     = false
  3221.      * StringUtils.isAlpha("  ")   = false
  3222.      * StringUtils.isAlpha("abc")  = true
  3223.      * StringUtils.isAlpha("ab2c") = false
  3224.      * StringUtils.isAlpha("ab-c") = false
  3225.      * </pre>
  3226.      *
  3227.      * @param cs  the CharSequence to check, may be null
  3228.      * @return {@code true} if only contains letters, and is non-null
  3229.      * @since 3.0 Changed signature from isAlpha(String) to isAlpha(CharSequence)
  3230.      * @since 3.0 Changed "" to return false and not true
  3231.      */
  3232.     public static boolean isAlpha(final CharSequence cs) {
  3233.         if (isEmpty(cs)) {
  3234.             return false;
  3235.         }
  3236.         final int sz = cs.length();
  3237.         for (int i = 0; i < sz; i++) {
  3238.             if (!Character.isLetter(cs.charAt(i))) {
  3239.                 return false;
  3240.             }
  3241.         }
  3242.         return true;
  3243.     }

  3244.     /**
  3245.      * Checks if the CharSequence contains only Unicode letters or digits.
  3246.      *
  3247.      * <p>{@code null} will return {@code false}.
  3248.      * An empty CharSequence (length()=0) will return {@code false}.</p>
  3249.      *
  3250.      * <pre>
  3251.      * StringUtils.isAlphanumeric(null)   = false
  3252.      * StringUtils.isAlphanumeric("")     = false
  3253.      * StringUtils.isAlphanumeric("  ")   = false
  3254.      * StringUtils.isAlphanumeric("abc")  = true
  3255.      * StringUtils.isAlphanumeric("ab c") = false
  3256.      * StringUtils.isAlphanumeric("ab2c") = true
  3257.      * StringUtils.isAlphanumeric("ab-c") = false
  3258.      * </pre>
  3259.      *
  3260.      * @param cs  the CharSequence to check, may be null
  3261.      * @return {@code true} if only contains letters or digits,
  3262.      *  and is non-null
  3263.      * @since 3.0 Changed signature from isAlphanumeric(String) to isAlphanumeric(CharSequence)
  3264.      * @since 3.0 Changed "" to return false and not true
  3265.      */
  3266.     public static boolean isAlphanumeric(final CharSequence cs) {
  3267.         if (isEmpty(cs)) {
  3268.             return false;
  3269.         }
  3270.         final int sz = cs.length();
  3271.         for (int i = 0; i < sz; i++) {
  3272.             if (!Character.isLetterOrDigit(cs.charAt(i))) {
  3273.                 return false;
  3274.             }
  3275.         }
  3276.         return true;
  3277.     }

  3278.     /**
  3279.      * Checks if the CharSequence contains only Unicode letters, digits
  3280.      * or space ({@code ' '}).
  3281.      *
  3282.      * <p>{@code null} will return {@code false}.
  3283.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3284.      *
  3285.      * <pre>
  3286.      * StringUtils.isAlphanumericSpace(null)   = false
  3287.      * StringUtils.isAlphanumericSpace("")     = true
  3288.      * StringUtils.isAlphanumericSpace("  ")   = true
  3289.      * StringUtils.isAlphanumericSpace("abc")  = true
  3290.      * StringUtils.isAlphanumericSpace("ab c") = true
  3291.      * StringUtils.isAlphanumericSpace("ab2c") = true
  3292.      * StringUtils.isAlphanumericSpace("ab-c") = false
  3293.      * </pre>
  3294.      *
  3295.      * @param cs  the CharSequence to check, may be null
  3296.      * @return {@code true} if only contains letters, digits or space,
  3297.      *  and is non-null
  3298.      * @since 3.0 Changed signature from isAlphanumericSpace(String) to isAlphanumericSpace(CharSequence)
  3299.      */
  3300.     public static boolean isAlphanumericSpace(final CharSequence cs) {
  3301.         if (cs == null) {
  3302.             return false;
  3303.         }
  3304.         final int sz = cs.length();
  3305.         for (int i = 0; i < sz; i++) {
  3306.             final char nowChar = cs.charAt(i);
  3307.             if (nowChar != ' ' && !Character.isLetterOrDigit(nowChar) ) {
  3308.                 return false;
  3309.             }
  3310.         }
  3311.         return true;
  3312.     }

  3313.     /**
  3314.      * Checks if the CharSequence contains only Unicode letters and
  3315.      * space (' ').
  3316.      *
  3317.      * <p>{@code null} will return {@code false}
  3318.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3319.      *
  3320.      * <pre>
  3321.      * StringUtils.isAlphaSpace(null)   = false
  3322.      * StringUtils.isAlphaSpace("")     = true
  3323.      * StringUtils.isAlphaSpace("  ")   = true
  3324.      * StringUtils.isAlphaSpace("abc")  = true
  3325.      * StringUtils.isAlphaSpace("ab c") = true
  3326.      * StringUtils.isAlphaSpace("ab2c") = false
  3327.      * StringUtils.isAlphaSpace("ab-c") = false
  3328.      * </pre>
  3329.      *
  3330.      * @param cs  the CharSequence to check, may be null
  3331.      * @return {@code true} if only contains letters and space,
  3332.      *  and is non-null
  3333.      * @since 3.0 Changed signature from isAlphaSpace(String) to isAlphaSpace(CharSequence)
  3334.      */
  3335.     public static boolean isAlphaSpace(final CharSequence cs) {
  3336.         if (cs == null) {
  3337.             return false;
  3338.         }
  3339.         final int sz = cs.length();
  3340.         for (int i = 0; i < sz; i++) {
  3341.             final char nowChar = cs.charAt(i);
  3342.             if (nowChar != ' ' && !Character.isLetter(nowChar)) {
  3343.                 return false;
  3344.             }
  3345.         }
  3346.         return true;
  3347.     }

  3348.     /**
  3349.      * Checks if any of the CharSequences are empty ("") or null or whitespace only.
  3350.      *
  3351.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  3352.      *
  3353.      * <pre>
  3354.      * StringUtils.isAnyBlank((String) null)    = true
  3355.      * StringUtils.isAnyBlank((String[]) null)  = false
  3356.      * StringUtils.isAnyBlank(null, "foo")      = true
  3357.      * StringUtils.isAnyBlank(null, null)       = true
  3358.      * StringUtils.isAnyBlank("", "bar")        = true
  3359.      * StringUtils.isAnyBlank("bob", "")        = true
  3360.      * StringUtils.isAnyBlank("  bob  ", null)  = true
  3361.      * StringUtils.isAnyBlank(" ", "bar")       = true
  3362.      * StringUtils.isAnyBlank(new String[] {})  = false
  3363.      * StringUtils.isAnyBlank(new String[]{""}) = true
  3364.      * StringUtils.isAnyBlank("foo", "bar")     = false
  3365.      * </pre>
  3366.      *
  3367.      * @param css  the CharSequences to check, may be null or empty
  3368.      * @return {@code true} if any of the CharSequences are empty or null or whitespace only
  3369.      * @since 3.2
  3370.      */
  3371.     public static boolean isAnyBlank(final CharSequence... css) {
  3372.         if (ArrayUtils.isEmpty(css)) {
  3373.             return false;
  3374.         }
  3375.         for (final CharSequence cs : css) {
  3376.             if (isBlank(cs)) {
  3377.                 return true;
  3378.             }
  3379.         }
  3380.         return false;
  3381.     }

  3382.     /**
  3383.      * Checks if any of the CharSequences are empty ("") or null.
  3384.      *
  3385.      * <pre>
  3386.      * StringUtils.isAnyEmpty((String) null)    = true
  3387.      * StringUtils.isAnyEmpty((String[]) null)  = false
  3388.      * StringUtils.isAnyEmpty(null, "foo")      = true
  3389.      * StringUtils.isAnyEmpty("", "bar")        = true
  3390.      * StringUtils.isAnyEmpty("bob", "")        = true
  3391.      * StringUtils.isAnyEmpty("  bob  ", null)  = true
  3392.      * StringUtils.isAnyEmpty(" ", "bar")       = false
  3393.      * StringUtils.isAnyEmpty("foo", "bar")     = false
  3394.      * StringUtils.isAnyEmpty(new String[]{})   = false
  3395.      * StringUtils.isAnyEmpty(new String[]{""}) = true
  3396.      * </pre>
  3397.      *
  3398.      * @param css  the CharSequences to check, may be null or empty
  3399.      * @return {@code true} if any of the CharSequences are empty or null
  3400.      * @since 3.2
  3401.      */
  3402.     public static boolean isAnyEmpty(final CharSequence... css) {
  3403.         if (ArrayUtils.isEmpty(css)) {
  3404.             return false;
  3405.         }
  3406.         for (final CharSequence cs : css) {
  3407.             if (isEmpty(cs)) {
  3408.                 return true;
  3409.             }
  3410.         }
  3411.         return false;
  3412.     }

  3413.     /**
  3414.      * Checks if the CharSequence contains only ASCII printable characters.
  3415.      *
  3416.      * <p>{@code null} will return {@code false}.
  3417.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3418.      *
  3419.      * <pre>
  3420.      * StringUtils.isAsciiPrintable(null)     = false
  3421.      * StringUtils.isAsciiPrintable("")       = true
  3422.      * StringUtils.isAsciiPrintable(" ")      = true
  3423.      * StringUtils.isAsciiPrintable("Ceki")   = true
  3424.      * StringUtils.isAsciiPrintable("ab2c")   = true
  3425.      * StringUtils.isAsciiPrintable("!ab-c~") = true
  3426.      * StringUtils.isAsciiPrintable("\u0020") = true
  3427.      * StringUtils.isAsciiPrintable("\u0021") = true
  3428.      * StringUtils.isAsciiPrintable("\u007e") = true
  3429.      * StringUtils.isAsciiPrintable("\u007f") = false
  3430.      * StringUtils.isAsciiPrintable("Ceki G\u00fclc\u00fc") = false
  3431.      * </pre>
  3432.      *
  3433.      * @param cs the CharSequence to check, may be null
  3434.      * @return {@code true} if every character is in the range
  3435.      *  32 through 126
  3436.      * @since 2.1
  3437.      * @since 3.0 Changed signature from isAsciiPrintable(String) to isAsciiPrintable(CharSequence)
  3438.      */
  3439.     public static boolean isAsciiPrintable(final CharSequence cs) {
  3440.         if (cs == null) {
  3441.             return false;
  3442.         }
  3443.         final int sz = cs.length();
  3444.         for (int i = 0; i < sz; i++) {
  3445.             if (!CharUtils.isAsciiPrintable(cs.charAt(i))) {
  3446.                 return false;
  3447.             }
  3448.         }
  3449.         return true;
  3450.     }

  3451.     /**
  3452.      * Checks if a CharSequence is empty (""), null or whitespace only.
  3453.      *
  3454.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  3455.      *
  3456.      * <pre>
  3457.      * StringUtils.isBlank(null)      = true
  3458.      * StringUtils.isBlank("")        = true
  3459.      * StringUtils.isBlank(" ")       = true
  3460.      * StringUtils.isBlank("bob")     = false
  3461.      * StringUtils.isBlank("  bob  ") = false
  3462.      * </pre>
  3463.      *
  3464.      * @param cs  the CharSequence to check, may be null
  3465.      * @return {@code true} if the CharSequence is null, empty or whitespace only
  3466.      * @since 2.0
  3467.      * @since 3.0 Changed signature from isBlank(String) to isBlank(CharSequence)
  3468.      */
  3469.     public static boolean isBlank(final CharSequence cs) {
  3470.         final int strLen = length(cs);
  3471.         if (strLen == 0) {
  3472.             return true;
  3473.         }
  3474.         for (int i = 0; i < strLen; i++) {
  3475.             if (!Character.isWhitespace(cs.charAt(i))) {
  3476.                 return false;
  3477.             }
  3478.         }
  3479.         return true;
  3480.     }

  3481.     /**
  3482.      * Checks if a CharSequence is empty ("") or null.
  3483.      *
  3484.      * <pre>
  3485.      * StringUtils.isEmpty(null)      = true
  3486.      * StringUtils.isEmpty("")        = true
  3487.      * StringUtils.isEmpty(" ")       = false
  3488.      * StringUtils.isEmpty("bob")     = false
  3489.      * StringUtils.isEmpty("  bob  ") = false
  3490.      * </pre>
  3491.      *
  3492.      * <p>NOTE: This method changed in Lang version 2.0.
  3493.      * It no longer trims the CharSequence.
  3494.      * That functionality is available in isBlank().</p>
  3495.      *
  3496.      * @param cs  the CharSequence to check, may be null
  3497.      * @return {@code true} if the CharSequence is empty or null
  3498.      * @since 3.0 Changed signature from isEmpty(String) to isEmpty(CharSequence)
  3499.      */
  3500.     public static boolean isEmpty(final CharSequence cs) {
  3501.         return cs == null || cs.length() == 0;
  3502.     }

  3503.     /**
  3504.      * Checks if the CharSequence contains mixed casing of both uppercase and lowercase characters.
  3505.      *
  3506.      * <p>{@code null} will return {@code false}. An empty CharSequence ({@code length()=0}) will return
  3507.      * {@code false}.</p>
  3508.      *
  3509.      * <pre>
  3510.      * StringUtils.isMixedCase(null)    = false
  3511.      * StringUtils.isMixedCase("")      = false
  3512.      * StringUtils.isMixedCase(" ")     = false
  3513.      * StringUtils.isMixedCase("ABC")   = false
  3514.      * StringUtils.isMixedCase("abc")   = false
  3515.      * StringUtils.isMixedCase("aBc")   = true
  3516.      * StringUtils.isMixedCase("A c")   = true
  3517.      * StringUtils.isMixedCase("A1c")   = true
  3518.      * StringUtils.isMixedCase("a/C")   = true
  3519.      * StringUtils.isMixedCase("aC\t")  = true
  3520.      * </pre>
  3521.      *
  3522.      * @param cs the CharSequence to check, may be null
  3523.      * @return {@code true} if the CharSequence contains both uppercase and lowercase characters
  3524.      * @since 3.5
  3525.      */
  3526.     public static boolean isMixedCase(final CharSequence cs) {
  3527.         if (isEmpty(cs) || cs.length() == 1) {
  3528.             return false;
  3529.         }
  3530.         boolean containsUppercase = false;
  3531.         boolean containsLowercase = false;
  3532.         final int sz = cs.length();
  3533.         for (int i = 0; i < sz; i++) {
  3534.             final char nowChar = cs.charAt(i);
  3535.             if (Character.isUpperCase(nowChar)) {
  3536.                 containsUppercase = true;
  3537.             } else if (Character.isLowerCase(nowChar)) {
  3538.                 containsLowercase = true;
  3539.             }
  3540.             if (containsUppercase && containsLowercase) {
  3541.                 return true;
  3542.             }
  3543.         }
  3544.         return false;
  3545.     }

  3546.     /**
  3547.      * Checks if none of the CharSequences are empty (""), null or whitespace only.
  3548.      *
  3549.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  3550.      *
  3551.      * <pre>
  3552.      * StringUtils.isNoneBlank((String) null)    = false
  3553.      * StringUtils.isNoneBlank((String[]) null)  = true
  3554.      * StringUtils.isNoneBlank(null, "foo")      = false
  3555.      * StringUtils.isNoneBlank(null, null)       = false
  3556.      * StringUtils.isNoneBlank("", "bar")        = false
  3557.      * StringUtils.isNoneBlank("bob", "")        = false
  3558.      * StringUtils.isNoneBlank("  bob  ", null)  = false
  3559.      * StringUtils.isNoneBlank(" ", "bar")       = false
  3560.      * StringUtils.isNoneBlank(new String[] {})  = true
  3561.      * StringUtils.isNoneBlank(new String[]{""}) = false
  3562.      * StringUtils.isNoneBlank("foo", "bar")     = true
  3563.      * </pre>
  3564.      *
  3565.      * @param css  the CharSequences to check, may be null or empty
  3566.      * @return {@code true} if none of the CharSequences are empty or null or whitespace only
  3567.      * @since 3.2
  3568.      */
  3569.     public static boolean isNoneBlank(final CharSequence... css) {
  3570.       return !isAnyBlank(css);
  3571.     }

  3572.     /**
  3573.      * Checks if none of the CharSequences are empty ("") or null.
  3574.      *
  3575.      * <pre>
  3576.      * StringUtils.isNoneEmpty((String) null)    = false
  3577.      * StringUtils.isNoneEmpty((String[]) null)  = true
  3578.      * StringUtils.isNoneEmpty(null, "foo")      = false
  3579.      * StringUtils.isNoneEmpty("", "bar")        = false
  3580.      * StringUtils.isNoneEmpty("bob", "")        = false
  3581.      * StringUtils.isNoneEmpty("  bob  ", null)  = false
  3582.      * StringUtils.isNoneEmpty(new String[] {})  = true
  3583.      * StringUtils.isNoneEmpty(new String[]{""}) = false
  3584.      * StringUtils.isNoneEmpty(" ", "bar")       = true
  3585.      * StringUtils.isNoneEmpty("foo", "bar")     = true
  3586.      * </pre>
  3587.      *
  3588.      * @param css  the CharSequences to check, may be null or empty
  3589.      * @return {@code true} if none of the CharSequences are empty or null
  3590.      * @since 3.2
  3591.      */
  3592.     public static boolean isNoneEmpty(final CharSequence... css) {
  3593.       return !isAnyEmpty(css);
  3594.     }

  3595.     /**
  3596.      * Checks if a CharSequence is not empty (""), not null and not whitespace only.
  3597.      *
  3598.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  3599.      *
  3600.      * <pre>
  3601.      * StringUtils.isNotBlank(null)      = false
  3602.      * StringUtils.isNotBlank("")        = false
  3603.      * StringUtils.isNotBlank(" ")       = false
  3604.      * StringUtils.isNotBlank("bob")     = true
  3605.      * StringUtils.isNotBlank("  bob  ") = true
  3606.      * </pre>
  3607.      *
  3608.      * @param cs  the CharSequence to check, may be null
  3609.      * @return {@code true} if the CharSequence is
  3610.      *  not empty and not null and not whitespace only
  3611.      * @since 2.0
  3612.      * @since 3.0 Changed signature from isNotBlank(String) to isNotBlank(CharSequence)
  3613.      */
  3614.     public static boolean isNotBlank(final CharSequence cs) {
  3615.         return !isBlank(cs);
  3616.     }

  3617.     /**
  3618.      * Checks if a CharSequence is not empty ("") and not null.
  3619.      *
  3620.      * <pre>
  3621.      * StringUtils.isNotEmpty(null)      = false
  3622.      * StringUtils.isNotEmpty("")        = false
  3623.      * StringUtils.isNotEmpty(" ")       = true
  3624.      * StringUtils.isNotEmpty("bob")     = true
  3625.      * StringUtils.isNotEmpty("  bob  ") = true
  3626.      * </pre>
  3627.      *
  3628.      * @param cs  the CharSequence to check, may be null
  3629.      * @return {@code true} if the CharSequence is not empty and not null
  3630.      * @since 3.0 Changed signature from isNotEmpty(String) to isNotEmpty(CharSequence)
  3631.      */
  3632.     public static boolean isNotEmpty(final CharSequence cs) {
  3633.         return !isEmpty(cs);
  3634.     }

  3635.     /**
  3636.      * Checks if the CharSequence contains only Unicode digits.
  3637.      * A decimal point is not a Unicode digit and returns false.
  3638.      *
  3639.      * <p>{@code null} will return {@code false}.
  3640.      * An empty CharSequence (length()=0) will return {@code false}.</p>
  3641.      *
  3642.      * <p>Note that the method does not allow for a leading sign, either positive or negative.
  3643.      * Also, if a String passes the numeric test, it may still generate a NumberFormatException
  3644.      * when parsed by Integer.parseInt or Long.parseLong, e.g. if the value is outside the range
  3645.      * for int or long respectively.</p>
  3646.      *
  3647.      * <pre>
  3648.      * StringUtils.isNumeric(null)   = false
  3649.      * StringUtils.isNumeric("")     = false
  3650.      * StringUtils.isNumeric("  ")   = false
  3651.      * StringUtils.isNumeric("123")  = true
  3652.      * StringUtils.isNumeric("\u0967\u0968\u0969")  = true
  3653.      * StringUtils.isNumeric("12 3") = false
  3654.      * StringUtils.isNumeric("ab2c") = false
  3655.      * StringUtils.isNumeric("12-3") = false
  3656.      * StringUtils.isNumeric("12.3") = false
  3657.      * StringUtils.isNumeric("-123") = false
  3658.      * StringUtils.isNumeric("+123") = false
  3659.      * </pre>
  3660.      *
  3661.      * @param cs  the CharSequence to check, may be null
  3662.      * @return {@code true} if only contains digits, and is non-null
  3663.      * @since 3.0 Changed signature from isNumeric(String) to isNumeric(CharSequence)
  3664.      * @since 3.0 Changed "" to return false and not true
  3665.      */
  3666.     public static boolean isNumeric(final CharSequence cs) {
  3667.         if (isEmpty(cs)) {
  3668.             return false;
  3669.         }
  3670.         final int sz = cs.length();
  3671.         for (int i = 0; i < sz; i++) {
  3672.             if (!Character.isDigit(cs.charAt(i))) {
  3673.                 return false;
  3674.             }
  3675.         }
  3676.         return true;
  3677.     }

  3678.     /**
  3679.      * Checks if the CharSequence contains only Unicode digits or space
  3680.      * ({@code ' '}).
  3681.      * A decimal point is not a Unicode digit and returns false.
  3682.      *
  3683.      * <p>{@code null} will return {@code false}.
  3684.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3685.      *
  3686.      * <pre>
  3687.      * StringUtils.isNumericSpace(null)   = false
  3688.      * StringUtils.isNumericSpace("")     = true
  3689.      * StringUtils.isNumericSpace("  ")   = true
  3690.      * StringUtils.isNumericSpace("123")  = true
  3691.      * StringUtils.isNumericSpace("12 3") = true
  3692.      * StringUtils.isNumericSpace("\u0967\u0968\u0969")   = true
  3693.      * StringUtils.isNumericSpace("\u0967\u0968 \u0969")  = true
  3694.      * StringUtils.isNumericSpace("ab2c") = false
  3695.      * StringUtils.isNumericSpace("12-3") = false
  3696.      * StringUtils.isNumericSpace("12.3") = false
  3697.      * </pre>
  3698.      *
  3699.      * @param cs  the CharSequence to check, may be null
  3700.      * @return {@code true} if only contains digits or space,
  3701.      *  and is non-null
  3702.      * @since 3.0 Changed signature from isNumericSpace(String) to isNumericSpace(CharSequence)
  3703.      */
  3704.     public static boolean isNumericSpace(final CharSequence cs) {
  3705.         if (cs == null) {
  3706.             return false;
  3707.         }
  3708.         final int sz = cs.length();
  3709.         for (int i = 0; i < sz; i++) {
  3710.             final char nowChar = cs.charAt(i);
  3711.             if (nowChar != ' ' && !Character.isDigit(nowChar)) {
  3712.                 return false;
  3713.             }
  3714.         }
  3715.         return true;
  3716.     }

  3717.     /**
  3718.      * Checks if the CharSequence contains only whitespace.
  3719.      *
  3720.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  3721.      *
  3722.      * <p>{@code null} will return {@code false}.
  3723.      * An empty CharSequence (length()=0) will return {@code true}.</p>
  3724.      *
  3725.      * <pre>
  3726.      * StringUtils.isWhitespace(null)   = false
  3727.      * StringUtils.isWhitespace("")     = true
  3728.      * StringUtils.isWhitespace("  ")   = true
  3729.      * StringUtils.isWhitespace("abc")  = false
  3730.      * StringUtils.isWhitespace("ab2c") = false
  3731.      * StringUtils.isWhitespace("ab-c") = false
  3732.      * </pre>
  3733.      *
  3734.      * @param cs  the CharSequence to check, may be null
  3735.      * @return {@code true} if only contains whitespace, and is non-null
  3736.      * @since 2.0
  3737.      * @since 3.0 Changed signature from isWhitespace(String) to isWhitespace(CharSequence)
  3738.      */
  3739.     public static boolean isWhitespace(final CharSequence cs) {
  3740.         if (cs == null) {
  3741.             return false;
  3742.         }
  3743.         final int sz = cs.length();
  3744.         for (int i = 0; i < sz; i++) {
  3745.             if (!Character.isWhitespace(cs.charAt(i))) {
  3746.                 return false;
  3747.             }
  3748.         }
  3749.         return true;
  3750.     }

  3751.     /**
  3752.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3753.      *
  3754.      * <p>
  3755.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3756.      * by empty strings.
  3757.      * </p>
  3758.      *
  3759.      * <pre>
  3760.      * StringUtils.join(null, *)             = null
  3761.      * StringUtils.join([], *)               = ""
  3762.      * StringUtils.join([null], *)           = ""
  3763.      * StringUtils.join([false, false], ';') = "false;false"
  3764.      * </pre>
  3765.      *
  3766.      * @param array
  3767.      *            the array of values to join together, may be null
  3768.      * @param delimiter
  3769.      *            the separator character to use
  3770.      * @return the joined String, {@code null} if null array input
  3771.      * @since 3.12.0
  3772.      */
  3773.     public static String join(final boolean[] array, final char delimiter) {
  3774.         if (array == null) {
  3775.             return null;
  3776.         }
  3777.         return join(array, delimiter, 0, array.length);
  3778.     }

  3779.     /**
  3780.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3781.      *
  3782.      * <p>
  3783.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3784.      * by empty strings.
  3785.      * </p>
  3786.      *
  3787.      * <pre>
  3788.      * StringUtils.join(null, *)                  = null
  3789.      * StringUtils.join([], *)                    = ""
  3790.      * StringUtils.join([null], *)                = ""
  3791.      * StringUtils.join([true, false, true], ';') = "true;false;true"
  3792.      * </pre>
  3793.      *
  3794.      * @param array
  3795.      *            the array of values to join together, may be null
  3796.      * @param delimiter
  3797.      *            the separator character to use
  3798.      * @param startIndex
  3799.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  3800.      *            array
  3801.      * @param endIndex
  3802.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  3803.      *            the array
  3804.      * @return the joined String, {@code null} if null array input
  3805.      * @since 3.12.0
  3806.      */
  3807.     public static String join(final boolean[] array, final char delimiter, final int startIndex, final int endIndex) {
  3808.         if (array == null) {
  3809.             return null;
  3810.         }
  3811.         if (endIndex - startIndex <= 0) {
  3812.             return EMPTY;
  3813.         }
  3814.         final StringBuilder stringBuilder = new StringBuilder(array.length * 5 + array.length - 1);
  3815.         for (int i = startIndex; i < endIndex; i++) {
  3816.             stringBuilder
  3817.                     .append(array[i])
  3818.                     .append(delimiter);
  3819.         }
  3820.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  3821.     }

  3822.     /**
  3823.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3824.      *
  3825.      * <p>
  3826.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3827.      * by empty strings.
  3828.      * </p>
  3829.      *
  3830.      * <pre>
  3831.      * StringUtils.join(null, *)         = null
  3832.      * StringUtils.join([], *)           = ""
  3833.      * StringUtils.join([null], *)       = ""
  3834.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3835.      * StringUtils.join([1, 2, 3], null) = "123"
  3836.      * </pre>
  3837.      *
  3838.      * @param array
  3839.      *            the array of values to join together, may be null
  3840.      * @param delimiter
  3841.      *            the separator character to use
  3842.      * @return the joined String, {@code null} if null array input
  3843.      * @since 3.2
  3844.      */
  3845.     public static String join(final byte[] array, final char delimiter) {
  3846.         if (array == null) {
  3847.             return null;
  3848.         }
  3849.         return join(array, delimiter, 0, array.length);
  3850.     }

  3851.     /**
  3852.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3853.      *
  3854.      * <p>
  3855.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3856.      * by empty strings.
  3857.      * </p>
  3858.      *
  3859.      * <pre>
  3860.      * StringUtils.join(null, *)         = null
  3861.      * StringUtils.join([], *)           = ""
  3862.      * StringUtils.join([null], *)       = ""
  3863.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3864.      * StringUtils.join([1, 2, 3], null) = "123"
  3865.      * </pre>
  3866.      *
  3867.      * @param array
  3868.      *            the array of values to join together, may be null
  3869.      * @param delimiter
  3870.      *            the separator character to use
  3871.      * @param startIndex
  3872.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  3873.      *            array
  3874.      * @param endIndex
  3875.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  3876.      *            the array
  3877.      * @return the joined String, {@code null} if null array input
  3878.      * @since 3.2
  3879.      */
  3880.     public static String join(final byte[] array, final char delimiter, final int startIndex, final int endIndex) {
  3881.         if (array == null) {
  3882.             return null;
  3883.         }
  3884.         if (endIndex - startIndex <= 0) {
  3885.             return EMPTY;
  3886.         }
  3887.         final StringBuilder stringBuilder = new StringBuilder();
  3888.         for (int i = startIndex; i < endIndex; i++) {
  3889.             stringBuilder
  3890.                     .append(array[i])
  3891.                     .append(delimiter);
  3892.         }
  3893.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  3894.     }

  3895.     /**
  3896.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3897.      *
  3898.      * <p>
  3899.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3900.      * by empty strings.
  3901.      * </p>
  3902.      *
  3903.      * <pre>
  3904.      * StringUtils.join(null, *)         = null
  3905.      * StringUtils.join([], *)           = ""
  3906.      * StringUtils.join([null], *)       = ""
  3907.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3908.      * StringUtils.join([1, 2, 3], null) = "123"
  3909.      * </pre>
  3910.      *
  3911.      * @param array
  3912.      *            the array of values to join together, may be null
  3913.      * @param delimiter
  3914.      *            the separator character to use
  3915.      * @return the joined String, {@code null} if null array input
  3916.      * @since 3.2
  3917.      */
  3918.     public static String join(final char[] array, final char delimiter) {
  3919.         if (array == null) {
  3920.             return null;
  3921.         }
  3922.         return join(array, delimiter, 0, array.length);
  3923.     }

  3924.     /**
  3925.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3926.      *
  3927.      * <p>
  3928.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3929.      * by empty strings.
  3930.      * </p>
  3931.      *
  3932.      * <pre>
  3933.      * StringUtils.join(null, *)         = null
  3934.      * StringUtils.join([], *)           = ""
  3935.      * StringUtils.join([null], *)       = ""
  3936.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3937.      * StringUtils.join([1, 2, 3], null) = "123"
  3938.      * </pre>
  3939.      *
  3940.      * @param array
  3941.      *            the array of values to join together, may be null
  3942.      * @param delimiter
  3943.      *            the separator character to use
  3944.      * @param startIndex
  3945.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  3946.      *            array
  3947.      * @param endIndex
  3948.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  3949.      *            the array
  3950.      * @return the joined String, {@code null} if null array input
  3951.      * @since 3.2
  3952.      */
  3953.     public static String join(final char[] array, final char delimiter, final int startIndex, final int endIndex) {
  3954.         if (array == null) {
  3955.             return null;
  3956.         }
  3957.         if (endIndex - startIndex <= 0) {
  3958.             return EMPTY;
  3959.         }
  3960.         final StringBuilder stringBuilder = new StringBuilder(array.length * 2 - 1);
  3961.         for (int i = startIndex; i < endIndex; i++) {
  3962.             stringBuilder
  3963.                     .append(array[i])
  3964.                     .append(delimiter);
  3965.         }
  3966.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  3967.     }

  3968.     /**
  3969.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3970.      *
  3971.      * <p>
  3972.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  3973.      * by empty strings.
  3974.      * </p>
  3975.      *
  3976.      * <pre>
  3977.      * StringUtils.join(null, *)               = null
  3978.      * StringUtils.join([], *)                 = ""
  3979.      * StringUtils.join([null], *)             = ""
  3980.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  3981.      * StringUtils.join([1, 2, 3], null) = "123"
  3982.      * </pre>
  3983.      *
  3984.      * @param array
  3985.      *            the array of values to join together, may be null
  3986.      * @param delimiter
  3987.      *            the separator character to use
  3988.      * @return the joined String, {@code null} if null array input
  3989.      * @since 3.2
  3990.      */
  3991.     public static String join(final double[] array, final char delimiter) {
  3992.         if (array == null) {
  3993.             return null;
  3994.         }
  3995.         return join(array, delimiter, 0, array.length);
  3996.     }

  3997.     /**
  3998.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  3999.      *
  4000.      * <p>
  4001.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4002.      * by empty strings.
  4003.      * </p>
  4004.      *
  4005.      * <pre>
  4006.      * StringUtils.join(null, *)               = null
  4007.      * StringUtils.join([], *)                 = ""
  4008.      * StringUtils.join([null], *)             = ""
  4009.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4010.      * StringUtils.join([1, 2, 3], null) = "123"
  4011.      * </pre>
  4012.      *
  4013.      * @param array
  4014.      *            the array of values to join together, may be null
  4015.      * @param delimiter
  4016.      *            the separator character to use
  4017.      * @param startIndex
  4018.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  4019.      *            array
  4020.      * @param endIndex
  4021.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  4022.      *            the array
  4023.      * @return the joined String, {@code null} if null array input
  4024.      * @since 3.2
  4025.      */
  4026.     public static String join(final double[] array, final char delimiter, final int startIndex, final int endIndex) {
  4027.         if (array == null) {
  4028.             return null;
  4029.         }
  4030.         if (endIndex - startIndex <= 0) {
  4031.             return EMPTY;
  4032.         }
  4033.         final StringBuilder stringBuilder = new StringBuilder();
  4034.         for (int i = startIndex; i < endIndex; i++) {
  4035.             stringBuilder
  4036.                     .append(array[i])
  4037.                     .append(delimiter);
  4038.         }
  4039.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  4040.     }

  4041.     /**
  4042.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4043.      *
  4044.      * <p>
  4045.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4046.      * by empty strings.
  4047.      * </p>
  4048.      *
  4049.      * <pre>
  4050.      * StringUtils.join(null, *)               = null
  4051.      * StringUtils.join([], *)                 = ""
  4052.      * StringUtils.join([null], *)             = ""
  4053.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4054.      * StringUtils.join([1, 2, 3], null) = "123"
  4055.      * </pre>
  4056.      *
  4057.      * @param array
  4058.      *            the array of values to join together, may be null
  4059.      * @param delimiter
  4060.      *            the separator character to use
  4061.      * @return the joined String, {@code null} if null array input
  4062.      * @since 3.2
  4063.      */
  4064.     public static String join(final float[] array, final char delimiter) {
  4065.         if (array == null) {
  4066.             return null;
  4067.         }
  4068.         return join(array, delimiter, 0, array.length);
  4069.     }

  4070.     /**
  4071.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4072.      *
  4073.      * <p>
  4074.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4075.      * by empty strings.
  4076.      * </p>
  4077.      *
  4078.      * <pre>
  4079.      * StringUtils.join(null, *)               = null
  4080.      * StringUtils.join([], *)                 = ""
  4081.      * StringUtils.join([null], *)             = ""
  4082.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4083.      * StringUtils.join([1, 2, 3], null) = "123"
  4084.      * </pre>
  4085.      *
  4086.      * @param array
  4087.      *            the array of values to join together, may be null
  4088.      * @param delimiter
  4089.      *            the separator character to use
  4090.      * @param startIndex
  4091.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  4092.      *            array
  4093.      * @param endIndex
  4094.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  4095.      *            the array
  4096.      * @return the joined String, {@code null} if null array input
  4097.      * @since 3.2
  4098.      */
  4099.     public static String join(final float[] array, final char delimiter, final int startIndex, final int endIndex) {
  4100.         if (array == null) {
  4101.             return null;
  4102.         }
  4103.         if (endIndex - startIndex <= 0) {
  4104.             return EMPTY;
  4105.         }
  4106.         final StringBuilder stringBuilder = new StringBuilder();
  4107.         for (int i = startIndex; i < endIndex; i++) {
  4108.             stringBuilder
  4109.                     .append(array[i])
  4110.                     .append(delimiter);
  4111.         }
  4112.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  4113.     }

  4114.     /**
  4115.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4116.      *
  4117.      * <p>
  4118.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4119.      * by empty strings.
  4120.      * </p>
  4121.      *
  4122.      * <pre>
  4123.      * StringUtils.join(null, *)               = null
  4124.      * StringUtils.join([], *)                 = ""
  4125.      * StringUtils.join([null], *)             = ""
  4126.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4127.      * StringUtils.join([1, 2, 3], null) = "123"
  4128.      * </pre>
  4129.      *
  4130.      * @param array
  4131.      *            the array of values to join together, may be null
  4132.      * @param separator
  4133.      *            the separator character to use
  4134.      * @return the joined String, {@code null} if null array input
  4135.      * @since 3.2
  4136.      */
  4137.     public static String join(final int[] array, final char separator) {
  4138.         if (array == null) {
  4139.             return null;
  4140.         }
  4141.         return join(array, separator, 0, array.length);
  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 int[] array, final char delimiter, final int startIndex, final int endIndex) {
  4173.         if (array == null) {
  4174.             return null;
  4175.         }
  4176.         if (endIndex - startIndex <= 0) {
  4177.             return EMPTY;
  4178.         }
  4179.         final StringBuilder stringBuilder = new StringBuilder();
  4180.         for (int i = startIndex; i < endIndex; i++) {
  4181.             stringBuilder
  4182.                     .append(array[i])
  4183.                     .append(delimiter);
  4184.         }
  4185.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  4186.     }

  4187.     /**
  4188.      * Joins the elements of the provided {@link Iterable} into
  4189.      * a single String containing the provided elements.
  4190.      *
  4191.      * <p>No delimiter is added before or after the list. Null objects or empty
  4192.      * strings within the iteration are represented by empty strings.</p>
  4193.      *
  4194.      * <p>See the examples here: {@link #join(Object[],char)}.</p>
  4195.      *
  4196.      * @param iterable  the {@link Iterable} providing the values to join together, may be null
  4197.      * @param separator  the separator character to use
  4198.      * @return the joined String, {@code null} if null iterator input
  4199.      * @since 2.3
  4200.      */
  4201.     public static String join(final Iterable<?> iterable, final char separator) {
  4202.         return iterable != null ? join(iterable.iterator(), separator) : null;
  4203.     }

  4204.     /**
  4205.      * Joins the elements of the provided {@link Iterable} into
  4206.      * a single String containing the provided elements.
  4207.      *
  4208.      * <p>No delimiter is added before or after the list.
  4209.      * A {@code null} separator is the same as an empty String ("").</p>
  4210.      *
  4211.      * <p>See the examples here: {@link #join(Object[],String)}.</p>
  4212.      *
  4213.      * @param iterable  the {@link Iterable} providing the values to join together, may be null
  4214.      * @param separator  the separator character to use, null treated as ""
  4215.      * @return the joined String, {@code null} if null iterator input
  4216.      * @since 2.3
  4217.      */
  4218.     public static String join(final Iterable<?> iterable, final String separator) {
  4219.         return iterable != null ? join(iterable.iterator(), separator) : null;
  4220.     }

  4221.     /**
  4222.      * Joins the elements of the provided {@link Iterator} into
  4223.      * a single String containing the provided elements.
  4224.      *
  4225.      * <p>No delimiter is added before or after the list. Null objects or empty
  4226.      * strings within the iteration are represented by empty strings.</p>
  4227.      *
  4228.      * <p>See the examples here: {@link #join(Object[],char)}.</p>
  4229.      *
  4230.      * @param iterator  the {@link Iterator} of values to join together, may be null
  4231.      * @param separator  the separator character to use
  4232.      * @return the joined String, {@code null} if null iterator input
  4233.      * @since 2.0
  4234.      */
  4235.     public static String join(final Iterator<?> iterator, final char separator) {
  4236.         // handle null, zero and one elements before building a buffer
  4237.         if (iterator == null) {
  4238.             return null;
  4239.         }
  4240.         if (!iterator.hasNext()) {
  4241.             return EMPTY;
  4242.         }
  4243.         return Streams.of(iterator).collect(LangCollectors.joining(toStringOrEmpty(String.valueOf(separator)), EMPTY, EMPTY, StringUtils::toStringOrEmpty));
  4244.     }

  4245.     /**
  4246.      * Joins the elements of the provided {@link Iterator} into
  4247.      * a single String containing the provided elements.
  4248.      *
  4249.      * <p>No delimiter is added before or after the list.
  4250.      * A {@code null} separator is the same as an empty String ("").</p>
  4251.      *
  4252.      * <p>See the examples here: {@link #join(Object[],String)}.</p>
  4253.      *
  4254.      * @param iterator  the {@link Iterator} of values to join together, may be null
  4255.      * @param separator  the separator character to use, null treated as ""
  4256.      * @return the joined String, {@code null} if null iterator input
  4257.      */
  4258.     public static String join(final Iterator<?> iterator, final String separator) {
  4259.         // handle null, zero and one elements before building a buffer
  4260.         if (iterator == null) {
  4261.             return null;
  4262.         }
  4263.         if (!iterator.hasNext()) {
  4264.             return EMPTY;
  4265.         }
  4266.         return Streams.of(iterator).collect(LangCollectors.joining(toStringOrEmpty(separator), EMPTY, EMPTY, StringUtils::toStringOrEmpty));
  4267.     }

  4268.     /**
  4269.      * Joins the elements of the provided {@link List} into a single String
  4270.      * containing the provided list of elements.
  4271.      *
  4272.      * <p>No delimiter is added before or after the list.
  4273.      * Null objects or empty strings within the array are represented by
  4274.      * empty strings.</p>
  4275.      *
  4276.      * <pre>
  4277.      * StringUtils.join(null, *)               = null
  4278.      * StringUtils.join([], *)                 = ""
  4279.      * StringUtils.join([null], *)             = ""
  4280.      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
  4281.      * StringUtils.join(["a", "b", "c"], null) = "abc"
  4282.      * StringUtils.join([null, "", "a"], ';')  = ";;a"
  4283.      * </pre>
  4284.      *
  4285.      * @param list  the {@link List} of values to join together, may be null
  4286.      * @param separator  the separator character to use
  4287.      * @param startIndex the first index to start joining from.  It is
  4288.      * an error to pass in a start index past the end of the list
  4289.      * @param endIndex the index to stop joining from (exclusive). It is
  4290.      * an error to pass in an end index past the end of the list
  4291.      * @return the joined String, {@code null} if null list input
  4292.      * @since 3.8
  4293.      */
  4294.     public static String join(final List<?> list, final char separator, final int startIndex, final int endIndex) {
  4295.         if (list == null) {
  4296.             return null;
  4297.         }
  4298.         final int noOfItems = endIndex - startIndex;
  4299.         if (noOfItems <= 0) {
  4300.             return EMPTY;
  4301.         }
  4302.         final List<?> subList = list.subList(startIndex, endIndex);
  4303.         return join(subList.iterator(), separator);
  4304.     }

  4305.     /**
  4306.      * Joins the elements of the provided {@link List} into a single String
  4307.      * containing the provided list of elements.
  4308.      *
  4309.      * <p>No delimiter is added before or after the list.
  4310.      * Null objects or empty strings within the array are represented by
  4311.      * empty strings.</p>
  4312.      *
  4313.      * <pre>
  4314.      * StringUtils.join(null, *)               = null
  4315.      * StringUtils.join([], *)                 = ""
  4316.      * StringUtils.join([null], *)             = ""
  4317.      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
  4318.      * StringUtils.join(["a", "b", "c"], null) = "abc"
  4319.      * StringUtils.join([null, "", "a"], ';')  = ";;a"
  4320.      * </pre>
  4321.      *
  4322.      * @param list  the {@link List} of values to join together, may be null
  4323.      * @param separator  the separator character to use
  4324.      * @param startIndex the first index to start joining from.  It is
  4325.      * an error to pass in a start index past the end of the list
  4326.      * @param endIndex the index to stop joining from (exclusive). It is
  4327.      * an error to pass in an end index past the end of the list
  4328.      * @return the joined String, {@code null} if null list input
  4329.      * @since 3.8
  4330.      */
  4331.     public static String join(final List<?> list, final String separator, final int startIndex, final int endIndex) {
  4332.         if (list == null) {
  4333.             return null;
  4334.         }
  4335.         final int noOfItems = endIndex - startIndex;
  4336.         if (noOfItems <= 0) {
  4337.             return EMPTY;
  4338.         }
  4339.         final List<?> subList = list.subList(startIndex, endIndex);
  4340.         return join(subList.iterator(), separator);
  4341.     }

  4342.     /**
  4343.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4344.      *
  4345.      * <p>
  4346.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4347.      * by empty strings.
  4348.      * </p>
  4349.      *
  4350.      * <pre>
  4351.      * StringUtils.join(null, *)               = null
  4352.      * StringUtils.join([], *)                 = ""
  4353.      * StringUtils.join([null], *)             = ""
  4354.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4355.      * StringUtils.join([1, 2, 3], null) = "123"
  4356.      * </pre>
  4357.      *
  4358.      * @param array
  4359.      *            the array of values to join together, may be null
  4360.      * @param separator
  4361.      *            the separator character to use
  4362.      * @return the joined String, {@code null} if null array input
  4363.      * @since 3.2
  4364.      */
  4365.     public static String join(final long[] array, final char separator) {
  4366.         if (array == null) {
  4367.             return null;
  4368.         }
  4369.         return join(array, separator, 0, array.length);
  4370.     }

  4371.     /**
  4372.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4373.      *
  4374.      * <p>
  4375.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4376.      * by empty strings.
  4377.      * </p>
  4378.      *
  4379.      * <pre>
  4380.      * StringUtils.join(null, *)               = null
  4381.      * StringUtils.join([], *)                 = ""
  4382.      * StringUtils.join([null], *)             = ""
  4383.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4384.      * StringUtils.join([1, 2, 3], null) = "123"
  4385.      * </pre>
  4386.      *
  4387.      * @param array
  4388.      *            the array of values to join together, may be null
  4389.      * @param delimiter
  4390.      *            the separator character to use
  4391.      * @param startIndex
  4392.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  4393.      *            array
  4394.      * @param endIndex
  4395.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  4396.      *            the array
  4397.      * @return the joined String, {@code null} if null array input
  4398.      * @since 3.2
  4399.      */
  4400.     public static String join(final long[] array, final char delimiter, final int startIndex, final int endIndex) {
  4401.         if (array == null) {
  4402.             return null;
  4403.         }
  4404.         if (endIndex - startIndex <= 0) {
  4405.             return EMPTY;
  4406.         }
  4407.         final StringBuilder stringBuilder = new StringBuilder();
  4408.         for (int i = startIndex; i < endIndex; i++) {
  4409.             stringBuilder
  4410.                     .append(array[i])
  4411.                     .append(delimiter);
  4412.         }
  4413.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  4414.     }

  4415.     /**
  4416.      * Joins the elements of the provided array into a single String
  4417.      * containing the provided list of elements.
  4418.      *
  4419.      * <p>No delimiter is added before or after the list.
  4420.      * Null objects or empty strings within the array are represented by
  4421.      * empty strings.</p>
  4422.      *
  4423.      * <pre>
  4424.      * StringUtils.join(null, *)               = null
  4425.      * StringUtils.join([], *)                 = ""
  4426.      * StringUtils.join([null], *)             = ""
  4427.      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
  4428.      * StringUtils.join(["a", "b", "c"], null) = "abc"
  4429.      * StringUtils.join([null, "", "a"], ';')  = ";;a"
  4430.      * </pre>
  4431.      *
  4432.      * @param array  the array of values to join together, may be null
  4433.      * @param delimiter  the separator character to use
  4434.      * @return the joined String, {@code null} if null array input
  4435.      * @since 2.0
  4436.      */
  4437.     public static String join(final Object[] array, final char delimiter) {
  4438.         if (array == null) {
  4439.             return null;
  4440.         }
  4441.         return join(array, delimiter, 0, array.length);
  4442.     }

  4443.     /**
  4444.      * Joins the elements of the provided array into a single String
  4445.      * containing the provided list of elements.
  4446.      *
  4447.      * <p>No delimiter is added before or after the list.
  4448.      * Null objects or empty strings within the array are represented by
  4449.      * empty strings.</p>
  4450.      *
  4451.      * <pre>
  4452.      * StringUtils.join(null, *)               = null
  4453.      * StringUtils.join([], *)                 = ""
  4454.      * StringUtils.join([null], *)             = ""
  4455.      * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
  4456.      * StringUtils.join(["a", "b", "c"], null) = "abc"
  4457.      * StringUtils.join([null, "", "a"], ';')  = ";;a"
  4458.      * </pre>
  4459.      *
  4460.      * @param array  the array of values to join together, may be null
  4461.      * @param delimiter  the separator character to use
  4462.      * @param startIndex the first index to start joining from.  It is
  4463.      * an error to pass in a start index past the end of the array
  4464.      * @param endIndex the index to stop joining from (exclusive). It is
  4465.      * an error to pass in an end index past the end of the array
  4466.      * @return the joined String, {@code null} if null array input
  4467.      * @since 2.0
  4468.      */
  4469.     public static String join(final Object[] array, final char delimiter, final int startIndex, final int endIndex) {
  4470.         return join(array, String.valueOf(delimiter), startIndex, endIndex);
  4471.     }

  4472.     /**
  4473.      * Joins the elements of the provided array into a single String
  4474.      * containing the provided list of elements.
  4475.      *
  4476.      * <p>No delimiter is added before or after the list.
  4477.      * A {@code null} separator is the same as an empty String ("").
  4478.      * Null objects or empty strings within the array are represented by
  4479.      * empty strings.</p>
  4480.      *
  4481.      * <pre>
  4482.      * StringUtils.join(null, *)                = null
  4483.      * StringUtils.join([], *)                  = ""
  4484.      * StringUtils.join([null], *)              = ""
  4485.      * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
  4486.      * StringUtils.join(["a", "b", "c"], null)  = "abc"
  4487.      * StringUtils.join(["a", "b", "c"], "")    = "abc"
  4488.      * StringUtils.join([null, "", "a"], ',')   = ",,a"
  4489.      * </pre>
  4490.      *
  4491.      * @param array  the array of values to join together, may be null
  4492.      * @param delimiter  the separator character to use, null treated as ""
  4493.      * @return the joined String, {@code null} if null array input
  4494.      */
  4495.     public static String join(final Object[] array, final String delimiter) {
  4496.         return array != null ? join(array, toStringOrEmpty(delimiter), 0, array.length) : null;
  4497.     }

  4498.     /**
  4499.      * Joins the elements of the provided array into a single String
  4500.      * containing the provided list of elements.
  4501.      *
  4502.      * <p>No delimiter is added before or after the list.
  4503.      * A {@code null} separator is the same as an empty String ("").
  4504.      * Null objects or empty strings within the array are represented by
  4505.      * empty strings.</p>
  4506.      *
  4507.      * <pre>
  4508.      * StringUtils.join(null, *, *, *)                = null
  4509.      * StringUtils.join([], *, *, *)                  = ""
  4510.      * StringUtils.join([null], *, *, *)              = ""
  4511.      * StringUtils.join(["a", "b", "c"], "--", 0, 3)  = "a--b--c"
  4512.      * StringUtils.join(["a", "b", "c"], "--", 1, 3)  = "b--c"
  4513.      * StringUtils.join(["a", "b", "c"], "--", 2, 3)  = "c"
  4514.      * StringUtils.join(["a", "b", "c"], "--", 2, 2)  = ""
  4515.      * StringUtils.join(["a", "b", "c"], null, 0, 3)  = "abc"
  4516.      * StringUtils.join(["a", "b", "c"], "", 0, 3)    = "abc"
  4517.      * StringUtils.join([null, "", "a"], ',', 0, 3)   = ",,a"
  4518.      * </pre>
  4519.      *
  4520.      * @param array  the array of values to join together, may be null
  4521.      * @param delimiter  the separator character to use, null treated as ""
  4522.      * @param startIndex the first index to start joining from.
  4523.      * @param endIndex the index to stop joining from (exclusive).
  4524.      * @return the joined String, {@code null} if null array input; or the empty string
  4525.      * if {@code endIndex - startIndex <= 0}. The number of joined entries is given by
  4526.      * {@code endIndex - startIndex}
  4527.      * @throws ArrayIndexOutOfBoundsException ife<br>
  4528.      * {@code startIndex < 0} or <br>
  4529.      * {@code startIndex >= array.length()} or <br>
  4530.      * {@code endIndex < 0} or <br>
  4531.      * {@code endIndex > array.length()}
  4532.      */
  4533.     public static String join(final Object[] array, final String delimiter, final int startIndex, final int endIndex) {
  4534.         return array != null ? Streams.of(array).skip(startIndex).limit(Math.max(0, endIndex - startIndex))
  4535.             .collect(LangCollectors.joining(delimiter, EMPTY, EMPTY, StringUtils::toStringOrEmpty)) : null;
  4536.     }

  4537.     /**
  4538.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4539.      *
  4540.      * <p>
  4541.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4542.      * by empty strings.
  4543.      * </p>
  4544.      *
  4545.      * <pre>
  4546.      * StringUtils.join(null, *)               = null
  4547.      * StringUtils.join([], *)                 = ""
  4548.      * StringUtils.join([null], *)             = ""
  4549.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4550.      * StringUtils.join([1, 2, 3], null) = "123"
  4551.      * </pre>
  4552.      *
  4553.      * @param array
  4554.      *            the array of values to join together, may be null
  4555.      * @param delimiter
  4556.      *            the separator character to use
  4557.      * @return the joined String, {@code null} if null array input
  4558.      * @since 3.2
  4559.      */
  4560.     public static String join(final short[] array, final char delimiter) {
  4561.         if (array == null) {
  4562.             return null;
  4563.         }
  4564.         return join(array, delimiter, 0, array.length);
  4565.     }

  4566.     /**
  4567.      * Joins the elements of the provided array into a single String containing the provided list of elements.
  4568.      *
  4569.      * <p>
  4570.      * No delimiter is added before or after the list. Null objects or empty strings within the array are represented
  4571.      * by empty strings.
  4572.      * </p>
  4573.      *
  4574.      * <pre>
  4575.      * StringUtils.join(null, *)               = null
  4576.      * StringUtils.join([], *)                 = ""
  4577.      * StringUtils.join([null], *)             = ""
  4578.      * StringUtils.join([1, 2, 3], ';')  = "1;2;3"
  4579.      * StringUtils.join([1, 2, 3], null) = "123"
  4580.      * </pre>
  4581.      *
  4582.      * @param array
  4583.      *            the array of values to join together, may be null
  4584.      * @param delimiter
  4585.      *            the separator character to use
  4586.      * @param startIndex
  4587.      *            the first index to start joining from. It is an error to pass in a start index past the end of the
  4588.      *            array
  4589.      * @param endIndex
  4590.      *            the index to stop joining from (exclusive). It is an error to pass in an end index past the end of
  4591.      *            the array
  4592.      * @return the joined String, {@code null} if null array input
  4593.      * @since 3.2
  4594.      */
  4595.     public static String join(final short[] array, final char delimiter, final int startIndex, final int endIndex) {
  4596.         if (array == null) {
  4597.             return null;
  4598.         }
  4599.         if (endIndex - startIndex <= 0) {
  4600.             return EMPTY;
  4601.         }
  4602.         final StringBuilder stringBuilder = new StringBuilder();
  4603.         for (int i = startIndex; i < endIndex; i++) {
  4604.             stringBuilder
  4605.                     .append(array[i])
  4606.                     .append(delimiter);
  4607.         }
  4608.         return stringBuilder.substring(0, stringBuilder.length() - 1);
  4609.     }

  4610.     /**
  4611.      * Joins the elements of the provided array into a single String
  4612.      * containing the provided list of elements.
  4613.      *
  4614.      * <p>No separator is added to the joined String.
  4615.      * Null objects or empty strings within the array are represented by
  4616.      * empty strings.</p>
  4617.      *
  4618.      * <pre>
  4619.      * StringUtils.join(null)            = null
  4620.      * StringUtils.join([])              = ""
  4621.      * StringUtils.join([null])          = ""
  4622.      * StringUtils.join(["a", "b", "c"]) = "abc"
  4623.      * StringUtils.join([null, "", "a"]) = "a"
  4624.      * </pre>
  4625.      *
  4626.      * @param <T> the specific type of values to join together
  4627.      * @param elements  the values to join together, may be null
  4628.      * @return the joined String, {@code null} if null array input
  4629.      * @since 2.0
  4630.      * @since 3.0 Changed signature to use varargs
  4631.      */
  4632.     @SafeVarargs
  4633.     public static <T> String join(final T... elements) {
  4634.         return join(elements, null);
  4635.     }

  4636.     /**
  4637.      * Joins the elements of the provided varargs into a
  4638.      * single String containing the provided elements.
  4639.      *
  4640.      * <p>No delimiter is added before or after the list.
  4641.      * {@code null} elements and separator are treated as empty Strings ("").</p>
  4642.      *
  4643.      * <pre>
  4644.      * StringUtils.joinWith(",", {"a", "b"})        = "a,b"
  4645.      * StringUtils.joinWith(",", {"a", "b",""})     = "a,b,"
  4646.      * StringUtils.joinWith(",", {"a", null, "b"})  = "a,,b"
  4647.      * StringUtils.joinWith(null, {"a", "b"})       = "ab"
  4648.      * </pre>
  4649.      *
  4650.      * @param delimiter the separator character to use, null treated as ""
  4651.      * @param array the varargs providing the values to join together. {@code null} elements are treated as ""
  4652.      * @return the joined String.
  4653.      * @throws IllegalArgumentException if a null varargs is provided
  4654.      * @since 3.5
  4655.      */
  4656.     public static String joinWith(final String delimiter, final Object... array) {
  4657.         if (array == null) {
  4658.             throw new IllegalArgumentException("Object varargs must not be null");
  4659.         }
  4660.         return join(array, delimiter);
  4661.     }

  4662.     /**
  4663.      * Finds the last index within a CharSequence, handling {@code null}.
  4664.      * This method uses {@link String#lastIndexOf(String)} if possible.
  4665.      *
  4666.      * <p>A {@code null} CharSequence will return {@code -1}.</p>
  4667.      *
  4668.      * <pre>
  4669.      * StringUtils.lastIndexOf(null, *)          = -1
  4670.      * StringUtils.lastIndexOf(*, null)          = -1
  4671.      * StringUtils.lastIndexOf("", "")           = 0
  4672.      * StringUtils.lastIndexOf("aabaabaa", "a")  = 7
  4673.      * StringUtils.lastIndexOf("aabaabaa", "b")  = 5
  4674.      * StringUtils.lastIndexOf("aabaabaa", "ab") = 4
  4675.      * StringUtils.lastIndexOf("aabaabaa", "")   = 8
  4676.      * </pre>
  4677.      *
  4678.      * @param seq  the CharSequence to check, may be null
  4679.      * @param searchSeq  the CharSequence to find, may be null
  4680.      * @return the last index of the search String,
  4681.      *  -1 if no match or {@code null} string input
  4682.      * @since 2.0
  4683.      * @since 3.0 Changed signature from lastIndexOf(String, String) to lastIndexOf(CharSequence, CharSequence)
  4684.      */
  4685.     public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq) {
  4686.         if (seq == null) {
  4687.             return INDEX_NOT_FOUND;
  4688.         }
  4689.         return CharSequenceUtils.lastIndexOf(seq, searchSeq, seq.length());
  4690.     }

  4691.     /**
  4692.      * Finds the last index within a CharSequence, handling {@code null}.
  4693.      * This method uses {@link String#lastIndexOf(String, int)} if possible.
  4694.      *
  4695.      * <p>A {@code null} CharSequence will return {@code -1}.
  4696.      * A negative start position returns {@code -1}.
  4697.      * An empty ("") search CharSequence always matches unless the start position is negative.
  4698.      * A start position greater than the string length searches the whole string.
  4699.      * The search starts at the startPos and works backwards; matches starting after the start
  4700.      * position are ignored.
  4701.      * </p>
  4702.      *
  4703.      * <pre>
  4704.      * StringUtils.lastIndexOf(null, *, *)          = -1
  4705.      * StringUtils.lastIndexOf(*, null, *)          = -1
  4706.      * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7
  4707.      * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5
  4708.      * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
  4709.      * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5
  4710.      * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
  4711.      * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0
  4712.      * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1
  4713.      * StringUtils.lastIndexOf("aabaabaa", "b", 1)  = -1
  4714.      * StringUtils.lastIndexOf("aabaabaa", "b", 2)  = 2
  4715.      * StringUtils.lastIndexOf("aabaabaa", "ba", 2)  = 2
  4716.      * </pre>
  4717.      *
  4718.      * @param seq  the CharSequence to check, may be null
  4719.      * @param searchSeq  the CharSequence to find, may be null
  4720.      * @param startPos  the start position, negative treated as zero
  4721.      * @return the last index of the search CharSequence (always &le; startPos),
  4722.      *  -1 if no match or {@code null} string input
  4723.      * @since 2.0
  4724.      * @since 3.0 Changed signature from lastIndexOf(String, String, int) to lastIndexOf(CharSequence, CharSequence, int)
  4725.      */
  4726.     public static int lastIndexOf(final CharSequence seq, final CharSequence searchSeq, final int startPos) {
  4727.         return CharSequenceUtils.lastIndexOf(seq, searchSeq, startPos);
  4728.     }

  4729.     /**
  4730.      * Returns the index within {@code seq} of the last occurrence of
  4731.      * the specified character. For values of {@code searchChar} in the
  4732.      * range from 0 to 0xFFFF (inclusive), the index (in Unicode code
  4733.      * units) returned is the largest value <em>k</em> such that:
  4734.      * <blockquote><pre>
  4735.      * this.charAt(<em>k</em>) == searchChar
  4736.      * </pre></blockquote>
  4737.      * is true. For other values of {@code searchChar}, it is the
  4738.      * largest value <em>k</em> such that:
  4739.      * <blockquote><pre>
  4740.      * this.codePointAt(<em>k</em>) == searchChar
  4741.      * </pre></blockquote>
  4742.      * is true.  In either case, if no such character occurs in this
  4743.      * string, then {@code -1} is returned. Furthermore, a {@code null} or empty ("")
  4744.      * {@link CharSequence} will return {@code -1}. The
  4745.      * {@code seq} {@link CharSequence} object is searched backwards
  4746.      * starting at the last character.
  4747.      *
  4748.      * <pre>
  4749.      * StringUtils.lastIndexOf(null, *)         = -1
  4750.      * StringUtils.lastIndexOf("", *)           = -1
  4751.      * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
  4752.      * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
  4753.      * </pre>
  4754.      *
  4755.      * @param seq  the {@link CharSequence} to check, may be null
  4756.      * @param searchChar  the character to find
  4757.      * @return the last index of the search character,
  4758.      *  -1 if no match or {@code null} string input
  4759.      * @since 2.0
  4760.      * @since 3.0 Changed signature from lastIndexOf(String, int) to lastIndexOf(CharSequence, int)
  4761.      * @since 3.6 Updated {@link CharSequenceUtils} call to behave more like {@link String}
  4762.      */
  4763.     public static int lastIndexOf(final CharSequence seq, final int searchChar) {
  4764.         if (isEmpty(seq)) {
  4765.             return INDEX_NOT_FOUND;
  4766.         }
  4767.         return CharSequenceUtils.lastIndexOf(seq, searchChar, seq.length());
  4768.     }

  4769.     /**
  4770.      * Returns the index within {@code seq} of the last occurrence of
  4771.      * the specified character, searching backward starting at the
  4772.      * specified index. For values of {@code searchChar} in the range
  4773.      * from 0 to 0xFFFF (inclusive), the index returned is the largest
  4774.      * value <em>k</em> such that:
  4775.      * <blockquote><pre>
  4776.      * (this.charAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &lt;= startPos)
  4777.      * </pre></blockquote>
  4778.      * is true. For other values of {@code searchChar}, it is the
  4779.      * largest value <em>k</em> such that:
  4780.      * <blockquote><pre>
  4781.      * (this.codePointAt(<em>k</em>) == searchChar) &amp;&amp; (<em>k</em> &lt;= startPos)
  4782.      * </pre></blockquote>
  4783.      * is true. In either case, if no such character occurs in {@code seq}
  4784.      * at or before position {@code startPos}, then
  4785.      * {@code -1} is returned. Furthermore, a {@code null} or empty ("")
  4786.      * {@link CharSequence} will return {@code -1}. A start position greater
  4787.      * than the string length searches the whole string.
  4788.      * The search starts at the {@code startPos} and works backwards;
  4789.      * matches starting after the start position are ignored.
  4790.      *
  4791.      * <p>All indices are specified in {@code char} values
  4792.      * (Unicode code units).
  4793.      *
  4794.      * <pre>
  4795.      * StringUtils.lastIndexOf(null, *, *)          = -1
  4796.      * StringUtils.lastIndexOf("", *,  *)           = -1
  4797.      * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5
  4798.      * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2
  4799.      * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1
  4800.      * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5
  4801.      * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
  4802.      * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0
  4803.      * </pre>
  4804.      *
  4805.      * @param seq  the CharSequence to check, may be null
  4806.      * @param searchChar  the character to find
  4807.      * @param startPos  the start position
  4808.      * @return the last index of the search character (always &le; startPos),
  4809.      *  -1 if no match or {@code null} string input
  4810.      * @since 2.0
  4811.      * @since 3.0 Changed signature from lastIndexOf(String, int, int) to lastIndexOf(CharSequence, int, int)
  4812.      */
  4813.     public static int lastIndexOf(final CharSequence seq, final int searchChar, final int startPos) {
  4814.         if (isEmpty(seq)) {
  4815.             return INDEX_NOT_FOUND;
  4816.         }
  4817.         return CharSequenceUtils.lastIndexOf(seq, searchChar, startPos);
  4818.     }

  4819.     /**
  4820.      * Find the latest index of any substring in a set of potential substrings.
  4821.      *
  4822.      * <p>A {@code null} CharSequence will return {@code -1}.
  4823.      * A {@code null} search array will return {@code -1}.
  4824.      * A {@code null} or zero length search array entry will be ignored,
  4825.      * but a search array containing "" will return the length of {@code str}
  4826.      * if {@code str} is not null. This method uses {@link String#indexOf(String)} if possible</p>
  4827.      *
  4828.      * <pre>
  4829.      * StringUtils.lastIndexOfAny(null, *)                    = -1
  4830.      * StringUtils.lastIndexOfAny(*, null)                    = -1
  4831.      * StringUtils.lastIndexOfAny(*, [])                      = -1
  4832.      * StringUtils.lastIndexOfAny(*, [null])                  = -1
  4833.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab", "cd"]) = 6
  4834.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd", "ab"]) = 6
  4835.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
  4836.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", "op"]) = -1
  4837.      * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn", ""])   = 10
  4838.      * </pre>
  4839.      *
  4840.      * @param str  the CharSequence to check, may be null
  4841.      * @param searchStrs  the CharSequences to search for, may be null
  4842.      * @return the last index of any of the CharSequences, -1 if no match
  4843.      * @since 3.0 Changed signature from lastIndexOfAny(String, String[]) to lastIndexOfAny(CharSequence, CharSequence)
  4844.      */
  4845.     public static int lastIndexOfAny(final CharSequence str, final CharSequence... searchStrs) {
  4846.         if (str == null || searchStrs == null) {
  4847.             return INDEX_NOT_FOUND;
  4848.         }
  4849.         int ret = INDEX_NOT_FOUND;
  4850.         int tmp;
  4851.         for (final CharSequence search : searchStrs) {
  4852.             if (search == null) {
  4853.                 continue;
  4854.             }
  4855.             tmp = CharSequenceUtils.lastIndexOf(str, search, str.length());
  4856.             if (tmp > ret) {
  4857.                 ret = tmp;
  4858.             }
  4859.         }
  4860.         return ret;
  4861.     }

  4862.     /**
  4863.      * Case in-sensitive find of the last index within a CharSequence.
  4864.      *
  4865.      * <p>A {@code null} CharSequence will return {@code -1}.
  4866.      * A negative start position returns {@code -1}.
  4867.      * An empty ("") search CharSequence always matches unless the start position is negative.
  4868.      * A start position greater than the string length searches the whole string.</p>
  4869.      *
  4870.      * <pre>
  4871.      * StringUtils.lastIndexOfIgnoreCase(null, *)          = -1
  4872.      * StringUtils.lastIndexOfIgnoreCase(*, null)          = -1
  4873.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A")  = 7
  4874.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B")  = 5
  4875.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB") = 4
  4876.      * </pre>
  4877.      *
  4878.      * @param str  the CharSequence to check, may be null
  4879.      * @param searchStr  the CharSequence to find, may be null
  4880.      * @return the first index of the search CharSequence,
  4881.      *  -1 if no match or {@code null} string input
  4882.      * @since 2.5
  4883.      * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String) to lastIndexOfIgnoreCase(CharSequence, CharSequence)
  4884.      */
  4885.     public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr) {
  4886.         if (str == null || searchStr == null) {
  4887.             return INDEX_NOT_FOUND;
  4888.         }
  4889.         return lastIndexOfIgnoreCase(str, searchStr, str.length());
  4890.     }

  4891.     /**
  4892.      * Case in-sensitive find of the last index within a CharSequence
  4893.      * from the specified position.
  4894.      *
  4895.      * <p>A {@code null} CharSequence will return {@code -1}.
  4896.      * A negative start position returns {@code -1}.
  4897.      * An empty ("") search CharSequence always matches unless the start position is negative.
  4898.      * A start position greater than the string length searches the whole string.
  4899.      * The search starts at the startPos and works backwards; matches starting after the start
  4900.      * position are ignored.
  4901.      * </p>
  4902.      *
  4903.      * <pre>
  4904.      * StringUtils.lastIndexOfIgnoreCase(null, *, *)          = -1
  4905.      * StringUtils.lastIndexOfIgnoreCase(*, null, *)          = -1
  4906.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 8)  = 7
  4907.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 8)  = 5
  4908.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "AB", 8) = 4
  4909.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 9)  = 5
  4910.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", -1) = -1
  4911.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "A", 0)  = 0
  4912.      * StringUtils.lastIndexOfIgnoreCase("aabaabaa", "B", 0)  = -1
  4913.      * </pre>
  4914.      *
  4915.      * @param str  the CharSequence to check, may be null
  4916.      * @param searchStr  the CharSequence to find, may be null
  4917.      * @param startPos  the start position
  4918.      * @return the last index of the search CharSequence (always &le; startPos),
  4919.      *  -1 if no match or {@code null} input
  4920.      * @since 2.5
  4921.      * @since 3.0 Changed signature from lastIndexOfIgnoreCase(String, String, int) to lastIndexOfIgnoreCase(CharSequence, CharSequence, int)
  4922.      */
  4923.     public static int lastIndexOfIgnoreCase(final CharSequence str, final CharSequence searchStr, int startPos) {
  4924.         if (str == null || searchStr == null) {
  4925.             return INDEX_NOT_FOUND;
  4926.         }
  4927.         final int searchStrLength = searchStr.length();
  4928.         final int strLength = str.length();
  4929.         if (startPos > strLength - searchStrLength) {
  4930.             startPos = strLength - searchStrLength;
  4931.         }
  4932.         if (startPos < 0) {
  4933.             return INDEX_NOT_FOUND;
  4934.         }
  4935.         if (searchStrLength == 0) {
  4936.             return startPos;
  4937.         }

  4938.         for (int i = startPos; i >= 0; i--) {
  4939.             if (CharSequenceUtils.regionMatches(str, true, i, searchStr, 0, searchStrLength)) {
  4940.                 return i;
  4941.             }
  4942.         }
  4943.         return INDEX_NOT_FOUND;
  4944.     }

  4945.     /**
  4946.      * Finds the n-th last index within a String, handling {@code null}.
  4947.      * This method uses {@link String#lastIndexOf(String)}.
  4948.      *
  4949.      * <p>A {@code null} String will return {@code -1}.</p>
  4950.      *
  4951.      * <pre>
  4952.      * StringUtils.lastOrdinalIndexOf(null, *, *)          = -1
  4953.      * StringUtils.lastOrdinalIndexOf(*, null, *)          = -1
  4954.      * StringUtils.lastOrdinalIndexOf("", "", *)           = 0
  4955.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 1)  = 7
  4956.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "a", 2)  = 6
  4957.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 1)  = 5
  4958.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "b", 2)  = 2
  4959.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 1) = 4
  4960.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "ab", 2) = 1
  4961.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 1)   = 8
  4962.      * StringUtils.lastOrdinalIndexOf("aabaabaa", "", 2)   = 8
  4963.      * </pre>
  4964.      *
  4965.      * <p>Note that 'tail(CharSequence str, int n)' may be implemented as: </p>
  4966.      *
  4967.      * <pre>
  4968.      *   str.substring(lastOrdinalIndexOf(str, "\n", n) + 1)
  4969.      * </pre>
  4970.      *
  4971.      * @param str  the CharSequence to check, may be null
  4972.      * @param searchStr  the CharSequence to find, may be null
  4973.      * @param ordinal  the n-th last {@code searchStr} to find
  4974.      * @return the n-th last index of the search CharSequence,
  4975.      *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
  4976.      * @since 2.5
  4977.      * @since 3.0 Changed signature from lastOrdinalIndexOf(String, String, int) to lastOrdinalIndexOf(CharSequence, CharSequence, int)
  4978.      */
  4979.     public static int lastOrdinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
  4980.         return ordinalIndexOf(str, searchStr, ordinal, true);
  4981.     }

  4982.     /**
  4983.      * Gets the leftmost {@code len} characters of a String.
  4984.      *
  4985.      * <p>If {@code len} characters are not available, or the
  4986.      * String is {@code null}, the String will be returned without
  4987.      * an exception. An empty String is returned if len is negative.</p>
  4988.      *
  4989.      * <pre>
  4990.      * StringUtils.left(null, *)    = null
  4991.      * StringUtils.left(*, -ve)     = ""
  4992.      * StringUtils.left("", *)      = ""
  4993.      * StringUtils.left("abc", 0)   = ""
  4994.      * StringUtils.left("abc", 2)   = "ab"
  4995.      * StringUtils.left("abc", 4)   = "abc"
  4996.      * </pre>
  4997.      *
  4998.      * @param str  the String to get the leftmost characters from, may be null
  4999.      * @param len  the length of the required String
  5000.      * @return the leftmost characters, {@code null} if null String input
  5001.      */
  5002.     public static String left(final String str, final int len) {
  5003.         if (str == null) {
  5004.             return null;
  5005.         }
  5006.         if (len < 0) {
  5007.             return EMPTY;
  5008.         }
  5009.         if (str.length() <= len) {
  5010.             return str;
  5011.         }
  5012.         return str.substring(0, len);
  5013.     }

  5014.     /**
  5015.      * Left pad a String with spaces (' ').
  5016.      *
  5017.      * <p>The String is padded to the size of {@code size}.</p>
  5018.      *
  5019.      * <pre>
  5020.      * StringUtils.leftPad(null, *)   = null
  5021.      * StringUtils.leftPad("", 3)     = "   "
  5022.      * StringUtils.leftPad("bat", 3)  = "bat"
  5023.      * StringUtils.leftPad("bat", 5)  = "  bat"
  5024.      * StringUtils.leftPad("bat", 1)  = "bat"
  5025.      * StringUtils.leftPad("bat", -1) = "bat"
  5026.      * </pre>
  5027.      *
  5028.      * @param str  the String to pad out, may be null
  5029.      * @param size  the size to pad to
  5030.      * @return left padded String or original String if no padding is necessary,
  5031.      *  {@code null} if null String input
  5032.      */
  5033.     public static String leftPad(final String str, final int size) {
  5034.         return leftPad(str, size, ' ');
  5035.     }

  5036.     /**
  5037.      * Left pad a String with a specified character.
  5038.      *
  5039.      * <p>Pad to a size of {@code size}.</p>
  5040.      *
  5041.      * <pre>
  5042.      * StringUtils.leftPad(null, *, *)     = null
  5043.      * StringUtils.leftPad("", 3, 'z')     = "zzz"
  5044.      * StringUtils.leftPad("bat", 3, 'z')  = "bat"
  5045.      * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
  5046.      * StringUtils.leftPad("bat", 1, 'z')  = "bat"
  5047.      * StringUtils.leftPad("bat", -1, 'z') = "bat"
  5048.      * </pre>
  5049.      *
  5050.      * @param str  the String to pad out, may be null
  5051.      * @param size  the size to pad to
  5052.      * @param padChar  the character to pad with
  5053.      * @return left padded String or original String if no padding is necessary,
  5054.      *  {@code null} if null String input
  5055.      * @since 2.0
  5056.      */
  5057.     public static String leftPad(final String str, final int size, final char padChar) {
  5058.         if (str == null) {
  5059.             return null;
  5060.         }
  5061.         final int pads = size - str.length();
  5062.         if (pads <= 0) {
  5063.             return str; // returns original String when possible
  5064.         }
  5065.         if (pads > PAD_LIMIT) {
  5066.             return leftPad(str, size, String.valueOf(padChar));
  5067.         }
  5068.         return repeat(padChar, pads).concat(str);
  5069.     }

  5070.     /**
  5071.      * Left pad a String with a specified String.
  5072.      *
  5073.      * <p>Pad to a size of {@code size}.</p>
  5074.      *
  5075.      * <pre>
  5076.      * StringUtils.leftPad(null, *, *)      = null
  5077.      * StringUtils.leftPad("", 3, "z")      = "zzz"
  5078.      * StringUtils.leftPad("bat", 3, "yz")  = "bat"
  5079.      * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
  5080.      * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
  5081.      * StringUtils.leftPad("bat", 1, "yz")  = "bat"
  5082.      * StringUtils.leftPad("bat", -1, "yz") = "bat"
  5083.      * StringUtils.leftPad("bat", 5, null)  = "  bat"
  5084.      * StringUtils.leftPad("bat", 5, "")    = "  bat"
  5085.      * </pre>
  5086.      *
  5087.      * @param str  the String to pad out, may be null
  5088.      * @param size  the size to pad to
  5089.      * @param padStr  the String to pad with, null or empty treated as single space
  5090.      * @return left padded String or original String if no padding is necessary,
  5091.      *  {@code null} if null String input
  5092.      */
  5093.     public static String leftPad(final String str, final int size, String padStr) {
  5094.         if (str == null) {
  5095.             return null;
  5096.         }
  5097.         if (isEmpty(padStr)) {
  5098.             padStr = SPACE;
  5099.         }
  5100.         final int padLen = padStr.length();
  5101.         final int strLen = str.length();
  5102.         final int pads = size - strLen;
  5103.         if (pads <= 0) {
  5104.             return str; // returns original String when possible
  5105.         }
  5106.         if (padLen == 1 && pads <= PAD_LIMIT) {
  5107.             return leftPad(str, size, padStr.charAt(0));
  5108.         }

  5109.         if (pads == padLen) {
  5110.             return padStr.concat(str);
  5111.         }
  5112.         if (pads < padLen) {
  5113.             return padStr.substring(0, pads).concat(str);
  5114.         }
  5115.         final char[] padding = new char[pads];
  5116.         final char[] padChars = padStr.toCharArray();
  5117.         for (int i = 0; i < pads; i++) {
  5118.             padding[i] = padChars[i % padLen];
  5119.         }
  5120.         return new String(padding).concat(str);
  5121.     }

  5122.     /**
  5123.      * Gets a CharSequence length or {@code 0} if the CharSequence is
  5124.      * {@code null}.
  5125.      *
  5126.      * @param cs
  5127.      *            a CharSequence or {@code null}
  5128.      * @return CharSequence length or {@code 0} if the CharSequence is
  5129.      *         {@code null}.
  5130.      * @since 2.4
  5131.      * @since 3.0 Changed signature from length(String) to length(CharSequence)
  5132.      */
  5133.     public static int length(final CharSequence cs) {
  5134.         return cs == null ? 0 : cs.length();
  5135.     }

  5136.     /**
  5137.      * Converts a String to lower case as per {@link String#toLowerCase()}.
  5138.      *
  5139.      * <p>A {@code null} input String returns {@code null}.</p>
  5140.      *
  5141.      * <pre>
  5142.      * StringUtils.lowerCase(null)  = null
  5143.      * StringUtils.lowerCase("")    = ""
  5144.      * StringUtils.lowerCase("aBc") = "abc"
  5145.      * </pre>
  5146.      *
  5147.      * <p><strong>Note:</strong> As described in the documentation for {@link String#toLowerCase()},
  5148.      * the result of this method is affected by the current locale.
  5149.      * For platform-independent case transformations, the method {@link #lowerCase(String, Locale)}
  5150.      * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
  5151.      *
  5152.      * @param str  the String to lower case, may be null
  5153.      * @return the lower cased String, {@code null} if null String input
  5154.      */
  5155.     public static String lowerCase(final String str) {
  5156.         if (str == null) {
  5157.             return null;
  5158.         }
  5159.         return str.toLowerCase();
  5160.     }

  5161.     /**
  5162.      * Converts a String to lower case as per {@link String#toLowerCase(Locale)}.
  5163.      *
  5164.      * <p>A {@code null} input String returns {@code null}.</p>
  5165.      *
  5166.      * <pre>
  5167.      * StringUtils.lowerCase(null, Locale.ENGLISH)  = null
  5168.      * StringUtils.lowerCase("", Locale.ENGLISH)    = ""
  5169.      * StringUtils.lowerCase("aBc", Locale.ENGLISH) = "abc"
  5170.      * </pre>
  5171.      *
  5172.      * @param str  the String to lower case, may be null
  5173.      * @param locale  the locale that defines the case transformation rules, must not be null
  5174.      * @return the lower cased String, {@code null} if null String input
  5175.      * @since 2.5
  5176.      */
  5177.     public static String lowerCase(final String str, final Locale locale) {
  5178.         if (str == null) {
  5179.             return null;
  5180.         }
  5181.         return str.toLowerCase(LocaleUtils.toLocale(locale));
  5182.     }

  5183.     private static int[] matches(final CharSequence first, final CharSequence second) {
  5184.         final CharSequence max;
  5185.         final CharSequence min;
  5186.         if (first.length() > second.length()) {
  5187.             max = first;
  5188.             min = second;
  5189.         } else {
  5190.             max = second;
  5191.             min = first;
  5192.         }
  5193.         final int range = Math.max(max.length() / 2 - 1, 0);
  5194.         final int[] matchIndexes = ArrayFill.fill(new int[min.length()], -1);
  5195.         final boolean[] matchFlags = new boolean[max.length()];
  5196.         int matches = 0;
  5197.         for (int mi = 0; mi < min.length(); mi++) {
  5198.             final char c1 = min.charAt(mi);
  5199.             for (int xi = Math.max(mi - range, 0), xn = Math.min(mi + range + 1, max.length()); xi < xn; xi++) {
  5200.                 if (!matchFlags[xi] && c1 == max.charAt(xi)) {
  5201.                     matchIndexes[mi] = xi;
  5202.                     matchFlags[xi] = true;
  5203.                     matches++;
  5204.                     break;
  5205.                 }
  5206.             }
  5207.         }
  5208.         final char[] ms1 = new char[matches];
  5209.         final char[] ms2 = new char[matches];
  5210.         for (int i = 0, si = 0; i < min.length(); i++) {
  5211.             if (matchIndexes[i] != -1) {
  5212.                 ms1[si] = min.charAt(i);
  5213.                 si++;
  5214.             }
  5215.         }
  5216.         for (int i = 0, si = 0; i < max.length(); i++) {
  5217.             if (matchFlags[i]) {
  5218.                 ms2[si] = max.charAt(i);
  5219.                 si++;
  5220.             }
  5221.         }
  5222.         int transpositions = 0;
  5223.         for (int mi = 0; mi < ms1.length; mi++) {
  5224.             if (ms1[mi] != ms2[mi]) {
  5225.                 transpositions++;
  5226.             }
  5227.         }
  5228.         int prefix = 0;
  5229.         for (int mi = 0; mi < min.length(); mi++) {
  5230.             if (first.charAt(mi) != second.charAt(mi)) {
  5231.                 break;
  5232.             }
  5233.             prefix++;
  5234.         }
  5235.         return new int[] { matches, transpositions / 2, prefix, max.length() };
  5236.     }

  5237.     /**
  5238.      * Gets {@code len} characters from the middle of a String.
  5239.      *
  5240.      * <p>If {@code len} characters are not available, the remainder
  5241.      * of the String will be returned without an exception. If the
  5242.      * String is {@code null}, {@code null} will be returned.
  5243.      * An empty String is returned if len is negative or exceeds the
  5244.      * length of {@code str}.</p>
  5245.      *
  5246.      * <pre>
  5247.      * StringUtils.mid(null, *, *)    = null
  5248.      * StringUtils.mid(*, *, -ve)     = ""
  5249.      * StringUtils.mid("", 0, *)      = ""
  5250.      * StringUtils.mid("abc", 0, 2)   = "ab"
  5251.      * StringUtils.mid("abc", 0, 4)   = "abc"
  5252.      * StringUtils.mid("abc", 2, 4)   = "c"
  5253.      * StringUtils.mid("abc", 4, 2)   = ""
  5254.      * StringUtils.mid("abc", -2, 2)  = "ab"
  5255.      * </pre>
  5256.      *
  5257.      * @param str  the String to get the characters from, may be null
  5258.      * @param pos  the position to start from, negative treated as zero
  5259.      * @param len  the length of the required String
  5260.      * @return the middle characters, {@code null} if null String input
  5261.      */
  5262.     public static String mid(final String str, int pos, final int len) {
  5263.         if (str == null) {
  5264.             return null;
  5265.         }
  5266.         if (len < 0 || pos > str.length()) {
  5267.             return EMPTY;
  5268.         }
  5269.         if (pos < 0) {
  5270.             pos = 0;
  5271.         }
  5272.         if (str.length() <= pos + len) {
  5273.             return str.substring(pos);
  5274.         }
  5275.         return str.substring(pos, pos + len);
  5276.     }

  5277.     /**
  5278.      * Similar to <a
  5279.      * href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize
  5280.      * -space</a>
  5281.      *
  5282.      * <p>
  5283.      * The function returns the argument string with whitespace normalized by using
  5284.      * {@code {@link #trim(String)}} to remove leading and trailing whitespace
  5285.      * and then replacing sequences of whitespace characters by a single space.
  5286.      * </p>
  5287.      * In XML Whitespace characters are the same as those allowed by the <a
  5288.      * href="https://www.w3.org/TR/REC-xml/#NT-S">S</a> production, which is S ::= (#x20 | #x9 | #xD | #xA)+
  5289.      * <p>
  5290.      * Java's regexp pattern \s defines whitespace as [ \t\n\x0B\f\r]
  5291.      *
  5292.      * <p>For reference:</p>
  5293.      * <ul>
  5294.      * <li>\x0B = vertical tab</li>
  5295.      * <li>\f = #xC = form feed</li>
  5296.      * <li>#x20 = space</li>
  5297.      * <li>#x9 = \t</li>
  5298.      * <li>#xA = \n</li>
  5299.      * <li>#xD = \r</li>
  5300.      * </ul>
  5301.      *
  5302.      * <p>
  5303.      * The difference is that Java's whitespace includes vertical tab and form feed, which this functional will also
  5304.      * normalize. Additionally {@code {@link #trim(String)}} removes control characters (char &lt;= 32) from both
  5305.      * ends of this String.
  5306.      * </p>
  5307.      *
  5308.      * @see Pattern
  5309.      * @see #trim(String)
  5310.      * @see <a
  5311.      *      href="https://www.w3.org/TR/xpath/#function-normalize-space">https://www.w3.org/TR/xpath/#function-normalize-space</a>
  5312.      * @param str the source String to normalize whitespaces from, may be null
  5313.      * @return the modified string with whitespace normalized, {@code null} if null String input
  5314.      *
  5315.      * @since 3.0
  5316.      */
  5317.     public static String normalizeSpace(final String str) {
  5318.         // LANG-1020: Improved performance significantly by normalizing manually instead of using regex
  5319.         // See https://github.com/librucha/commons-lang-normalizespaces-benchmark for performance test
  5320.         if (isEmpty(str)) {
  5321.             return str;
  5322.         }
  5323.         final int size = str.length();
  5324.         final char[] newChars = new char[size];
  5325.         int count = 0;
  5326.         int whitespacesCount = 0;
  5327.         boolean startWhitespaces = true;
  5328.         for (int i = 0; i < size; i++) {
  5329.             final char actualChar = str.charAt(i);
  5330.             final boolean isWhitespace = Character.isWhitespace(actualChar);
  5331.             if (isWhitespace) {
  5332.                 if (whitespacesCount == 0 && !startWhitespaces) {
  5333.                     newChars[count++] = SPACE.charAt(0);
  5334.                 }
  5335.                 whitespacesCount++;
  5336.             } else {
  5337.                 startWhitespaces = false;
  5338.                 newChars[count++] = actualChar == 160 ? 32 : actualChar;
  5339.                 whitespacesCount = 0;
  5340.             }
  5341.         }
  5342.         if (startWhitespaces) {
  5343.             return EMPTY;
  5344.         }
  5345.         return new String(newChars, 0, count - (whitespacesCount > 0 ? 1 : 0)).trim();
  5346.     }

  5347.     /**
  5348.      * Finds the n-th index within a CharSequence, handling {@code null}.
  5349.      * This method uses {@link String#indexOf(String)} if possible.
  5350.      * <p><b>Note:</b> The code starts looking for a match at the start of the target,
  5351.      * incrementing the starting index by one after each successful match
  5352.      * (unless {@code searchStr} is an empty string in which case the position
  5353.      * is never incremented and {@code 0} is returned immediately).
  5354.      * This means that matches may overlap.</p>
  5355.      * <p>A {@code null} CharSequence will return {@code -1}.</p>
  5356.      *
  5357.      * <pre>
  5358.      * StringUtils.ordinalIndexOf(null, *, *)          = -1
  5359.      * StringUtils.ordinalIndexOf(*, null, *)          = -1
  5360.      * StringUtils.ordinalIndexOf("", "", *)           = 0
  5361.      * StringUtils.ordinalIndexOf("aabaabaa", "a", 1)  = 0
  5362.      * StringUtils.ordinalIndexOf("aabaabaa", "a", 2)  = 1
  5363.      * StringUtils.ordinalIndexOf("aabaabaa", "b", 1)  = 2
  5364.      * StringUtils.ordinalIndexOf("aabaabaa", "b", 2)  = 5
  5365.      * StringUtils.ordinalIndexOf("aabaabaa", "ab", 1) = 1
  5366.      * StringUtils.ordinalIndexOf("aabaabaa", "ab", 2) = 4
  5367.      * StringUtils.ordinalIndexOf("aabaabaa", "", 1)   = 0
  5368.      * StringUtils.ordinalIndexOf("aabaabaa", "", 2)   = 0
  5369.      * </pre>
  5370.      *
  5371.      * <p>Matches may overlap:</p>
  5372.      * <pre>
  5373.      * StringUtils.ordinalIndexOf("ababab", "aba", 1)   = 0
  5374.      * StringUtils.ordinalIndexOf("ababab", "aba", 2)   = 2
  5375.      * StringUtils.ordinalIndexOf("ababab", "aba", 3)   = -1
  5376.      *
  5377.      * StringUtils.ordinalIndexOf("abababab", "abab", 1) = 0
  5378.      * StringUtils.ordinalIndexOf("abababab", "abab", 2) = 2
  5379.      * StringUtils.ordinalIndexOf("abababab", "abab", 3) = 4
  5380.      * StringUtils.ordinalIndexOf("abababab", "abab", 4) = -1
  5381.      * </pre>
  5382.      *
  5383.      * <p>Note that 'head(CharSequence str, int n)' may be implemented as: </p>
  5384.      *
  5385.      * <pre>
  5386.      *   str.substring(0, lastOrdinalIndexOf(str, "\n", n))
  5387.      * </pre>
  5388.      *
  5389.      * @param str  the CharSequence to check, may be null
  5390.      * @param searchStr  the CharSequence to find, may be null
  5391.      * @param ordinal  the n-th {@code searchStr} to find
  5392.      * @return the n-th index of the search CharSequence,
  5393.      *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
  5394.      * @since 2.1
  5395.      * @since 3.0 Changed signature from ordinalIndexOf(String, String, int) to ordinalIndexOf(CharSequence, CharSequence, int)
  5396.      */
  5397.     public static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal) {
  5398.         return ordinalIndexOf(str, searchStr, ordinal, false);
  5399.     }

  5400.     /**
  5401.      * Finds the n-th index within a String, handling {@code null}.
  5402.      * This method uses {@link String#indexOf(String)} if possible.
  5403.      * <p>Note that matches may overlap<p>
  5404.      *
  5405.      * <p>A {@code null} CharSequence will return {@code -1}.</p>
  5406.      *
  5407.      * @param str  the CharSequence to check, may be null
  5408.      * @param searchStr  the CharSequence to find, may be null
  5409.      * @param ordinal  the n-th {@code searchStr} to find, overlapping matches are allowed.
  5410.      * @param lastIndex true if lastOrdinalIndexOf() otherwise false if ordinalIndexOf()
  5411.      * @return the n-th index of the search CharSequence,
  5412.      *  {@code -1} ({@code INDEX_NOT_FOUND}) if no match or {@code null} string input
  5413.      */
  5414.     // Shared code between ordinalIndexOf(String, String, int) and lastOrdinalIndexOf(String, String, int)
  5415.     private static int ordinalIndexOf(final CharSequence str, final CharSequence searchStr, final int ordinal, final boolean lastIndex) {
  5416.         if (str == null || searchStr == null || ordinal <= 0) {
  5417.             return INDEX_NOT_FOUND;
  5418.         }
  5419.         if (searchStr.length() == 0) {
  5420.             return lastIndex ? str.length() : 0;
  5421.         }
  5422.         int found = 0;
  5423.         // set the initial index beyond the end of the string
  5424.         // this is to allow for the initial index decrement/increment
  5425.         int index = lastIndex ? str.length() : INDEX_NOT_FOUND;
  5426.         do {
  5427.             if (lastIndex) {
  5428.                 index = CharSequenceUtils.lastIndexOf(str, searchStr, index - 1); // step backwards through string
  5429.             } else {
  5430.                 index = CharSequenceUtils.indexOf(str, searchStr, index + 1); // step forwards through string
  5431.             }
  5432.             if (index < 0) {
  5433.                 return index;
  5434.             }
  5435.             found++;
  5436.         } while (found < ordinal);
  5437.         return index;
  5438.     }

  5439.     /**
  5440.      * Overlays part of a String with another String.
  5441.      *
  5442.      * <p>A {@code null} string input returns {@code null}.
  5443.      * A negative index is treated as zero.
  5444.      * An index greater than the string length is treated as the string length.
  5445.      * The start index is always the smaller of the two indices.</p>
  5446.      *
  5447.      * <pre>
  5448.      * StringUtils.overlay(null, *, *, *)            = null
  5449.      * StringUtils.overlay("", "abc", 0, 0)          = "abc"
  5450.      * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
  5451.      * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
  5452.      * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
  5453.      * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
  5454.      * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
  5455.      * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
  5456.      * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
  5457.      * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
  5458.      * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
  5459.      * </pre>
  5460.      *
  5461.      * @param str  the String to do overlaying in, may be null
  5462.      * @param overlay  the String to overlay, may be null
  5463.      * @param start  the position to start overlaying at
  5464.      * @param end  the position to stop overlaying before
  5465.      * @return overlayed String, {@code null} if null String input
  5466.      * @since 2.0
  5467.      */
  5468.     public static String overlay(final String str, String overlay, int start, int end) {
  5469.         if (str == null) {
  5470.             return null;
  5471.         }
  5472.         if (overlay == null) {
  5473.             overlay = EMPTY;
  5474.         }
  5475.         final int len = str.length();
  5476.         if (start < 0) {
  5477.             start = 0;
  5478.         }
  5479.         if (start > len) {
  5480.             start = len;
  5481.         }
  5482.         if (end < 0) {
  5483.             end = 0;
  5484.         }
  5485.         if (end > len) {
  5486.             end = len;
  5487.         }
  5488.         if (start > end) {
  5489.             final int temp = start;
  5490.             start = end;
  5491.             end = temp;
  5492.         }
  5493.         return str.substring(0, start) +
  5494.             overlay +
  5495.             str.substring(end);
  5496.     }

  5497.     /**
  5498.      * Prepends the prefix to the start of the string if the string does not
  5499.      * already start with any of the prefixes.
  5500.      *
  5501.      * @param str The string.
  5502.      * @param prefix The prefix to prepend to the start of the string.
  5503.      * @param ignoreCase Indicates whether the compare should ignore case.
  5504.      * @param prefixes Additional prefixes that are valid (optional).
  5505.      *
  5506.      * @return A new String if prefix was prepended, the same string otherwise.
  5507.      */
  5508.     private static String prependIfMissing(final String str, final CharSequence prefix, final boolean ignoreCase, final CharSequence... prefixes) {
  5509.         if (str == null || isEmpty(prefix) || startsWith(str, prefix, ignoreCase)) {
  5510.             return str;
  5511.         }
  5512.         if (ArrayUtils.isNotEmpty(prefixes)) {
  5513.             for (final CharSequence p : prefixes) {
  5514.                 if (startsWith(str, p, ignoreCase)) {
  5515.                     return str;
  5516.                 }
  5517.             }
  5518.         }
  5519.         return prefix + str;
  5520.     }

  5521.     /**
  5522.      * Prepends the prefix to the start of the string if the string does not
  5523.      * already start with any of the prefixes.
  5524.      *
  5525.      * <pre>
  5526.      * StringUtils.prependIfMissing(null, null) = null
  5527.      * StringUtils.prependIfMissing("abc", null) = "abc"
  5528.      * StringUtils.prependIfMissing("", "xyz") = "xyz"
  5529.      * StringUtils.prependIfMissing("abc", "xyz") = "xyzabc"
  5530.      * StringUtils.prependIfMissing("xyzabc", "xyz") = "xyzabc"
  5531.      * StringUtils.prependIfMissing("XYZabc", "xyz") = "xyzXYZabc"
  5532.      * </pre>
  5533.      * <p>With additional prefixes,</p>
  5534.      * <pre>
  5535.      * StringUtils.prependIfMissing(null, null, null) = null
  5536.      * StringUtils.prependIfMissing("abc", null, null) = "abc"
  5537.      * StringUtils.prependIfMissing("", "xyz", null) = "xyz"
  5538.      * StringUtils.prependIfMissing("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
  5539.      * StringUtils.prependIfMissing("abc", "xyz", "") = "abc"
  5540.      * StringUtils.prependIfMissing("abc", "xyz", "mno") = "xyzabc"
  5541.      * StringUtils.prependIfMissing("xyzabc", "xyz", "mno") = "xyzabc"
  5542.      * StringUtils.prependIfMissing("mnoabc", "xyz", "mno") = "mnoabc"
  5543.      * StringUtils.prependIfMissing("XYZabc", "xyz", "mno") = "xyzXYZabc"
  5544.      * StringUtils.prependIfMissing("MNOabc", "xyz", "mno") = "xyzMNOabc"
  5545.      * </pre>
  5546.      *
  5547.      * @param str The string.
  5548.      * @param prefix The prefix to prepend to the start of the string.
  5549.      * @param prefixes Additional prefixes that are valid.
  5550.      *
  5551.      * @return A new String if prefix was prepended, the same string otherwise.
  5552.      *
  5553.      * @since 3.2
  5554.      */
  5555.     public static String prependIfMissing(final String str, final CharSequence prefix, final CharSequence... prefixes) {
  5556.         return prependIfMissing(str, prefix, false, prefixes);
  5557.     }

  5558.     /**
  5559.      * Prepends the prefix to the start of the string if the string does not
  5560.      * already start, case-insensitive, with any of the prefixes.
  5561.      *
  5562.      * <pre>
  5563.      * StringUtils.prependIfMissingIgnoreCase(null, null) = null
  5564.      * StringUtils.prependIfMissingIgnoreCase("abc", null) = "abc"
  5565.      * StringUtils.prependIfMissingIgnoreCase("", "xyz") = "xyz"
  5566.      * StringUtils.prependIfMissingIgnoreCase("abc", "xyz") = "xyzabc"
  5567.      * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz") = "xyzabc"
  5568.      * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz") = "XYZabc"
  5569.      * </pre>
  5570.      * <p>With additional prefixes,</p>
  5571.      * <pre>
  5572.      * StringUtils.prependIfMissingIgnoreCase(null, null, null) = null
  5573.      * StringUtils.prependIfMissingIgnoreCase("abc", null, null) = "abc"
  5574.      * StringUtils.prependIfMissingIgnoreCase("", "xyz", null) = "xyz"
  5575.      * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", new CharSequence[]{null}) = "xyzabc"
  5576.      * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "") = "abc"
  5577.      * StringUtils.prependIfMissingIgnoreCase("abc", "xyz", "mno") = "xyzabc"
  5578.      * StringUtils.prependIfMissingIgnoreCase("xyzabc", "xyz", "mno") = "xyzabc"
  5579.      * StringUtils.prependIfMissingIgnoreCase("mnoabc", "xyz", "mno") = "mnoabc"
  5580.      * StringUtils.prependIfMissingIgnoreCase("XYZabc", "xyz", "mno") = "XYZabc"
  5581.      * StringUtils.prependIfMissingIgnoreCase("MNOabc", "xyz", "mno") = "MNOabc"
  5582.      * </pre>
  5583.      *
  5584.      * @param str The string.
  5585.      * @param prefix The prefix to prepend to the start of the string.
  5586.      * @param prefixes Additional prefixes that are valid (optional).
  5587.      *
  5588.      * @return A new String if prefix was prepended, the same string otherwise.
  5589.      *
  5590.      * @since 3.2
  5591.      */
  5592.     public static String prependIfMissingIgnoreCase(final String str, final CharSequence prefix, final CharSequence... prefixes) {
  5593.         return prependIfMissing(str, prefix, true, prefixes);
  5594.     }

  5595.     /**
  5596.      * Removes all occurrences of a character from within the source string.
  5597.      *
  5598.      * <p>A {@code null} source string will return {@code null}.
  5599.      * An empty ("") source string will return the empty string.</p>
  5600.      *
  5601.      * <pre>
  5602.      * StringUtils.remove(null, *)       = null
  5603.      * StringUtils.remove("", *)         = ""
  5604.      * StringUtils.remove("queued", 'u') = "qeed"
  5605.      * StringUtils.remove("queued", 'z') = "queued"
  5606.      * </pre>
  5607.      *
  5608.      * @param str  the source String to search, may be null
  5609.      * @param remove  the char to search for and remove, may be null
  5610.      * @return the substring with the char removed if found,
  5611.      *  {@code null} if null String input
  5612.      * @since 2.1
  5613.      */
  5614.     public static String remove(final String str, final char remove) {
  5615.         if (isEmpty(str) || str.indexOf(remove) == INDEX_NOT_FOUND) {
  5616.             return str;
  5617.         }
  5618.         final char[] chars = str.toCharArray();
  5619.         int pos = 0;
  5620.         for (int i = 0; i < chars.length; i++) {
  5621.             if (chars[i] != remove) {
  5622.                 chars[pos++] = chars[i];
  5623.             }
  5624.         }
  5625.         return new String(chars, 0, pos);
  5626.     }

  5627.     /**
  5628.      * Removes all occurrences of a substring from within the source string.
  5629.      *
  5630.      * <p>A {@code null} source string will return {@code null}.
  5631.      * An empty ("") source string will return the empty string.
  5632.      * A {@code null} remove string will return the source string.
  5633.      * An empty ("") remove string will return the source string.</p>
  5634.      *
  5635.      * <pre>
  5636.      * StringUtils.remove(null, *)        = null
  5637.      * StringUtils.remove("", *)          = ""
  5638.      * StringUtils.remove(*, null)        = *
  5639.      * StringUtils.remove(*, "")          = *
  5640.      * StringUtils.remove("queued", "ue") = "qd"
  5641.      * StringUtils.remove("queued", "zz") = "queued"
  5642.      * </pre>
  5643.      *
  5644.      * @param str  the source String to search, may be null
  5645.      * @param remove  the String to search for and remove, may be null
  5646.      * @return the substring with the string removed if found,
  5647.      *  {@code null} if null String input
  5648.      * @since 2.1
  5649.      */
  5650.     public static String remove(final String str, final String remove) {
  5651.         if (isEmpty(str) || isEmpty(remove)) {
  5652.             return str;
  5653.         }
  5654.         return replace(str, remove, EMPTY, -1);
  5655.     }

  5656.     /**
  5657.      * Removes each substring of the text String that matches the given regular expression.
  5658.      *
  5659.      * This method is a {@code null} safe equivalent to:
  5660.      * <ul>
  5661.      *  <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li>
  5662.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
  5663.      * </ul>
  5664.      *
  5665.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  5666.      *
  5667.      * <p>Unlike in the {@link #removePattern(String, String)} method, the {@link Pattern#DOTALL} option
  5668.      * is NOT automatically added.
  5669.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  5670.      * DOTALL is also known as single-line mode in Perl.</p>
  5671.      *
  5672.      * <pre>{@code
  5673.      * StringUtils.removeAll(null, *)      = null
  5674.      * StringUtils.removeAll("any", (String) null)  = "any"
  5675.      * StringUtils.removeAll("any", "")    = "any"
  5676.      * StringUtils.removeAll("any", ".*")  = ""
  5677.      * StringUtils.removeAll("any", ".+")  = ""
  5678.      * StringUtils.removeAll("abc", ".?")  = ""
  5679.      * StringUtils.removeAll("A<__>\n<__>B", "<.*>")      = "A\nB"
  5680.      * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>")  = "AB"
  5681.      * StringUtils.removeAll("ABCabc123abc", "[a-z]")     = "ABC123"
  5682.      * }</pre>
  5683.      *
  5684.      * @param text  text to remove from, may be null
  5685.      * @param regex  the regular expression to which this string is to be matched
  5686.      * @return  the text with any removes processed,
  5687.      *              {@code null} if null String input
  5688.      *
  5689.      * @throws  java.util.regex.PatternSyntaxException
  5690.      *              if the regular expression's syntax is invalid
  5691.      *
  5692.      * @see #replaceAll(String, String, String)
  5693.      * @see #removePattern(String, String)
  5694.      * @see String#replaceAll(String, String)
  5695.      * @see java.util.regex.Pattern
  5696.      * @see java.util.regex.Pattern#DOTALL
  5697.      * @since 3.5
  5698.      *
  5699.      * @deprecated Moved to RegExUtils.
  5700.      */
  5701.     @Deprecated
  5702.     public static String removeAll(final String text, final String regex) {
  5703.         return RegExUtils.removeAll(text, regex);
  5704.     }

  5705.     /**
  5706.      * Removes a substring only if it is at the end of a source string,
  5707.      * otherwise returns the source string.
  5708.      *
  5709.      * <p>A {@code null} source string will return {@code null}.
  5710.      * An empty ("") source string will return the empty string.
  5711.      * A {@code null} search string will return the source string.</p>
  5712.      *
  5713.      * <pre>
  5714.      * StringUtils.removeEnd(null, *)      = null
  5715.      * StringUtils.removeEnd("", *)        = ""
  5716.      * StringUtils.removeEnd(*, null)      = *
  5717.      * StringUtils.removeEnd("www.domain.com", ".com.")  = "www.domain.com"
  5718.      * StringUtils.removeEnd("www.domain.com", ".com")   = "www.domain"
  5719.      * StringUtils.removeEnd("www.domain.com", "domain") = "www.domain.com"
  5720.      * StringUtils.removeEnd("abc", "")    = "abc"
  5721.      * </pre>
  5722.      *
  5723.      * @param str  the source String to search, may be null
  5724.      * @param remove  the String to search for and remove, may be null
  5725.      * @return the substring with the string removed if found,
  5726.      *  {@code null} if null String input
  5727.      * @since 2.1
  5728.      */
  5729.     public static String removeEnd(final String str, final String remove) {
  5730.         if (isEmpty(str) || isEmpty(remove)) {
  5731.             return str;
  5732.         }
  5733.         if (str.endsWith(remove)) {
  5734.             return str.substring(0, str.length() - remove.length());
  5735.         }
  5736.         return str;
  5737.     }

  5738.     /**
  5739.      * Case-insensitive removal of a substring if it is at the end of a source string,
  5740.      * otherwise returns the source string.
  5741.      *
  5742.      * <p>A {@code null} source string will return {@code null}.
  5743.      * An empty ("") source string will return the empty string.
  5744.      * A {@code null} search string will return the source string.</p>
  5745.      *
  5746.      * <pre>
  5747.      * StringUtils.removeEndIgnoreCase(null, *)      = null
  5748.      * StringUtils.removeEndIgnoreCase("", *)        = ""
  5749.      * StringUtils.removeEndIgnoreCase(*, null)      = *
  5750.      * StringUtils.removeEndIgnoreCase("www.domain.com", ".com.")  = "www.domain.com"
  5751.      * StringUtils.removeEndIgnoreCase("www.domain.com", ".com")   = "www.domain"
  5752.      * StringUtils.removeEndIgnoreCase("www.domain.com", "domain") = "www.domain.com"
  5753.      * StringUtils.removeEndIgnoreCase("abc", "")    = "abc"
  5754.      * StringUtils.removeEndIgnoreCase("www.domain.com", ".COM") = "www.domain")
  5755.      * StringUtils.removeEndIgnoreCase("www.domain.COM", ".com") = "www.domain")
  5756.      * </pre>
  5757.      *
  5758.      * @param str  the source String to search, may be null
  5759.      * @param remove  the String to search for (case-insensitive) and remove, may be null
  5760.      * @return the substring with the string removed if found,
  5761.      *  {@code null} if null String input
  5762.      * @since 2.4
  5763.      */
  5764.     public static String removeEndIgnoreCase(final String str, final String remove) {
  5765.         if (isEmpty(str) || isEmpty(remove)) {
  5766.             return str;
  5767.         }
  5768.         if (endsWithIgnoreCase(str, remove)) {
  5769.             return str.substring(0, str.length() - remove.length());
  5770.         }
  5771.         return str;
  5772.     }

  5773.     /**
  5774.      * Removes the first substring of the text string that matches the given regular expression.
  5775.      *
  5776.      * This method is a {@code null} safe equivalent to:
  5777.      * <ul>
  5778.      *  <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li>
  5779.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
  5780.      * </ul>
  5781.      *
  5782.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  5783.      *
  5784.      * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
  5785.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  5786.      * DOTALL is also known as single-line mode in Perl.</p>
  5787.      *
  5788.      * <pre>{@code
  5789.      * StringUtils.removeFirst(null, *)      = null
  5790.      * StringUtils.removeFirst("any", (String) null)  = "any"
  5791.      * StringUtils.removeFirst("any", "")    = "any"
  5792.      * StringUtils.removeFirst("any", ".*")  = ""
  5793.      * StringUtils.removeFirst("any", ".+")  = ""
  5794.      * StringUtils.removeFirst("abc", ".?")  = "bc"
  5795.      * StringUtils.removeFirst("A<__>\n<__>B", "<.*>")      = "A\n<__>B"
  5796.      * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>")  = "AB"
  5797.      * StringUtils.removeFirst("ABCabc123", "[a-z]")          = "ABCbc123"
  5798.      * StringUtils.removeFirst("ABCabc123abc", "[a-z]+")      = "ABC123abc"
  5799.      * }</pre>
  5800.      *
  5801.      * @param text  text to remove from, may be null
  5802.      * @param regex  the regular expression to which this string is to be matched
  5803.      * @return  the text with the first replacement processed,
  5804.      *              {@code null} if null String input
  5805.      *
  5806.      * @throws  java.util.regex.PatternSyntaxException
  5807.      *              if the regular expression's syntax is invalid
  5808.      *
  5809.      * @see #replaceFirst(String, String, String)
  5810.      * @see String#replaceFirst(String, String)
  5811.      * @see java.util.regex.Pattern
  5812.      * @see java.util.regex.Pattern#DOTALL
  5813.      * @since 3.5
  5814.      *
  5815.      * @deprecated Moved to RegExUtils.
  5816.      */
  5817.     @Deprecated
  5818.     public static String removeFirst(final String text, final String regex) {
  5819.         return replaceFirst(text, regex, EMPTY);
  5820.     }

  5821.     /**
  5822.      * Case-insensitive removal of all occurrences of a substring from within
  5823.      * the source string.
  5824.      *
  5825.      * <p>
  5826.      * A {@code null} source string will return {@code null}. An empty ("")
  5827.      * source string will return the empty string. A {@code null} remove string
  5828.      * will return the source string. An empty ("") remove string will return
  5829.      * the source string.
  5830.      * </p>
  5831.      *
  5832.      * <pre>
  5833.      * StringUtils.removeIgnoreCase(null, *)        = null
  5834.      * StringUtils.removeIgnoreCase("", *)          = ""
  5835.      * StringUtils.removeIgnoreCase(*, null)        = *
  5836.      * StringUtils.removeIgnoreCase(*, "")          = *
  5837.      * StringUtils.removeIgnoreCase("queued", "ue") = "qd"
  5838.      * StringUtils.removeIgnoreCase("queued", "zz") = "queued"
  5839.      * StringUtils.removeIgnoreCase("quEUed", "UE") = "qd"
  5840.      * StringUtils.removeIgnoreCase("queued", "zZ") = "queued"
  5841.      * </pre>
  5842.      *
  5843.      * @param str
  5844.      *            the source String to search, may be null
  5845.      * @param remove
  5846.      *            the String to search for (case-insensitive) and remove, may be
  5847.      *            null
  5848.      * @return the substring with the string removed if found, {@code null} if
  5849.      *         null String input
  5850.      * @since 3.5
  5851.      */
  5852.     public static String removeIgnoreCase(final String str, final String remove) {
  5853.         return replaceIgnoreCase(str, remove, EMPTY, -1);
  5854.     }

  5855.     /**
  5856.      * Removes each substring of the source String that matches the given regular expression using the DOTALL option.
  5857.      *
  5858.      * This call is a {@code null} safe equivalent to:
  5859.      * <ul>
  5860.      * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, StringUtils.EMPTY)}</li>
  5861.      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(StringUtils.EMPTY)}</li>
  5862.      * </ul>
  5863.      *
  5864.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  5865.      *
  5866.      * <pre>{@code
  5867.      * StringUtils.removePattern(null, *)       = null
  5868.      * StringUtils.removePattern("any", (String) null)   = "any"
  5869.      * StringUtils.removePattern("A<__>\n<__>B", "<.*>")  = "AB"
  5870.      * StringUtils.removePattern("ABCabc123", "[a-z]")    = "ABC123"
  5871.      * }</pre>
  5872.      *
  5873.      * @param source
  5874.      *            the source string
  5875.      * @param regex
  5876.      *            the regular expression to which this string is to be matched
  5877.      * @return The resulting {@link String}
  5878.      * @see #replacePattern(String, String, String)
  5879.      * @see String#replaceAll(String, String)
  5880.      * @see Pattern#DOTALL
  5881.      * @since 3.2
  5882.      * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
  5883.      *
  5884.      * @deprecated Moved to RegExUtils.
  5885.      */
  5886.     @Deprecated
  5887.     public static String removePattern(final String source, final String regex) {
  5888.         return RegExUtils.removePattern(source, regex);
  5889.     }

  5890.     /**
  5891.      * Removes a char only if it is at the beginning of a source string,
  5892.      * otherwise returns the source string.
  5893.      *
  5894.      * <p>A {@code null} source string will return {@code null}.
  5895.      * An empty ("") source string will return the empty string.
  5896.      * A {@code null} search char will return the source string.</p>
  5897.      *
  5898.      * <pre>
  5899.      * StringUtils.removeStart(null, *)      = null
  5900.      * StringUtils.removeStart("", *)        = ""
  5901.      * StringUtils.removeStart(*, null)      = *
  5902.      * StringUtils.removeStart("/path", '/') = "path"
  5903.      * StringUtils.removeStart("path", '/')  = "path"
  5904.      * StringUtils.removeStart("path", 0)    = "path"
  5905.      * </pre>
  5906.      *
  5907.      * @param str  the source String to search, may be null.
  5908.      * @param remove  the char to search for and remove.
  5909.      * @return the substring with the char removed if found,
  5910.      *  {@code null} if null String input.
  5911.      * @since 3.13.0
  5912.      */
  5913.     public static String removeStart(final String str, final char remove) {
  5914.         if (isEmpty(str)) {
  5915.             return str;
  5916.         }
  5917.         return str.charAt(0) == remove ? str.substring(1) : str;
  5918.     }

  5919.     /**
  5920.      * Removes a substring only if it is at the beginning of a source string,
  5921.      * otherwise returns the source string.
  5922.      *
  5923.      * <p>A {@code null} source string will return {@code null}.
  5924.      * An empty ("") source string will return the empty string.
  5925.      * A {@code null} search string will return the source string.</p>
  5926.      *
  5927.      * <pre>
  5928.      * StringUtils.removeStart(null, *)      = null
  5929.      * StringUtils.removeStart("", *)        = ""
  5930.      * StringUtils.removeStart(*, null)      = *
  5931.      * StringUtils.removeStart("www.domain.com", "www.")   = "domain.com"
  5932.      * StringUtils.removeStart("domain.com", "www.")       = "domain.com"
  5933.      * StringUtils.removeStart("www.domain.com", "domain") = "www.domain.com"
  5934.      * StringUtils.removeStart("abc", "")    = "abc"
  5935.      * </pre>
  5936.      *
  5937.      * @param str  the source String to search, may be null
  5938.      * @param remove  the String to search for and remove, may be null
  5939.      * @return the substring with the string removed if found,
  5940.      *  {@code null} if null String input
  5941.      * @since 2.1
  5942.      */
  5943.     public static String removeStart(final String str, final String remove) {
  5944.         if (isEmpty(str) || isEmpty(remove)) {
  5945.             return str;
  5946.         }
  5947.         if (str.startsWith(remove)) {
  5948.             return str.substring(remove.length());
  5949.         }
  5950.         return str;
  5951.     }

  5952.     /**
  5953.      * Case-insensitive removal of a substring if it is at the beginning of a source string,
  5954.      * otherwise returns the source string.
  5955.      *
  5956.      * <p>A {@code null} source string will return {@code null}.
  5957.      * An empty ("") source string will return the empty string.
  5958.      * A {@code null} search string will return the source string.</p>
  5959.      *
  5960.      * <pre>
  5961.      * StringUtils.removeStartIgnoreCase(null, *)      = null
  5962.      * StringUtils.removeStartIgnoreCase("", *)        = ""
  5963.      * StringUtils.removeStartIgnoreCase(*, null)      = *
  5964.      * StringUtils.removeStartIgnoreCase("www.domain.com", "www.")   = "domain.com"
  5965.      * StringUtils.removeStartIgnoreCase("www.domain.com", "WWW.")   = "domain.com"
  5966.      * StringUtils.removeStartIgnoreCase("domain.com", "www.")       = "domain.com"
  5967.      * StringUtils.removeStartIgnoreCase("www.domain.com", "domain") = "www.domain.com"
  5968.      * StringUtils.removeStartIgnoreCase("abc", "")    = "abc"
  5969.      * </pre>
  5970.      *
  5971.      * @param str  the source String to search, may be null
  5972.      * @param remove  the String to search for (case-insensitive) and remove, may be null
  5973.      * @return the substring with the string removed if found,
  5974.      *  {@code null} if null String input
  5975.      * @since 2.4
  5976.      */
  5977.     public static String removeStartIgnoreCase(final String str, final String remove) {
  5978.         if (str != null && startsWithIgnoreCase(str, remove)) {
  5979.             return str.substring(length(remove));
  5980.         }
  5981.         return str;
  5982.     }

  5983.     /**
  5984.      * Returns padding using the specified delimiter repeated
  5985.      * to a given length.
  5986.      *
  5987.      * <pre>
  5988.      * StringUtils.repeat('e', 0)  = ""
  5989.      * StringUtils.repeat('e', 3)  = "eee"
  5990.      * StringUtils.repeat('e', -2) = ""
  5991.      * </pre>
  5992.      *
  5993.      * <p>Note: this method does not support padding with
  5994.      * <a href="https://www.unicode.org/glossary/#supplementary_character">Unicode Supplementary Characters</a>
  5995.      * as they require a pair of {@code char}s to be represented.
  5996.      * If you are needing to support full I18N of your applications
  5997.      * consider using {@link #repeat(String, int)} instead.
  5998.      * </p>
  5999.      *
  6000.      * @param ch  character to repeat
  6001.      * @param repeat  number of times to repeat char, negative treated as zero
  6002.      * @return String with repeated character
  6003.      * @see #repeat(String, int)
  6004.      */
  6005.     public static String repeat(final char ch, final int repeat) {
  6006.         if (repeat <= 0) {
  6007.             return EMPTY;
  6008.         }
  6009.         return new String(ArrayFill.fill(new char[repeat], ch));
  6010.     }

  6011.     /**
  6012.      * Repeat a String {@code repeat} times to form a
  6013.      * new String.
  6014.      *
  6015.      * <pre>
  6016.      * StringUtils.repeat(null, 2) = null
  6017.      * StringUtils.repeat("", 0)   = ""
  6018.      * StringUtils.repeat("", 2)   = ""
  6019.      * StringUtils.repeat("a", 3)  = "aaa"
  6020.      * StringUtils.repeat("ab", 2) = "abab"
  6021.      * StringUtils.repeat("a", -2) = ""
  6022.      * </pre>
  6023.      *
  6024.      * @param str  the String to repeat, may be null
  6025.      * @param repeat  number of times to repeat str, negative treated as zero
  6026.      * @return a new String consisting of the original String repeated,
  6027.      *  {@code null} if null String input
  6028.      */
  6029.     public static String repeat(final String str, final int repeat) {
  6030.         // Performance tuned for 2.0 (JDK1.4)
  6031.         if (str == null) {
  6032.             return null;
  6033.         }
  6034.         if (repeat <= 0) {
  6035.             return EMPTY;
  6036.         }
  6037.         final int inputLength = str.length();
  6038.         if (repeat == 1 || inputLength == 0) {
  6039.             return str;
  6040.         }
  6041.         if (inputLength == 1 && repeat <= PAD_LIMIT) {
  6042.             return repeat(str.charAt(0), repeat);
  6043.         }

  6044.         final int outputLength = inputLength * repeat;
  6045.         switch (inputLength) {
  6046.             case 1 :
  6047.                 return repeat(str.charAt(0), repeat);
  6048.             case 2 :
  6049.                 final char ch0 = str.charAt(0);
  6050.                 final char ch1 = str.charAt(1);
  6051.                 final char[] output2 = new char[outputLength];
  6052.                 for (int i = repeat * 2 - 2; i >= 0; i--, i--) {
  6053.                     output2[i] = ch0;
  6054.                     output2[i + 1] = ch1;
  6055.                 }
  6056.                 return new String(output2);
  6057.             default :
  6058.                 final StringBuilder buf = new StringBuilder(outputLength);
  6059.                 for (int i = 0; i < repeat; i++) {
  6060.                     buf.append(str);
  6061.                 }
  6062.                 return buf.toString();
  6063.         }
  6064.     }

  6065.     /**
  6066.      * Repeat a String {@code repeat} times to form a
  6067.      * new String, with a String separator injected each time.
  6068.      *
  6069.      * <pre>
  6070.      * StringUtils.repeat(null, null, 2) = null
  6071.      * StringUtils.repeat(null, "x", 2)  = null
  6072.      * StringUtils.repeat("", null, 0)   = ""
  6073.      * StringUtils.repeat("", "", 2)     = ""
  6074.      * StringUtils.repeat("", "x", 3)    = "xx"
  6075.      * StringUtils.repeat("?", ", ", 3)  = "?, ?, ?"
  6076.      * </pre>
  6077.      *
  6078.      * @param str        the String to repeat, may be null
  6079.      * @param separator  the String to inject, may be null
  6080.      * @param repeat     number of times to repeat str, negative treated as zero
  6081.      * @return a new String consisting of the original String repeated,
  6082.      *  {@code null} if null String input
  6083.      * @since 2.5
  6084.      */
  6085.     public static String repeat(final String str, final String separator, final int repeat) {
  6086.         if (str == null || separator == null) {
  6087.             return repeat(str, repeat);
  6088.         }
  6089.         // given that repeat(String, int) is quite optimized, better to rely on it than try and splice this into it
  6090.         final String result = repeat(str + separator, repeat);
  6091.         return removeEnd(result, separator);
  6092.     }

  6093.     /**
  6094.      * Replaces all occurrences of a String within another String.
  6095.      *
  6096.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6097.      *
  6098.      * <pre>
  6099.      * StringUtils.replace(null, *, *)        = null
  6100.      * StringUtils.replace("", *, *)          = ""
  6101.      * StringUtils.replace("any", null, *)    = "any"
  6102.      * StringUtils.replace("any", *, null)    = "any"
  6103.      * StringUtils.replace("any", "", *)      = "any"
  6104.      * StringUtils.replace("aba", "a", null)  = "aba"
  6105.      * StringUtils.replace("aba", "a", "")    = "b"
  6106.      * StringUtils.replace("aba", "a", "z")   = "zbz"
  6107.      * </pre>
  6108.      *
  6109.      * @see #replace(String text, String searchString, String replacement, int max)
  6110.      * @param text  text to search and replace in, may be null
  6111.      * @param searchString  the String to search for, may be null
  6112.      * @param replacement  the String to replace it with, may be null
  6113.      * @return the text with any replacements processed,
  6114.      *  {@code null} if null String input
  6115.      */
  6116.     public static String replace(final String text, final String searchString, final String replacement) {
  6117.         return replace(text, searchString, replacement, -1);
  6118.     }

  6119.     /**
  6120.      * Replaces a String with another String inside a larger String,
  6121.      * for the first {@code max} values of the search String.
  6122.      *
  6123.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6124.      *
  6125.      * <pre>
  6126.      * StringUtils.replace(null, *, *, *)         = null
  6127.      * StringUtils.replace("", *, *, *)           = ""
  6128.      * StringUtils.replace("any", null, *, *)     = "any"
  6129.      * StringUtils.replace("any", *, null, *)     = "any"
  6130.      * StringUtils.replace("any", "", *, *)       = "any"
  6131.      * StringUtils.replace("any", *, *, 0)        = "any"
  6132.      * StringUtils.replace("abaa", "a", null, -1) = "abaa"
  6133.      * StringUtils.replace("abaa", "a", "", -1)   = "b"
  6134.      * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
  6135.      * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
  6136.      * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
  6137.      * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
  6138.      * </pre>
  6139.      *
  6140.      * @param text  text to search and replace in, may be null
  6141.      * @param searchString  the String to search for, may be null
  6142.      * @param replacement  the String to replace it with, may be null
  6143.      * @param max  maximum number of values to replace, or {@code -1} if no maximum
  6144.      * @return the text with any replacements processed,
  6145.      *  {@code null} if null String input
  6146.      */
  6147.     public static String replace(final String text, final String searchString, final String replacement, final int max) {
  6148.         return replace(text, searchString, replacement, max, false);
  6149.     }

  6150.     /**
  6151.      * Replaces a String with another String inside a larger String,
  6152.      * for the first {@code max} values of the search String,
  6153.      * case-sensitively/insensitively based on {@code ignoreCase} value.
  6154.      *
  6155.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6156.      *
  6157.      * <pre>
  6158.      * StringUtils.replace(null, *, *, *, false)         = null
  6159.      * StringUtils.replace("", *, *, *, false)           = ""
  6160.      * StringUtils.replace("any", null, *, *, false)     = "any"
  6161.      * StringUtils.replace("any", *, null, *, false)     = "any"
  6162.      * StringUtils.replace("any", "", *, *, false)       = "any"
  6163.      * StringUtils.replace("any", *, *, 0, false)        = "any"
  6164.      * StringUtils.replace("abaa", "a", null, -1, false) = "abaa"
  6165.      * StringUtils.replace("abaa", "a", "", -1, false)   = "b"
  6166.      * StringUtils.replace("abaa", "a", "z", 0, false)   = "abaa"
  6167.      * StringUtils.replace("abaa", "A", "z", 1, false)   = "abaa"
  6168.      * StringUtils.replace("abaa", "A", "z", 1, true)   = "zbaa"
  6169.      * StringUtils.replace("abAa", "a", "z", 2, true)   = "zbza"
  6170.      * StringUtils.replace("abAa", "a", "z", -1, true)  = "zbzz"
  6171.      * </pre>
  6172.      *
  6173.      * @param text  text to search and replace in, may be null
  6174.      * @param searchString  the String to search for (case-insensitive), may be null
  6175.      * @param replacement  the String to replace it with, may be null
  6176.      * @param max  maximum number of values to replace, or {@code -1} if no maximum
  6177.      * @param ignoreCase if true replace is case-insensitive, otherwise case-sensitive
  6178.      * @return the text with any replacements processed,
  6179.      *  {@code null} if null String input
  6180.      */
  6181.      private static String replace(final String text, String searchString, final String replacement, int max, final boolean ignoreCase) {
  6182.          if (isEmpty(text) || isEmpty(searchString) || replacement == null || max == 0) {
  6183.              return text;
  6184.          }
  6185.          if (ignoreCase) {
  6186.              searchString = searchString.toLowerCase();
  6187.          }
  6188.          int start = 0;
  6189.          int end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start);
  6190.          if (end == INDEX_NOT_FOUND) {
  6191.              return text;
  6192.          }
  6193.          final int replLength = searchString.length();
  6194.          int increase = Math.max(replacement.length() - replLength, 0);
  6195.          increase *= max < 0 ? 16 : Math.min(max, 64);
  6196.          final StringBuilder buf = new StringBuilder(text.length() + increase);
  6197.          while (end != INDEX_NOT_FOUND) {
  6198.              buf.append(text, start, end).append(replacement);
  6199.              start = end + replLength;
  6200.              if (--max == 0) {
  6201.                  break;
  6202.              }
  6203.              end = ignoreCase ? indexOfIgnoreCase(text, searchString, start) : indexOf(text, searchString, start);
  6204.          }
  6205.          buf.append(text, start, text.length());
  6206.          return buf.toString();
  6207.      }

  6208.     /**
  6209.      * Replaces each substring of the text String that matches the given regular expression
  6210.      * with the given replacement.
  6211.      *
  6212.      * This method is a {@code null} safe equivalent to:
  6213.      * <ul>
  6214.      *  <li>{@code text.replaceAll(regex, replacement)}</li>
  6215.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li>
  6216.      * </ul>
  6217.      *
  6218.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6219.      *
  6220.      * <p>Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option
  6221.      * is NOT automatically added.
  6222.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  6223.      * DOTALL is also known as single-line mode in Perl.</p>
  6224.      *
  6225.      * <pre>{@code
  6226.      * StringUtils.replaceAll(null, *, *)       = null
  6227.      * StringUtils.replaceAll("any", (String) null, *)   = "any"
  6228.      * StringUtils.replaceAll("any", *, null)   = "any"
  6229.      * StringUtils.replaceAll("", "", "zzz")    = "zzz"
  6230.      * StringUtils.replaceAll("", ".*", "zzz")  = "zzz"
  6231.      * StringUtils.replaceAll("", ".+", "zzz")  = ""
  6232.      * StringUtils.replaceAll("abc", "", "ZZ")  = "ZZaZZbZZcZZ"
  6233.      * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z")      = "z\nz"
  6234.      * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z")  = "z"
  6235.      * StringUtils.replaceAll("ABCabc123", "[a-z]", "_")       = "ABC___123"
  6236.      * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
  6237.      * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
  6238.      * StringUtils.replaceAll("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
  6239.      * }</pre>
  6240.      *
  6241.      * @param text  text to search and replace in, may be null
  6242.      * @param regex  the regular expression to which this string is to be matched
  6243.      * @param replacement  the string to be substituted for each match
  6244.      * @return  the text with any replacements processed,
  6245.      *              {@code null} if null String input
  6246.      *
  6247.      * @throws  java.util.regex.PatternSyntaxException
  6248.      *              if the regular expression's syntax is invalid
  6249.      *
  6250.      * @see #replacePattern(String, String, String)
  6251.      * @see String#replaceAll(String, String)
  6252.      * @see java.util.regex.Pattern
  6253.      * @see java.util.regex.Pattern#DOTALL
  6254.      * @since 3.5
  6255.      *
  6256.      * @deprecated Moved to RegExUtils.
  6257.      */
  6258.     @Deprecated
  6259.     public static String replaceAll(final String text, final String regex, final String replacement) {
  6260.         return RegExUtils.replaceAll(text, regex, replacement);
  6261.     }

  6262.     /**
  6263.      * Replaces all occurrences of a character in a String with another.
  6264.      * This is a null-safe version of {@link String#replace(char, char)}.
  6265.      *
  6266.      * <p>A {@code null} string input returns {@code null}.
  6267.      * An empty ("") string input returns an empty string.</p>
  6268.      *
  6269.      * <pre>
  6270.      * StringUtils.replaceChars(null, *, *)        = null
  6271.      * StringUtils.replaceChars("", *, *)          = ""
  6272.      * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
  6273.      * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
  6274.      * </pre>
  6275.      *
  6276.      * @param str  String to replace characters in, may be null
  6277.      * @param searchChar  the character to search for, may be null
  6278.      * @param replaceChar  the character to replace, may be null
  6279.      * @return modified String, {@code null} if null string input
  6280.      * @since 2.0
  6281.      */
  6282.     public static String replaceChars(final String str, final char searchChar, final char replaceChar) {
  6283.         if (str == null) {
  6284.             return null;
  6285.         }
  6286.         return str.replace(searchChar, replaceChar);
  6287.     }

  6288.     /**
  6289.      * Replaces multiple characters in a String in one go.
  6290.      * This method can also be used to delete characters.
  6291.      *
  6292.      * <p>For example:<br>
  6293.      * {@code replaceChars(&quot;hello&quot;, &quot;ho&quot;, &quot;jy&quot;) = jelly}.</p>
  6294.      *
  6295.      * <p>A {@code null} string input returns {@code null}.
  6296.      * An empty ("") string input returns an empty string.
  6297.      * A null or empty set of search characters returns the input string.</p>
  6298.      *
  6299.      * <p>The length of the search characters should normally equal the length
  6300.      * of the replace characters.
  6301.      * If the search characters is longer, then the extra search characters
  6302.      * are deleted.
  6303.      * If the search characters is shorter, then the extra replace characters
  6304.      * are ignored.</p>
  6305.      *
  6306.      * <pre>
  6307.      * StringUtils.replaceChars(null, *, *)           = null
  6308.      * StringUtils.replaceChars("", *, *)             = ""
  6309.      * StringUtils.replaceChars("abc", null, *)       = "abc"
  6310.      * StringUtils.replaceChars("abc", "", *)         = "abc"
  6311.      * StringUtils.replaceChars("abc", "b", null)     = "ac"
  6312.      * StringUtils.replaceChars("abc", "b", "")       = "ac"
  6313.      * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
  6314.      * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
  6315.      * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
  6316.      * </pre>
  6317.      *
  6318.      * @param str  String to replace characters in, may be null
  6319.      * @param searchChars  a set of characters to search for, may be null
  6320.      * @param replaceChars  a set of characters to replace, may be null
  6321.      * @return modified String, {@code null} if null string input
  6322.      * @since 2.0
  6323.      */
  6324.     public static String replaceChars(final String str, final String searchChars, String replaceChars) {
  6325.         if (isEmpty(str) || isEmpty(searchChars)) {
  6326.             return str;
  6327.         }
  6328.         if (replaceChars == null) {
  6329.             replaceChars = EMPTY;
  6330.         }
  6331.         boolean modified = false;
  6332.         final int replaceCharsLength = replaceChars.length();
  6333.         final int strLength = str.length();
  6334.         final StringBuilder buf = new StringBuilder(strLength);
  6335.         for (int i = 0; i < strLength; i++) {
  6336.             final char ch = str.charAt(i);
  6337.             final int index = searchChars.indexOf(ch);
  6338.             if (index >= 0) {
  6339.                 modified = true;
  6340.                 if (index < replaceCharsLength) {
  6341.                     buf.append(replaceChars.charAt(index));
  6342.                 }
  6343.             } else {
  6344.                 buf.append(ch);
  6345.             }
  6346.         }
  6347.         if (modified) {
  6348.             return buf.toString();
  6349.         }
  6350.         return str;
  6351.     }

  6352.     /**
  6353.      * Replaces all occurrences of Strings within another String.
  6354.      *
  6355.      * <p>
  6356.      * A {@code null} reference passed to this method is a no-op, or if
  6357.      * any "search string" or "string to replace" is null, that replace will be
  6358.      * ignored. This will not repeat. For repeating replaces, call the
  6359.      * overloaded method.
  6360.      * </p>
  6361.      *
  6362.      * <pre>
  6363.      *  StringUtils.replaceEach(null, *, *)        = null
  6364.      *  StringUtils.replaceEach("", *, *)          = ""
  6365.      *  StringUtils.replaceEach("aba", null, null) = "aba"
  6366.      *  StringUtils.replaceEach("aba", new String[0], null) = "aba"
  6367.      *  StringUtils.replaceEach("aba", null, new String[0]) = "aba"
  6368.      *  StringUtils.replaceEach("aba", new String[]{"a"}, null)  = "aba"
  6369.      *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""})  = "b"
  6370.      *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"})  = "aba"
  6371.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"})  = "wcte"
  6372.      *  (example of how it does not repeat)
  6373.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"})  = "dcte"
  6374.      * </pre>
  6375.      *
  6376.      * @param text
  6377.      *            text to search and replace in, no-op if null
  6378.      * @param searchList
  6379.      *            the Strings to search for, no-op if null
  6380.      * @param replacementList
  6381.      *            the Strings to replace them with, no-op if null
  6382.      * @return the text with any replacements processed, {@code null} if
  6383.      *         null String input
  6384.      * @throws IllegalArgumentException
  6385.      *             if the lengths of the arrays are not the same (null is ok,
  6386.      *             and/or size 0)
  6387.      * @since 2.4
  6388.      */
  6389.     public static String replaceEach(final String text, final String[] searchList, final String[] replacementList) {
  6390.         return replaceEach(text, searchList, replacementList, false, 0);
  6391.     }

  6392.     /**
  6393.      * Replace all occurrences of Strings within another String.
  6394.      * This is a private recursive helper method for {@link #replaceEachRepeatedly(String, String[], String[])} and
  6395.      * {@link #replaceEach(String, String[], String[])}
  6396.      *
  6397.      * <p>
  6398.      * A {@code null} reference passed to this method is a no-op, or if
  6399.      * any "search string" or "string to replace" is null, that replace will be
  6400.      * ignored.
  6401.      * </p>
  6402.      *
  6403.      * <pre>
  6404.      *  StringUtils.replaceEach(null, *, *, *, *) = null
  6405.      *  StringUtils.replaceEach("", *, *, *, *) = ""
  6406.      *  StringUtils.replaceEach("aba", null, null, *, *) = "aba"
  6407.      *  StringUtils.replaceEach("aba", new String[0], null, *, *) = "aba"
  6408.      *  StringUtils.replaceEach("aba", null, new String[0], *, *) = "aba"
  6409.      *  StringUtils.replaceEach("aba", new String[]{"a"}, null, *, *) = "aba"
  6410.      *  StringUtils.replaceEach("aba", new String[]{"a"}, new String[]{""}, *, >=0) = "b"
  6411.      *  StringUtils.replaceEach("aba", new String[]{null}, new String[]{"a"}, *, >=0) = "aba"
  6412.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"w", "t"}, *, >=0) = "wcte"
  6413.      *  (example of how it repeats)
  6414.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, false, >=0) = "dcte"
  6415.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "t"}, true, >=2) = "tcte"
  6416.      *  StringUtils.replaceEach("abcde", new String[]{"ab", "d"}, new String[]{"d", "ab"}, *, *) = IllegalStateException
  6417.      * </pre>
  6418.      *
  6419.      * @param text
  6420.      *            text to search and replace in, no-op if null
  6421.      * @param searchList
  6422.      *            the Strings to search for, no-op if null
  6423.      * @param replacementList
  6424.      *            the Strings to replace them with, no-op if null
  6425.      * @param repeat if true, then replace repeatedly
  6426.      *       until there are no more possible replacements or timeToLive < 0
  6427.      * @param timeToLive
  6428.      *            if less than 0 then there is a circular reference and endless
  6429.      *            loop
  6430.      * @return the text with any replacements processed, {@code null} if
  6431.      *         null String input
  6432.      * @throws IllegalStateException
  6433.      *             if the search is repeating and there is an endless loop due
  6434.      *             to outputs of one being inputs to another
  6435.      * @throws IllegalArgumentException
  6436.      *             if the lengths of the arrays are not the same (null is ok,
  6437.      *             and/or size 0)
  6438.      * @since 2.4
  6439.      */
  6440.     private static String replaceEach(
  6441.             final String text, final String[] searchList, final String[] replacementList, final boolean repeat, final int timeToLive) {

  6442.         // mchyzer Performance note: This creates very few new objects (one major goal)
  6443.         // let me know if there are performance requests, we can create a harness to measure

  6444.         // if recursing, this shouldn't be less than 0
  6445.         if (timeToLive < 0) {
  6446.             final Set<String> searchSet = new HashSet<>(Arrays.asList(searchList));
  6447.             final Set<String> replacementSet = new HashSet<>(Arrays.asList(replacementList));
  6448.             searchSet.retainAll(replacementSet);
  6449.             if (!searchSet.isEmpty()) {
  6450.                 throw new IllegalStateException("Aborting to protect against StackOverflowError - " +
  6451.                         "output of one loop is the input of another");
  6452.             }
  6453.         }

  6454.         if (isEmpty(text) || ArrayUtils.isEmpty(searchList) || ArrayUtils.isEmpty(replacementList) || ArrayUtils.isNotEmpty(searchList) && timeToLive == -1) {
  6455.             return text;
  6456.         }

  6457.         final int searchLength = searchList.length;
  6458.         final int replacementLength = replacementList.length;

  6459.         // make sure lengths are ok, these need to be equal
  6460.         if (searchLength != replacementLength) {
  6461.             throw new IllegalArgumentException("Search and Replace array lengths don't match: "
  6462.                 + searchLength
  6463.                 + " vs "
  6464.                 + replacementLength);
  6465.         }

  6466.         // keep track of which still have matches
  6467.         final boolean[] noMoreMatchesForReplIndex = new boolean[searchLength];

  6468.         // index on index that the match was found
  6469.         int textIndex = -1;
  6470.         int replaceIndex = -1;
  6471.         int tempIndex;

  6472.         // index of replace array that will replace the search string found
  6473.         // NOTE: logic duplicated below START
  6474.         for (int i = 0; i < searchLength; i++) {
  6475.             if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) {
  6476.                 continue;
  6477.             }
  6478.             tempIndex = text.indexOf(searchList[i]);

  6479.             // see if we need to keep searching for this
  6480.             if (tempIndex == -1) {
  6481.                 noMoreMatchesForReplIndex[i] = true;
  6482.             } else if (textIndex == -1 || tempIndex < textIndex) {
  6483.                 textIndex = tempIndex;
  6484.                 replaceIndex = i;
  6485.             }
  6486.         }
  6487.         // NOTE: logic mostly below END

  6488.         // no search strings found, we are done
  6489.         if (textIndex == -1) {
  6490.             return text;
  6491.         }

  6492.         int start = 0;

  6493.         // get a good guess on the size of the result buffer so it doesn't have to double if it goes over a bit
  6494.         int increase = 0;

  6495.         // count the replacement text elements that are larger than their corresponding text being replaced
  6496.         for (int i = 0; i < searchList.length; i++) {
  6497.             if (searchList[i] == null || replacementList[i] == null) {
  6498.                 continue;
  6499.             }
  6500.             final int greater = replacementList[i].length() - searchList[i].length();
  6501.             if (greater > 0) {
  6502.                 increase += 3 * greater; // assume 3 matches
  6503.             }
  6504.         }
  6505.         // have upper-bound at 20% increase, then let Java take over
  6506.         increase = Math.min(increase, text.length() / 5);

  6507.         final StringBuilder buf = new StringBuilder(text.length() + increase);

  6508.         while (textIndex != -1) {

  6509.             for (int i = start; i < textIndex; i++) {
  6510.                 buf.append(text.charAt(i));
  6511.             }
  6512.             buf.append(replacementList[replaceIndex]);

  6513.             start = textIndex + searchList[replaceIndex].length();

  6514.             textIndex = -1;
  6515.             replaceIndex = -1;
  6516.             // find the next earliest match
  6517.             // NOTE: logic mostly duplicated above START
  6518.             for (int i = 0; i < searchLength; i++) {
  6519.                 if (noMoreMatchesForReplIndex[i] || isEmpty(searchList[i]) || replacementList[i] == null) {
  6520.                     continue;
  6521.                 }
  6522.                 tempIndex = text.indexOf(searchList[i], start);

  6523.                 // see if we need to keep searching for this
  6524.                 if (tempIndex == -1) {
  6525.                     noMoreMatchesForReplIndex[i] = true;
  6526.                 } else if (textIndex == -1 || tempIndex < textIndex) {
  6527.                     textIndex = tempIndex;
  6528.                     replaceIndex = i;
  6529.                 }
  6530.             }
  6531.             // NOTE: logic duplicated above END

  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.         return replaceEach(result, searchList, replacementList, repeat, timeToLive - 1);
  6542.     }

  6543.     /**
  6544.      * Replaces all occurrences of Strings within another String.
  6545.      *
  6546.      * <p>
  6547.      * A {@code null} reference passed to this method is a no-op, or if
  6548.      * any "search string" or "string to replace" is null, that replace will be
  6549.      * 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"}) = IllegalStateException
  6565.      * </pre>
  6566.      *
  6567.      * @param text
  6568.      *            text to search and replace in, no-op if null
  6569.      * @param searchList
  6570.      *            the Strings to search for, no-op if null
  6571.      * @param replacementList
  6572.      *            the Strings to replace them with, no-op if null
  6573.      * @return the text with any replacements processed, {@code null} if
  6574.      *         null String input
  6575.      * @throws IllegalStateException
  6576.      *             if the search is repeating and there is an endless loop due
  6577.      *             to outputs of one being inputs to another
  6578.      * @throws IllegalArgumentException
  6579.      *             if the lengths of the arrays are not the same (null is ok,
  6580.      *             and/or size 0)
  6581.      * @since 2.4
  6582.      */
  6583.     public static String replaceEachRepeatedly(final String text, final String[] searchList, final String[] replacementList) {
  6584.         return replaceEach(text, searchList, replacementList, true, ArrayUtils.getLength(searchList));
  6585.     }

  6586.     /**
  6587.      * Replaces the first substring of the text string that matches the given regular expression
  6588.      * with the given replacement.
  6589.      *
  6590.      * This method is a {@code null} safe equivalent to:
  6591.      * <ul>
  6592.      *  <li>{@code text.replaceFirst(regex, replacement)}</li>
  6593.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>
  6594.      * </ul>
  6595.      *
  6596.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6597.      *
  6598.      * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
  6599.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  6600.      * DOTALL is also known as single-line mode in Perl.</p>
  6601.      *
  6602.      * <pre>{@code
  6603.      * StringUtils.replaceFirst(null, *, *)       = null
  6604.      * StringUtils.replaceFirst("any", (String) null, *)   = "any"
  6605.      * StringUtils.replaceFirst("any", *, null)   = "any"
  6606.      * StringUtils.replaceFirst("", "", "zzz")    = "zzz"
  6607.      * StringUtils.replaceFirst("", ".*", "zzz")  = "zzz"
  6608.      * StringUtils.replaceFirst("", ".+", "zzz")  = ""
  6609.      * StringUtils.replaceFirst("abc", "", "ZZ")  = "ZZabc"
  6610.      * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z")      = "z\n<__>"
  6611.      * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z")  = "z"
  6612.      * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_")          = "ABC_bc123"
  6613.      * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_")  = "ABC_123abc"
  6614.      * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "")   = "ABC123abc"
  6615.      * StringUtils.replaceFirst("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum  dolor   sit"
  6616.      * }</pre>
  6617.      *
  6618.      * @param text  text to search and replace in, may be null
  6619.      * @param regex  the regular expression to which this string is to be matched
  6620.      * @param replacement  the string to be substituted for the first match
  6621.      * @return  the text with the first replacement processed,
  6622.      *              {@code null} if null String input
  6623.      *
  6624.      * @throws  java.util.regex.PatternSyntaxException
  6625.      *              if the regular expression's syntax is invalid
  6626.      *
  6627.      * @see String#replaceFirst(String, String)
  6628.      * @see java.util.regex.Pattern
  6629.      * @see java.util.regex.Pattern#DOTALL
  6630.      * @since 3.5
  6631.      *
  6632.      * @deprecated Moved to RegExUtils.
  6633.      */
  6634.     @Deprecated
  6635.     public static String replaceFirst(final String text, final String regex, final String replacement) {
  6636.         return RegExUtils.replaceFirst(text, regex, replacement);
  6637.     }

  6638.     /**
  6639.      * Case insensitively replaces all occurrences of a String within another String.
  6640.      *
  6641.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6642.      *
  6643.      * <pre>
  6644.      * StringUtils.replaceIgnoreCase(null, *, *)        = null
  6645.      * StringUtils.replaceIgnoreCase("", *, *)          = ""
  6646.      * StringUtils.replaceIgnoreCase("any", null, *)    = "any"
  6647.      * StringUtils.replaceIgnoreCase("any", *, null)    = "any"
  6648.      * StringUtils.replaceIgnoreCase("any", "", *)      = "any"
  6649.      * StringUtils.replaceIgnoreCase("aba", "a", null)  = "aba"
  6650.      * StringUtils.replaceIgnoreCase("abA", "A", "")    = "b"
  6651.      * StringUtils.replaceIgnoreCase("aba", "A", "z")   = "zbz"
  6652.      * </pre>
  6653.      *
  6654.      * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
  6655.      * @param text  text to search and replace in, may be null
  6656.      * @param searchString  the String to search for (case-insensitive), may be null
  6657.      * @param replacement  the String to replace it with, may be null
  6658.      * @return the text with any replacements processed,
  6659.      *  {@code null} if null String input
  6660.      * @since 3.5
  6661.      */
  6662.      public static String replaceIgnoreCase(final String text, final String searchString, final String replacement) {
  6663.          return replaceIgnoreCase(text, searchString, replacement, -1);
  6664.      }

  6665.     /**
  6666.      * Case insensitively replaces a String with another String inside a larger String,
  6667.      * for the first {@code max} values of the search String.
  6668.      *
  6669.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6670.      *
  6671.      * <pre>
  6672.      * StringUtils.replaceIgnoreCase(null, *, *, *)         = null
  6673.      * StringUtils.replaceIgnoreCase("", *, *, *)           = ""
  6674.      * StringUtils.replaceIgnoreCase("any", null, *, *)     = "any"
  6675.      * StringUtils.replaceIgnoreCase("any", *, null, *)     = "any"
  6676.      * StringUtils.replaceIgnoreCase("any", "", *, *)       = "any"
  6677.      * StringUtils.replaceIgnoreCase("any", *, *, 0)        = "any"
  6678.      * StringUtils.replaceIgnoreCase("abaa", "a", null, -1) = "abaa"
  6679.      * StringUtils.replaceIgnoreCase("abaa", "a", "", -1)   = "b"
  6680.      * StringUtils.replaceIgnoreCase("abaa", "a", "z", 0)   = "abaa"
  6681.      * StringUtils.replaceIgnoreCase("abaa", "A", "z", 1)   = "zbaa"
  6682.      * StringUtils.replaceIgnoreCase("abAa", "a", "z", 2)   = "zbza"
  6683.      * StringUtils.replaceIgnoreCase("abAa", "a", "z", -1)  = "zbzz"
  6684.      * </pre>
  6685.      *
  6686.      * @param text  text to search and replace in, may be null
  6687.      * @param searchString  the String to search for (case-insensitive), may be null
  6688.      * @param replacement  the String to replace it with, may be null
  6689.      * @param max  maximum number of values to replace, or {@code -1} if no maximum
  6690.      * @return the text with any replacements processed,
  6691.      *  {@code null} if null String input
  6692.      * @since 3.5
  6693.      */
  6694.     public static String replaceIgnoreCase(final String text, final String searchString, final String replacement, final int max) {
  6695.         return replace(text, searchString, replacement, max, true);
  6696.     }

  6697.     /**
  6698.      * Replaces a String with another String inside a larger String, once.
  6699.      *
  6700.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6701.      *
  6702.      * <pre>
  6703.      * StringUtils.replaceOnce(null, *, *)        = null
  6704.      * StringUtils.replaceOnce("", *, *)          = ""
  6705.      * StringUtils.replaceOnce("any", null, *)    = "any"
  6706.      * StringUtils.replaceOnce("any", *, null)    = "any"
  6707.      * StringUtils.replaceOnce("any", "", *)      = "any"
  6708.      * StringUtils.replaceOnce("aba", "a", null)  = "aba"
  6709.      * StringUtils.replaceOnce("aba", "a", "")    = "ba"
  6710.      * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
  6711.      * </pre>
  6712.      *
  6713.      * @see #replace(String text, String searchString, String replacement, int max)
  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,
  6718.      *  {@code null} if null String input
  6719.      */
  6720.     public static String replaceOnce(final String text, final String searchString, final String replacement) {
  6721.         return replace(text, searchString, replacement, 1);
  6722.     }

  6723.     /**
  6724.      * Case insensitively replaces a String with another String inside a larger String, once.
  6725.      *
  6726.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6727.      *
  6728.      * <pre>
  6729.      * StringUtils.replaceOnceIgnoreCase(null, *, *)        = null
  6730.      * StringUtils.replaceOnceIgnoreCase("", *, *)          = ""
  6731.      * StringUtils.replaceOnceIgnoreCase("any", null, *)    = "any"
  6732.      * StringUtils.replaceOnceIgnoreCase("any", *, null)    = "any"
  6733.      * StringUtils.replaceOnceIgnoreCase("any", "", *)      = "any"
  6734.      * StringUtils.replaceOnceIgnoreCase("aba", "a", null)  = "aba"
  6735.      * StringUtils.replaceOnceIgnoreCase("aba", "a", "")    = "ba"
  6736.      * StringUtils.replaceOnceIgnoreCase("aba", "a", "z")   = "zba"
  6737.      * StringUtils.replaceOnceIgnoreCase("FoOFoofoo", "foo", "") = "Foofoo"
  6738.      * </pre>
  6739.      *
  6740.      * @see #replaceIgnoreCase(String text, String searchString, String replacement, int max)
  6741.      * @param text  text to search and replace in, may be null
  6742.      * @param searchString  the String to search for (case-insensitive), may be null
  6743.      * @param replacement  the String to replace with, may be null
  6744.      * @return the text with any replacements processed,
  6745.      *  {@code null} if null String input
  6746.      * @since 3.5
  6747.      */
  6748.     public static String replaceOnceIgnoreCase(final String text, final String searchString, final String replacement) {
  6749.         return replaceIgnoreCase(text, searchString, replacement, 1);
  6750.     }

  6751.     /**
  6752.      * Replaces each substring of the source String that matches the given regular expression with the given
  6753.      * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.
  6754.      *
  6755.      * This call is a {@code null} safe equivalent to:
  6756.      * <ul>
  6757.      * <li>{@code source.replaceAll(&quot;(?s)&quot; + regex, replacement)}</li>
  6758.      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(source).replaceAll(replacement)}</li>
  6759.      * </ul>
  6760.      *
  6761.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  6762.      *
  6763.      * <pre>{@code
  6764.      * StringUtils.replacePattern(null, *, *)       = null
  6765.      * StringUtils.replacePattern("any", (String) null, *)   = "any"
  6766.      * StringUtils.replacePattern("any", *, null)   = "any"
  6767.      * StringUtils.replacePattern("", "", "zzz")    = "zzz"
  6768.      * StringUtils.replacePattern("", ".*", "zzz")  = "zzz"
  6769.      * StringUtils.replacePattern("", ".+", "zzz")  = ""
  6770.      * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z")       = "z"
  6771.      * StringUtils.replacePattern("ABCabc123", "[a-z]", "_")       = "ABC___123"
  6772.      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
  6773.      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
  6774.      * StringUtils.replacePattern("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
  6775.      * }</pre>
  6776.      *
  6777.      * @param source
  6778.      *            the source string
  6779.      * @param regex
  6780.      *            the regular expression to which this string is to be matched
  6781.      * @param replacement
  6782.      *            the string to be substituted for each match
  6783.      * @return The resulting {@link String}
  6784.      * @see #replaceAll(String, String, String)
  6785.      * @see String#replaceAll(String, String)
  6786.      * @see Pattern#DOTALL
  6787.      * @since 3.2
  6788.      * @since 3.5 Changed {@code null} reference passed to this method is a no-op.
  6789.      *
  6790.      * @deprecated Moved to RegExUtils.
  6791.      */
  6792.     @Deprecated
  6793.     public static String replacePattern(final String source, final String regex, final String replacement) {
  6794.         return RegExUtils.replacePattern(source, regex, replacement);
  6795.     }

  6796.     /**
  6797.      * Reverses a String as per {@link StringBuilder#reverse()}.
  6798.      *
  6799.      * <p>A {@code null} String returns {@code null}.</p>
  6800.      *
  6801.      * <pre>
  6802.      * StringUtils.reverse(null)  = null
  6803.      * StringUtils.reverse("")    = ""
  6804.      * StringUtils.reverse("bat") = "tab"
  6805.      * </pre>
  6806.      *
  6807.      * @param str  the String to reverse, may be null
  6808.      * @return the reversed String, {@code null} if null String input
  6809.      */
  6810.     public static String reverse(final String str) {
  6811.         if (str == null) {
  6812.             return null;
  6813.         }
  6814.         return new StringBuilder(str).reverse().toString();
  6815.     }

  6816.     /**
  6817.      * Reverses a String that is delimited by a specific character.
  6818.      *
  6819.      * <p>The Strings between the delimiters are not reversed.
  6820.      * Thus java.lang.String becomes String.lang.java (if the delimiter
  6821.      * is {@code '.'}).</p>
  6822.      *
  6823.      * <pre>
  6824.      * StringUtils.reverseDelimited(null, *)      = null
  6825.      * StringUtils.reverseDelimited("", *)        = ""
  6826.      * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
  6827.      * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
  6828.      * </pre>
  6829.      *
  6830.      * @param str  the String to reverse, may be null
  6831.      * @param separatorChar  the separator character to use
  6832.      * @return the reversed String, {@code null} if null String input
  6833.      * @since 2.0
  6834.      */
  6835.     public static String reverseDelimited(final String str, final char separatorChar) {
  6836.         final String[] strs = split(str, separatorChar);
  6837.         ArrayUtils.reverse(strs);
  6838.         return join(strs, separatorChar);
  6839.     }

  6840.     /**
  6841.      * Gets the rightmost {@code len} characters of a String.
  6842.      *
  6843.      * <p>If {@code len} characters are not available, or the String
  6844.      * is {@code null}, the String will be returned without an
  6845.      * an exception. An empty String is returned if len is negative.</p>
  6846.      *
  6847.      * <pre>
  6848.      * StringUtils.right(null, *)    = null
  6849.      * StringUtils.right(*, -ve)     = ""
  6850.      * StringUtils.right("", *)      = ""
  6851.      * StringUtils.right("abc", 0)   = ""
  6852.      * StringUtils.right("abc", 2)   = "bc"
  6853.      * StringUtils.right("abc", 4)   = "abc"
  6854.      * </pre>
  6855.      *
  6856.      * @param str  the String to get the rightmost characters from, may be null
  6857.      * @param len  the length of the required String
  6858.      * @return the rightmost characters, {@code null} if null String input
  6859.      */
  6860.     public static String right(final String str, final int len) {
  6861.         if (str == null) {
  6862.             return null;
  6863.         }
  6864.         if (len < 0) {
  6865.             return EMPTY;
  6866.         }
  6867.         if (str.length() <= len) {
  6868.             return str;
  6869.         }
  6870.         return str.substring(str.length() - len);
  6871.     }

  6872.     /**
  6873.      * Right pad a String with spaces (' ').
  6874.      *
  6875.      * <p>The String is padded to the size of {@code size}.</p>
  6876.      *
  6877.      * <pre>
  6878.      * StringUtils.rightPad(null, *)   = null
  6879.      * StringUtils.rightPad("", 3)     = "   "
  6880.      * StringUtils.rightPad("bat", 3)  = "bat"
  6881.      * StringUtils.rightPad("bat", 5)  = "bat  "
  6882.      * StringUtils.rightPad("bat", 1)  = "bat"
  6883.      * StringUtils.rightPad("bat", -1) = "bat"
  6884.      * </pre>
  6885.      *
  6886.      * @param str  the String to pad out, may be null
  6887.      * @param size  the size to pad to
  6888.      * @return right padded String or original String if no padding is necessary,
  6889.      *  {@code null} if null String input
  6890.      */
  6891.     public static String rightPad(final String str, final int size) {
  6892.         return rightPad(str, size, ' ');
  6893.     }

  6894.     /**
  6895.      * Right pad a String with a specified character.
  6896.      *
  6897.      * <p>The String is padded to the size of {@code size}.</p>
  6898.      *
  6899.      * <pre>
  6900.      * StringUtils.rightPad(null, *, *)     = null
  6901.      * StringUtils.rightPad("", 3, 'z')     = "zzz"
  6902.      * StringUtils.rightPad("bat", 3, 'z')  = "bat"
  6903.      * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
  6904.      * StringUtils.rightPad("bat", 1, 'z')  = "bat"
  6905.      * StringUtils.rightPad("bat", -1, 'z') = "bat"
  6906.      * </pre>
  6907.      *
  6908.      * @param str  the String to pad out, may be null
  6909.      * @param size  the size to pad to
  6910.      * @param padChar  the character to pad with
  6911.      * @return right padded String or original String if no padding is necessary,
  6912.      *  {@code null} if null String input
  6913.      * @since 2.0
  6914.      */
  6915.     public static String rightPad(final String str, final int size, final char padChar) {
  6916.         if (str == null) {
  6917.             return null;
  6918.         }
  6919.         final int pads = size - str.length();
  6920.         if (pads <= 0) {
  6921.             return str; // returns original String when possible
  6922.         }
  6923.         if (pads > PAD_LIMIT) {
  6924.             return rightPad(str, size, String.valueOf(padChar));
  6925.         }
  6926.         return str.concat(repeat(padChar, pads));
  6927.     }

  6928.     /**
  6929.      * Right pad a String with a specified String.
  6930.      *
  6931.      * <p>The String is padded to the size of {@code size}.</p>
  6932.      *
  6933.      * <pre>
  6934.      * StringUtils.rightPad(null, *, *)      = null
  6935.      * StringUtils.rightPad("", 3, "z")      = "zzz"
  6936.      * StringUtils.rightPad("bat", 3, "yz")  = "bat"
  6937.      * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
  6938.      * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
  6939.      * StringUtils.rightPad("bat", 1, "yz")  = "bat"
  6940.      * StringUtils.rightPad("bat", -1, "yz") = "bat"
  6941.      * StringUtils.rightPad("bat", 5, null)  = "bat  "
  6942.      * StringUtils.rightPad("bat", 5, "")    = "bat  "
  6943.      * </pre>
  6944.      *
  6945.      * @param str  the String to pad out, may be null
  6946.      * @param size  the size to pad to
  6947.      * @param padStr  the String to pad with, null or empty treated as single space
  6948.      * @return right padded String or original String if no padding is necessary,
  6949.      *  {@code null} if null String input
  6950.      */
  6951.     public static String rightPad(final String str, final int size, String padStr) {
  6952.         if (str == null) {
  6953.             return null;
  6954.         }
  6955.         if (isEmpty(padStr)) {
  6956.             padStr = SPACE;
  6957.         }
  6958.         final int padLen = padStr.length();
  6959.         final int strLen = str.length();
  6960.         final int pads = size - strLen;
  6961.         if (pads <= 0) {
  6962.             return str; // returns original String when possible
  6963.         }
  6964.         if (padLen == 1 && pads <= PAD_LIMIT) {
  6965.             return rightPad(str, size, padStr.charAt(0));
  6966.         }

  6967.         if (pads == padLen) {
  6968.             return str.concat(padStr);
  6969.         }
  6970.         if (pads < padLen) {
  6971.             return str.concat(padStr.substring(0, pads));
  6972.         }
  6973.         final char[] padding = new char[pads];
  6974.         final char[] padChars = padStr.toCharArray();
  6975.         for (int i = 0; i < pads; i++) {
  6976.             padding[i] = padChars[i % padLen];
  6977.         }
  6978.         return str.concat(new String(padding));
  6979.     }

  6980.     /**
  6981.      * Rotate (circular shift) a String of {@code shift} characters.
  6982.      * <ul>
  6983.      *  <li>If {@code shift > 0}, right circular shift (ex : ABCDEF =&gt; FABCDE)</li>
  6984.      *  <li>If {@code shift < 0}, left circular shift (ex : ABCDEF =&gt; BCDEFA)</li>
  6985.      * </ul>
  6986.      *
  6987.      * <pre>
  6988.      * StringUtils.rotate(null, *)        = null
  6989.      * StringUtils.rotate("", *)          = ""
  6990.      * StringUtils.rotate("abcdefg", 0)   = "abcdefg"
  6991.      * StringUtils.rotate("abcdefg", 2)   = "fgabcde"
  6992.      * StringUtils.rotate("abcdefg", -2)  = "cdefgab"
  6993.      * StringUtils.rotate("abcdefg", 7)   = "abcdefg"
  6994.      * StringUtils.rotate("abcdefg", -7)  = "abcdefg"
  6995.      * StringUtils.rotate("abcdefg", 9)   = "fgabcde"
  6996.      * StringUtils.rotate("abcdefg", -9)  = "cdefgab"
  6997.      * </pre>
  6998.      *
  6999.      * @param str  the String to rotate, may be null
  7000.      * @param shift  number of time to shift (positive : right shift, negative : left shift)
  7001.      * @return the rotated String,
  7002.      *          or the original String if {@code shift == 0},
  7003.      *          or {@code null} if null String input
  7004.      * @since 3.5
  7005.      */
  7006.     public static String rotate(final String str, final int shift) {
  7007.         if (str == null) {
  7008.             return null;
  7009.         }

  7010.         final int strLen = str.length();
  7011.         if (shift == 0 || strLen == 0 || shift % strLen == 0) {
  7012.             return str;
  7013.         }

  7014.         final StringBuilder builder = new StringBuilder(strLen);
  7015.         final int offset = - (shift % strLen);
  7016.         builder.append(substring(str, offset));
  7017.         builder.append(substring(str, 0, offset));
  7018.         return builder.toString();
  7019.     }

  7020.     /**
  7021.      * Splits the provided text into an array, using whitespace as the
  7022.      * separator.
  7023.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  7024.      *
  7025.      * <p>The separator is not included in the returned String array.
  7026.      * Adjacent separators are treated as one separator.
  7027.      * For more control over the split use the StrTokenizer class.</p>
  7028.      *
  7029.      * <p>A {@code null} input String returns {@code null}.</p>
  7030.      *
  7031.      * <pre>
  7032.      * StringUtils.split(null)       = null
  7033.      * StringUtils.split("")         = []
  7034.      * StringUtils.split("abc def")  = ["abc", "def"]
  7035.      * StringUtils.split("abc  def") = ["abc", "def"]
  7036.      * StringUtils.split(" abc ")    = ["abc"]
  7037.      * </pre>
  7038.      *
  7039.      * @param str  the String to parse, may be null
  7040.      * @return an array of parsed Strings, {@code null} if null String input
  7041.      */
  7042.     public static String[] split(final String str) {
  7043.         return split(str, null, -1);
  7044.     }

  7045.     /**
  7046.      * Splits the provided text into an array, separator specified.
  7047.      * This is an alternative to using StringTokenizer.
  7048.      *
  7049.      * <p>The separator is not included in the returned String array.
  7050.      * Adjacent separators are treated as one separator.
  7051.      * For more control over the split use the StrTokenizer class.</p>
  7052.      *
  7053.      * <p>A {@code null} input String returns {@code null}.</p>
  7054.      *
  7055.      * <pre>
  7056.      * StringUtils.split(null, *)         = null
  7057.      * StringUtils.split("", *)           = []
  7058.      * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
  7059.      * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
  7060.      * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
  7061.      * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
  7062.      * </pre>
  7063.      *
  7064.      * @param str  the String to parse, may be null
  7065.      * @param separatorChar  the character used as the delimiter
  7066.      * @return an array of parsed Strings, {@code null} if null String input
  7067.      * @since 2.0
  7068.      */
  7069.     public static String[] split(final String str, final char separatorChar) {
  7070.         return splitWorker(str, separatorChar, false);
  7071.     }

  7072.     /**
  7073.      * Splits the provided text into an array, separators specified.
  7074.      * This is an alternative to using StringTokenizer.
  7075.      *
  7076.      * <p>The separator is not included in the returned String array.
  7077.      * Adjacent separators are treated as one separator.
  7078.      * For more control over the split use the StrTokenizer class.</p>
  7079.      *
  7080.      * <p>A {@code null} input String returns {@code null}.
  7081.      * A {@code null} separatorChars splits on whitespace.</p>
  7082.      *
  7083.      * <pre>
  7084.      * StringUtils.split(null, *)         = null
  7085.      * StringUtils.split("", *)           = []
  7086.      * StringUtils.split("abc def", null) = ["abc", "def"]
  7087.      * StringUtils.split("abc def", " ")  = ["abc", "def"]
  7088.      * StringUtils.split("abc  def", " ") = ["abc", "def"]
  7089.      * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
  7090.      * </pre>
  7091.      *
  7092.      * @param str  the String to parse, may be null
  7093.      * @param separatorChars  the characters used as the delimiters,
  7094.      *  {@code null} splits on whitespace
  7095.      * @return an array of parsed Strings, {@code null} if null String input
  7096.      */
  7097.     public static String[] split(final String str, final String separatorChars) {
  7098.         return splitWorker(str, separatorChars, -1, false);
  7099.     }

  7100.     /**
  7101.      * Splits the provided text into an array with a maximum length,
  7102.      * separators specified.
  7103.      *
  7104.      * <p>The separator is not included in the returned String array.
  7105.      * Adjacent separators are treated as one separator.</p>
  7106.      *
  7107.      * <p>A {@code null} input String returns {@code null}.
  7108.      * A {@code null} separatorChars splits on whitespace.</p>
  7109.      *
  7110.      * <p>If more than {@code max} delimited substrings are found, the last
  7111.      * returned string includes all characters after the first {@code max - 1}
  7112.      * returned strings (including separator characters).</p>
  7113.      *
  7114.      * <pre>
  7115.      * StringUtils.split(null, *, *)            = null
  7116.      * StringUtils.split("", *, *)              = []
  7117.      * StringUtils.split("ab cd ef", null, 0)   = ["ab", "cd", "ef"]
  7118.      * StringUtils.split("ab   cd ef", null, 0) = ["ab", "cd", "ef"]
  7119.      * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
  7120.      * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
  7121.      * </pre>
  7122.      *
  7123.      * @param str  the String to parse, may be null
  7124.      * @param separatorChars  the characters used as the delimiters,
  7125.      *  {@code null} splits on whitespace
  7126.      * @param max  the maximum number of elements to include in the
  7127.      *  array. A zero or negative value implies no limit
  7128.      * @return an array of parsed Strings, {@code null} if null String input
  7129.      */
  7130.     public static String[] split(final String str, final String separatorChars, final int max) {
  7131.         return splitWorker(str, separatorChars, max, false);
  7132.     }

  7133.     /**
  7134.      * Splits a String by Character type as returned by
  7135.      * {@code java.lang.Character.getType(char)}. Groups of contiguous
  7136.      * characters of the same type are returned as complete tokens.
  7137.      * <pre>
  7138.      * StringUtils.splitByCharacterType(null)         = null
  7139.      * StringUtils.splitByCharacterType("")           = []
  7140.      * StringUtils.splitByCharacterType("ab de fg")   = ["ab", " ", "de", " ", "fg"]
  7141.      * StringUtils.splitByCharacterType("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
  7142.      * StringUtils.splitByCharacterType("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
  7143.      * StringUtils.splitByCharacterType("number5")    = ["number", "5"]
  7144.      * StringUtils.splitByCharacterType("fooBar")     = ["foo", "B", "ar"]
  7145.      * StringUtils.splitByCharacterType("foo200Bar")  = ["foo", "200", "B", "ar"]
  7146.      * StringUtils.splitByCharacterType("ASFRules")   = ["ASFR", "ules"]
  7147.      * </pre>
  7148.      * @param str the String to split, may be {@code null}
  7149.      * @return an array of parsed Strings, {@code null} if null String input
  7150.      * @since 2.4
  7151.      */
  7152.     public static String[] splitByCharacterType(final String str) {
  7153.         return splitByCharacterType(str, false);
  7154.     }

  7155.     /**
  7156.      * <p>Splits a String by Character type as returned by
  7157.      * {@code java.lang.Character.getType(char)}. Groups of contiguous
  7158.      * characters of the same type are returned as complete tokens, with the
  7159.      * following exception: if {@code camelCase} is {@code true},
  7160.      * the character of type {@code Character.UPPERCASE_LETTER}, if any,
  7161.      * immediately preceding a token of type {@code Character.LOWERCASE_LETTER}
  7162.      * will belong to the following token rather than to the preceding, if any,
  7163.      * {@code Character.UPPERCASE_LETTER} token.
  7164.      * @param str the String to split, may be {@code null}
  7165.      * @param camelCase whether to use so-called "camel-case" for letter types
  7166.      * @return an array of parsed Strings, {@code null} if null String input
  7167.      * @since 2.4
  7168.      */
  7169.     private static String[] splitByCharacterType(final String str, final boolean camelCase) {
  7170.         if (str == null) {
  7171.             return null;
  7172.         }
  7173.         if (str.isEmpty()) {
  7174.             return ArrayUtils.EMPTY_STRING_ARRAY;
  7175.         }
  7176.         final char[] c = str.toCharArray();
  7177.         final List<String> list = new ArrayList<>();
  7178.         int tokenStart = 0;
  7179.         int currentType = Character.getType(c[tokenStart]);
  7180.         for (int pos = tokenStart + 1; pos < c.length; pos++) {
  7181.             final int type = Character.getType(c[pos]);
  7182.             if (type == currentType) {
  7183.                 continue;
  7184.             }
  7185.             if (camelCase && type == Character.LOWERCASE_LETTER && currentType == Character.UPPERCASE_LETTER) {
  7186.                 final int newTokenStart = pos - 1;
  7187.                 if (newTokenStart != tokenStart) {
  7188.                     list.add(new String(c, tokenStart, newTokenStart - tokenStart));
  7189.                     tokenStart = newTokenStart;
  7190.                 }
  7191.             } else {
  7192.                 list.add(new String(c, tokenStart, pos - tokenStart));
  7193.                 tokenStart = pos;
  7194.             }
  7195.             currentType = type;
  7196.         }
  7197.         list.add(new String(c, tokenStart, c.length - tokenStart));
  7198.         return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  7199.     }

  7200.     /**
  7201.      * <p>Splits a String by Character type as returned by
  7202.      * {@code java.lang.Character.getType(char)}. Groups of contiguous
  7203.      * characters of the same type are returned as complete tokens, with the
  7204.      * following exception: the character of type
  7205.      * {@code Character.UPPERCASE_LETTER}, if any, immediately
  7206.      * preceding a token of type {@code Character.LOWERCASE_LETTER}
  7207.      * will belong to the following token rather than to the preceding, if any,
  7208.      * {@code Character.UPPERCASE_LETTER} token.
  7209.      * <pre>
  7210.      * StringUtils.splitByCharacterTypeCamelCase(null)         = null
  7211.      * StringUtils.splitByCharacterTypeCamelCase("")           = []
  7212.      * StringUtils.splitByCharacterTypeCamelCase("ab de fg")   = ["ab", " ", "de", " ", "fg"]
  7213.      * StringUtils.splitByCharacterTypeCamelCase("ab   de fg") = ["ab", "   ", "de", " ", "fg"]
  7214.      * StringUtils.splitByCharacterTypeCamelCase("ab:cd:ef")   = ["ab", ":", "cd", ":", "ef"]
  7215.      * StringUtils.splitByCharacterTypeCamelCase("number5")    = ["number", "5"]
  7216.      * StringUtils.splitByCharacterTypeCamelCase("fooBar")     = ["foo", "Bar"]
  7217.      * StringUtils.splitByCharacterTypeCamelCase("foo200Bar")  = ["foo", "200", "Bar"]
  7218.      * StringUtils.splitByCharacterTypeCamelCase("ASFRules")   = ["ASF", "Rules"]
  7219.      * </pre>
  7220.      * @param str the String to split, may be {@code null}
  7221.      * @return an array of parsed Strings, {@code null} if null String input
  7222.      * @since 2.4
  7223.      */
  7224.     public static String[] splitByCharacterTypeCamelCase(final String str) {
  7225.         return splitByCharacterType(str, true);
  7226.     }

  7227.     /**
  7228.      * <p>Splits the provided text into an array, separator string specified.
  7229.      *
  7230.      * <p>The separator(s) will not be included in the returned String array.
  7231.      * Adjacent separators are treated as one separator.</p>
  7232.      *
  7233.      * <p>A {@code null} input String returns {@code null}.
  7234.      * A {@code null} separator splits on whitespace.</p>
  7235.      *
  7236.      * <pre>
  7237.      * StringUtils.splitByWholeSeparator(null, *)               = null
  7238.      * StringUtils.splitByWholeSeparator("", *)                 = []
  7239.      * StringUtils.splitByWholeSeparator("ab de fg", null)      = ["ab", "de", "fg"]
  7240.      * StringUtils.splitByWholeSeparator("ab   de fg", null)    = ["ab", "de", "fg"]
  7241.      * StringUtils.splitByWholeSeparator("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
  7242.      * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
  7243.      * </pre>
  7244.      *
  7245.      * @param str  the String to parse, may be null
  7246.      * @param separator  String containing the String to be used as a delimiter,
  7247.      *  {@code null} splits on whitespace
  7248.      * @return an array of parsed Strings, {@code null} if null String was input
  7249.      */
  7250.     public static String[] splitByWholeSeparator(final String str, final String separator) {
  7251.         return splitByWholeSeparatorWorker(str, separator, -1, false);
  7252.     }

  7253.     /**
  7254.      * Splits the provided text into an array, separator string specified.
  7255.      * Returns a maximum of {@code max} substrings.
  7256.      *
  7257.      * <p>The separator(s) will not be included in the returned String array.
  7258.      * Adjacent separators are treated as one separator.</p>
  7259.      *
  7260.      * <p>A {@code null} input String returns {@code null}.
  7261.      * A {@code null} separator splits on whitespace.</p>
  7262.      *
  7263.      * <pre>
  7264.      * StringUtils.splitByWholeSeparator(null, *, *)               = null
  7265.      * StringUtils.splitByWholeSeparator("", *, *)                 = []
  7266.      * StringUtils.splitByWholeSeparator("ab de fg", null, 0)      = ["ab", "de", "fg"]
  7267.      * StringUtils.splitByWholeSeparator("ab   de fg", null, 0)    = ["ab", "de", "fg"]
  7268.      * StringUtils.splitByWholeSeparator("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
  7269.      * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
  7270.      * StringUtils.splitByWholeSeparator("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
  7271.      * </pre>
  7272.      *
  7273.      * @param str  the String to parse, may be null
  7274.      * @param separator  String containing the String to be used as a delimiter,
  7275.      *  {@code null} splits on whitespace
  7276.      * @param max  the maximum number of elements to include in the returned
  7277.      *  array. A zero or negative value implies no limit.
  7278.      * @return an array of parsed Strings, {@code null} if null String was input
  7279.      */
  7280.     public static String[] splitByWholeSeparator( final String str, final String separator, final int max) {
  7281.         return splitByWholeSeparatorWorker(str, separator, max, false);
  7282.     }

  7283.     /**
  7284.      * Splits the provided text into an array, separator string specified.
  7285.      *
  7286.      * <p>The separator is not included in the returned String array.
  7287.      * Adjacent separators are treated as separators for empty tokens.
  7288.      * For more control over the split use the StrTokenizer class.</p>
  7289.      *
  7290.      * <p>A {@code null} input String returns {@code null}.
  7291.      * A {@code null} separator splits on whitespace.</p>
  7292.      *
  7293.      * <pre>
  7294.      * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *)               = null
  7295.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *)                 = []
  7296.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null)      = ["ab", "de", "fg"]
  7297.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null)    = ["ab", "", "", "de", "fg"]
  7298.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":")       = ["ab", "cd", "ef"]
  7299.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-") = ["ab", "cd", "ef"]
  7300.      * </pre>
  7301.      *
  7302.      * @param str  the String to parse, may be null
  7303.      * @param separator  String containing the String to be used as a delimiter,
  7304.      *  {@code null} splits on whitespace
  7305.      * @return an array of parsed Strings, {@code null} if null String was input
  7306.      * @since 2.4
  7307.      */
  7308.     public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator) {
  7309.         return splitByWholeSeparatorWorker(str, separator, -1, true);
  7310.     }

  7311.     /**
  7312.      * Splits the provided text into an array, separator string specified.
  7313.      * Returns a maximum of {@code max} substrings.
  7314.      *
  7315.      * <p>The separator is not included in the returned String array.
  7316.      * Adjacent separators are treated as separators for empty tokens.
  7317.      * For more control over the split use the StrTokenizer class.</p>
  7318.      *
  7319.      * <p>A {@code null} input String returns {@code null}.
  7320.      * A {@code null} separator splits on whitespace.</p>
  7321.      *
  7322.      * <pre>
  7323.      * StringUtils.splitByWholeSeparatorPreserveAllTokens(null, *, *)               = null
  7324.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("", *, *)                 = []
  7325.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab de fg", null, 0)      = ["ab", "de", "fg"]
  7326.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab   de fg", null, 0)    = ["ab", "", "", "de", "fg"]
  7327.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab:cd:ef", ":", 2)       = ["ab", "cd:ef"]
  7328.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 5) = ["ab", "cd", "ef"]
  7329.      * StringUtils.splitByWholeSeparatorPreserveAllTokens("ab-!-cd-!-ef", "-!-", 2) = ["ab", "cd-!-ef"]
  7330.      * </pre>
  7331.      *
  7332.      * @param str  the String to parse, may be null
  7333.      * @param separator  String containing the String to be used as a delimiter,
  7334.      *  {@code null} splits on whitespace
  7335.      * @param max  the maximum number of elements to include in the returned
  7336.      *  array. A zero or negative value implies no limit.
  7337.      * @return an array of parsed Strings, {@code null} if null String was input
  7338.      * @since 2.4
  7339.      */
  7340.     public static String[] splitByWholeSeparatorPreserveAllTokens(final String str, final String separator, final int max) {
  7341.         return splitByWholeSeparatorWorker(str, separator, max, true);
  7342.     }

  7343.     /**
  7344.      * Performs the logic for the {@code splitByWholeSeparatorPreserveAllTokens} methods.
  7345.      *
  7346.      * @param str  the String to parse, may be {@code null}
  7347.      * @param separator  String containing the String to be used as a delimiter,
  7348.      *  {@code null} splits on whitespace
  7349.      * @param max  the maximum number of elements to include in the returned
  7350.      *  array. A zero or negative value implies no limit.
  7351.      * @param preserveAllTokens if {@code true}, adjacent separators are
  7352.      * treated as empty token separators; if {@code false}, adjacent
  7353.      * separators are treated as one separator.
  7354.      * @return an array of parsed Strings, {@code null} if null String input
  7355.      * @since 2.4
  7356.      */
  7357.     private static String[] splitByWholeSeparatorWorker(
  7358.             final String str, final String separator, final int max, final boolean preserveAllTokens) {
  7359.         if (str == null) {
  7360.             return null;
  7361.         }

  7362.         final int len = str.length();

  7363.         if (len == 0) {
  7364.             return ArrayUtils.EMPTY_STRING_ARRAY;
  7365.         }

  7366.         if (separator == null || EMPTY.equals(separator)) {
  7367.             // Split on whitespace.
  7368.             return splitWorker(str, null, max, preserveAllTokens);
  7369.         }

  7370.         final int separatorLength = separator.length();

  7371.         final ArrayList<String> substrings = new ArrayList<>();
  7372.         int numberOfSubstrings = 0;
  7373.         int beg = 0;
  7374.         int end = 0;
  7375.         while (end < len) {
  7376.             end = str.indexOf(separator, beg);

  7377.             if (end > -1) {
  7378.                 if (end > beg) {
  7379.                     numberOfSubstrings += 1;

  7380.                     if (numberOfSubstrings == max) {
  7381.                         end = len;
  7382.                         substrings.add(str.substring(beg));
  7383.                     } else {
  7384.                         // The following is OK, because String.substring( beg, end ) excludes
  7385.                         // the character at the position 'end'.
  7386.                         substrings.add(str.substring(beg, end));

  7387.                         // Set the starting point for the next search.
  7388.                         // The following is equivalent to beg = end + (separatorLength - 1) + 1,
  7389.                         // which is the right calculation:
  7390.                         beg = end + separatorLength;
  7391.                     }
  7392.                 } else {
  7393.                     // We found a consecutive occurrence of the separator, so skip it.
  7394.                     if (preserveAllTokens) {
  7395.                         numberOfSubstrings += 1;
  7396.                         if (numberOfSubstrings == max) {
  7397.                             end = len;
  7398.                             substrings.add(str.substring(beg));
  7399.                         } else {
  7400.                             substrings.add(EMPTY);
  7401.                         }
  7402.                     }
  7403.                     beg = end + separatorLength;
  7404.                 }
  7405.             } else {
  7406.                 // String.substring( beg ) goes from 'beg' to the end of the String.
  7407.                 substrings.add(str.substring(beg));
  7408.                 end = len;
  7409.             }
  7410.         }

  7411.         return substrings.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  7412.     }

  7413.     /**
  7414.      * Splits the provided text into an array, using whitespace as the
  7415.      * separator, preserving all tokens, including empty tokens created by
  7416.      * adjacent separators. This is an alternative to using StringTokenizer.
  7417.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  7418.      *
  7419.      * <p>The separator is not included in the returned String array.
  7420.      * Adjacent separators are treated as separators for empty tokens.
  7421.      * For more control over the split use the StrTokenizer class.</p>
  7422.      *
  7423.      * <p>A {@code null} input String returns {@code null}.</p>
  7424.      *
  7425.      * <pre>
  7426.      * StringUtils.splitPreserveAllTokens(null)       = null
  7427.      * StringUtils.splitPreserveAllTokens("")         = []
  7428.      * StringUtils.splitPreserveAllTokens("abc def")  = ["abc", "def"]
  7429.      * StringUtils.splitPreserveAllTokens("abc  def") = ["abc", "", "def"]
  7430.      * StringUtils.splitPreserveAllTokens(" abc ")    = ["", "abc", ""]
  7431.      * </pre>
  7432.      *
  7433.      * @param str  the String to parse, may be {@code null}
  7434.      * @return an array of parsed Strings, {@code null} if null String input
  7435.      * @since 2.1
  7436.      */
  7437.     public static String[] splitPreserveAllTokens(final String str) {
  7438.         return splitWorker(str, null, -1, true);
  7439.     }

  7440.     /**
  7441.      * Splits the provided text into an array, separator specified,
  7442.      * preserving all tokens, including empty tokens created by adjacent
  7443.      * separators. This is an alternative to using StringTokenizer.
  7444.      *
  7445.      * <p>The separator is not included in the returned String array.
  7446.      * Adjacent separators are treated as separators for empty tokens.
  7447.      * For more control over the split use the StrTokenizer class.</p>
  7448.      *
  7449.      * <p>A {@code null} input String returns {@code null}.</p>
  7450.      *
  7451.      * <pre>
  7452.      * StringUtils.splitPreserveAllTokens(null, *)         = null
  7453.      * StringUtils.splitPreserveAllTokens("", *)           = []
  7454.      * StringUtils.splitPreserveAllTokens("a.b.c", '.')    = ["a", "b", "c"]
  7455.      * StringUtils.splitPreserveAllTokens("a..b.c", '.')   = ["a", "", "b", "c"]
  7456.      * StringUtils.splitPreserveAllTokens("a:b:c", '.')    = ["a:b:c"]
  7457.      * StringUtils.splitPreserveAllTokens("a\tb\nc", null) = ["a", "b", "c"]
  7458.      * StringUtils.splitPreserveAllTokens("a b c", ' ')    = ["a", "b", "c"]
  7459.      * StringUtils.splitPreserveAllTokens("a b c ", ' ')   = ["a", "b", "c", ""]
  7460.      * StringUtils.splitPreserveAllTokens("a b c  ", ' ')  = ["a", "b", "c", "", ""]
  7461.      * StringUtils.splitPreserveAllTokens(" a b c", ' ')   = ["", "a", "b", "c"]
  7462.      * StringUtils.splitPreserveAllTokens("  a b c", ' ')  = ["", "", "a", "b", "c"]
  7463.      * StringUtils.splitPreserveAllTokens(" a b c ", ' ')  = ["", "a", "b", "c", ""]
  7464.      * </pre>
  7465.      *
  7466.      * @param str  the String to parse, may be {@code null}
  7467.      * @param separatorChar  the character used as the delimiter,
  7468.      *  {@code null} splits on whitespace
  7469.      * @return an array of parsed Strings, {@code null} if null String input
  7470.      * @since 2.1
  7471.      */
  7472.     public static String[] splitPreserveAllTokens(final String str, final char separatorChar) {
  7473.         return splitWorker(str, separatorChar, true);
  7474.     }

  7475.     /**
  7476.      * Splits the provided text into an array, separators specified,
  7477.      * preserving all tokens, including empty tokens created by adjacent
  7478.      * separators. This is an alternative to using StringTokenizer.
  7479.      *
  7480.      * <p>The separator is not included in the returned String array.
  7481.      * Adjacent separators are treated as separators for empty tokens.
  7482.      * For more control over the split use the StrTokenizer class.</p>
  7483.      *
  7484.      * <p>A {@code null} input String returns {@code null}.
  7485.      * A {@code null} separatorChars splits on whitespace.</p>
  7486.      *
  7487.      * <pre>
  7488.      * StringUtils.splitPreserveAllTokens(null, *)           = null
  7489.      * StringUtils.splitPreserveAllTokens("", *)             = []
  7490.      * StringUtils.splitPreserveAllTokens("abc def", null)   = ["abc", "def"]
  7491.      * StringUtils.splitPreserveAllTokens("abc def", " ")    = ["abc", "def"]
  7492.      * StringUtils.splitPreserveAllTokens("abc  def", " ")   = ["abc", "", "def"]
  7493.      * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":")   = ["ab", "cd", "ef"]
  7494.      * StringUtils.splitPreserveAllTokens("ab:cd:ef:", ":")  = ["ab", "cd", "ef", ""]
  7495.      * StringUtils.splitPreserveAllTokens("ab:cd:ef::", ":") = ["ab", "cd", "ef", "", ""]
  7496.      * StringUtils.splitPreserveAllTokens("ab::cd:ef", ":")  = ["ab", "", "cd", "ef"]
  7497.      * StringUtils.splitPreserveAllTokens(":cd:ef", ":")     = ["", "cd", "ef"]
  7498.      * StringUtils.splitPreserveAllTokens("::cd:ef", ":")    = ["", "", "cd", "ef"]
  7499.      * StringUtils.splitPreserveAllTokens(":cd:ef:", ":")    = ["", "cd", "ef", ""]
  7500.      * </pre>
  7501.      *
  7502.      * @param str  the String to parse, may be {@code null}
  7503.      * @param separatorChars  the characters used as the delimiters,
  7504.      *  {@code null} splits on whitespace
  7505.      * @return an array of parsed Strings, {@code null} if null String input
  7506.      * @since 2.1
  7507.      */
  7508.     public static String[] splitPreserveAllTokens(final String str, final String separatorChars) {
  7509.         return splitWorker(str, separatorChars, -1, true);
  7510.     }

  7511.     /**
  7512.      * Splits the provided text into an array with a maximum length,
  7513.      * separators specified, preserving all tokens, including empty tokens
  7514.      * created by adjacent separators.
  7515.      *
  7516.      * <p>The separator is not included in the returned String array.
  7517.      * Adjacent separators are treated as separators for empty tokens.
  7518.      * Adjacent separators are treated as one separator.</p>
  7519.      *
  7520.      * <p>A {@code null} input String returns {@code null}.
  7521.      * A {@code null} separatorChars splits on whitespace.</p>
  7522.      *
  7523.      * <p>If more than {@code max} delimited substrings are found, the last
  7524.      * returned string includes all characters after the first {@code max - 1}
  7525.      * returned strings (including separator characters).</p>
  7526.      *
  7527.      * <pre>
  7528.      * StringUtils.splitPreserveAllTokens(null, *, *)            = null
  7529.      * StringUtils.splitPreserveAllTokens("", *, *)              = []
  7530.      * StringUtils.splitPreserveAllTokens("ab de fg", null, 0)   = ["ab", "de", "fg"]
  7531.      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 0) = ["ab", "", "", "de", "fg"]
  7532.      * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
  7533.      * StringUtils.splitPreserveAllTokens("ab:cd:ef", ":", 2)    = ["ab", "cd:ef"]
  7534.      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 2) = ["ab", "  de fg"]
  7535.      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 3) = ["ab", "", " de fg"]
  7536.      * StringUtils.splitPreserveAllTokens("ab   de fg", null, 4) = ["ab", "", "", "de fg"]
  7537.      * </pre>
  7538.      *
  7539.      * @param str  the String to parse, may be {@code null}
  7540.      * @param separatorChars  the characters used as the delimiters,
  7541.      *  {@code null} splits on whitespace
  7542.      * @param max  the maximum number of elements to include in the
  7543.      *  array. A zero or negative value implies no limit
  7544.      * @return an array of parsed Strings, {@code null} if null String input
  7545.      * @since 2.1
  7546.      */
  7547.     public static String[] splitPreserveAllTokens(final String str, final String separatorChars, final int max) {
  7548.         return splitWorker(str, separatorChars, max, true);
  7549.     }

  7550.     /**
  7551.      * Performs the logic for the {@code split} and
  7552.      * {@code splitPreserveAllTokens} methods that do not return a
  7553.      * maximum array length.
  7554.      *
  7555.      * @param str  the String to parse, may be {@code null}
  7556.      * @param separatorChar the separate character
  7557.      * @param preserveAllTokens if {@code true}, adjacent separators are
  7558.      * treated as empty token separators; if {@code false}, adjacent
  7559.      * separators are treated as one separator.
  7560.      * @return an array of parsed Strings, {@code null} if null String input
  7561.      */
  7562.     private static String[] splitWorker(final String str, final char separatorChar, final boolean preserveAllTokens) {
  7563.         // Performance tuned for 2.0 (JDK1.4)
  7564.         if (str == null) {
  7565.             return null;
  7566.         }
  7567.         final int len = str.length();
  7568.         if (len == 0) {
  7569.             return ArrayUtils.EMPTY_STRING_ARRAY;
  7570.         }
  7571.         final List<String> list = new ArrayList<>();
  7572.         int i = 0;
  7573.         int start = 0;
  7574.         boolean match = false;
  7575.         boolean lastMatch = false;
  7576.         while (i < len) {
  7577.             if (str.charAt(i) == separatorChar) {
  7578.                 if (match || preserveAllTokens) {
  7579.                     list.add(str.substring(start, i));
  7580.                     match = false;
  7581.                     lastMatch = true;
  7582.                 }
  7583.                 start = ++i;
  7584.                 continue;
  7585.             }
  7586.             lastMatch = false;
  7587.             match = true;
  7588.             i++;
  7589.         }
  7590.         if (match || preserveAllTokens && lastMatch) {
  7591.             list.add(str.substring(start, i));
  7592.         }
  7593.         return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  7594.     }

  7595.     /**
  7596.      * Performs the logic for the {@code split} and
  7597.      * {@code splitPreserveAllTokens} methods that return a maximum array
  7598.      * length.
  7599.      *
  7600.      * @param str  the String to parse, may be {@code null}
  7601.      * @param separatorChars the separate character
  7602.      * @param max  the maximum number of elements to include in the
  7603.      *  array. A zero or negative value implies no limit.
  7604.      * @param preserveAllTokens if {@code true}, adjacent separators are
  7605.      * treated as empty token separators; if {@code false}, adjacent
  7606.      * separators are treated as one separator.
  7607.      * @return an array of parsed Strings, {@code null} if null String input
  7608.      */
  7609.     private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
  7610.         // Performance tuned for 2.0 (JDK1.4)
  7611.         // Direct code is quicker than StringTokenizer.
  7612.         // Also, StringTokenizer uses isSpace() not isWhitespace()

  7613.         if (str == null) {
  7614.             return null;
  7615.         }
  7616.         final int len = str.length();
  7617.         if (len == 0) {
  7618.             return ArrayUtils.EMPTY_STRING_ARRAY;
  7619.         }
  7620.         final List<String> list = new ArrayList<>();
  7621.         int sizePlus1 = 1;
  7622.         int i = 0;
  7623.         int start = 0;
  7624.         boolean match = false;
  7625.         boolean lastMatch = false;
  7626.         if (separatorChars == null) {
  7627.             // Null separator means use whitespace
  7628.             while (i < len) {
  7629.                 if (Character.isWhitespace(str.charAt(i))) {
  7630.                     if (match || preserveAllTokens) {
  7631.                         lastMatch = true;
  7632.                         if (sizePlus1++ == max) {
  7633.                             i = len;
  7634.                             lastMatch = false;
  7635.                         }
  7636.                         list.add(str.substring(start, i));
  7637.                         match = false;
  7638.                     }
  7639.                     start = ++i;
  7640.                     continue;
  7641.                 }
  7642.                 lastMatch = false;
  7643.                 match = true;
  7644.                 i++;
  7645.             }
  7646.         } else if (separatorChars.length() == 1) {
  7647.             // Optimise 1 character case
  7648.             final char sep = separatorChars.charAt(0);
  7649.             while (i < len) {
  7650.                 if (str.charAt(i) == sep) {
  7651.                     if (match || preserveAllTokens) {
  7652.                         lastMatch = true;
  7653.                         if (sizePlus1++ == max) {
  7654.                             i = len;
  7655.                             lastMatch = false;
  7656.                         }
  7657.                         list.add(str.substring(start, i));
  7658.                         match = false;
  7659.                     }
  7660.                     start = ++i;
  7661.                     continue;
  7662.                 }
  7663.                 lastMatch = false;
  7664.                 match = true;
  7665.                 i++;
  7666.             }
  7667.         } else {
  7668.             // standard case
  7669.             while (i < len) {
  7670.                 if (separatorChars.indexOf(str.charAt(i)) >= 0) {
  7671.                     if (match || preserveAllTokens) {
  7672.                         lastMatch = true;
  7673.                         if (sizePlus1++ == max) {
  7674.                             i = len;
  7675.                             lastMatch = false;
  7676.                         }
  7677.                         list.add(str.substring(start, i));
  7678.                         match = false;
  7679.                     }
  7680.                     start = ++i;
  7681.                     continue;
  7682.                 }
  7683.                 lastMatch = false;
  7684.                 match = true;
  7685.                 i++;
  7686.             }
  7687.         }
  7688.         if (match || preserveAllTokens && lastMatch) {
  7689.             list.add(str.substring(start, i));
  7690.         }
  7691.         return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  7692.     }

  7693.     /**
  7694.      * Check if a CharSequence starts with a specified prefix.
  7695.      *
  7696.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  7697.      * references are considered to be equal. The comparison is case-sensitive.</p>
  7698.      *
  7699.      * <pre>
  7700.      * StringUtils.startsWith(null, null)      = true
  7701.      * StringUtils.startsWith(null, "abc")     = false
  7702.      * StringUtils.startsWith("abcdef", null)  = false
  7703.      * StringUtils.startsWith("abcdef", "abc") = true
  7704.      * StringUtils.startsWith("ABCDEF", "abc") = false
  7705.      * </pre>
  7706.      *
  7707.      * @see String#startsWith(String)
  7708.      * @param str  the CharSequence to check, may be null
  7709.      * @param prefix the prefix to find, may be null
  7710.      * @return {@code true} if the CharSequence starts with the prefix, case-sensitive, or
  7711.      *  both {@code null}
  7712.      * @since 2.4
  7713.      * @since 3.0 Changed signature from startsWith(String, String) to startsWith(CharSequence, CharSequence)
  7714.      */
  7715.     public static boolean startsWith(final CharSequence str, final CharSequence prefix) {
  7716.         return startsWith(str, prefix, false);
  7717.     }

  7718.     /**
  7719.      * Check if a CharSequence starts with a specified prefix (optionally case-insensitive).
  7720.      *
  7721.      * @see String#startsWith(String)
  7722.      * @param str  the CharSequence to check, may be null
  7723.      * @param prefix the prefix to find, may be null
  7724.      * @param ignoreCase indicates whether the compare should ignore case
  7725.      *  (case-insensitive) or not.
  7726.      * @return {@code true} if the CharSequence starts with the prefix or
  7727.      *  both {@code null}
  7728.      */
  7729.     private static boolean startsWith(final CharSequence str, final CharSequence prefix, final boolean ignoreCase) {
  7730.         if (str == null || prefix == null) {
  7731.             return str == prefix;
  7732.         }
  7733.         // Get length once instead of twice in the unlikely case that it changes.
  7734.         final int preLen = prefix.length();
  7735.         if (preLen > str.length()) {
  7736.             return false;
  7737.         }
  7738.         return CharSequenceUtils.regionMatches(str, ignoreCase, 0, prefix, 0, preLen);
  7739.     }

  7740.     /**
  7741.      * Check if a CharSequence starts with any of the provided case-sensitive prefixes.
  7742.      *
  7743.      * <pre>
  7744.      * StringUtils.startsWithAny(null, null)      = false
  7745.      * StringUtils.startsWithAny(null, new String[] {"abc"})  = false
  7746.      * StringUtils.startsWithAny("abcxyz", null)     = false
  7747.      * StringUtils.startsWithAny("abcxyz", new String[] {""}) = true
  7748.      * StringUtils.startsWithAny("abcxyz", new String[] {"abc"}) = true
  7749.      * StringUtils.startsWithAny("abcxyz", new String[] {null, "xyz", "abc"}) = true
  7750.      * StringUtils.startsWithAny("abcxyz", null, "xyz", "ABCX") = false
  7751.      * StringUtils.startsWithAny("ABCXYZ", null, "xyz", "abc") = false
  7752.      * </pre>
  7753.      *
  7754.      * @param sequence the CharSequence to check, may be null
  7755.      * @param searchStrings the case-sensitive CharSequence prefixes, may be empty or contain {@code null}
  7756.      * @see StringUtils#startsWith(CharSequence, CharSequence)
  7757.      * @return {@code true} if the input {@code sequence} is {@code null} AND no {@code searchStrings} are provided, or
  7758.      *   the input {@code sequence} begins with any of the provided case-sensitive {@code searchStrings}.
  7759.      * @since 2.5
  7760.      * @since 3.0 Changed signature from startsWithAny(String, String[]) to startsWithAny(CharSequence, CharSequence...)
  7761.      */
  7762.     public static boolean startsWithAny(final CharSequence sequence, final CharSequence... searchStrings) {
  7763.         if (isEmpty(sequence) || ArrayUtils.isEmpty(searchStrings)) {
  7764.             return false;
  7765.         }
  7766.         for (final CharSequence searchString : searchStrings) {
  7767.             if (startsWith(sequence, searchString)) {
  7768.                 return true;
  7769.             }
  7770.         }
  7771.         return false;
  7772.     }

  7773.     /**
  7774.      * Case-insensitive check if a CharSequence starts with a specified prefix.
  7775.      *
  7776.      * <p>{@code null}s are handled without exceptions. Two {@code null}
  7777.      * references are considered to be equal. The comparison is case insensitive.</p>
  7778.      *
  7779.      * <pre>
  7780.      * StringUtils.startsWithIgnoreCase(null, null)      = true
  7781.      * StringUtils.startsWithIgnoreCase(null, "abc")     = false
  7782.      * StringUtils.startsWithIgnoreCase("abcdef", null)  = false
  7783.      * StringUtils.startsWithIgnoreCase("abcdef", "abc") = true
  7784.      * StringUtils.startsWithIgnoreCase("ABCDEF", "abc") = true
  7785.      * </pre>
  7786.      *
  7787.      * @see String#startsWith(String)
  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
  7791.      *  both {@code null}
  7792.      * @since 2.4
  7793.      * @since 3.0 Changed signature from startsWithIgnoreCase(String, String) to startsWithIgnoreCase(CharSequence, CharSequence)
  7794.      */
  7795.     public static boolean startsWithIgnoreCase(final CharSequence str, final CharSequence prefix) {
  7796.         return startsWith(str, prefix, true);
  7797.     }

  7798.     /**
  7799.      * Strips whitespace from the start and end of a String.
  7800.      *
  7801.      * <p>This is similar to {@link #trim(String)} but removes whitespace.
  7802.      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  7803.      *
  7804.      * <p>A {@code null} input String returns {@code null}.</p>
  7805.      *
  7806.      * <pre>
  7807.      * StringUtils.strip(null)     = null
  7808.      * StringUtils.strip("")       = ""
  7809.      * StringUtils.strip("   ")    = ""
  7810.      * StringUtils.strip("abc")    = "abc"
  7811.      * StringUtils.strip("  abc")  = "abc"
  7812.      * StringUtils.strip("abc  ")  = "abc"
  7813.      * StringUtils.strip(" abc ")  = "abc"
  7814.      * StringUtils.strip(" ab c ") = "ab c"
  7815.      * </pre>
  7816.      *
  7817.      * @param str  the String to remove whitespace from, may be null
  7818.      * @return the stripped String, {@code null} if null String input
  7819.      */
  7820.     public static String strip(final String str) {
  7821.         return strip(str, null);
  7822.     }

  7823.     /**
  7824.      * Strips any of a set of characters from the start and end of a String.
  7825.      * This is similar to {@link String#trim()} but allows the characters
  7826.      * to be stripped to be controlled.
  7827.      *
  7828.      * <p>A {@code null} input String returns {@code null}.
  7829.      * An empty string ("") input returns the empty string.</p>
  7830.      *
  7831.      * <p>If the stripChars String is {@code null}, whitespace is
  7832.      * stripped as defined by {@link Character#isWhitespace(char)}.
  7833.      * Alternatively use {@link #strip(String)}.</p>
  7834.      *
  7835.      * <pre>
  7836.      * StringUtils.strip(null, *)          = null
  7837.      * StringUtils.strip("", *)            = ""
  7838.      * StringUtils.strip("abc", null)      = "abc"
  7839.      * StringUtils.strip("  abc", null)    = "abc"
  7840.      * StringUtils.strip("abc  ", null)    = "abc"
  7841.      * StringUtils.strip(" abc ", null)    = "abc"
  7842.      * StringUtils.strip("  abcyx", "xyz") = "  abc"
  7843.      * </pre>
  7844.      *
  7845.      * @param str  the String to remove characters from, may be null
  7846.      * @param stripChars  the characters to remove, null treated as whitespace
  7847.      * @return the stripped String, {@code null} if null String input
  7848.      */
  7849.     public static String strip(String str, final String stripChars) {
  7850.         str = stripStart(str, stripChars);
  7851.         return stripEnd(str, stripChars);
  7852.     }

  7853.     /**
  7854.      * Removes diacritics (~= accents) from a string. The case will not be altered.
  7855.      * <p>For instance, '&agrave;' will be replaced by 'a'.</p>
  7856.      * <p>Decomposes ligatures and digraphs per the KD column in the
  7857.      * <a href = "https://www.unicode.org/charts/normalization/">Unicode Normalization Chart.</a></p>
  7858.      *
  7859.      * <pre>
  7860.      * StringUtils.stripAccents(null)                = null
  7861.      * StringUtils.stripAccents("")                  = ""
  7862.      * StringUtils.stripAccents("control")           = "control"
  7863.      * StringUtils.stripAccents("&eacute;clair")     = "eclair"
  7864.      * </pre>
  7865.      *
  7866.      * @param input String to be stripped
  7867.      * @return input text with diacritics removed
  7868.      *
  7869.      * @since 3.0
  7870.      */
  7871.     // See also Lucene's ASCIIFoldingFilter (Lucene 2.9) that replaces accented characters by their unaccented equivalent (and uncommitted bug fix: https://issues.apache.org/jira/browse/LUCENE-1343?focusedCommentId=12858907&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_12858907).
  7872.     public static String stripAccents(final String input) {
  7873.         if (isEmpty(input)) {
  7874.             return input;
  7875.         }
  7876.         final StringBuilder decomposed = new StringBuilder(Normalizer.normalize(input, Normalizer.Form.NFKD));
  7877.         convertRemainingAccentCharacters(decomposed);
  7878.         return STRIP_ACCENTS_PATTERN.matcher(decomposed).replaceAll(EMPTY);
  7879.     }

  7880.     /**
  7881.      * Strips whitespace from the start and end of every String in an array.
  7882.      * Whitespace is defined by {@link Character#isWhitespace(char)}.
  7883.      *
  7884.      * <p>A new array is returned each time, except for length zero.
  7885.      * A {@code null} array will return {@code null}.
  7886.      * An empty array will return itself.
  7887.      * A {@code null} array entry will be ignored.</p>
  7888.      *
  7889.      * <pre>
  7890.      * StringUtils.stripAll(null)             = null
  7891.      * StringUtils.stripAll([])               = []
  7892.      * StringUtils.stripAll(["abc", "  abc"]) = ["abc", "abc"]
  7893.      * StringUtils.stripAll(["abc  ", null])  = ["abc", null]
  7894.      * </pre>
  7895.      *
  7896.      * @param strs  the array to remove whitespace from, may be null
  7897.      * @return the stripped Strings, {@code null} if null array input
  7898.      */
  7899.     public static String[] stripAll(final String... strs) {
  7900.         return stripAll(strs, null);
  7901.     }

  7902.     /**
  7903.      * Strips any of a set of characters from the start and end of every
  7904.      * String in an array.
  7905.      * <p>Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  7906.      *
  7907.      * <p>A new array is returned each time, except for length zero.
  7908.      * A {@code null} array will return {@code null}.
  7909.      * An empty array will return itself.
  7910.      * A {@code null} array entry will be ignored.
  7911.      * A {@code null} stripChars will strip whitespace as defined by
  7912.      * {@link Character#isWhitespace(char)}.</p>
  7913.      *
  7914.      * <pre>
  7915.      * StringUtils.stripAll(null, *)                = null
  7916.      * StringUtils.stripAll([], *)                  = []
  7917.      * StringUtils.stripAll(["abc", "  abc"], null) = ["abc", "abc"]
  7918.      * StringUtils.stripAll(["abc  ", null], null)  = ["abc", null]
  7919.      * StringUtils.stripAll(["abc  ", null], "yz")  = ["abc  ", null]
  7920.      * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]
  7921.      * </pre>
  7922.      *
  7923.      * @param strs  the array to remove characters from, may be null
  7924.      * @param stripChars  the characters to remove, null treated as whitespace
  7925.      * @return the stripped Strings, {@code null} if null array input
  7926.      */
  7927.     public static String[] stripAll(final String[] strs, final String stripChars) {
  7928.         final int strsLen = ArrayUtils.getLength(strs);
  7929.         if (strsLen == 0) {
  7930.             return strs;
  7931.         }
  7932.         final String[] newArr = new String[strsLen];
  7933.         Arrays.setAll(newArr, i -> strip(strs[i], stripChars));
  7934.         return newArr;
  7935.     }

  7936.     /**
  7937.      * Strips any of a set of characters from the end of a String.
  7938.      *
  7939.      * <p>A {@code null} input String returns {@code null}.
  7940.      * An empty string ("") input returns the empty string.</p>
  7941.      *
  7942.      * <p>If the stripChars String is {@code null}, whitespace is
  7943.      * stripped as defined by {@link Character#isWhitespace(char)}.</p>
  7944.      *
  7945.      * <pre>
  7946.      * StringUtils.stripEnd(null, *)          = null
  7947.      * StringUtils.stripEnd("", *)            = ""
  7948.      * StringUtils.stripEnd("abc", "")        = "abc"
  7949.      * StringUtils.stripEnd("abc", null)      = "abc"
  7950.      * StringUtils.stripEnd("  abc", null)    = "  abc"
  7951.      * StringUtils.stripEnd("abc  ", null)    = "abc"
  7952.      * StringUtils.stripEnd(" abc ", null)    = " abc"
  7953.      * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
  7954.      * StringUtils.stripEnd("120.00", ".0")   = "12"
  7955.      * </pre>
  7956.      *
  7957.      * @param str  the String to remove characters from, may be null
  7958.      * @param stripChars  the set of characters to remove, null treated as whitespace
  7959.      * @return the stripped String, {@code null} if null String input
  7960.      */
  7961.     public static String stripEnd(final String str, final String stripChars) {
  7962.         int end = length(str);
  7963.         if (end == 0) {
  7964.             return str;
  7965.         }

  7966.         if (stripChars == null) {
  7967.             while (end != 0 && Character.isWhitespace(str.charAt(end - 1))) {
  7968.                 end--;
  7969.             }
  7970.         } else if (stripChars.isEmpty()) {
  7971.             return str;
  7972.         } else {
  7973.             while (end != 0 && stripChars.indexOf(str.charAt(end - 1)) != INDEX_NOT_FOUND) {
  7974.                 end--;
  7975.             }
  7976.         }
  7977.         return str.substring(0, end);
  7978.     }

  7979.     /**
  7980.      * Strips any of a set of characters from the start of a String.
  7981.      *
  7982.      * <p>A {@code null} input String returns {@code null}.
  7983.      * An empty string ("") input returns the empty string.</p>
  7984.      *
  7985.      * <p>If the stripChars String is {@code null}, whitespace is
  7986.      * stripped as defined by {@link Character#isWhitespace(char)}.</p>
  7987.      *
  7988.      * <pre>
  7989.      * StringUtils.stripStart(null, *)          = null
  7990.      * StringUtils.stripStart("", *)            = ""
  7991.      * StringUtils.stripStart("abc", "")        = "abc"
  7992.      * StringUtils.stripStart("abc", null)      = "abc"
  7993.      * StringUtils.stripStart("  abc", null)    = "abc"
  7994.      * StringUtils.stripStart("abc  ", null)    = "abc  "
  7995.      * StringUtils.stripStart(" abc ", null)    = "abc "
  7996.      * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
  7997.      * </pre>
  7998.      *
  7999.      * @param str  the String to remove characters from, may be null
  8000.      * @param stripChars  the characters to remove, null treated as whitespace
  8001.      * @return the stripped String, {@code null} if null String input
  8002.      */
  8003.     public static String stripStart(final String str, final String stripChars) {
  8004.         final int strLen = length(str);
  8005.         if (strLen == 0) {
  8006.             return str;
  8007.         }
  8008.         int start = 0;
  8009.         if (stripChars == null) {
  8010.             while (start != strLen && Character.isWhitespace(str.charAt(start))) {
  8011.                 start++;
  8012.             }
  8013.         } else if (stripChars.isEmpty()) {
  8014.             return str;
  8015.         } else {
  8016.             while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
  8017.                 start++;
  8018.             }
  8019.         }
  8020.         return str.substring(start);
  8021.     }

  8022.     /**
  8023.      * Strips whitespace from the start and end of a String  returning
  8024.      * an empty String if {@code null} input.
  8025.      *
  8026.      * <p>This is similar to {@link #trimToEmpty(String)} but removes whitespace.
  8027.      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  8028.      *
  8029.      * <pre>
  8030.      * StringUtils.stripToEmpty(null)     = ""
  8031.      * StringUtils.stripToEmpty("")       = ""
  8032.      * StringUtils.stripToEmpty("   ")    = ""
  8033.      * StringUtils.stripToEmpty("abc")    = "abc"
  8034.      * StringUtils.stripToEmpty("  abc")  = "abc"
  8035.      * StringUtils.stripToEmpty("abc  ")  = "abc"
  8036.      * StringUtils.stripToEmpty(" abc ")  = "abc"
  8037.      * StringUtils.stripToEmpty(" ab c ") = "ab c"
  8038.      * </pre>
  8039.      *
  8040.      * @param str  the String to be stripped, may be null
  8041.      * @return the trimmed String, or an empty String if {@code null} input
  8042.      * @since 2.0
  8043.      */
  8044.     public static String stripToEmpty(final String str) {
  8045.         return str == null ? EMPTY : strip(str, null);
  8046.     }

  8047.     /**
  8048.      * Strips whitespace from the start and end of a String  returning
  8049.      * {@code null} if the String is empty ("") after the strip.
  8050.      *
  8051.      * <p>This is similar to {@link #trimToNull(String)} but removes whitespace.
  8052.      * Whitespace is defined by {@link Character#isWhitespace(char)}.</p>
  8053.      *
  8054.      * <pre>
  8055.      * StringUtils.stripToNull(null)     = null
  8056.      * StringUtils.stripToNull("")       = null
  8057.      * StringUtils.stripToNull("   ")    = null
  8058.      * StringUtils.stripToNull("abc")    = "abc"
  8059.      * StringUtils.stripToNull("  abc")  = "abc"
  8060.      * StringUtils.stripToNull("abc  ")  = "abc"
  8061.      * StringUtils.stripToNull(" abc ")  = "abc"
  8062.      * StringUtils.stripToNull(" ab c ") = "ab c"
  8063.      * </pre>
  8064.      *
  8065.      * @param str  the String to be stripped, may be null
  8066.      * @return the stripped String,
  8067.      *  {@code null} if whitespace, empty or null String input
  8068.      * @since 2.0
  8069.      */
  8070.     public static String stripToNull(String str) {
  8071.         if (str == null) {
  8072.             return null;
  8073.         }
  8074.         str = strip(str, null);
  8075.         return str.isEmpty() ? null : str; // NOSONARLINT str cannot be null here
  8076.     }

  8077.     /**
  8078.      * Gets a substring from the specified String avoiding exceptions.
  8079.      *
  8080.      * <p>A negative start position can be used to start {@code n}
  8081.      * characters from the end of the String.</p>
  8082.      *
  8083.      * <p>A {@code null} String will return {@code null}.
  8084.      * An empty ("") String will return "".</p>
  8085.      *
  8086.      * <pre>
  8087.      * StringUtils.substring(null, *)   = null
  8088.      * StringUtils.substring("", *)     = ""
  8089.      * StringUtils.substring("abc", 0)  = "abc"
  8090.      * StringUtils.substring("abc", 2)  = "c"
  8091.      * StringUtils.substring("abc", 4)  = ""
  8092.      * StringUtils.substring("abc", -2) = "bc"
  8093.      * StringUtils.substring("abc", -4) = "abc"
  8094.      * </pre>
  8095.      *
  8096.      * @param str  the String to get the substring from, may be null
  8097.      * @param start  the position to start from, negative means
  8098.      *  count back from the end of the String by this many characters
  8099.      * @return substring from start position, {@code null} if null String input
  8100.      */
  8101.     public static String substring(final String str, int start) {
  8102.         if (str == null) {
  8103.             return null;
  8104.         }

  8105.         // handle negatives, which means last n characters
  8106.         if (start < 0) {
  8107.             start = str.length() + start; // remember start is negative
  8108.         }

  8109.         if (start < 0) {
  8110.             start = 0;
  8111.         }
  8112.         if (start > str.length()) {
  8113.             return EMPTY;
  8114.         }

  8115.         return str.substring(start);
  8116.     }

  8117.     /**
  8118.      * Gets a substring from the specified String avoiding exceptions.
  8119.      *
  8120.      * <p>A negative start position can be used to start/end {@code n}
  8121.      * characters from the end of the String.</p>
  8122.      *
  8123.      * <p>The returned substring starts with the character in the {@code start}
  8124.      * position and ends before the {@code end} position. All position counting is
  8125.      * zero-based -- i.e., to start at the beginning of the string use
  8126.      * {@code start = 0}. Negative start and end positions can be used to
  8127.      * specify offsets relative to the end of the String.</p>
  8128.      *
  8129.      * <p>If {@code start} is not strictly to the left of {@code end}, ""
  8130.      * is returned.</p>
  8131.      *
  8132.      * <pre>
  8133.      * StringUtils.substring(null, *, *)    = null
  8134.      * StringUtils.substring("", * ,  *)    = "";
  8135.      * StringUtils.substring("abc", 0, 2)   = "ab"
  8136.      * StringUtils.substring("abc", 2, 0)   = ""
  8137.      * StringUtils.substring("abc", 2, 4)   = "c"
  8138.      * StringUtils.substring("abc", 4, 6)   = ""
  8139.      * StringUtils.substring("abc", 2, 2)   = ""
  8140.      * StringUtils.substring("abc", -2, -1) = "b"
  8141.      * StringUtils.substring("abc", -4, 2)  = "ab"
  8142.      * </pre>
  8143.      *
  8144.      * @param str  the String to get the substring from, may be null
  8145.      * @param start  the position to start from, negative means
  8146.      *  count back from the end of the String by this many characters
  8147.      * @param end  the position to end at (exclusive), negative means
  8148.      *  count back from the end of the String by this many characters
  8149.      * @return substring from start position to end position,
  8150.      *  {@code null} if null String input
  8151.      */
  8152.     public static String substring(final String str, int start, int end) {
  8153.         if (str == null) {
  8154.             return null;
  8155.         }

  8156.         // handle negatives
  8157.         if (end < 0) {
  8158.             end = str.length() + end; // remember end is negative
  8159.         }
  8160.         if (start < 0) {
  8161.             start = str.length() + start; // remember start is negative
  8162.         }

  8163.         // check length next
  8164.         if (end > str.length()) {
  8165.             end = str.length();
  8166.         }

  8167.         // if start is greater than end, return ""
  8168.         if (start > end) {
  8169.             return EMPTY;
  8170.         }

  8171.         if (start < 0) {
  8172.             start = 0;
  8173.         }
  8174.         if (end < 0) {
  8175.             end = 0;
  8176.         }

  8177.         return str.substring(start, end);
  8178.     }

  8179.     /**
  8180.      * Gets the substring after the first occurrence of a separator.
  8181.      * The separator is not returned.
  8182.      *
  8183.      * <p>A {@code null} string input will return {@code null}.
  8184.      * An empty ("") string input will return the empty string.
  8185.      *
  8186.      * <p>If nothing is found, the empty string is returned.</p>
  8187.      *
  8188.      * <pre>
  8189.      * StringUtils.substringAfter(null, *)      = null
  8190.      * StringUtils.substringAfter("", *)        = ""
  8191.      * StringUtils.substringAfter("abc", 'a')   = "bc"
  8192.      * StringUtils.substringAfter("abcba", 'b') = "cba"
  8193.      * StringUtils.substringAfter("abc", 'c')   = ""
  8194.      * StringUtils.substringAfter("abc", 'd')   = ""
  8195.      * StringUtils.substringAfter(" abc", 32)   = "abc"
  8196.      * </pre>
  8197.      *
  8198.      * @param str  the String to get a substring from, may be null
  8199.      * @param separator  the character (Unicode code point) to search.
  8200.      * @return the substring after the first occurrence of the separator,
  8201.      *  {@code null} if null String input
  8202.      * @since 3.11
  8203.      */
  8204.     public static String substringAfter(final String str, final int separator) {
  8205.         if (isEmpty(str)) {
  8206.             return str;
  8207.         }
  8208.         final int pos = str.indexOf(separator);
  8209.         if (pos == INDEX_NOT_FOUND) {
  8210.             return EMPTY;
  8211.         }
  8212.         return str.substring(pos + 1);
  8213.     }

  8214.     /**
  8215.      * Gets the substring after the first occurrence of a separator.
  8216.      * The separator is not returned.
  8217.      *
  8218.      * <p>A {@code null} string input will return {@code null}.
  8219.      * An empty ("") string input will return the empty string.
  8220.      * A {@code null} separator will return the empty string if the
  8221.      * input string is not {@code null}.</p>
  8222.      *
  8223.      * <p>If nothing is found, the empty string is returned.</p>
  8224.      *
  8225.      * <pre>
  8226.      * StringUtils.substringAfter(null, *)      = null
  8227.      * StringUtils.substringAfter("", *)        = ""
  8228.      * StringUtils.substringAfter(*, null)      = ""
  8229.      * StringUtils.substringAfter("abc", "a")   = "bc"
  8230.      * StringUtils.substringAfter("abcba", "b") = "cba"
  8231.      * StringUtils.substringAfter("abc", "c")   = ""
  8232.      * StringUtils.substringAfter("abc", "d")   = ""
  8233.      * StringUtils.substringAfter("abc", "")    = "abc"
  8234.      * </pre>
  8235.      *
  8236.      * @param str  the String to get a substring from, may be null
  8237.      * @param separator  the String to search for, may be null
  8238.      * @return the substring after the first occurrence of the separator,
  8239.      *  {@code null} if null String input
  8240.      * @since 2.0
  8241.      */
  8242.     public static String substringAfter(final String str, final String separator) {
  8243.         if (isEmpty(str)) {
  8244.             return str;
  8245.         }
  8246.         if (separator == null) {
  8247.             return EMPTY;
  8248.         }
  8249.         final int pos = str.indexOf(separator);
  8250.         if (pos == INDEX_NOT_FOUND) {
  8251.             return EMPTY;
  8252.         }
  8253.         return str.substring(pos + separator.length());
  8254.     }

  8255.     /**
  8256.      * Gets the substring after the last occurrence of a separator.
  8257.      * The separator is not returned.
  8258.      *
  8259.      * <p>A {@code null} string input will return {@code null}.
  8260.      * An empty ("") string input will return the empty string.
  8261.      *
  8262.      * <p>If nothing is found, the empty string is returned.</p>
  8263.      *
  8264.      * <pre>
  8265.      * StringUtils.substringAfterLast(null, *)      = null
  8266.      * StringUtils.substringAfterLast("", *)        = ""
  8267.      * StringUtils.substringAfterLast("abc", 'a')   = "bc"
  8268.      * StringUtils.substringAfterLast(" bc", 32)    = "bc"
  8269.      * StringUtils.substringAfterLast("abcba", 'b') = "a"
  8270.      * StringUtils.substringAfterLast("abc", 'c')   = ""
  8271.      * StringUtils.substringAfterLast("a", 'a')     = ""
  8272.      * StringUtils.substringAfterLast("a", 'z')     = ""
  8273.      * </pre>
  8274.      *
  8275.      * @param str  the String to get a substring from, may be null
  8276.      * @param separator  the character (Unicode code point) to search.
  8277.      * @return the substring after the last occurrence of the separator,
  8278.      *  {@code null} if null String input
  8279.      * @since 3.11
  8280.      */
  8281.     public static String substringAfterLast(final String str, final int separator) {
  8282.         if (isEmpty(str)) {
  8283.             return str;
  8284.         }
  8285.         final int pos = str.lastIndexOf(separator);
  8286.         if (pos == INDEX_NOT_FOUND || pos == str.length() - 1) {
  8287.             return EMPTY;
  8288.         }
  8289.         return str.substring(pos + 1);
  8290.     }

  8291.     /**
  8292.      * Gets the substring after the last occurrence of a separator.
  8293.      * The separator is not returned.
  8294.      *
  8295.      * <p>A {@code null} string input will return {@code null}.
  8296.      * An empty ("") string input will return the empty string.
  8297.      * An empty or {@code null} separator will return the empty string if
  8298.      * the input string is not {@code null}.</p>
  8299.      *
  8300.      * <p>If nothing is found, the empty string is returned.</p>
  8301.      *
  8302.      * <pre>
  8303.      * StringUtils.substringAfterLast(null, *)      = null
  8304.      * StringUtils.substringAfterLast("", *)        = ""
  8305.      * StringUtils.substringAfterLast(*, "")        = ""
  8306.      * StringUtils.substringAfterLast(*, null)      = ""
  8307.      * StringUtils.substringAfterLast("abc", "a")   = "bc"
  8308.      * StringUtils.substringAfterLast("abcba", "b") = "a"
  8309.      * StringUtils.substringAfterLast("abc", "c")   = ""
  8310.      * StringUtils.substringAfterLast("a", "a")     = ""
  8311.      * StringUtils.substringAfterLast("a", "z")     = ""
  8312.      * </pre>
  8313.      *
  8314.      * @param str  the String to get a substring from, may be null
  8315.      * @param separator  the String to search for, may be null
  8316.      * @return the substring after the last occurrence of the separator,
  8317.      *  {@code null} if null String input
  8318.      * @since 2.0
  8319.      */
  8320.     public static String substringAfterLast(final String str, final String separator) {
  8321.         if (isEmpty(str)) {
  8322.             return str;
  8323.         }
  8324.         if (isEmpty(separator)) {
  8325.             return EMPTY;
  8326.         }
  8327.         final int pos = str.lastIndexOf(separator);
  8328.         if (pos == INDEX_NOT_FOUND || pos == str.length() - separator.length()) {
  8329.             return EMPTY;
  8330.         }
  8331.         return str.substring(pos + separator.length());
  8332.     }

  8333.     /**
  8334.      * Gets the substring before the first occurrence of a separator. The separator is not returned.
  8335.      *
  8336.      * <p>
  8337.      * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string.
  8338.      * </p>
  8339.      *
  8340.      * <p>
  8341.      * If nothing is found, the string input is returned.
  8342.      * </p>
  8343.      *
  8344.      * <pre>
  8345.      * StringUtils.substringBefore(null, *)      = null
  8346.      * StringUtils.substringBefore("", *)        = ""
  8347.      * StringUtils.substringBefore("abc", 'a')   = ""
  8348.      * StringUtils.substringBefore("abcba", 'b') = "a"
  8349.      * StringUtils.substringBefore("abc", 'c')   = "ab"
  8350.      * StringUtils.substringBefore("abc", 'd')   = "abc"
  8351.      * </pre>
  8352.      *
  8353.      * @param str the String to get a substring from, may be null
  8354.      * @param separator the character (Unicode code point) to search.
  8355.      * @return the substring before the first occurrence of the separator, {@code null} if null String input
  8356.      * @since 3.12.0
  8357.      */
  8358.     public static String substringBefore(final String str, final int separator) {
  8359.         if (isEmpty(str)) {
  8360.             return str;
  8361.         }
  8362.         final int pos = str.indexOf(separator);
  8363.         if (pos == INDEX_NOT_FOUND) {
  8364.             return str;
  8365.         }
  8366.         return str.substring(0, pos);
  8367.     }

  8368.     /**
  8369.      * Gets the substring before the first occurrence of a separator.
  8370.      * The separator is not returned.
  8371.      *
  8372.      * <p>A {@code null} string input will return {@code null}.
  8373.      * An empty ("") string input will return the empty string.
  8374.      * A {@code null} separator will return the input string.</p>
  8375.      *
  8376.      * <p>If nothing is found, the string input is returned.</p>
  8377.      *
  8378.      * <pre>
  8379.      * StringUtils.substringBefore(null, *)      = null
  8380.      * StringUtils.substringBefore("", *)        = ""
  8381.      * StringUtils.substringBefore("abc", "a")   = ""
  8382.      * StringUtils.substringBefore("abcba", "b") = "a"
  8383.      * StringUtils.substringBefore("abc", "c")   = "ab"
  8384.      * StringUtils.substringBefore("abc", "d")   = "abc"
  8385.      * StringUtils.substringBefore("abc", "")    = ""
  8386.      * StringUtils.substringBefore("abc", null)  = "abc"
  8387.      * </pre>
  8388.      *
  8389.      * @param str  the String to get a substring from, may be null
  8390.      * @param separator  the String to search for, may be null
  8391.      * @return the substring before the first occurrence of the separator,
  8392.      *  {@code null} if null String input
  8393.      * @since 2.0
  8394.      */
  8395.     public static String substringBefore(final String str, final String separator) {
  8396.         if (isEmpty(str) || separator == null) {
  8397.             return str;
  8398.         }
  8399.         if (separator.isEmpty()) {
  8400.             return EMPTY;
  8401.         }
  8402.         final int pos = str.indexOf(separator);
  8403.         if (pos == INDEX_NOT_FOUND) {
  8404.             return str;
  8405.         }
  8406.         return str.substring(0, pos);
  8407.     }

  8408.     /**
  8409.      * Gets the substring before the last occurrence of a separator.
  8410.      * The separator is not returned.
  8411.      *
  8412.      * <p>A {@code null} string input will return {@code null}.
  8413.      * An empty ("") string input will return the empty string.
  8414.      * An empty or {@code null} separator will return the input string.</p>
  8415.      *
  8416.      * <p>If nothing is found, the string input is returned.</p>
  8417.      *
  8418.      * <pre>
  8419.      * StringUtils.substringBeforeLast(null, *)      = null
  8420.      * StringUtils.substringBeforeLast("", *)        = ""
  8421.      * StringUtils.substringBeforeLast("abcba", "b") = "abc"
  8422.      * StringUtils.substringBeforeLast("abc", "c")   = "ab"
  8423.      * StringUtils.substringBeforeLast("a", "a")     = ""
  8424.      * StringUtils.substringBeforeLast("a", "z")     = "a"
  8425.      * StringUtils.substringBeforeLast("a", null)    = "a"
  8426.      * StringUtils.substringBeforeLast("a", "")      = "a"
  8427.      * </pre>
  8428.      *
  8429.      * @param str  the String to get a substring from, may be null
  8430.      * @param separator  the String to search for, may be null
  8431.      * @return the substring before the last occurrence of the separator,
  8432.      *  {@code null} if null String input
  8433.      * @since 2.0
  8434.      */
  8435.     public static String substringBeforeLast(final String str, final String separator) {
  8436.         if (isEmpty(str) || isEmpty(separator)) {
  8437.             return str;
  8438.         }
  8439.         final int pos = str.lastIndexOf(separator);
  8440.         if (pos == INDEX_NOT_FOUND) {
  8441.             return str;
  8442.         }
  8443.         return str.substring(0, pos);
  8444.     }

  8445.     /**
  8446.      * Gets the String that is nested in between two instances of the
  8447.      * same String.
  8448.      *
  8449.      * <p>A {@code null} input String returns {@code null}.
  8450.      * A {@code null} tag returns {@code null}.</p>
  8451.      *
  8452.      * <pre>
  8453.      * StringUtils.substringBetween(null, *)            = null
  8454.      * StringUtils.substringBetween("", "")             = ""
  8455.      * StringUtils.substringBetween("", "tag")          = null
  8456.      * StringUtils.substringBetween("tagabctag", null)  = null
  8457.      * StringUtils.substringBetween("tagabctag", "")    = ""
  8458.      * StringUtils.substringBetween("tagabctag", "tag") = "abc"
  8459.      * </pre>
  8460.      *
  8461.      * @param str  the String containing the substring, may be null
  8462.      * @param tag  the String before and after the substring, may be null
  8463.      * @return the substring, {@code null} if no match
  8464.      * @since 2.0
  8465.      */
  8466.     public static String substringBetween(final String str, final String tag) {
  8467.         return substringBetween(str, tag, tag);
  8468.     }

  8469.     /**
  8470.      * Gets the String that is nested in between two Strings.
  8471.      * Only the first match is returned.
  8472.      *
  8473.      * <p>A {@code null} input String returns {@code null}.
  8474.      * A {@code null} open/close returns {@code null} (no match).
  8475.      * An empty ("") open and close returns an empty string.</p>
  8476.      *
  8477.      * <pre>
  8478.      * StringUtils.substringBetween("wx[b]yz", "[", "]") = "b"
  8479.      * StringUtils.substringBetween(null, *, *)          = null
  8480.      * StringUtils.substringBetween(*, null, *)          = null
  8481.      * StringUtils.substringBetween(*, *, null)          = null
  8482.      * StringUtils.substringBetween("", "", "")          = ""
  8483.      * StringUtils.substringBetween("", "", "]")         = null
  8484.      * StringUtils.substringBetween("", "[", "]")        = null
  8485.      * StringUtils.substringBetween("yabcz", "", "")     = ""
  8486.      * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
  8487.      * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
  8488.      * </pre>
  8489.      *
  8490.      * @param str  the String containing the substring, may be null
  8491.      * @param open  the String before the substring, may be null
  8492.      * @param close  the String after the substring, may be null
  8493.      * @return the substring, {@code null} if no match
  8494.      * @since 2.0
  8495.      */
  8496.     public static String substringBetween(final String str, final String open, final String close) {
  8497.         if (!ObjectUtils.allNotNull(str, open, close)) {
  8498.             return null;
  8499.         }
  8500.         final int start = str.indexOf(open);
  8501.         if (start != INDEX_NOT_FOUND) {
  8502.             final int end = str.indexOf(close, start + open.length());
  8503.             if (end != INDEX_NOT_FOUND) {
  8504.                 return str.substring(start + open.length(), end);
  8505.             }
  8506.         }
  8507.         return null;
  8508.     }

  8509.     /**
  8510.      * Searches a String for substrings delimited by a start and end tag,
  8511.      * returning all matching substrings in an array.
  8512.      *
  8513.      * <p>A {@code null} input String returns {@code null}.
  8514.      * A {@code null} open/close returns {@code null} (no match).
  8515.      * An empty ("") open/close returns {@code null} (no match).</p>
  8516.      *
  8517.      * <pre>
  8518.      * StringUtils.substringsBetween("[a][b][c]", "[", "]") = ["a","b","c"]
  8519.      * StringUtils.substringsBetween(null, *, *)            = null
  8520.      * StringUtils.substringsBetween(*, null, *)            = null
  8521.      * StringUtils.substringsBetween(*, *, null)            = null
  8522.      * StringUtils.substringsBetween("", "[", "]")          = []
  8523.      * </pre>
  8524.      *
  8525.      * @param str  the String containing the substrings, null returns null, empty returns empty
  8526.      * @param open  the String identifying the start of the substring, empty returns null
  8527.      * @param close  the String identifying the end of the substring, empty returns null
  8528.      * @return a String Array of substrings, or {@code null} if no match
  8529.      * @since 2.3
  8530.      */
  8531.     public static String[] substringsBetween(final String str, final String open, final String close) {
  8532.         if (str == null || isEmpty(open) || isEmpty(close)) {
  8533.             return null;
  8534.         }
  8535.         final int strLen = str.length();
  8536.         if (strLen == 0) {
  8537.             return ArrayUtils.EMPTY_STRING_ARRAY;
  8538.         }
  8539.         final int closeLen = close.length();
  8540.         final int openLen = open.length();
  8541.         final List<String> list = new ArrayList<>();
  8542.         int pos = 0;
  8543.         while (pos < strLen - closeLen) {
  8544.             int start = str.indexOf(open, pos);
  8545.             if (start < 0) {
  8546.                 break;
  8547.             }
  8548.             start += openLen;
  8549.             final int end = str.indexOf(close, start);
  8550.             if (end < 0) {
  8551.                 break;
  8552.             }
  8553.             list.add(str.substring(start, end));
  8554.             pos = end + closeLen;
  8555.         }
  8556.         if (list.isEmpty()) {
  8557.             return null;
  8558.         }
  8559.         return list.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
  8560.     }

  8561.     /**
  8562.      * Swaps the case of a String changing upper and title case to
  8563.      * lower case, and lower case to upper case.
  8564.      *
  8565.      * <ul>
  8566.      *  <li>Upper case character converts to Lower case</li>
  8567.      *  <li>Title case character converts to Lower case</li>
  8568.      *  <li>Lower case character converts to Upper case</li>
  8569.      * </ul>
  8570.      *
  8571.      * <p>For a word based algorithm, see {@link org.apache.commons.text.WordUtils#swapCase(String)}.
  8572.      * A {@code null} input String returns {@code null}.</p>
  8573.      *
  8574.      * <pre>
  8575.      * StringUtils.swapCase(null)                 = null
  8576.      * StringUtils.swapCase("")                   = ""
  8577.      * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
  8578.      * </pre>
  8579.      *
  8580.      * <p>NOTE: This method changed in Lang version 2.0.
  8581.      * It no longer performs a word based algorithm.
  8582.      * If you only use ASCII, you will notice no change.
  8583.      * That functionality is available in org.apache.commons.lang3.text.WordUtils.</p>
  8584.      *
  8585.      * @param str  the String to swap case, may be null
  8586.      * @return the changed String, {@code null} if null String input
  8587.      */
  8588.     public static String swapCase(final String str) {
  8589.         if (isEmpty(str)) {
  8590.             return str;
  8591.         }

  8592.         final int strLen = str.length();
  8593.         final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
  8594.         int outOffset = 0;
  8595.         for (int i = 0; i < strLen; ) {
  8596.             final int oldCodepoint = str.codePointAt(i);
  8597.             final int newCodePoint;
  8598.             if (Character.isUpperCase(oldCodepoint) || Character.isTitleCase(oldCodepoint)) {
  8599.                 newCodePoint = Character.toLowerCase(oldCodepoint);
  8600.             } else if (Character.isLowerCase(oldCodepoint)) {
  8601.                 newCodePoint = Character.toUpperCase(oldCodepoint);
  8602.             } else {
  8603.                 newCodePoint = oldCodepoint;
  8604.             }
  8605.             newCodePoints[outOffset++] = newCodePoint;
  8606.             i += Character.charCount(newCodePoint);
  8607.          }
  8608.         return new String(newCodePoints, 0, outOffset);
  8609.     }

  8610.     /**
  8611.      * Converts a {@link CharSequence} into an array of code points.
  8612.      *
  8613.      * <p>Valid pairs of surrogate code units will be converted into a single supplementary
  8614.      * code point. Isolated surrogate code units (i.e. a high surrogate not followed by a low surrogate or
  8615.      * a low surrogate not preceded by a high surrogate) will be returned as-is.</p>
  8616.      *
  8617.      * <pre>
  8618.      * StringUtils.toCodePoints(null)   =  null
  8619.      * StringUtils.toCodePoints("")     =  []  // empty array
  8620.      * </pre>
  8621.      *
  8622.      * @param cs the character sequence to convert
  8623.      * @return an array of code points
  8624.      * @since 3.6
  8625.      */
  8626.     public static int[] toCodePoints(final CharSequence cs) {
  8627.         if (cs == null) {
  8628.             return null;
  8629.         }
  8630.         if (cs.length() == 0) {
  8631.             return ArrayUtils.EMPTY_INT_ARRAY;
  8632.         }

  8633.         final String s = cs.toString();
  8634.         final int[] result = new int[s.codePointCount(0, s.length())];
  8635.         int index = 0;
  8636.         for (int i = 0; i < result.length; i++) {
  8637.             result[i] = s.codePointAt(index);
  8638.             index += Character.charCount(result[i]);
  8639.         }
  8640.         return result;
  8641.     }

  8642.     /**
  8643.      * Converts a {@code byte[]} to a String using the specified character encoding.
  8644.      *
  8645.      * @param bytes
  8646.      *            the byte array to read from
  8647.      * @param charset
  8648.      *            the encoding to use, if null then use the platform default
  8649.      * @return a new String
  8650.      * @throws NullPointerException
  8651.      *             if {@code bytes} is null
  8652.      * @since 3.2
  8653.      * @since 3.3 No longer throws {@link UnsupportedEncodingException}.
  8654.      */
  8655.     public static String toEncodedString(final byte[] bytes, final Charset charset) {
  8656.         return new String(bytes, Charsets.toCharset(charset));
  8657.     }

  8658.     /**
  8659.      * Converts the given source String as a lower-case using the {@link Locale#ROOT} locale in a null-safe manner.
  8660.      *
  8661.      * @param source A source String or null.
  8662.      * @return the given source String as a lower-case using the {@link Locale#ROOT} locale or null.
  8663.      * @since 3.10
  8664.      */
  8665.     public static String toRootLowerCase(final String source) {
  8666.         return source == null ? null : source.toLowerCase(Locale.ROOT);
  8667.     }

  8668.     /**
  8669.      * Converts the given source String as an upper-case using the {@link Locale#ROOT} locale in a null-safe manner.
  8670.      *
  8671.      * @param source A source String or null.
  8672.      * @return the given source String as an upper-case using the {@link Locale#ROOT} locale or null.
  8673.      * @since 3.10
  8674.      */
  8675.     public static String toRootUpperCase(final String source) {
  8676.         return source == null ? null : source.toUpperCase(Locale.ROOT);
  8677.     }

  8678.     /**
  8679.      * Converts a {@code byte[]} to a String using the specified character encoding.
  8680.      *
  8681.      * @param bytes
  8682.      *            the byte array to read from
  8683.      * @param charsetName
  8684.      *            the encoding to use, if null then use the platform default
  8685.      * @return a new String
  8686.      * @throws NullPointerException
  8687.      *             if the input is null
  8688.      * @deprecated use {@link StringUtils#toEncodedString(byte[], Charset)} instead of String constants in your code
  8689.      * @since 3.1
  8690.      */
  8691.     @Deprecated
  8692.     public static String toString(final byte[] bytes, final String charsetName) {
  8693.         return new String(bytes, Charsets.toCharset(charsetName));
  8694.     }

  8695.     private static String toStringOrEmpty(final Object obj) {
  8696.         return Objects.toString(obj, EMPTY);
  8697.     }

  8698.     /**
  8699.      * Removes control characters (char &lt;= 32) from both
  8700.      * ends of this String, handling {@code null} by returning
  8701.      * {@code null}.
  8702.      *
  8703.      * <p>The String is trimmed using {@link String#trim()}.
  8704.      * Trim removes start and end characters &lt;= 32.
  8705.      * To strip whitespace use {@link #strip(String)}.</p>
  8706.      *
  8707.      * <p>To trim your choice of characters, use the
  8708.      * {@link #strip(String, String)} methods.</p>
  8709.      *
  8710.      * <pre>
  8711.      * StringUtils.trim(null)          = null
  8712.      * StringUtils.trim("")            = ""
  8713.      * StringUtils.trim("     ")       = ""
  8714.      * StringUtils.trim("abc")         = "abc"
  8715.      * StringUtils.trim("    abc    ") = "abc"
  8716.      * </pre>
  8717.      *
  8718.      * @param str  the String to be trimmed, may be null
  8719.      * @return the trimmed string, {@code null} if null String input
  8720.      */
  8721.     public static String trim(final String str) {
  8722.         return str == null ? null : str.trim();
  8723.     }

  8724.     /**
  8725.      * Removes control characters (char &lt;= 32) from both
  8726.      * ends of this String returning an empty String ("") if the String
  8727.      * is empty ("") after the trim or if it is {@code null}.
  8728.      *
  8729.      * <p>The String is trimmed using {@link String#trim()}.
  8730.      * Trim removes start and end characters &lt;= 32.
  8731.      * To strip whitespace use {@link #stripToEmpty(String)}.
  8732.      *
  8733.      * <pre>
  8734.      * StringUtils.trimToEmpty(null)          = ""
  8735.      * StringUtils.trimToEmpty("")            = ""
  8736.      * StringUtils.trimToEmpty("     ")       = ""
  8737.      * StringUtils.trimToEmpty("abc")         = "abc"
  8738.      * StringUtils.trimToEmpty("    abc    ") = "abc"
  8739.      * </pre>
  8740.      *
  8741.      * @param str  the String to be trimmed, may be null
  8742.      * @return the trimmed String, or an empty String if {@code null} input
  8743.      * @since 2.0
  8744.      */
  8745.     public static String trimToEmpty(final String str) {
  8746.         return str == null ? EMPTY : str.trim();
  8747.     }

  8748.     /**
  8749.      * Removes control characters (char &lt;= 32) from both
  8750.      * ends of this String returning {@code null} if the String is
  8751.      * empty ("") after the trim or if it is {@code null}.
  8752.      *
  8753.      * <p>The String is trimmed using {@link String#trim()}.
  8754.      * Trim removes start and end characters &lt;= 32.
  8755.      * To strip whitespace use {@link #stripToNull(String)}.
  8756.      *
  8757.      * <pre>
  8758.      * StringUtils.trimToNull(null)          = null
  8759.      * StringUtils.trimToNull("")            = null
  8760.      * StringUtils.trimToNull("     ")       = null
  8761.      * StringUtils.trimToNull("abc")         = "abc"
  8762.      * StringUtils.trimToNull("    abc    ") = "abc"
  8763.      * </pre>
  8764.      *
  8765.      * @param str  the String to be trimmed, may be null
  8766.      * @return the trimmed String,
  8767.      *  {@code null} if only chars &lt;= 32, empty or null String input
  8768.      * @since 2.0
  8769.      */
  8770.     public static String trimToNull(final String str) {
  8771.         final String ts = trim(str);
  8772.         return isEmpty(ts) ? null : ts;
  8773.     }

  8774.     /**
  8775.      * Truncates a String. This will turn
  8776.      * "Now is the time for all good men" into "Now is the time for".
  8777.      *
  8778.      * <p>Specifically:</p>
  8779.      * <ul>
  8780.      *   <li>If {@code str} is less than {@code maxWidth} characters
  8781.      *       long, return it.</li>
  8782.      *   <li>Else truncate it to {@code substring(str, 0, maxWidth)}.</li>
  8783.      *   <li>If {@code maxWidth} is less than {@code 0}, throw an
  8784.      *       {@link IllegalArgumentException}.</li>
  8785.      *   <li>In no case will it return a String of length greater than
  8786.      *       {@code maxWidth}.</li>
  8787.      * </ul>
  8788.      *
  8789.      * <pre>
  8790.      * StringUtils.truncate(null, 0)       = null
  8791.      * StringUtils.truncate(null, 2)       = null
  8792.      * StringUtils.truncate("", 4)         = ""
  8793.      * StringUtils.truncate("abcdefg", 4)  = "abcd"
  8794.      * StringUtils.truncate("abcdefg", 6)  = "abcdef"
  8795.      * StringUtils.truncate("abcdefg", 7)  = "abcdefg"
  8796.      * StringUtils.truncate("abcdefg", 8)  = "abcdefg"
  8797.      * StringUtils.truncate("abcdefg", -1) = throws an IllegalArgumentException
  8798.      * </pre>
  8799.      *
  8800.      * @param str  the String to truncate, may be null
  8801.      * @param maxWidth  maximum length of result String, must be positive
  8802.      * @return truncated String, {@code null} if null String input
  8803.      * @throws IllegalArgumentException If {@code maxWidth} is less than {@code 0}
  8804.      * @since 3.5
  8805.      */
  8806.     public static String truncate(final String str, final int maxWidth) {
  8807.         return truncate(str, 0, maxWidth);
  8808.     }

  8809.     /**
  8810.      * Truncates a String. This will turn
  8811.      * "Now is the time for all good men" into "is the time for all".
  8812.      *
  8813.      * <p>Works like {@code truncate(String, int)}, but allows you to specify
  8814.      * a "left edge" offset.
  8815.      *
  8816.      * <p>Specifically:</p>
  8817.      * <ul>
  8818.      *   <li>If {@code str} is less than {@code maxWidth} characters
  8819.      *       long, return it.</li>
  8820.      *   <li>Else truncate it to {@code substring(str, offset, maxWidth)}.</li>
  8821.      *   <li>If {@code maxWidth} is less than {@code 0}, throw an
  8822.      *       {@link IllegalArgumentException}.</li>
  8823.      *   <li>If {@code offset} is less than {@code 0}, throw an
  8824.      *       {@link IllegalArgumentException}.</li>
  8825.      *   <li>In no case will it return a String of length greater than
  8826.      *       {@code maxWidth}.</li>
  8827.      * </ul>
  8828.      *
  8829.      * <pre>
  8830.      * StringUtils.truncate(null, 0, 0) = null
  8831.      * StringUtils.truncate(null, 2, 4) = null
  8832.      * StringUtils.truncate("", 0, 10) = ""
  8833.      * StringUtils.truncate("", 2, 10) = ""
  8834.      * StringUtils.truncate("abcdefghij", 0, 3) = "abc"
  8835.      * StringUtils.truncate("abcdefghij", 5, 6) = "fghij"
  8836.      * StringUtils.truncate("raspberry peach", 10, 15) = "peach"
  8837.      * StringUtils.truncate("abcdefghijklmno", 0, 10) = "abcdefghij"
  8838.      * StringUtils.truncate("abcdefghijklmno", -1, 10) = throws an IllegalArgumentException
  8839.      * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, 10) = throws an IllegalArgumentException
  8840.      * StringUtils.truncate("abcdefghijklmno", Integer.MIN_VALUE, Integer.MAX_VALUE) = throws an IllegalArgumentException
  8841.      * StringUtils.truncate("abcdefghijklmno", 0, Integer.MAX_VALUE) = "abcdefghijklmno"
  8842.      * StringUtils.truncate("abcdefghijklmno", 1, 10) = "bcdefghijk"
  8843.      * StringUtils.truncate("abcdefghijklmno", 2, 10) = "cdefghijkl"
  8844.      * StringUtils.truncate("abcdefghijklmno", 3, 10) = "defghijklm"
  8845.      * StringUtils.truncate("abcdefghijklmno", 4, 10) = "efghijklmn"
  8846.      * StringUtils.truncate("abcdefghijklmno", 5, 10) = "fghijklmno"
  8847.      * StringUtils.truncate("abcdefghijklmno", 5, 5) = "fghij"
  8848.      * StringUtils.truncate("abcdefghijklmno", 5, 3) = "fgh"
  8849.      * StringUtils.truncate("abcdefghijklmno", 10, 3) = "klm"
  8850.      * StringUtils.truncate("abcdefghijklmno", 10, Integer.MAX_VALUE) = "klmno"
  8851.      * StringUtils.truncate("abcdefghijklmno", 13, 1) = "n"
  8852.      * StringUtils.truncate("abcdefghijklmno", 13, Integer.MAX_VALUE) = "no"
  8853.      * StringUtils.truncate("abcdefghijklmno", 14, 1) = "o"
  8854.      * StringUtils.truncate("abcdefghijklmno", 14, Integer.MAX_VALUE) = "o"
  8855.      * StringUtils.truncate("abcdefghijklmno", 15, 1) = ""
  8856.      * StringUtils.truncate("abcdefghijklmno", 15, Integer.MAX_VALUE) = ""
  8857.      * StringUtils.truncate("abcdefghijklmno", Integer.MAX_VALUE, Integer.MAX_VALUE) = ""
  8858.      * StringUtils.truncate("abcdefghij", 3, -1) = throws an IllegalArgumentException
  8859.      * StringUtils.truncate("abcdefghij", -2, 4) = throws an IllegalArgumentException
  8860.      * </pre>
  8861.      *
  8862.      * @param str  the String to truncate, may be null
  8863.      * @param offset  left edge of source String
  8864.      * @param maxWidth  maximum length of result String, must be positive
  8865.      * @return truncated String, {@code null} if null String input
  8866.      * @throws IllegalArgumentException If {@code offset} or {@code maxWidth} is less than {@code 0}
  8867.      * @since 3.5
  8868.      */
  8869.     public static String truncate(final String str, final int offset, final int maxWidth) {
  8870.         if (offset < 0) {
  8871.             throw new IllegalArgumentException("offset cannot be negative");
  8872.         }
  8873.         if (maxWidth < 0) {
  8874.             throw new IllegalArgumentException("maxWith cannot be negative");
  8875.         }
  8876.         if (str == null) {
  8877.             return null;
  8878.         }
  8879.         if (offset > str.length()) {
  8880.             return EMPTY;
  8881.         }
  8882.         if (str.length() > maxWidth) {
  8883.             final int ix = Math.min(offset + maxWidth, str.length());
  8884.             return str.substring(offset, ix);
  8885.         }
  8886.         return str.substring(offset);
  8887.     }

  8888.     /**
  8889.      * Uncapitalizes a String, changing the first character to lower case as
  8890.      * per {@link Character#toLowerCase(int)}. No other characters are changed.
  8891.      *
  8892.      * <p>For a word based algorithm, see {@link org.apache.commons.text.WordUtils#uncapitalize(String)}.
  8893.      * A {@code null} input String returns {@code null}.</p>
  8894.      *
  8895.      * <pre>
  8896.      * StringUtils.uncapitalize(null)  = null
  8897.      * StringUtils.uncapitalize("")    = ""
  8898.      * StringUtils.uncapitalize("cat") = "cat"
  8899.      * StringUtils.uncapitalize("Cat") = "cat"
  8900.      * StringUtils.uncapitalize("CAT") = "cAT"
  8901.      * </pre>
  8902.      *
  8903.      * @param str the String to uncapitalize, may be null
  8904.      * @return the uncapitalized String, {@code null} if null String input
  8905.      * @see org.apache.commons.text.WordUtils#uncapitalize(String)
  8906.      * @see #capitalize(String)
  8907.      * @since 2.0
  8908.      */
  8909.     public static String uncapitalize(final String str) {
  8910.         final int strLen = length(str);
  8911.         if (strLen == 0) {
  8912.             return str;
  8913.         }

  8914.         final int firstCodePoint = str.codePointAt(0);
  8915.         final int newCodePoint = Character.toLowerCase(firstCodePoint);
  8916.         if (firstCodePoint == newCodePoint) {
  8917.             // already capitalized
  8918.             return str;
  8919.         }

  8920.         final int[] newCodePoints = new int[strLen]; // cannot be longer than the char array
  8921.         int outOffset = 0;
  8922.         newCodePoints[outOffset++] = newCodePoint; // copy the first code point
  8923.         for (int inOffset = Character.charCount(firstCodePoint); inOffset < strLen; ) {
  8924.             final int codePoint = str.codePointAt(inOffset);
  8925.             newCodePoints[outOffset++] = codePoint; // copy the remaining ones
  8926.             inOffset += Character.charCount(codePoint);
  8927.          }
  8928.         return new String(newCodePoints, 0, outOffset);
  8929.     }

  8930.     /**
  8931.      * Unwraps a given string from a character.
  8932.      *
  8933.      * <pre>
  8934.      * StringUtils.unwrap(null, null)         = null
  8935.      * StringUtils.unwrap(null, '\0')         = null
  8936.      * StringUtils.unwrap(null, '1')          = null
  8937.      * StringUtils.unwrap("a", 'a')           = "a"
  8938.      * StringUtils.unwrap("aa", 'a')           = ""
  8939.      * StringUtils.unwrap("\'abc\'", '\'')    = "abc"
  8940.      * StringUtils.unwrap("AABabcBAA", 'A')   = "ABabcBA"
  8941.      * StringUtils.unwrap("A", '#')           = "A"
  8942.      * StringUtils.unwrap("#A", '#')          = "#A"
  8943.      * StringUtils.unwrap("A#", '#')          = "A#"
  8944.      * </pre>
  8945.      *
  8946.      * @param str
  8947.      *          the String to be unwrapped, can be null
  8948.      * @param wrapChar
  8949.      *          the character used to unwrap
  8950.      * @return unwrapped String or the original string
  8951.      *          if it is not quoted properly with the wrapChar
  8952.      * @since 3.6
  8953.      */
  8954.     public static String unwrap(final String str, final char wrapChar) {
  8955.         if (isEmpty(str) || wrapChar == CharUtils.NUL || str.length() == 1) {
  8956.             return str;
  8957.         }

  8958.         if (str.charAt(0) == wrapChar && str.charAt(str.length() - 1) == wrapChar) {
  8959.             final int startIndex = 0;
  8960.             final int endIndex = str.length() - 1;

  8961.             return str.substring(startIndex + 1, endIndex);
  8962.         }

  8963.         return str;
  8964.     }

  8965.     /**
  8966.      * Unwraps a given string from another string.
  8967.      *
  8968.      * <pre>
  8969.      * StringUtils.unwrap(null, null)         = null
  8970.      * StringUtils.unwrap(null, "")           = null
  8971.      * StringUtils.unwrap(null, "1")          = null
  8972.      * StringUtils.unwrap("a", "a")           = "a"
  8973.      * StringUtils.unwrap("aa", "a")          = ""
  8974.      * StringUtils.unwrap("\'abc\'", "\'")    = "abc"
  8975.      * StringUtils.unwrap("\"abc\"", "\"")    = "abc"
  8976.      * StringUtils.unwrap("AABabcBAA", "AA")  = "BabcB"
  8977.      * StringUtils.unwrap("A", "#")           = "A"
  8978.      * StringUtils.unwrap("#A", "#")          = "#A"
  8979.      * StringUtils.unwrap("A#", "#")          = "A#"
  8980.      * </pre>
  8981.      *
  8982.      * @param str
  8983.      *          the String to be unwrapped, can be null
  8984.      * @param wrapToken
  8985.      *          the String used to unwrap
  8986.      * @return unwrapped String or the original string
  8987.      *          if it is not quoted properly with the wrapToken
  8988.      * @since 3.6
  8989.      */
  8990.     public static String unwrap(final String str, final String wrapToken) {
  8991.         if (isEmpty(str) || isEmpty(wrapToken) || str.length() < 2 * wrapToken.length()) {
  8992.             return str;
  8993.         }

  8994.         if (startsWith(str, wrapToken) && endsWith(str, wrapToken)) {
  8995.             return str.substring(wrapToken.length(), str.lastIndexOf(wrapToken));
  8996.         }

  8997.         return str;
  8998.     }

  8999.     /**
  9000.      * Converts a String to upper case as per {@link String#toUpperCase()}.
  9001.      *
  9002.      * <p>A {@code null} input String returns {@code null}.</p>
  9003.      *
  9004.      * <pre>
  9005.      * StringUtils.upperCase(null)  = null
  9006.      * StringUtils.upperCase("")    = ""
  9007.      * StringUtils.upperCase("aBc") = "ABC"
  9008.      * </pre>
  9009.      *
  9010.      * <p><strong>Note:</strong> As described in the documentation for {@link String#toUpperCase()},
  9011.      * the result of this method is affected by the current locale.
  9012.      * For platform-independent case transformations, the method {@link #upperCase(String, Locale)}
  9013.      * should be used with a specific locale (e.g. {@link Locale#ENGLISH}).</p>
  9014.      *
  9015.      * @param str  the String to upper case, may be null
  9016.      * @return the upper-cased String, {@code null} if null String input
  9017.      */
  9018.     public static String upperCase(final String str) {
  9019.         if (str == null) {
  9020.             return null;
  9021.         }
  9022.         return str.toUpperCase();
  9023.     }

  9024.     /**
  9025.      * Converts a String to upper case as per {@link String#toUpperCase(Locale)}.
  9026.      *
  9027.      * <p>A {@code null} input String returns {@code null}.</p>
  9028.      *
  9029.      * <pre>
  9030.      * StringUtils.upperCase(null, Locale.ENGLISH)  = null
  9031.      * StringUtils.upperCase("", Locale.ENGLISH)    = ""
  9032.      * StringUtils.upperCase("aBc", Locale.ENGLISH) = "ABC"
  9033.      * </pre>
  9034.      *
  9035.      * @param str  the String to upper case, may be null
  9036.      * @param locale  the locale that defines the case transformation rules, must not be null
  9037.      * @return the upper-cased String, {@code null} if null String input
  9038.      * @since 2.5
  9039.      */
  9040.     public static String upperCase(final String str, final Locale locale) {
  9041.         if (str == null) {
  9042.             return null;
  9043.         }
  9044.         return str.toUpperCase(LocaleUtils.toLocale(locale));
  9045.     }

  9046.     /**
  9047.      * Returns the string representation of the {@code char} array or null.
  9048.      *
  9049.      * @param value the character array.
  9050.      * @return a String or null
  9051.      * @see String#valueOf(char[])
  9052.      * @since 3.9
  9053.      */
  9054.     public static String valueOf(final char[] value) {
  9055.         return value == null ? null : String.valueOf(value);
  9056.     }

  9057.     /**
  9058.      * Wraps a string with a char.
  9059.      *
  9060.      * <pre>
  9061.      * StringUtils.wrap(null, *)        = null
  9062.      * StringUtils.wrap("", *)          = ""
  9063.      * StringUtils.wrap("ab", '\0')     = "ab"
  9064.      * StringUtils.wrap("ab", 'x')      = "xabx"
  9065.      * StringUtils.wrap("ab", '\'')     = "'ab'"
  9066.      * StringUtils.wrap("\"ab\"", '\"') = "\"\"ab\"\""
  9067.      * </pre>
  9068.      *
  9069.      * @param str
  9070.      *            the string to be wrapped, may be {@code null}
  9071.      * @param wrapWith
  9072.      *            the char that will wrap {@code str}
  9073.      * @return the wrapped string, or {@code null} if {@code str == null}
  9074.      * @since 3.4
  9075.      */
  9076.     public static String wrap(final String str, final char wrapWith) {

  9077.         if (isEmpty(str) || wrapWith == CharUtils.NUL) {
  9078.             return str;
  9079.         }

  9080.         return wrapWith + str + wrapWith;
  9081.     }

  9082.     /**
  9083.      * Wraps a String with another String.
  9084.      *
  9085.      * <p>
  9086.      * A {@code null} input String returns {@code null}.
  9087.      * </p>
  9088.      *
  9089.      * <pre>
  9090.      * StringUtils.wrap(null, *)         = null
  9091.      * StringUtils.wrap("", *)           = ""
  9092.      * StringUtils.wrap("ab", null)      = "ab"
  9093.      * StringUtils.wrap("ab", "x")       = "xabx"
  9094.      * StringUtils.wrap("ab", "\"")      = "\"ab\""
  9095.      * StringUtils.wrap("\"ab\"", "\"")  = "\"\"ab\"\""
  9096.      * StringUtils.wrap("ab", "'")       = "'ab'"
  9097.      * StringUtils.wrap("'abcd'", "'")   = "''abcd''"
  9098.      * StringUtils.wrap("\"abcd\"", "'") = "'\"abcd\"'"
  9099.      * StringUtils.wrap("'abcd'", "\"")  = "\"'abcd'\""
  9100.      * </pre>
  9101.      *
  9102.      * @param str
  9103.      *            the String to be wrapper, may be null
  9104.      * @param wrapWith
  9105.      *            the String that will wrap str
  9106.      * @return wrapped String, {@code null} if null String input
  9107.      * @since 3.4
  9108.      */
  9109.     public static String wrap(final String str, final String wrapWith) {

  9110.         if (isEmpty(str) || isEmpty(wrapWith)) {
  9111.             return str;
  9112.         }

  9113.         return wrapWith.concat(str).concat(wrapWith);
  9114.     }

  9115.     /**
  9116.      * Wraps a string with a char if that char is missing from the start or end of the given string.
  9117.      *
  9118.      * <p>A new {@link String} will not be created if {@code str} is already wrapped.</p>
  9119.      *
  9120.      * <pre>
  9121.      * StringUtils.wrapIfMissing(null, *)        = null
  9122.      * StringUtils.wrapIfMissing("", *)          = ""
  9123.      * StringUtils.wrapIfMissing("ab", '\0')     = "ab"
  9124.      * StringUtils.wrapIfMissing("ab", 'x')      = "xabx"
  9125.      * StringUtils.wrapIfMissing("ab", '\'')     = "'ab'"
  9126.      * StringUtils.wrapIfMissing("\"ab\"", '\"') = "\"ab\""
  9127.      * StringUtils.wrapIfMissing("/", '/')  = "/"
  9128.      * StringUtils.wrapIfMissing("a/b/c", '/')  = "/a/b/c/"
  9129.      * StringUtils.wrapIfMissing("/a/b/c", '/')  = "/a/b/c/"
  9130.      * StringUtils.wrapIfMissing("a/b/c/", '/')  = "/a/b/c/"
  9131.      * </pre>
  9132.      *
  9133.      * @param str
  9134.      *            the string to be wrapped, may be {@code null}
  9135.      * @param wrapWith
  9136.      *            the char that will wrap {@code str}
  9137.      * @return the wrapped string, or {@code null} if {@code str == null}
  9138.      * @since 3.5
  9139.      */
  9140.     public static String wrapIfMissing(final String str, final char wrapWith) {
  9141.         if (isEmpty(str) || wrapWith == CharUtils.NUL) {
  9142.             return str;
  9143.         }
  9144.         final boolean wrapStart = str.charAt(0) != wrapWith;
  9145.         final boolean wrapEnd = str.charAt(str.length() - 1) != wrapWith;
  9146.         if (!wrapStart && !wrapEnd) {
  9147.             return str;
  9148.         }

  9149.         final StringBuilder builder = new StringBuilder(str.length() + 2);
  9150.         if (wrapStart) {
  9151.             builder.append(wrapWith);
  9152.         }
  9153.         builder.append(str);
  9154.         if (wrapEnd) {
  9155.             builder.append(wrapWith);
  9156.         }
  9157.         return builder.toString();
  9158.     }

  9159.     /**
  9160.      * Wraps a string with a string if that string is missing from the start or end of the given string.
  9161.      *
  9162.      * <p>A new {@link String} will not be created if {@code str} is already wrapped.</p>
  9163.      *
  9164.      * <pre>
  9165.      * StringUtils.wrapIfMissing(null, *)         = null
  9166.      * StringUtils.wrapIfMissing("", *)           = ""
  9167.      * StringUtils.wrapIfMissing("ab", null)      = "ab"
  9168.      * StringUtils.wrapIfMissing("ab", "x")       = "xabx"
  9169.      * StringUtils.wrapIfMissing("ab", "\"")      = "\"ab\""
  9170.      * StringUtils.wrapIfMissing("\"ab\"", "\"")  = "\"ab\""
  9171.      * StringUtils.wrapIfMissing("ab", "'")       = "'ab'"
  9172.      * StringUtils.wrapIfMissing("'abcd'", "'")   = "'abcd'"
  9173.      * StringUtils.wrapIfMissing("\"abcd\"", "'") = "'\"abcd\"'"
  9174.      * StringUtils.wrapIfMissing("'abcd'", "\"")  = "\"'abcd'\""
  9175.      * StringUtils.wrapIfMissing("/", "/")  = "/"
  9176.      * StringUtils.wrapIfMissing("a/b/c", "/")  = "/a/b/c/"
  9177.      * StringUtils.wrapIfMissing("/a/b/c", "/")  = "/a/b/c/"
  9178.      * StringUtils.wrapIfMissing("a/b/c/", "/")  = "/a/b/c/"
  9179.      * </pre>
  9180.      *
  9181.      * @param str
  9182.      *            the string to be wrapped, may be {@code null}
  9183.      * @param wrapWith
  9184.      *            the string that will wrap {@code str}
  9185.      * @return the wrapped string, or {@code null} if {@code str == null}
  9186.      * @since 3.5
  9187.      */
  9188.     public static String wrapIfMissing(final String str, final String wrapWith) {
  9189.         if (isEmpty(str) || isEmpty(wrapWith)) {
  9190.             return str;
  9191.         }

  9192.         final boolean wrapStart = !str.startsWith(wrapWith);
  9193.         final boolean wrapEnd = !str.endsWith(wrapWith);
  9194.         if (!wrapStart && !wrapEnd) {
  9195.             return str;
  9196.         }

  9197.         final StringBuilder builder = new StringBuilder(str.length() + wrapWith.length() + wrapWith.length());
  9198.         if (wrapStart) {
  9199.             builder.append(wrapWith);
  9200.         }
  9201.         builder.append(str);
  9202.         if (wrapEnd) {
  9203.             builder.append(wrapWith);
  9204.         }
  9205.         return builder.toString();
  9206.     }

  9207.     /**
  9208.      * {@link StringUtils} instances should NOT be constructed in
  9209.      * standard programming. Instead, the class should be used as
  9210.      * {@code StringUtils.trim(" foo ");}.
  9211.      *
  9212.      * <p>This constructor is public to permit tools that require a JavaBean
  9213.      * instance to operate.</p>
  9214.      *
  9215.      * @deprecated TODO Make private in 4.0.
  9216.      */
  9217.     @Deprecated
  9218.     public StringUtils() {
  9219.         // empty
  9220.     }

  9221. }