1 /*******************************************************************************
2 * Copyright (c) 2000, 2004 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Common Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/cpl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11 package org.eclipse.jdt.core.compiler;
14 * This class is a collection of helper methods to manipulate char arrays.
18 public final class CharOperation {
21 * Constant for an empty char array
23 public static final char[] NO_CHAR = new char[0];
26 * Constant for an empty char array with two dimensions.
28 public static final char[][] NO_CHAR_CHAR = new char[0][];
31 * Constant for an empty String array.
34 public static final String[] NO_STRINGS = new String[0];
37 * Answers a new array with appending the suffix character at the end of the array.
43 * array = { 'a', 'b' }
45 * => result = { 'a', 'b' , 'c' }
55 * @param array the array that is concanated with the suffix character
56 * @param suffix the suffix character
57 * @return the new array
59 public static final char[] append(char[] array, char suffix) {
61 return new char[] { suffix };
62 int length = array.length;
63 System.arraycopy(array, 0, array = new char[length + 1], 0, length);
64 array[length] = suffix;
68 * Append the given subarray to the target array starting at the given index in the target array.
69 * The start of the subarray is inclusive, the end is exclusive.
70 * Answers a new target array if it needs to grow, otherwise answers the same target array.
75 * target = { 'a', 'b', '0' }
77 * array = { 'c', 'd' }
80 * => result = { 'a', 'b' , 'c' }
84 * target = { 'a', 'b' }
86 * array = { 'c', 'd' }
89 * => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
92 * target = { 'a', 'b', 'c' }
94 * array = { 'c', 'd', 'e', 'f' }
97 * => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
101 * @param target the given target
102 * @param index the given index
103 * @param array the given array
104 * @param start the given start index
105 * @param end the given end index
107 * @return the new array
108 * @throws NullPointerException if the target array is null
110 public static final char[] append(char[] target, int index, char[] array, int start, int end) {
111 int targetLength = target.length;
112 int subLength = end-start;
113 int newTargetLength = subLength+index;
114 if (newTargetLength > targetLength) {
115 System.arraycopy(target, 0, target = new char[newTargetLength*2], 0, index);
117 System.arraycopy(array, start, target, index, subLength);
122 * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
123 * If the first array is null, then the second array is returned.
124 * If the second array is null, then the first array is returned.
136 * first = { { ' a' } }
138 * => result = { { ' a' } }
143 * second = { { ' a' } }
144 * => result = { { ' a' } }
148 * first = { { ' b' } }
149 * second = { { ' a' } }
150 * => result = { { ' b' }, { ' a' } }
155 * @param first the first array to concatenate
156 * @param second the second array to concatenate
157 * @return the concatenation of the two arrays, or null if the two arrays are null.
159 public static final char[][] arrayConcat(char[][] first, char[][] second) {
165 int length1 = first.length;
166 int length2 = second.length;
167 char[][] result = new char[length1 + length2][];
168 System.arraycopy(first, 0, result, 0, length1);
169 System.arraycopy(second, 0, result, length1, length2);
173 * Returns the char arrays as an array of Strings
175 * @param charArrays the char array to convert
176 * @return the char arrays as an array of Strings or null if the given char arrays is null.
179 public static String[] charArrayToStringArray(char[][] charArrays) {
180 if (charArrays == null)
182 int length = charArrays.length;
185 String[] strings= new String[length];
186 for (int i= 0; i < length; i++)
187 strings[i]= new String(charArrays[i]);
191 * Returns the char array as a String
193 * @param charArray the char array to convert
194 * @return the char array as a String or null if the given char array is null.
197 public static String charToString(char[] charArray) {
198 if (charArray == null) return null;
199 return new String(charArray);
203 * Answers a new array adding the second array at the end of first array.
204 * It answers null if the first and second are null.
205 * If the first array is null, then a new array char[][] is created with second.
206 * If the second array is null, then the first array is returned.
214 * => result = { { ' a' } }
217 * first = { { ' a' } }
219 * => result = { { ' a' } }
223 * first = { { ' a' } }
225 * => result = { { ' a' } , { ' b' } }
230 * @param first the first array to concatenate
231 * @param second the array to add at the end of the first array
232 * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
234 public static final char[][] arrayConcat(char[][] first, char[] second) {
238 return new char[][] { second };
240 int length = first.length;
241 char[][] result = new char[length + 1][];
242 System.arraycopy(first, 0, result, 0, length);
243 result[length] = second;
248 * Compares the contents of the two arrays array and prefix. Returns
250 * <li>zero if the array starts with the prefix contents</li>
251 * <li>the difference between the first two characters that are not equal </li>
252 * <li>one if array length is lower than the prefix length and that the prefix starts with the
253 * array contents.</li>
261 * => result = NullPointerException
265 * array = { 'a', 'b', 'c', 'd', 'e' }
266 * prefix = { 'a', 'b', 'c'}
271 * array = { 'a', 'b', 'c', 'd', 'e' }
272 * prefix = { 'a', 'B', 'c'}
277 * array = { 'd', 'b', 'c', 'd', 'e' }
278 * prefix = { 'a', 'b', 'c'}
283 * array = { 'a', 'b', 'c', 'd', 'e' }
284 * prefix = { 'd', 'b', 'c'}
289 * array = { 'a', 'a', 'c', 'd', 'e' }
290 * prefix = { 'a', 'e', 'c'}
297 * @param array the given array
298 * @param prefix the given prefix
299 * @return the result of the comparison (>=0 if array>prefix)
300 * @throws NullPointerException if either array or prefix is null
302 public static final int compareWith(char[] array, char[] prefix) {
303 int arrayLength = array.length;
304 int prefixLength = prefix.length;
305 int min = Math.min(arrayLength, prefixLength);
309 char c2 = prefix[i++];
313 if (prefixLength == i)
315 return -1; // array is shorter than prefix (e.g. array:'ab' < prefix:'abc').
319 * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
320 * If the first array is null, then the second array is returned.
321 * If the second array is null, then the first array is returned.
329 * => result = { ' a' }
335 * => result = { ' a' }
341 * => result = { ' a' , ' b' }
346 * @param first the first array to concatenate
347 * @param second the second array to concatenate
348 * @return the concatenation of the two arrays, or null if the two arrays are null.
350 public static final char[] concat(char[] first, char[] second) {
356 int length1 = first.length;
357 int length2 = second.length;
358 char[] result = new char[length1 + length2];
359 System.arraycopy(first, 0, result, 0, length1);
360 System.arraycopy(second, 0, result, length1, length2);
365 * Answers the concatenation of the three arrays. It answers null if the three arrays are null.
366 * If first is null, it answers the concatenation of second and third.
367 * If second is null, it answers the concatenation of first and third.
368 * If third is null, it answers the concatenation of first and second.
377 * => result = { ' a', 'b' }
384 * => result = { ' a', 'b' }
391 * => result = { ' a', 'b' }
405 * => result = { 'a', 'b', 'c' }
410 * @param first the first array to concatenate
411 * @param second the second array to concatenate
412 * @param third the third array to concatenate
414 * @return the concatenation of the three arrays, or null if the three arrays are null.
416 public static final char[] concat(
421 return concat(second, third);
423 return concat(first, third);
425 return concat(first, second);
427 int length1 = first.length;
428 int length2 = second.length;
429 int length3 = third.length;
430 char[] result = new char[length1 + length2 + length3];
431 System.arraycopy(first, 0, result, 0, length1);
432 System.arraycopy(second, 0, result, length1, length2);
433 System.arraycopy(third, 0, result, length1 + length2, length3);
438 * Answers the concatenation of the two arrays inserting the separator character between the two arrays.
439 * It answers null if the two arrays are null.
440 * If the first array is null, then the second array is returned.
441 * If the second array is null, then the first array is returned.
450 * => result = { ' a' }
457 * => result = { ' a' }
464 * => result = { ' a' , '/', 'b' }
469 * @param first the first array to concatenate
470 * @param second the second array to concatenate
471 * @param separator the character to insert
472 * @return the concatenation of the two arrays inserting the separator character
473 * between the two arrays , or null if the two arrays are null.
475 public static final char[] concat(
484 int length1 = first.length;
487 int length2 = second.length;
491 char[] result = new char[length1 + length2 + 1];
492 System.arraycopy(first, 0, result, 0, length1);
493 result[length1] = separator;
494 System.arraycopy(second, 0, result, length1 + 1, length2);
499 * Answers the concatenation of the three arrays inserting the sep1 character between the
500 * first two arrays and sep2 between the last two.
501 * It answers null if the three arrays are null.
502 * If the first array is null, then it answers the concatenation of second and third inserting
503 * the sep2 character between them.
504 * If the second array is null, then it answers the concatenation of first and third inserting
505 * the sep1 character between them.
506 * If the third array is null, then it answers the concatenation of first and second inserting
507 * the sep1 character between them.
518 * => result = { ' a' , ':', 'b' }
527 * => result = { ' a' , '/', 'b' }
536 * => result = { ' a' , '/', 'b' }
545 * => result = { ' a' , '/', 'b' , ':', 'c' }
550 * @param first the first array to concatenate
551 * @param sep1 the character to insert
552 * @param second the second array to concatenate
553 * @param sep2 the character to insert
554 * @param third the second array to concatenate
555 * @return the concatenation of the three arrays inserting the sep1 character between the
556 * two arrays and sep2 between the last two.
558 public static final char[] concat(
565 return concat(second, third, sep2);
567 return concat(first, third, sep1);
569 return concat(first, second, sep1);
571 int length1 = first.length;
572 int length2 = second.length;
573 int length3 = third.length;
574 char[] result = new char[length1 + length2 + length3 + 2];
575 System.arraycopy(first, 0, result, 0, length1);
576 result[length1] = sep1;
577 System.arraycopy(second, 0, result, length1 + 1, length2);
578 result[length1 + length2 + 1] = sep2;
579 System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
584 * Answers a new array with prepending the prefix character and appending the suffix
585 * character at the end of the array. If array is null, it answers a new array containing the
586 * prefix and the suffix characters.
595 * => result = { 'a', 'b' , 'c' }
602 * => result = { 'a', 'c' }
606 * @param prefix the prefix character
607 * @param array the array that is concanated with the prefix and suffix characters
608 * @param suffix the suffix character
609 * @return the new array
611 public static final char[] concat(char prefix, char[] array, char suffix) {
613 return new char[] { prefix, suffix };
615 int length = array.length;
616 char[] result = new char[length + 2];
618 System.arraycopy(array, 0, result, 1, length);
619 result[length + 1] = suffix;
624 * Answers the concatenation of the given array parts using the given separator between each
625 * part and appending the given name at the end.
632 * array = { { 'a' }, { 'b' } }
634 * => result = { 'a', '.', 'b' , '.', 'c' }
639 * array = { { 'a' }, { 'b' } }
641 * => result = { 'a', '.', 'b' }
647 * => result = { 'c' }
651 * @param name the given name
652 * @param array the given array
653 * @param separator the given separator
654 * @return the concatenation of the given array parts using the given separator between each
655 * part and appending the given name at the end
657 public static final char[] concatWith(
661 int nameLength = name == null ? 0 : name.length;
663 return concatWith(array, separator);
665 int length = array == null ? 0 : array.length;
669 int size = nameLength;
672 if (array[index].length > 0)
673 size += array[index].length + 1;
674 char[] result = new char[size];
676 for (int i = length - 1; i >= 0; i--) {
677 int subLength = array[i].length;
680 System.arraycopy(array[i], 0, result, index, subLength);
681 result[--index] = separator;
684 System.arraycopy(name, 0, result, 0, nameLength);
689 * Answers the concatenation of the given array parts using the given separator between each
690 * part and appending the given name at the end.
697 * array = { { 'a' }, { 'b' } }
699 * => result = { 'a', '.', 'b' , '.', 'c' }
704 * array = { { 'a' }, { 'b' } }
706 * => result = { 'a', '.', 'b' }
712 * => result = { 'c' }
716 * @param array the given array
717 * @param name the given name
718 * @param separator the given separator
719 * @return the concatenation of the given array parts using the given separator between each
720 * part and appending the given name at the end
722 public static final char[] concatWith(
726 int nameLength = name == null ? 0 : name.length;
728 return concatWith(array, separator);
730 int length = array == null ? 0 : array.length;
734 int size = nameLength;
737 if (array[index].length > 0)
738 size += array[index].length + 1;
739 char[] result = new char[size];
741 for (int i = 0; i < length; i++) {
742 int subLength = array[i].length;
744 System.arraycopy(array[i], 0, result, index, subLength);
746 result[index++] = separator;
749 System.arraycopy(name, 0, result, index, nameLength);
754 * Answers the concatenation of the given array parts using the given separator between each part.
760 * array = { { 'a' }, { 'b' } }
762 * => result = { 'a', '.', 'b' }
772 * @param array the given array
773 * @param separator the given separator
774 * @return the concatenation of the given array parts using the given separator between each part
776 public static final char[] concatWith(char[][] array, char separator) {
777 int length = array == null ? 0 : array.length;
779 return CharOperation.NO_CHAR;
781 int size = length - 1;
783 while (--index >= 0) {
784 if (array[index].length == 0)
787 size += array[index].length;
790 return CharOperation.NO_CHAR;
791 char[] result = new char[size];
793 while (--index >= 0) {
794 length = array[index].length;
803 result[size] = separator;
810 * Answers true if the array contains an occurrence of character, false otherwise.
818 * array = { { ' a' }, { ' b' } }
824 * array = { { ' a' }, { ' b' } }
830 * @param character the character to search
831 * @param array the array in which the search is done
832 * @return true if the array contains an occurrence of character, false otherwise.
833 * @throws NullPointerException if array is null.
835 public static final boolean contains(char character, char[][] array) {
836 for (int i = array.length; --i >= 0;) {
837 char[] subarray = array[i];
838 for (int j = subarray.length; --j >= 0;)
839 if (subarray[j] == character)
846 * Answers true if the array contains an occurrence of character, false otherwise.
860 * array = { ' a' , ' b' }
866 * @param character the character to search
867 * @param array the array in which the search is done
868 * @return true if the array contains an occurrence of character, false otherwise.
869 * @throws NullPointerException if array is null.
871 public static final boolean contains(char character, char[] array) {
872 for (int i = array.length; --i >= 0;)
873 if (array[i] == character)
879 * Answers true if the array contains an occurrence of one of the characters, false otherwise.
886 * characters = { 'c', 'd' }
887 * array = { 'a', ' b' }
892 * characters = { 'c', 'd' }
893 * array = { 'a', ' b', 'c' }
899 * @param characters the characters to search
900 * @param array the array in which the search is done
901 * @return true if the array contains an occurrence of one of the characters, false otherwise.
902 * @throws NullPointerException if array is null.
904 public static final boolean contains(char[] characters, char[] array) {
905 for (int i = array.length; --i >= 0;)
906 for (int j = characters.length; --j >= 0;)
907 if (array[i] == characters[j])
913 * Answers a deep copy of the toCopy array.
915 * @param toCopy the array to copy
916 * @return a deep copy of the toCopy array.
918 public static final char[][] deepCopy(char[][] toCopy) {
919 int toCopyLength = toCopy.length;
920 char[][] result = new char[toCopyLength][];
921 for (int i = 0; i < toCopyLength; i++) {
922 char[] toElement = toCopy[i];
923 int toElementLength = toElement.length;
924 char[] resultElement = new char[toElementLength];
925 System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
926 result[i] = resultElement;
932 * Return true if array ends with the sequence of characters contained in toBeFound,
939 * array = { 'a', 'b', 'c', 'd' }
940 * toBeFound = { 'b', 'c' }
945 * array = { 'a', 'b', 'c' }
946 * toBeFound = { 'b', 'c' }
952 * @param array the array to check
953 * @param toBeFound the array to find
954 * @return true if array ends with the sequence of characters contained in toBeFound,
956 * @throws NullPointerException if array is null or toBeFound is null
958 public static final boolean endsWith(char[] array, char[] toBeFound) {
959 int i = toBeFound.length;
960 int j = array.length - i;
965 if (toBeFound[i] != array[i + j])
971 * Answers true if the two arrays are identical character by character, otherwise false.
972 * The equality is case sensitive.
990 * first = { { 'a' } }
991 * second = { { 'a' } }
996 * first = { { 'A' } }
997 * second = { { 'a' } }
1002 * @param first the first array
1003 * @param second the second array
1004 * @return true if the two arrays are identical character by character, otherwise false
1006 public static final boolean equals(char[][] first, char[][] second) {
1007 if (first == second)
1009 if (first == null || second == null)
1011 if (first.length != second.length)
1014 for (int i = first.length; --i >= 0;)
1015 if (!equals(first[i], second[i]))
1021 * If isCaseSensite is true, answers true if the two arrays are identical character
1022 * by character, otherwise false.
1023 * If it is false, answers true if the two arrays are identical character by
1024 * character without checking the case, otherwise false.
1032 * isCaseSensitive = true
1039 * isCaseSensitive = true
1044 * first = { { 'A' } }
1045 * second = { { 'a' } }
1046 * isCaseSensitive = true
1051 * first = { { 'A' } }
1052 * second = { { 'a' } }
1053 * isCaseSensitive = false
1059 * @param first the first array
1060 * @param second the second array
1061 * @param isCaseSensitive check whether or not the equality should be case sensitive
1062 * @return true if the two arrays are identical character by character according to the value
1063 * of isCaseSensitive, otherwise false
1065 public static final boolean equals(
1068 boolean isCaseSensitive) {
1070 if (isCaseSensitive) {
1071 return equals(first, second);
1073 if (first == second)
1075 if (first == null || second == null)
1077 if (first.length != second.length)
1080 for (int i = first.length; --i >= 0;)
1081 if (!equals(first[i], second[i], false))
1087 * Answers true if the two arrays are identical character by character, otherwise false.
1088 * The equality is case sensitive.
1118 * @param first the first array
1119 * @param second the second array
1120 * @return true if the two arrays are identical character by character, otherwise false
1122 public static final boolean equals(char[] first, char[] second) {
1123 if (first == second)
1125 if (first == null || second == null)
1127 if (first.length != second.length)
1130 for (int i = first.length; --i >= 0;)
1131 if (first[i] != second[i])
1137 * Answers true if the first array is identical character by character to a portion of the second array
1138 * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false.
1139 * The equality is case sensitive.
1177 * @param first the first array
1178 * @param second the second array
1179 * @param secondStart inclusive start position in the second array to compare
1180 * @param secondEnd exclusive end position in the second array to compare
1181 * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
1184 public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd) {
1185 if (first == second)
1187 if (first == null || second == null)
1189 if (first.length != secondEnd - secondStart)
1192 for (int i = first.length; --i >= 0;)
1193 if (first[i] != second[i+secondStart])
1199 * If isCaseSensite is true, answers true if the two arrays are identical character
1200 * by character, otherwise false.
1201 * If it is false, answers true if the two arrays are identical character by
1202 * character without checking the case, otherwise false.
1210 * isCaseSensitive = true
1217 * isCaseSensitive = true
1224 * isCaseSensitive = true
1231 * isCaseSensitive = false
1237 * @param first the first array
1238 * @param second the second array
1239 * @param isCaseSensitive check whether or not the equality should be case sensitive
1240 * @return true if the two arrays are identical character by character according to the value
1241 * of isCaseSensitive, otherwise false
1243 public static final boolean equals(
1246 boolean isCaseSensitive) {
1248 if (isCaseSensitive) {
1249 return equals(first, second);
1251 if (first == second)
1253 if (first == null || second == null)
1255 if (first.length != second.length)
1258 for (int i = first.length; --i >= 0;)
1259 if (Character.toLowerCase(first[i])
1260 != Character.toLowerCase(second[i]))
1265 * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive.
1267 * Answers true if the name contains the fragment at the starting index startIndex, otherwise false.
1273 * fragment = { 'b', 'c' , 'd' }
1274 * name = { 'a', 'b', 'c' , 'd' }
1276 * isCaseSensitive = true
1281 * fragment = { 'b', 'c' , 'd' }
1282 * name = { 'a', 'b', 'C' , 'd' }
1284 * isCaseSensitive = true
1289 * fragment = { 'b', 'c' , 'd' }
1290 * name = { 'a', 'b', 'C' , 'd' }
1292 * isCaseSensitive = false
1297 * fragment = { 'b', 'c' , 'd' }
1298 * name = { 'a', 'b'}
1300 * isCaseSensitive = true
1306 * @param fragment the fragment to check
1307 * @param name the array to check
1308 * @param startIndex the starting index
1309 * @param isCaseSensitive check whether or not the equality should be case sensitive
1310 * @return true if the name contains the fragment at the starting index startIndex according to the
1311 * value of isCaseSensitive, otherwise false.
1312 * @throws NullPointerException if fragment or name is null.
1314 public static final boolean fragmentEquals(
1318 boolean isCaseSensitive) {
1320 int max = fragment.length;
1321 if (name.length < max + startIndex)
1323 if (isCaseSensitive) {
1326 ) // assumes the prefix is not larger than the name
1327 if (fragment[i] != name[i + startIndex])
1333 ) // assumes the prefix is not larger than the name
1334 if (Character.toLowerCase(fragment[i])
1335 != Character.toLowerCase(name[i + startIndex]))
1341 * Answers a hashcode for the array
1343 * @param array the array for which a hashcode is required
1344 * @return the hashcode
1345 * @throws NullPointerException if array is null
1347 public static final int hashCode(char[] array) {
1350 int length = array.length;
1352 for (int i = length; i > 0; i--)
1353 hash = (hash * 37) + array[offset++];
1355 // only sample some characters
1356 int skip = length / 8;
1357 for (int i = length; i > 0; i -= skip, offset += skip)
1358 hash = (hash * 39) + array[offset];
1360 return hash & 0x7FFFFFFF;
1363 * Answers true if c is a whitespace according to the JLS (\u000a, \u000c, \u000d, \u0009), otherwise false.
1380 * @param c the character to check
1381 * @return true if c is a whitespace according to the JLS, otherwise false.
1383 public static boolean isWhitespace(char c) {
1385 case 10 : /* \ u000a: LINE FEED */
1386 case 12 : /* \ u000c: FORM FEED */
1387 case 13 : /* \ u000d: CARRIAGE RETURN */
1388 case 32 : /* \ u0020: SPACE */
1389 case 9 : /* \ u0009: HORIZONTAL TABULATION */
1397 * Answers the first index in the array for which the corresponding character is
1398 * equal to toBeFound. Answers -1 if no occurrence of this character is found.
1405 * array = { ' a', 'b', 'c', 'd' }
1411 * array = { ' a', 'b', 'c', 'd' }
1417 * @param toBeFound the character to search
1418 * @param array the array to be searched
1419 * @return the first index in the array for which the corresponding character is
1420 * equal to toBeFound, -1 otherwise
1421 * @throws NullPointerException if array is null
1423 public static final int indexOf(char toBeFound, char[] array) {
1424 for (int i = 0; i < array.length; i++)
1425 if (toBeFound == array[i])
1431 * Answers the first index in the array for which the corresponding character is
1432 * equal to toBeFound starting the search at index start.
1433 * Answers -1 if no occurrence of this character is found.
1440 * array = { ' a', 'b', 'c', 'd' }
1447 * array = { ' a', 'b', 'c', 'd' }
1454 * array = { ' a', 'b', 'c', 'd' }
1461 * @param toBeFound the character to search
1462 * @param array the array to be searched
1463 * @param start the starting index
1464 * @return the first index in the array for which the corresponding character is
1465 * equal to toBeFound, -1 otherwise
1466 * @throws NullPointerException if array is null
1467 * @throws ArrayIndexOutOfBoundsException if start is lower than 0
1469 public static final int indexOf(char toBeFound, char[] array, int start) {
1470 for (int i = start; i < array.length; i++)
1471 if (toBeFound == array[i])
1477 * Answers the last index in the array for which the corresponding character is
1478 * equal to toBeFound starting from the end of the array.
1479 * Answers -1 if no occurrence of this character is found.
1486 * array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
1492 * array = { ' a', 'b', 'c', 'd' }
1498 * @param toBeFound the character to search
1499 * @param array the array to be searched
1500 * @return the last index in the array for which the corresponding character is
1501 * equal to toBeFound starting from the end of the array, -1 otherwise
1502 * @throws NullPointerException if array is null
1504 public static final int lastIndexOf(char toBeFound, char[] array) {
1505 for (int i = array.length; --i >= 0;)
1506 if (toBeFound == array[i])
1512 * Answers the last index in the array for which the corresponding character is
1513 * equal to toBeFound stopping at the index startIndex.
1514 * Answers -1 if no occurrence of this character is found.
1521 * array = { ' a', 'b', 'c', 'd' }
1528 * array = { ' a', 'b', 'c', 'd', 'e' }
1535 * array = { ' a', 'b', 'c', 'd' }
1542 * @param toBeFound the character to search
1543 * @param array the array to be searched
1544 * @param startIndex the stopping index
1545 * @return the last index in the array for which the corresponding character is
1546 * equal to toBeFound stopping at the index startIndex, -1 otherwise
1547 * @throws NullPointerException if array is null
1548 * @throws ArrayIndexOutOfBoundsException if startIndex is lower than 0
1550 public static final int lastIndexOf(
1554 for (int i = array.length; --i >= startIndex;)
1555 if (toBeFound == array[i])
1561 * Answers the last index in the array for which the corresponding character is
1562 * equal to toBeFound starting from endIndex to startIndex.
1563 * Answers -1 if no occurrence of this character is found.
1570 * array = { ' a', 'b', 'c', 'd' }
1578 * array = { ' a', 'b', 'c', 'd', 'e' }
1586 * array = { ' a', 'b', 'c', 'd' }
1594 * @param toBeFound the character to search
1595 * @param array the array to be searched
1596 * @param startIndex the stopping index
1597 * @param endIndex the starting index
1598 * @return the last index in the array for which the corresponding character is
1599 * equal to toBeFound starting from endIndex to startIndex, -1 otherwise
1600 * @throws NullPointerException if array is null
1601 * @throws ArrayIndexOutOfBoundsException if endIndex is greater or equals to array length or starting is lower than 0
1603 public static final int lastIndexOf(
1608 for (int i = endIndex; --i >= startIndex;)
1609 if (toBeFound == array[i])
1615 * Answers the last portion of a name given a separator.
1620 * lastSegment("java.lang.Object".toCharArray(),'.') --> Object
1623 * @param array the array
1624 * @param separator the given separator
1625 * @return the last portion of a name given a separator
1626 * @throws NullPointerException if array is null
1628 final static public char[] lastSegment(char[] array, char separator) {
1629 int pos = lastIndexOf(separator, array);
1632 return subarray(array, pos + 1, array.length);
1636 * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching
1637 * accepts wild-cards '*' and '?'.
1639 * When not case sensitive, the pattern is assumed to already be lowercased, the
1640 * name will be lowercased character per character as comparing.
1641 * If name is null, the answer is false.
1642 * If pattern is null, the answer is true if name is not null.
1648 * pattern = { '?', 'b', '*' }
1649 * name = { 'a', 'b', 'c' , 'd' }
1650 * isCaseSensitive = true
1655 * pattern = { '?', 'b', '?' }
1656 * name = { 'a', 'b', 'c' , 'd' }
1657 * isCaseSensitive = true
1662 * pattern = { 'b', '*' }
1663 * name = { 'a', 'b', 'c' , 'd' }
1664 * isCaseSensitive = true
1670 * @param pattern the given pattern
1671 * @param name the given name
1672 * @param isCaseSensitive flag to know whether or not the matching should be case sensitive
1673 * @return true if the pattern matches the given name, false otherwise
1675 public static final boolean match(
1678 boolean isCaseSensitive) {
1681 return false; // null name cannot match
1682 if (pattern == null)
1683 return true; // null pattern is equivalent to '*'
1696 * Answers true if the a sub-pattern matches the subpart of the given name, false otherwise.
1697 * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only subset of name/pattern.
1698 * end positions are non-inclusive.
1699 * The subpattern is defined by the patternStart and pattternEnd positions.
1700 * When not case sensitive, the pattern is assumed to already be lowercased, the
1701 * name will be lowercased character per character as comparing.
1707 * pattern = { '?', 'b', '*' }
1710 * name = { 'a', 'b', 'c' , 'd' }
1713 * isCaseSensitive = true
1718 * pattern = { '?', 'b', '*' }
1721 * name = { 'a', 'b', 'c' , 'd' }
1724 * isCaseSensitive = true
1730 * @param pattern the given pattern
1731 * @param patternStart the given pattern start
1732 * @param patternEnd the given pattern end
1733 * @param name the given name
1734 * @param nameStart the given name start
1735 * @param nameEnd the given name end
1736 * @param isCaseSensitive flag to know if the matching should be case sensitive
1737 * @return true if the a sub-pattern matches the subpart of the given name, false otherwise
1739 public static final boolean match(
1746 boolean isCaseSensitive) {
1749 return false; // null name cannot match
1750 if (pattern == null)
1751 return true; // null pattern is equivalent to '*'
1752 int iPattern = patternStart;
1753 int iName = nameStart;
1756 patternEnd = pattern.length;
1758 nameEnd = name.length;
1760 /* check first segment */
1761 char patternChar = 0;
1762 while ((iPattern < patternEnd)
1763 && (patternChar = pattern[iPattern]) != '*') {
1764 if (iName == nameEnd)
1769 : Character.toLowerCase(name[iName]))
1770 && patternChar != '?') {
1776 /* check sequence of star+segment */
1778 if (patternChar == '*') {
1779 segmentStart = ++iPattern; // skip star
1781 segmentStart = 0; // force iName check
1783 int prefixStart = iName;
1784 checkSegment : while (iName < nameEnd) {
1785 if (iPattern == patternEnd) {
1786 iPattern = segmentStart; // mismatch - restart current segment
1787 iName = ++prefixStart;
1788 continue checkSegment;
1790 /* segment is ending */
1791 if ((patternChar = pattern[iPattern]) == '*') {
1792 segmentStart = ++iPattern; // skip start
1793 if (segmentStart == patternEnd) {
1796 prefixStart = iName;
1797 continue checkSegment;
1799 /* check current name character */
1800 if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName]))
1802 && patternChar != '?') {
1803 iPattern = segmentStart; // mismatch - restart current segment
1804 iName = ++prefixStart;
1805 continue checkSegment;
1811 return (segmentStart == patternEnd)
1812 || (iName == nameEnd && iPattern == patternEnd)
1813 || (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
1817 * Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
1819 * Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks
1820 * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
1821 * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
1822 * any folder combination.
1824 * - foo\ is equivalent to foo\**
1825 * When not case sensitive, the pattern is assumed to already be lowercased, the
1826 * name will be lowercased character per character as comparing.
1828 * @param pattern the given pattern
1829 * @param filepath the given path
1830 * @param isCaseSensitive to find out whether or not the matching should be case sensitive
1831 * @param pathSeparator the given path separator
1832 * @return true if the pattern matches the filepath using the pathSepatator, false otherwise
1834 public static final boolean pathMatch(
1837 boolean isCaseSensitive,
1838 char pathSeparator) {
1840 if (filepath == null)
1841 return false; // null name cannot match
1842 if (pattern == null)
1843 return true; // null pattern is equivalent to '*'
1845 // offsets inside pattern
1846 int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
1847 int pLength = pattern.length;
1848 int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart+1);
1849 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1851 // special case: pattern foo\ is equivalent to foo\**
1852 boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
1854 // offsets inside filepath
1855 int fSegmentStart, fLength = filepath.length;
1856 if (filepath[0] != pathSeparator){
1861 if (fSegmentStart != pSegmentStart) {
1862 return false; // both must start with a separator or none.
1864 int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart+1);
1865 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1868 while (pSegmentStart < pLength
1869 && !(pSegmentEnd == pLength && freeTrailingDoubleStar
1870 || (pSegmentEnd == pSegmentStart + 2
1871 && pattern[pSegmentStart] == '*'
1872 && pattern[pSegmentStart + 1] == '*'))) {
1874 if (fSegmentStart >= fLength)
1888 // jump to next segment
1890 CharOperation.indexOf(
1893 pSegmentStart = pSegmentEnd + 1);
1895 if (pSegmentEnd < 0)
1896 pSegmentEnd = pLength;
1899 CharOperation.indexOf(
1902 fSegmentStart = fSegmentEnd + 1);
1904 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1907 /* check sequence of doubleStar+segment */
1908 int pSegmentRestart;
1909 if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
1910 || (pSegmentEnd == pSegmentStart + 2
1911 && pattern[pSegmentStart] == '*'
1912 && pattern[pSegmentStart + 1] == '*')) {
1914 CharOperation.indexOf(
1917 pSegmentStart = pSegmentEnd + 1);
1919 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1920 pSegmentRestart = pSegmentStart;
1922 if (pSegmentStart >= pLength) return fSegmentStart >= fLength; // true if filepath is done too.
1923 pSegmentRestart = 0; // force fSegmentStart check
1925 int fSegmentRestart = fSegmentStart;
1926 checkSegment : while (fSegmentStart < fLength) {
1928 if (pSegmentStart >= pLength) {
1929 if (freeTrailingDoubleStar) return true;
1930 // mismatch - restart current path segment
1932 CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
1933 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1936 CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
1938 if (fSegmentRestart < 0) {
1939 fSegmentRestart = fLength;
1944 CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
1945 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1946 continue checkSegment;
1949 /* path segment is ending */
1950 if (pSegmentEnd == pSegmentStart + 2
1951 && pattern[pSegmentStart] == '*'
1952 && pattern[pSegmentStart + 1] == '*') {
1954 CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
1956 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1957 pSegmentRestart = pSegmentStart;
1958 fSegmentRestart = fSegmentStart;
1959 if (pSegmentStart >= pLength) return true;
1960 continue checkSegment;
1962 /* chech current path segment */
1963 if (!CharOperation.match(
1971 // mismatch - restart current path segment
1973 CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
1974 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1977 CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
1979 if (fSegmentRestart < 0) {
1980 fSegmentRestart = fLength;
1985 CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
1986 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1987 continue checkSegment;
1989 // jump to next segment
1991 CharOperation.indexOf(
1994 pSegmentStart = pSegmentEnd + 1);
1996 if (pSegmentEnd < 0)
1997 pSegmentEnd = pLength;
2000 CharOperation.indexOf(
2003 fSegmentStart = fSegmentEnd + 1);
2005 if (fSegmentEnd < 0)
2006 fSegmentEnd = fLength;
2009 return (pSegmentRestart >= pSegmentEnd)
2010 || (fSegmentStart >= fLength && pSegmentStart >= pLength)
2011 || (pSegmentStart == pLength - 2
2012 && pattern[pSegmentStart] == '*'
2013 && pattern[pSegmentStart + 1] == '*')
2014 || (pSegmentStart == pLength && freeTrailingDoubleStar);
2018 * Answers the number of occurrences of the given character in the given array, 0 if any.
2026 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2032 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2038 * @param toBeFound the given character
2039 * @param array the given array
2040 * @return the number of occurrences of the given character in the given array, 0 if any
2041 * @throws NullPointerException if array is null
2043 public static final int occurencesOf(char toBeFound, char[] array) {
2045 for (int i = 0; i < array.length; i++)
2046 if (toBeFound == array[i])
2052 * Answers the number of occurrences of the given character in the given array starting
2053 * at the given index, 0 if any.
2061 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2068 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2075 * @param toBeFound the given character
2076 * @param array the given array
2077 * @param start the given index
2078 * @return the number of occurrences of the given character in the given array, 0 if any
2079 * @throws NullPointerException if array is null
2080 * @throws ArrayIndexOutOfBoundsException if start is lower than 0
2082 public static final int occurencesOf(
2087 for (int i = start; i < array.length; i++)
2088 if (toBeFound == array[i])
2094 * Answers true if the given name starts with the given prefix, false otherwise.
2095 * The comparison is case sensitive.
2101 * prefix = { 'a' , 'b' }
2102 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2107 * prefix = { 'a' , 'c' }
2108 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2114 * @param prefix the given prefix
2115 * @param name the given name
2116 * @return true if the given name starts with the given prefix, false otherwise
2117 * @throws NullPointerException if the given name is null or if the given prefix is null
2119 public static final boolean prefixEquals(char[] prefix, char[] name) {
2121 int max = prefix.length;
2122 if (name.length < max)
2126 ) // assumes the prefix is not larger than the name
2127 if (prefix[i] != name[i])
2133 * Answers true if the given name starts with the given prefix, false otherwise.
2134 * isCaseSensitive is used to find out whether or not the comparison should be case sensitive.
2140 * prefix = { 'a' , 'B' }
2141 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2142 * isCaseSensitive = false
2147 * prefix = { 'a' , 'B' }
2148 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2149 * isCaseSensitive = true
2155 * @param prefix the given prefix
2156 * @param name the given name
2157 * @param isCaseSensitive to find out whether or not the comparison should be case sensitive
2158 * @return true if the given name starts with the given prefix, false otherwise
2159 * @throws NullPointerException if the given name is null or if the given prefix is null
2161 public static final boolean prefixEquals(
2164 boolean isCaseSensitive) {
2166 int max = prefix.length;
2167 if (name.length < max)
2169 if (isCaseSensitive) {
2172 ) // assumes the prefix is not larger than the name
2173 if (prefix[i] != name[i])
2180 ) // assumes the prefix is not larger than the name
2181 if (Character.toLowerCase(prefix[i])
2182 != Character.toLowerCase(name[i]))
2188 * Replace all occurrence of the character to be replaced with the remplacement character in the
2195 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2196 * toBeReplaced = 'b'
2197 * replacementChar = 'a'
2198 * result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
2202 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2203 * toBeReplaced = 'c'
2204 * replacementChar = 'a'
2205 * result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
2210 * @param array the given array
2211 * @param toBeReplaced the character to be replaced
2212 * @param replacementChar the replacement character
2213 * @throws NullPointerException if the given array is null
2215 public static final void replace(
2218 char replacementChar) {
2219 if (toBeReplaced != replacementChar) {
2220 for (int i = 0, max = array.length; i < max; i++) {
2221 if (array[i] == toBeReplaced)
2222 array[i] = replacementChar;
2228 * Answers a new array of characters with substitutions. No side-effect is operated on the original
2229 * array, in case no substitution happened, then the result is the same as the
2236 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2237 * toBeReplaced = { 'b' }
2238 * replacementChar = { 'a', 'a' }
2239 * result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
2243 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2244 * toBeReplaced = { 'c' }
2245 * replacementChar = { 'a' }
2246 * result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
2251 * @param array the given array
2252 * @param toBeReplaced characters to be replaced
2253 * @param replacementChars the replacement characters
2254 * @return a new array of characters with substitutions or the given array if none
2255 * @throws NullPointerException if the given array is null
2257 public static final char[] replace(
2259 char[] toBeReplaced,
2260 char[] replacementChars) {
2262 int max = array.length;
2263 int replacedLength = toBeReplaced.length;
2264 int replacementLength = replacementChars.length;
2266 int[] starts = new int[5];
2267 int occurrenceCount = 0;
2269 if (!equals(toBeReplaced, replacementChars)) {
2271 next : for (int i = 0; i < max; i++) {
2273 while (j < replacedLength) {
2276 if (array[i + j] != toBeReplaced[j++])
2279 if (occurrenceCount == starts.length) {
2283 starts = new int[occurrenceCount * 2],
2287 starts[occurrenceCount++] = i;
2290 if (occurrenceCount == 0)
2294 + occurrenceCount * (replacementLength - replacedLength)];
2295 int inStart = 0, outStart = 0;
2296 for (int i = 0; i < occurrenceCount; i++) {
2297 int offset = starts[i] - inStart;
2298 System.arraycopy(array, inStart, result, outStart, offset);
2307 inStart += replacedLength;
2308 outStart += replacementLength;
2310 System.arraycopy(array, inStart, result, outStart, max - inStart);
2315 * Replace all occurrence of the character to be replaced with the remplacement character
2316 * in a copy of the given array. Returns the given array if no occurrences of the character
2317 * to be replaced are found.
2323 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2324 * toBeReplaced = 'b'
2325 * replacementChar = 'a'
2326 * result => A new array that is equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
2330 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2331 * toBeReplaced = 'c'
2332 * replacementChar = 'a'
2333 * result => The original array that remains unchanged.
2338 * @param array the given array
2339 * @param toBeReplaced the character to be replaced
2340 * @param replacementChar the replacement character
2341 * @throws NullPointerException if the given array is null
2344 public static final char[] replaceOnCopy(
2347 char replacementChar) {
2349 char[] result = null;
2350 for (int i = 0, length = array.length; i < length; i++) {
2352 if (c == toBeReplaced) {
2353 if (result == null) {
2354 result = new char[length];
2355 System.arraycopy(array, 0, result, 0, i);
2357 result[i] = replacementChar;
2358 } else if (result != null) {
2362 if (result == null) return array;
2367 * Return a new array which is the split of the given array using the given divider and triming each subarray to remove
2368 * whitespaces equals to ' '.
2375 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2376 * result => { { 'a' }, { }, { 'a' }, { 'a' } }
2381 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2382 * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2387 * array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
2388 * result => { { 'a' }, { }, { 'a' }, { 'a' } }
2393 * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
2394 * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2399 * @param divider the given divider
2400 * @param array the given array
2401 * @return a new array which is the split of the given array using the given divider and triming each subarray to remove
2402 * whitespaces equals to ' '
2404 public static final char[][] splitAndTrimOn(char divider, char[] array) {
2405 int length = array == null ? 0 : array.length;
2407 return NO_CHAR_CHAR;
2410 for (int i = 0; i < length; i++)
2411 if (array[i] == divider)
2413 char[][] split = new char[wordCount][];
2414 int last = 0, currentWord = 0;
2415 for (int i = 0; i < length; i++) {
2416 if (array[i] == divider) {
2417 int start = last, end = i - 1;
2418 while (start < i && array[start] == ' ')
2420 while (end > start && array[end] == ' ')
2422 split[currentWord] = new char[end - start + 1];
2426 split[currentWord++],
2432 int start = last, end = length - 1;
2433 while (start < length && array[start] == ' ')
2435 while (end > start && array[end] == ' ')
2437 split[currentWord] = new char[end - start + 1];
2441 split[currentWord++],
2448 * Return a new array which is the split of the given array using the given divider.
2455 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2456 * result => { { 'a' }, { }, { 'a' }, { 'a' } }
2461 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2462 * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2467 * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
2468 * result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
2473 * @param divider the given divider
2474 * @param array the given array
2475 * @return a new array which is the split of the given array using the given divider
2477 public static final char[][] splitOn(char divider, char[] array) {
2478 int length = array == null ? 0 : array.length;
2480 return NO_CHAR_CHAR;
2483 for (int i = 0; i < length; i++)
2484 if (array[i] == divider)
2486 char[][] split = new char[wordCount][];
2487 int last = 0, currentWord = 0;
2488 for (int i = 0; i < length; i++) {
2489 if (array[i] == divider) {
2490 split[currentWord] = new char[i - last];
2494 split[currentWord++],
2500 split[currentWord] = new char[length - last];
2501 System.arraycopy(array, last, split[currentWord], 0, length - last);
2506 * Return a new array which is the split of the given array using the given divider. The given end
2507 * is exclusive and the given start is inclusive.
2514 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2517 * result => { { }, { 'a' }, { } }
2522 * @param divider the given divider
2523 * @param array the given array
2524 * @param start the given starting index
2525 * @param end the given ending index
2526 * @return a new array which is the split of the given array using the given divider
2527 * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
2529 public static final char[][] splitOn(
2534 int length = array == null ? 0 : array.length;
2535 if (length == 0 || start > end)
2536 return NO_CHAR_CHAR;
2539 for (int i = start; i < end; i++)
2540 if (array[i] == divider)
2542 char[][] split = new char[wordCount][];
2543 int last = start, currentWord = 0;
2544 for (int i = start; i < end; i++) {
2545 if (array[i] == divider) {
2546 split[currentWord] = new char[i - last];
2550 split[currentWord++],
2556 split[currentWord] = new char[end - last];
2557 System.arraycopy(array, last, split[currentWord], 0, end - last);
2562 * Answers a new array which is a copy of the given array starting at the given start and
2563 * ending at the given end. The given start is inclusive and the given end is exclusive.
2564 * Answers null if start is greater than end, if start is lower than 0 or if end is greater
2565 * than the length of the given array. If end equals -1, it is converted to the array length.
2571 * array = { { 'a' } , { 'b' } }
2574 * result => { { 'a' } }
2578 * array = { { 'a' } , { 'b' } }
2581 * result => { { 'a' }, { 'b' } }
2586 * @param array the given array
2587 * @param start the given starting index
2588 * @param end the given ending index
2589 * @return a new array which is a copy of the given array starting at the given start and
2590 * ending at the given end
2591 * @throws NullPointerException if the given array is null
2593 public static final char[][] subarray(char[][] array, int start, int end) {
2600 if (end > array.length)
2603 char[][] result = new char[end - start][];
2604 System.arraycopy(array, start, result, 0, end - start);
2609 * Answers a new array which is a copy of the given array starting at the given start and
2610 * ending at the given end. The given start is inclusive and the given end is exclusive.
2611 * Answers null if start is greater than end, if start is lower than 0 or if end is greater
2612 * than the length of the given array. If end equals -1, it is converted to the array length.
2618 * array = { 'a' , 'b' }
2625 * array = { 'a', 'b' }
2628 * result => { 'a' , 'b' }
2633 * @param array the given array
2634 * @param start the given starting index
2635 * @param end the given ending index
2636 * @return a new array which is a copy of the given array starting at the given start and
2637 * ending at the given end
2638 * @throws NullPointerException if the given array is null
2640 public static final char[] subarray(char[] array, int start, int end) {
2647 if (end > array.length)
2650 char[] result = new char[end - start];
2651 System.arraycopy(array, start, result, 0, end - start);
2655 * Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null.
2657 * NOTE: If no conversion was necessary, then answers back the argument one.
2663 * chars = { 'a' , 'b' }
2664 * result => { 'a' , 'b' }
2668 * array = { 'A', 'b' }
2669 * result => { 'a' , 'b' }
2674 * @param chars the chars to convert
2675 * @return the result of a char[] conversion to lowercase
2677 final static public char[] toLowerCase(char[] chars) {
2680 int length = chars.length;
2681 char[] lowerChars = null;
2682 for (int i = 0; i < length; i++) {
2684 char lc = Character.toLowerCase(c);
2685 if ((c != lc) || (lowerChars != null)) {
2686 if (lowerChars == null) {
2690 lowerChars = new char[length],
2697 return lowerChars == null ? chars : lowerChars;
2701 * Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no
2702 * space characters to remove.
2708 * chars = { ' ', 'a' , 'b', ' ', ' ' }
2709 * result => { 'a' , 'b' }
2713 * array = { 'A', 'b' }
2714 * result => { 'A' , 'b' }
2719 * @param chars the given array
2720 * @return a new array removing leading and trailing spaces (' ')
2722 final static public char[] trim(char[] chars) {
2727 int start = 0, length = chars.length, end = length - 1;
2728 while (start < length && chars[start] == ' ') {
2731 while (end > start && chars[end] == ' ') {
2734 if (start != 0 || end != length - 1) {
2735 return subarray(chars, start, end + 1);
2741 * Answers a string which is the concatenation of the given array using the '.' as a separator.
2747 * array = { { 'a' } , { 'b' } }
2752 * array = { { ' ', 'a' } , { 'b' } }
2758 * @param array the given array
2759 * @return a string which is the concatenation of the given array using the '.' as a separator
2761 final static public String toString(char[][] array) {
2762 char[] result = concatWith(array, '.');
2763 return new String(result);
2766 * Answers an array of strings from the given array of char array.
2768 * @param array the given array
2769 * @return an array of strings
2772 final static public String[] toStrings(char[][] array) {
2773 if (array == null) return NO_STRINGS;
2774 int length = array.length;
2775 if (length == 0) return NO_STRINGS;
2776 String[] result = new String[length];
2777 for (int i = 0; i < length; i++)
2778 result[i] = new String(array[i]);