## lang/src/main/java/org/apache/commons/lang3/StringUtils.java:7562-7620
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:     /**
7597:      * Performs the logic for the {@code split} and {@code splitPreserveAllTokens} methods that return a maximum array length.
7598:      *
7599:      * @param str               the String to parse, may be {@code null}.
7600:      * @param separatorChars    the separate character.
7601:      * @param max               the maximum number of elements to include in the array. A zero or negative value implies no limit.
7602:      * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty token separators; if {@code false}, adjacent separators are treated as
7603:      *                          one separator.
7604:      * @return an array of parsed Strings, {@code null} if null String input.
7605:      */
7606:     private static String[] splitWorker(final String str, final String separatorChars, final int max, final boolean preserveAllTokens) {
7607:         // Performance tuned for 2.0 (JDK1.4)
7608:         // Direct code is quicker than StringTokenizer.
7609:         // Also, StringTokenizer uses isSpace() not isWhitespace()
7610:         if (str == null) {
7611:             return null;
7612:         }
7613:         final int len = str.length();
7614:         if (len == 0) {
7615:             return ArrayUtils.EMPTY_STRING_ARRAY;
7616:         }
7617:         final List<String> list = new ArrayList<>();
7618:         int sizePlus1 = 1;
7619:         int i = 0;
7620:         int start = 0;

## lang/src/main/java/org/apache/commons/lang3/StringUtils.java:7998-8017
7998:     public static String stripStart(final String str, final String stripChars) {
7999:         final int strLen = length(str);
8000:         if (strLen == 0) {
8001:             return str;
8002:         }
8003:         int start = 0;
8004:         if (stripChars == null) {
8005:             while (start != strLen && Character.isWhitespace(str.charAt(start))) {
8006:                 start++;
8007:             }
8008:         } else if (stripChars.isEmpty()) {
8009:             return str;
8010:         } else {
8011:             while (start != strLen && stripChars.indexOf(str.charAt(start)) != INDEX_NOT_FOUND) {
8012:                 start++;
8013:             }
8014:         }
8015:         return str.substring(start);
8016:     }
8017: 

## lang/src/main/java/org/apache/commons/lang3/StringUtils.java:8099-8185
8099:     public static String substring(final String str, int start) {
8100:         if (str == null) {
8101:             return null;
8102:         }
8103:         // handle negatives, which means last n characters
8104:         if (start < 0) {
8105:             start = str.length() + start; // remember start is negative
8106:         }
8107:         if (start < 0) {
8108:             start = 0;
8109:         }
8110:         if (start > str.length()) {
8111:             return EMPTY;
8112:         }
8113:         return str.substring(start);
8114:     }
8115: 
8116:     /**
8117:      * Gets a substring from the specified String avoiding exceptions.
8118:      *
8119:      * <p>
8120:      * A negative start position can be used to start/end {@code n} characters from the end of the String.
8121:      * </p>
8122:      *
8123:      * <p>
8124:      * The returned substring starts with the character in the {@code start} 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 {@code start = 0}. Negative start and end positions can be used to specify offsets
8126:      * relative to the end of the String.
8127:      * </p>
8128:      *
8129:      * <p>
8130:      * If {@code start} is not strictly to the left of {@code end}, "" is returned.
8131:      * </p>
8132:      *
8133:      * <pre>
8134:      * StringUtils.substring(null, *, *)    = null
8135:      * StringUtils.substring("", * ,  *)    = "";
8136:      * StringUtils.substring("abc", 0, 2)   = "ab"
8137:      * StringUtils.substring("abc", 2, 0)   = ""
8138:      * StringUtils.substring("abc", 2, 4)   = "c"
8139:      * StringUtils.substring("abc", 4, 6)   = ""
8140:      * StringUtils.substring("abc", 2, 2)   = ""
8141:      * StringUtils.substring("abc", -2, -1) = "b"
8142:      * StringUtils.substring("abc", -4, 2)  = "ab"
8143:      * </pre>
8144:      *
8145:      * @param str   the String to get the substring from, may be null.
8146:      * @param start the position to start from, negative means count back from the end of the String by this many characters.
8147:      * @param end   the position to end at (exclusive), negative means count back from the end of the String by this many characters.
8148:      * @return substring from start position to end position, {@code null} if null String input.
8149:      */
8150:     public static String substring(final String str, int start, int end) {
8151:         if (str == null) {
8152:             return null;
8153:         }
8154:         // handle negatives
8155:         if (end < 0) {
8156:             end = str.length() + end; // remember end is negative
8157:         }
8158:         if (start < 0) {
8159:             start = str.length() + start; // remember start is negative
8160:         }
8161:         // check length next
8162:         if (end > str.length()) {
8163:             end = str.length();
8164:         }
8165:         // if start is greater than end, return ""
8166:         if (start > end) {
8167:             return EMPTY;
8168:         }
8169:         if (start < 0) {
8170:             start = 0;
8171:         }
8172:         if (end < 0) {
8173:             end = 0;
8174:         }
8175:         return str.substring(start, end);
8176:     }
8177: 
8178:     /**
8179:      * Gets the substring after the first occurrence of a separator. The separator is not returned.
8180:      *
8181:      * <p>
8182:      * A {@code null} string input will return {@code null}. An empty ("") string input will return the empty string.
8183:      *
8184:      * <p>
8185:      * If nothing is found, the empty string is returned.

## lang/src/test/java/org/apache/commons/lang3/StringUtilsTrimStripTest.java:180-215
180:     void testStripString() {
181:         assertNull(StringUtils.strip(null));
182:         assertEquals("", StringUtils.strip(""));
183:         assertEquals("", StringUtils.strip("        "));
184:         assertEquals("abc", StringUtils.strip("  abc  "));
185:         assertEquals(StringUtilsTest.NON_WHITESPACE,
186:                 StringUtils.strip(StringUtilsTest.WHITESPACE + StringUtilsTest.NON_WHITESPACE + StringUtilsTest.WHITESPACE));
187:     }
188: 
189:     @Test
190:     void testStripStringString() {
191:         // null strip
192:         assertNull(StringUtils.strip(null, null));
193:         assertEquals("", StringUtils.strip("", null));
194:         assertEquals("", StringUtils.strip("        ", null));
195:         assertEquals("abc", StringUtils.strip("  abc  ", null));
196:         assertEquals(StringUtilsTest.NON_WHITESPACE,
197:                 StringUtils.strip(StringUtilsTest.WHITESPACE + StringUtilsTest.NON_WHITESPACE + StringUtilsTest.WHITESPACE, null));
198: 
199:         // "" strip
200:         assertNull(StringUtils.strip(null, ""));
201:         assertEquals("", StringUtils.strip("", ""));
202:         assertEquals("        ", StringUtils.strip("        ", ""));
203:         assertEquals("  abc  ", StringUtils.strip("  abc  ", ""));
204:         assertEquals(StringUtilsTest.WHITESPACE, StringUtils.strip(StringUtilsTest.WHITESPACE, ""));
205: 
206:         // " " strip
207:         assertNull(StringUtils.strip(null, " "));
208:         assertEquals("", StringUtils.strip("", " "));
209:         assertEquals("", StringUtils.strip("        ", " "));
210:         assertEquals("abc", StringUtils.strip("  abc  ", " "));
211: 
212:         // "ab" strip
213:         assertNull(StringUtils.strip(null, "ab"));
214:         assertEquals("", StringUtils.strip("", "ab"));
215:         assertEquals("        ", StringUtils.strip("        ", "ab"));
