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 * Answers a new array with appending the suffix character at the end of the array.
37 * array = { 'a', 'b' }
39 * => result = { 'a', 'b' , 'c' }
49 * @param array the array that is concanated with the suffix character
50 * @param suffix the suffix character
51 * @return the new array
53 public static final char[] append(char[] array, char suffix) {
55 return new char[] { suffix };
56 int length = array.length;
57 System.arraycopy(array, 0, array = new char[length + 1], 0, length);
58 array[length] = suffix;
62 * Append the given subarray to the target array starting at the given index in the target array.
63 * The start of the subarray is inclusive, the end is exclusive.
64 * Answers a new target array if it needs to grow, otherwise answers the same target array.
69 * target = { 'a', 'b', '0' }
71 * array = { 'c', 'd' }
74 * => result = { 'a', 'b' , 'c' }
78 * target = { 'a', 'b' }
80 * array = { 'c', 'd' }
83 * => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
86 * target = { 'a', 'b', 'c' }
88 * array = { 'c', 'd', 'e', 'f' }
91 * => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
95 * @param target the given target
96 * @param index the given index
97 * @param array the given array
98 * @param start the given start index
99 * @param end the given end index
101 * @return the new array
102 * @throws NullPointerException if the target array is null
104 public static final char[] append(char[] target, int index, char[] array, int start, int end) {
105 int targetLength = target.length;
106 int subLength = end-start;
107 int newTargetLength = subLength+index;
108 if (newTargetLength > targetLength) {
109 System.arraycopy(target, 0, target = new char[newTargetLength*2], 0, index);
111 System.arraycopy(array, start, target, index, subLength);
116 * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
117 * If the first array is null, then the second array is returned.
118 * If the second array is null, then the first array is returned.
130 * first = { { ' a' } }
132 * => result = { { ' a' } }
137 * second = { { ' a' } }
138 * => result = { { ' a' } }
142 * first = { { ' b' } }
143 * second = { { ' a' } }
144 * => result = { { ' b' }, { ' a' } }
149 * @param first the first array to concatenate
150 * @param second the second array to concatenate
151 * @return the concatenation of the two arrays, or null if the two arrays are null.
153 public static final char[][] arrayConcat(char[][] first, char[][] second) {
159 int length1 = first.length;
160 int length2 = second.length;
161 char[][] result = new char[length1 + length2][];
162 System.arraycopy(first, 0, result, 0, length1);
163 System.arraycopy(second, 0, result, length1, length2);
167 * Returns the char arrays as an array of Strings
169 * @param charArrays the char array to convert
170 * @return the char arrays as an array of Strings or null if the given char arrays is null.
173 public static String[] charArrayToStringArray(char[][] charArrays) {
174 if (charArrays == null) {
177 String[] strings= new String[charArrays.length];
178 for (int i= 0; i < charArrays.length; i++) {
179 strings[i]= new String(charArrays[i]);
184 * Returns the char array as a String
186 * @param charArray the char array to convert
187 * @return the char array as a String or null if the given char array is null.
190 public static String charToString(char[] charArray) {
191 if (charArray == null) return null;
192 return new String(charArray);
196 * Answers a new array adding the second array at the end of first array.
197 * It answers null if the first and second are null.
198 * If the first array is null, then a new array char[][] is created with second.
199 * If the second array is null, then the first array is returned.
207 * => result = { { ' a' } }
210 * first = { { ' a' } }
212 * => result = { { ' a' } }
216 * first = { { ' a' } }
218 * => result = { { ' a' } , { ' b' } }
223 * @param first the first array to concatenate
224 * @param second the array to add at the end of the first array
225 * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
227 public static final char[][] arrayConcat(char[][] first, char[] second) {
231 return new char[][] { second };
233 int length = first.length;
234 char[][] result = new char[length + 1][];
235 System.arraycopy(first, 0, result, 0, length);
236 result[length] = second;
241 * Compares the contents of the two arrays array and prefix. Returns
243 * <li>zero if the array starts with the prefix contents</li>
244 * <li>the difference between the first two characters that are not equal </li>
245 * <li>one if array length is lower than the prefix length and that the prefix starts with the
246 * array contents.</li>
254 * => result = NullPointerException
258 * array = { 'a', 'b', 'c', 'd', 'e' }
259 * prefix = { 'a', 'b', 'c'}
264 * array = { 'a', 'b', 'c', 'd', 'e' }
265 * prefix = { 'a', 'B', 'c'}
270 * array = { 'd', 'b', 'c', 'd', 'e' }
271 * prefix = { 'a', 'b', 'c'}
276 * array = { 'a', 'b', 'c', 'd', 'e' }
277 * prefix = { 'd', 'b', 'c'}
282 * array = { 'a', 'a', 'c', 'd', 'e' }
283 * prefix = { 'a', 'e', 'c'}
290 * @param array the given array
291 * @param prefix the given prefix
292 * @return the result of the comparison (>=0 if array>prefix)
293 * @throws NullPointerException if either array or prefix is null
295 public static final int compareWith(char[] array, char[] prefix) {
296 int arrayLength = array.length;
297 int prefixLength = prefix.length;
298 int min = Math.min(arrayLength, prefixLength);
302 char c2 = prefix[i++];
306 if (prefixLength == i)
308 return -1; // array is shorter than prefix (e.g. array:'ab' < prefix:'abc').
312 * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
313 * If the first array is null, then the second array is returned.
314 * If the second array is null, then the first array is returned.
322 * => result = { ' a' }
328 * => result = { ' a' }
334 * => result = { ' a' , ' b' }
339 * @param first the first array to concatenate
340 * @param second the second array to concatenate
341 * @return the concatenation of the two arrays, or null if the two arrays are null.
343 public static final char[] concat(char[] first, char[] second) {
349 int length1 = first.length;
350 int length2 = second.length;
351 char[] result = new char[length1 + length2];
352 System.arraycopy(first, 0, result, 0, length1);
353 System.arraycopy(second, 0, result, length1, length2);
358 * Answers the concatenation of the three arrays. It answers null if the three arrays are null.
359 * If first is null, it answers the concatenation of second and third.
360 * If second is null, it answers the concatenation of first and third.
361 * If third is null, it answers the concatenation of first and second.
370 * => result = { ' a', 'b' }
377 * => result = { ' a', 'b' }
384 * => result = { ' a', 'b' }
398 * => result = { 'a', 'b', 'c' }
403 * @param first the first array to concatenate
404 * @param second the second array to concatenate
405 * @param third the third array to concatenate
407 * @return the concatenation of the three arrays, or null if the three arrays are null.
409 public static final char[] concat(
414 return concat(second, third);
416 return concat(first, third);
418 return concat(first, second);
420 int length1 = first.length;
421 int length2 = second.length;
422 int length3 = third.length;
423 char[] result = new char[length1 + length2 + length3];
424 System.arraycopy(first, 0, result, 0, length1);
425 System.arraycopy(second, 0, result, length1, length2);
426 System.arraycopy(third, 0, result, length1 + length2, length3);
431 * Answers the concatenation of the two arrays inserting the separator character between the two arrays.
432 * It answers null if the two arrays are null.
433 * If the first array is null, then the second array is returned.
434 * If the second array is null, then the first array is returned.
443 * => result = { ' a' }
450 * => result = { ' a' }
457 * => result = { ' a' , '/', 'b' }
462 * @param first the first array to concatenate
463 * @param second the second array to concatenate
464 * @param separator the character to insert
465 * @return the concatenation of the two arrays inserting the separator character
466 * between the two arrays , or null if the two arrays are null.
468 public static final char[] concat(
477 int length1 = first.length;
480 int length2 = second.length;
484 char[] result = new char[length1 + length2 + 1];
485 System.arraycopy(first, 0, result, 0, length1);
486 result[length1] = separator;
487 System.arraycopy(second, 0, result, length1 + 1, length2);
492 * Answers the concatenation of the three arrays inserting the sep1 character between the
493 * two arrays and sep2 between the last two.
494 * It answers null if the three arrays are null.
495 * If the first array is null, then it answers the concatenation of second and third inserting
496 * the sep2 character between them.
497 * If the second array is null, then it answers the concatenation of first and third inserting
498 * the sep1 character between them.
499 * If the third array is null, then it answers the concatenation of first and second inserting
500 * the sep1 character between them.
511 * => result = { ' a' , ':', 'b' }
520 * => result = { ' a' , '/', 'b' }
529 * => result = { ' a' , '/', 'b' }
538 * => result = { ' a' , '/', 'b' , ':', 'c' }
543 * @param first the first array to concatenate
544 * @param sep1 the character to insert
545 * @param second the second array to concatenate
546 * @param sep2 the character to insert
547 * @param third the second array to concatenate
548 * @return the concatenation of the three arrays inserting the sep1 character between the
549 * two arrays and sep2 between the last two.
551 public static final char[] concat(
558 return concat(second, third, sep2);
560 return concat(first, third, sep1);
562 return concat(first, second, sep1);
564 int length1 = first.length;
565 int length2 = second.length;
566 int length3 = third.length;
567 char[] result = new char[length1 + length2 + length3 + 2];
568 System.arraycopy(first, 0, result, 0, length1);
569 result[length1] = sep1;
570 System.arraycopy(second, 0, result, length1 + 1, length2);
571 result[length1 + length2 + 1] = sep2;
572 System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
577 * Answers a new array with prepending the prefix character and appending the suffix
578 * character at the end of the array. If array is null, it answers a new array containing the
579 * prefix and the suffix characters.
588 * => result = { 'a', 'b' , 'c' }
595 * => result = { 'a', 'c' }
599 * @param prefix the prefix character
600 * @param array the array that is concanated with the prefix and suffix characters
601 * @param suffix the suffix character
602 * @return the new array
604 public static final char[] concat(char prefix, char[] array, char suffix) {
606 return new char[] { prefix, suffix };
608 int length = array.length;
609 char[] result = new char[length + 2];
611 System.arraycopy(array, 0, result, 1, length);
612 result[length + 1] = suffix;
617 * Answers the concatenation of the given array parts using the given separator between each
618 * part and appending the given name at the end.
625 * array = { { 'a' }, { 'b' } }
627 * => result = { 'a', '.', 'b' , '.', 'c' }
632 * array = { { 'a' }, { 'b' } }
634 * => result = { 'a', '.', 'b' }
640 * => result = { 'c' }
644 * @param name the given name
645 * @param array the given array
646 * @param separator the given separator
647 * @return the concatenation of the given array parts using the given separator between each
648 * part and appending the given name at the end
650 public static final char[] concatWith(
654 int nameLength = name == null ? 0 : name.length;
656 return concatWith(array, separator);
658 int length = array == null ? 0 : array.length;
662 int size = nameLength;
665 if (array[index].length > 0)
666 size += array[index].length + 1;
667 char[] result = new char[size];
669 for (int i = length - 1; i >= 0; i--) {
670 int subLength = array[i].length;
673 System.arraycopy(array[i], 0, result, index, subLength);
674 result[--index] = separator;
677 System.arraycopy(name, 0, result, 0, nameLength);
682 * Answers the concatenation of the given array parts using the given separator between each
683 * part and appending the given name at the end.
690 * array = { { 'a' }, { 'b' } }
692 * => result = { 'a', '.', 'b' , '.', 'c' }
697 * array = { { 'a' }, { 'b' } }
699 * => result = { 'a', '.', 'b' }
705 * => result = { 'c' }
709 * @param array the given array
710 * @param name the given name
711 * @param separator the given separator
712 * @return the concatenation of the given array parts using the given separator between each
713 * part and appending the given name at the end
715 public static final char[] concatWith(
719 int nameLength = name == null ? 0 : name.length;
721 return concatWith(array, separator);
723 int length = array == null ? 0 : array.length;
727 int size = nameLength;
730 if (array[index].length > 0)
731 size += array[index].length + 1;
732 char[] result = new char[size];
734 for (int i = 0; i < length; i++) {
735 int subLength = array[i].length;
737 System.arraycopy(array[i], 0, result, index, subLength);
739 result[index++] = separator;
742 System.arraycopy(name, 0, result, index, nameLength);
747 * Answers the concatenation of the given array parts using the given separator between each part.
753 * array = { { 'a' }, { 'b' } }
755 * => result = { 'a', '.', 'b' }
765 * @param array the given array
766 * @param separator the given separator
767 * @return the concatenation of the given array parts using the given separator between each part
769 public static final char[] concatWith(char[][] array, char separator) {
770 int length = array == null ? 0 : array.length;
772 return CharOperation.NO_CHAR;
774 int size = length - 1;
776 while (--index >= 0) {
777 if (array[index].length == 0)
780 size += array[index].length;
783 return CharOperation.NO_CHAR;
784 char[] result = new char[size];
786 while (--index >= 0) {
787 length = array[index].length;
796 result[size] = separator;
803 * Answers true if the array contains an occurrence of character, false otherwise.
811 * array = { { ' a' }, { ' b' } }
817 * array = { { ' a' }, { ' b' } }
823 * @param character the character to search
824 * @param array the array in which the search is done
825 * @return true if the array contains an occurrence of character, false otherwise.
826 * @throws NullPointerException if array is null.
828 public static final boolean contains(char character, char[][] array) {
829 for (int i = array.length; --i >= 0;) {
830 char[] subarray = array[i];
831 for (int j = subarray.length; --j >= 0;)
832 if (subarray[j] == character)
839 * Answers true if the array contains an occurrence of character, false otherwise.
853 * array = { ' a' , ' b' }
859 * @param character the character to search
860 * @param array the array in which the search is done
861 * @return true if the array contains an occurrence of character, false otherwise.
862 * @throws NullPointerException if array is null.
864 public static final boolean contains(char character, char[] array) {
865 for (int i = array.length; --i >= 0;)
866 if (array[i] == character)
872 * Answers a deep copy of the toCopy array.
874 * @param toCopy the array to copy
875 * @return a deep copy of the toCopy array.
877 public static final char[][] deepCopy(char[][] toCopy) {
878 int toCopyLength = toCopy.length;
879 char[][] result = new char[toCopyLength][];
880 for (int i = 0; i < toCopyLength; i++) {
881 char[] toElement = toCopy[i];
882 int toElementLength = toElement.length;
883 char[] resultElement = new char[toElementLength];
884 System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
885 result[i] = resultElement;
891 * Return true if array ends with the sequence of characters contained in toBeFound,
898 * array = { 'a', 'b', 'c', 'd' }
899 * toBeFound = { 'b', 'c' }
904 * array = { 'a', 'b', 'c' }
905 * toBeFound = { 'b', 'c' }
911 * @param array the array to check
912 * @param toBeFound the array to find
913 * @return true if array ends with the sequence of characters contained in toBeFound,
915 * @throws NullPointerException if array is null or toBeFound is null
917 public static final boolean endsWith(char[] array, char[] toBeFound) {
918 int i = toBeFound.length;
919 int j = array.length - i;
924 if (toBeFound[i] != array[i + j])
930 * Answers true if the two arrays are identical character by character, otherwise false.
931 * The equality is case sensitive.
949 * first = { { 'a' } }
950 * second = { { 'a' } }
955 * first = { { 'A' } }
956 * second = { { 'a' } }
961 * @param first the first array
962 * @param second the second array
963 * @return true if the two arrays are identical character by character, otherwise false
965 public static final boolean equals(char[][] first, char[][] second) {
968 if (first == null || second == null)
970 if (first.length != second.length)
973 for (int i = first.length; --i >= 0;)
974 if (!equals(first[i], second[i]))
980 * If isCaseSensite is true, answers true if the two arrays are identical character
981 * by character, otherwise false.
982 * If it is false, answers true if the two arrays are identical character by
983 * character without checking the case, otherwise false.
991 * isCaseSensitive = true
998 * isCaseSensitive = true
1003 * first = { { 'A' } }
1004 * second = { { 'a' } }
1005 * isCaseSensitive = true
1010 * first = { { 'A' } }
1011 * second = { { 'a' } }
1012 * isCaseSensitive = false
1018 * @param first the first array
1019 * @param second the second array
1020 * @param isCaseSensitive check whether or not the equality should be case sensitive
1021 * @return true if the two arrays are identical character by character according to the value
1022 * of isCaseSensitive, otherwise false
1024 public static final boolean equals(
1027 boolean isCaseSensitive) {
1029 if (isCaseSensitive) {
1030 return equals(first, second);
1032 if (first == second)
1034 if (first == null || second == null)
1036 if (first.length != second.length)
1039 for (int i = first.length; --i >= 0;)
1040 if (!equals(first[i], second[i], false))
1046 * Answers true if the two arrays are identical character by character, otherwise false.
1047 * The equality is case sensitive.
1077 * @param first the first array
1078 * @param second the second array
1079 * @return true if the two arrays are identical character by character, otherwise false
1081 public static final boolean equals(char[] first, char[] second) {
1082 if (first == second)
1084 if (first == null || second == null)
1086 if (first.length != second.length)
1089 for (int i = first.length; --i >= 0;)
1090 if (first[i] != second[i])
1096 * Answers true if the first array is identical character by character to a portion of the second array
1097 * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false.
1098 * The equality is case sensitive.
1136 * @param first the first array
1137 * @param second the second array
1138 * @param secondStart inclusive start position in the second array to compare
1139 * @param secondEnd exclusive end position in the second array to compare
1140 * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
1143 public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd) {
1144 if (first == second)
1146 if (first == null || second == null)
1148 if (first.length != secondEnd - secondStart)
1151 for (int i = first.length; --i >= 0;)
1152 if (first[i] != second[i+secondStart])
1158 * If isCaseSensite is true, answers true if the two arrays are identical character
1159 * by character, otherwise false.
1160 * If it is false, answers true if the two arrays are identical character by
1161 * character without checking the case, otherwise false.
1169 * isCaseSensitive = true
1176 * isCaseSensitive = true
1183 * isCaseSensitive = true
1190 * isCaseSensitive = false
1196 * @param first the first array
1197 * @param second the second array
1198 * @param isCaseSensitive check whether or not the equality should be case sensitive
1199 * @return true if the two arrays are identical character by character according to the value
1200 * of isCaseSensitive, otherwise false
1202 public static final boolean equals(
1205 boolean isCaseSensitive) {
1207 if (isCaseSensitive) {
1208 return equals(first, second);
1210 if (first == second)
1212 if (first == null || second == null)
1214 if (first.length != second.length)
1217 for (int i = first.length; --i >= 0;)
1218 if (Character.toLowerCase(first[i])
1219 != Character.toLowerCase(second[i]))
1224 * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive.
1226 * Answers true if the name contains the fragment at the starting index startIndex, otherwise false.
1232 * fragment = { 'b', 'c' , 'd' }
1233 * name = { 'a', 'b', 'c' , 'd' }
1235 * isCaseSensitive = true
1240 * fragment = { 'b', 'c' , 'd' }
1241 * name = { 'a', 'b', 'C' , 'd' }
1243 * isCaseSensitive = true
1248 * fragment = { 'b', 'c' , 'd' }
1249 * name = { 'a', 'b', 'C' , 'd' }
1251 * isCaseSensitive = false
1256 * fragment = { 'b', 'c' , 'd' }
1257 * name = { 'a', 'b'}
1259 * isCaseSensitive = true
1265 * @param fragment the fragment to check
1266 * @param name the array to check
1267 * @param startIndex the starting index
1268 * @param isCaseSensitive check whether or not the equality should be case sensitive
1269 * @return true if the name contains the fragment at the starting index startIndex according to the
1270 * value of isCaseSensitive, otherwise false.
1271 * @throws NullPointerException if fragment or name is null.
1273 public static final boolean fragmentEquals(
1277 boolean isCaseSensitive) {
1279 int max = fragment.length;
1280 if (name.length < max + startIndex)
1282 if (isCaseSensitive) {
1285 ) // assumes the prefix is not larger than the name
1286 if (fragment[i] != name[i + startIndex])
1292 ) // assumes the prefix is not larger than the name
1293 if (Character.toLowerCase(fragment[i])
1294 != Character.toLowerCase(name[i + startIndex]))
1300 * Answers a hashcode for the array
1302 * @param array the array for which a hashcode is required
1303 * @return the hashcode
1304 * @throws NullPointerException if array is null
1306 public static final int hashCode(char[] array) {
1309 int length = array.length;
1311 for (int i = length; i > 0; i--)
1312 hash = (hash * 37) + array[offset++];
1314 // only sample some characters
1315 int skip = length / 8;
1316 for (int i = length; i > 0; i -= skip, offset += skip)
1317 hash = (hash * 39) + array[offset];
1319 return hash & 0x7FFFFFFF;
1322 * Answers true if c is a whitespace according to the JLS (\u000a, \u000c, \u000d, \u0009), otherwise false.
1339 * @param c the character to check
1340 * @return true if c is a whitespace according to the JLS, otherwise false.
1342 public static boolean isWhitespace(char c) {
1344 case 10 : /* \ u000a: LINE FEED */
1345 case 12 : /* \ u000c: FORM FEED */
1346 case 13 : /* \ u000d: CARRIAGE RETURN */
1347 case 32 : /* \ u0020: SPACE */
1348 case 9 : /* \ u0009: HORIZONTAL TABULATION */
1356 * Answers the first index in the array for which the corresponding character is
1357 * equal to toBeFound. Answers -1 if no occurrence of this character is found.
1364 * array = { ' a', 'b', 'c', 'd' }
1370 * array = { ' a', 'b', 'c', 'd' }
1376 * @param toBeFound the character to search
1377 * @param array the array to be searched
1378 * @return the first index in the array for which the corresponding character is
1379 * equal to toBeFound, -1 otherwise
1380 * @throws NullPointerException if array is null
1382 public static final int indexOf(char toBeFound, char[] array) {
1383 for (int i = 0; i < array.length; i++)
1384 if (toBeFound == array[i])
1390 * Answers the first index in the array for which the corresponding character is
1391 * equal to toBeFound starting the search at index start.
1392 * Answers -1 if no occurrence of this character is found.
1399 * array = { ' a', 'b', 'c', 'd' }
1406 * array = { ' a', 'b', 'c', 'd' }
1413 * array = { ' a', 'b', 'c', 'd' }
1420 * @param toBeFound the character to search
1421 * @param array the array to be searched
1422 * @param start the starting index
1423 * @return the first index in the array for which the corresponding character is
1424 * equal to toBeFound, -1 otherwise
1425 * @throws NullPointerException if array is null
1426 * @throws ArrayIndexOutOfBoundsException if start is lower than 0
1428 public static final int indexOf(char toBeFound, char[] array, int start) {
1429 for (int i = start; i < array.length; i++)
1430 if (toBeFound == array[i])
1436 * Answers the last index in the array for which the corresponding character is
1437 * equal to toBeFound starting from the end of the array.
1438 * Answers -1 if no occurrence of this character is found.
1445 * array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
1451 * array = { ' a', 'b', 'c', 'd' }
1457 * @param toBeFound the character to search
1458 * @param array the array to be searched
1459 * @return the last index in the array for which the corresponding character is
1460 * equal to toBeFound starting from the end of the array, -1 otherwise
1461 * @throws NullPointerException if array is null
1463 public static final int lastIndexOf(char toBeFound, char[] array) {
1464 for (int i = array.length; --i >= 0;)
1465 if (toBeFound == array[i])
1471 * Answers the last index in the array for which the corresponding character is
1472 * equal to toBeFound stopping at the index startIndex.
1473 * Answers -1 if no occurrence of this character is found.
1480 * array = { ' a', 'b', 'c', 'd' }
1487 * array = { ' a', 'b', 'c', 'd', 'e' }
1494 * array = { ' a', 'b', 'c', 'd' }
1501 * @param toBeFound the character to search
1502 * @param array the array to be searched
1503 * @param startIndex the stopping index
1504 * @return the last index in the array for which the corresponding character is
1505 * equal to toBeFound stopping at the index startIndex, -1 otherwise
1506 * @throws NullPointerException if array is null
1507 * @throws ArrayIndexOutOfBoundsException if startIndex is lower than 0
1509 public static final int lastIndexOf(
1513 for (int i = array.length; --i >= startIndex;)
1514 if (toBeFound == array[i])
1520 * Answers the last index in the array for which the corresponding character is
1521 * equal to toBeFound starting from endIndex to startIndex.
1522 * Answers -1 if no occurrence of this character is found.
1529 * array = { ' a', 'b', 'c', 'd' }
1537 * array = { ' a', 'b', 'c', 'd', 'e' }
1545 * array = { ' a', 'b', 'c', 'd' }
1553 * @param toBeFound the character to search
1554 * @param array the array to be searched
1555 * @param startIndex the stopping index
1556 * @param endIndex the starting index
1557 * @return the last index in the array for which the corresponding character is
1558 * equal to toBeFound starting from endIndex to startIndex, -1 otherwise
1559 * @throws NullPointerException if array is null
1560 * @throws ArrayIndexOutOfBoundsException if endIndex is greater or equals to array length or starting is lower than 0
1562 public static final int lastIndexOf(
1567 for (int i = endIndex; --i >= startIndex;)
1568 if (toBeFound == array[i])
1574 * Answers the last portion of a name given a separator.
1579 * lastSegment("java.lang.Object".toCharArray(),'.') --> Object
1582 * @param array the array
1583 * @param separator the given separator
1584 * @return the last portion of a name given a separator
1585 * @throws NullPointerException if array is null
1587 final static public char[] lastSegment(char[] array, char separator) {
1588 int pos = lastIndexOf(separator, array);
1591 return subarray(array, pos + 1, array.length);
1595 * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching
1596 * accepts wild-cards '*' and '?'.
1598 * When not case sensitive, the pattern is assumed to already be lowercased, the
1599 * name will be lowercased character per character as comparing.
1600 * If name is null, the answer is false.
1601 * If pattern is null, the answer is true if name is not null.
1607 * pattern = { '?', 'b', '*' }
1608 * name = { 'a', 'b', 'c' , 'd' }
1609 * isCaseSensitive = true
1614 * pattern = { '?', 'b', '?' }
1615 * name = { 'a', 'b', 'c' , 'd' }
1616 * isCaseSensitive = true
1621 * pattern = { 'b', '*' }
1622 * name = { 'a', 'b', 'c' , 'd' }
1623 * isCaseSensitive = true
1629 * @param pattern the given pattern
1630 * @param name the given name
1631 * @param isCaseSensitive flag to know whether or not the matching should be case sensitive
1632 * @return true if the pattern matches the given name, false otherwise
1634 public static final boolean match(
1637 boolean isCaseSensitive) {
1640 return false; // null name cannot match
1641 if (pattern == null)
1642 return true; // null pattern is equivalent to '*'
1655 * Answers true if the a sub-pattern matches the subpart of the given name, false otherwise.
1656 * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only subset of name/pattern.
1657 * end positions are non-inclusive.
1658 * The subpattern is defined by the patternStart and pattternEnd positions.
1659 * When not case sensitive, the pattern is assumed to already be lowercased, the
1660 * name will be lowercased character per character as comparing.
1666 * pattern = { '?', 'b', '*' }
1669 * name = { 'a', 'b', 'c' , 'd' }
1672 * isCaseSensitive = true
1677 * pattern = { '?', 'b', '*' }
1680 * name = { 'a', 'b', 'c' , 'd' }
1683 * isCaseSensitive = true
1689 * @param pattern the given pattern
1690 * @param patternStart the given pattern start
1691 * @param patternEnd the given pattern end
1692 * @param name the given name
1693 * @param nameStart the given name start
1694 * @param nameEnd the given name end
1695 * @param isCaseSensitive flag to know if the matching should be case sensitive
1696 * @return true if the a sub-pattern matches the subpart of the given name, false otherwise
1698 public static final boolean match(
1705 boolean isCaseSensitive) {
1708 return false; // null name cannot match
1709 if (pattern == null)
1710 return true; // null pattern is equivalent to '*'
1711 int iPattern = patternStart;
1712 int iName = nameStart;
1715 patternEnd = pattern.length;
1717 nameEnd = name.length;
1719 /* check first segment */
1720 char patternChar = 0;
1721 while ((iPattern < patternEnd)
1722 && (patternChar = pattern[iPattern]) != '*') {
1723 if (iName == nameEnd)
1728 : Character.toLowerCase(name[iName]))
1729 && patternChar != '?') {
1735 /* check sequence of star+segment */
1737 if (patternChar == '*') {
1738 segmentStart = ++iPattern; // skip star
1740 segmentStart = 0; // force iName check
1742 int prefixStart = iName;
1743 checkSegment : while (iName < nameEnd) {
1744 if (iPattern == patternEnd) {
1745 iPattern = segmentStart; // mismatch - restart current segment
1746 iName = ++prefixStart;
1747 continue checkSegment;
1749 /* segment is ending */
1750 if ((patternChar = pattern[iPattern]) == '*') {
1751 segmentStart = ++iPattern; // skip start
1752 if (segmentStart == patternEnd) {
1755 prefixStart = iName;
1756 continue checkSegment;
1758 /* check current name character */
1759 if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName]))
1761 && patternChar != '?') {
1762 iPattern = segmentStart; // mismatch - restart current segment
1763 iName = ++prefixStart;
1764 continue checkSegment;
1770 return (segmentStart == patternEnd)
1771 || (iName == nameEnd && iPattern == patternEnd)
1772 || (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
1776 * Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
1778 * Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks
1779 * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
1780 * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
1781 * any folder combination.
1783 * - foo\ is equivalent to foo\**
1784 * When not case sensitive, the pattern is assumed to already be lowercased, the
1785 * name will be lowercased character per character as comparing.
1787 * @param pattern the given pattern
1788 * @param filepath the given path
1789 * @param isCaseSensitive to find out whether or not the matching should be case sensitive
1790 * @param pathSeparator the given path separator
1791 * @return true if the pattern matches the filepath using the pathSepatator, false otherwise
1793 public static final boolean pathMatch(
1796 boolean isCaseSensitive,
1797 char pathSeparator) {
1799 if (filepath == null)
1800 return false; // null name cannot match
1801 if (pattern == null)
1802 return true; // null pattern is equivalent to '*'
1804 // offsets inside pattern
1805 int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
1806 int pLength = pattern.length;
1807 int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart+1);
1808 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1810 // special case: pattern foo\ is equivalent to foo\**
1811 boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
1813 // offsets inside filepath
1814 int fSegmentStart, fLength = filepath.length;
1815 if (filepath[0] != pathSeparator){
1820 if (fSegmentStart != pSegmentStart) {
1821 return false; // both must start with a separator or none.
1823 int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart+1);
1824 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1827 while (pSegmentStart < pLength
1828 && !(pSegmentEnd == pLength && freeTrailingDoubleStar
1829 || (pSegmentEnd == pSegmentStart + 2
1830 && pattern[pSegmentStart] == '*'
1831 && pattern[pSegmentStart + 1] == '*'))) {
1833 if (fSegmentStart >= fLength)
1847 // jump to next segment
1849 CharOperation.indexOf(
1852 pSegmentStart = pSegmentEnd + 1);
1854 if (pSegmentEnd < 0)
1855 pSegmentEnd = pLength;
1858 CharOperation.indexOf(
1861 fSegmentStart = fSegmentEnd + 1);
1863 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1866 /* check sequence of doubleStar+segment */
1867 int pSegmentRestart;
1868 if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
1869 || (pSegmentEnd == pSegmentStart + 2
1870 && pattern[pSegmentStart] == '*'
1871 && pattern[pSegmentStart + 1] == '*')) {
1873 CharOperation.indexOf(
1876 pSegmentStart = pSegmentEnd + 1);
1878 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1879 pSegmentRestart = pSegmentStart;
1881 if (pSegmentStart >= pLength) return fSegmentStart >= fLength; // true if filepath is done too.
1882 pSegmentRestart = 0; // force fSegmentStart check
1884 int fSegmentRestart = fSegmentStart;
1885 checkSegment : while (fSegmentStart < fLength) {
1887 if (pSegmentStart >= pLength) {
1888 if (freeTrailingDoubleStar) return true;
1889 // mismatch - restart current path segment
1891 CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
1892 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1895 CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
1897 if (fSegmentRestart < 0) {
1898 fSegmentRestart = fLength;
1903 CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
1904 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1905 continue checkSegment;
1908 /* path segment is ending */
1909 if (pSegmentEnd == pSegmentStart + 2
1910 && pattern[pSegmentStart] == '*'
1911 && pattern[pSegmentStart + 1] == '*') {
1913 CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
1915 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1916 pSegmentRestart = pSegmentStart;
1917 fSegmentRestart = fSegmentStart;
1918 if (pSegmentStart >= pLength) return true;
1919 continue checkSegment;
1921 /* chech current path segment */
1922 if (!CharOperation.match(
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;
1948 // jump to next segment
1950 CharOperation.indexOf(
1953 pSegmentStart = pSegmentEnd + 1);
1955 if (pSegmentEnd < 0)
1956 pSegmentEnd = pLength;
1959 CharOperation.indexOf(
1962 fSegmentStart = fSegmentEnd + 1);
1964 if (fSegmentEnd < 0)
1965 fSegmentEnd = fLength;
1968 return (pSegmentRestart >= pSegmentEnd)
1969 || (fSegmentStart >= fLength && pSegmentStart >= pLength)
1970 || (pSegmentStart == pLength - 2
1971 && pattern[pSegmentStart] == '*'
1972 && pattern[pSegmentStart + 1] == '*')
1973 || (pSegmentStart == pLength && freeTrailingDoubleStar);
1977 * Answers the number of occurrences of the given character in the given array, 0 if any.
1985 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
1991 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
1997 * @param toBeFound the given character
1998 * @param array the given array
1999 * @return the number of occurrences of the given character in the given array, 0 if any
2000 * @throws NullPointerException if array is null
2002 public static final int occurencesOf(char toBeFound, char[] array) {
2004 for (int i = 0; i < array.length; i++)
2005 if (toBeFound == array[i])
2011 * Answers the number of occurrences of the given character in the given array starting
2012 * at the given index, 0 if any.
2020 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2027 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2034 * @param toBeFound the given character
2035 * @param array the given array
2036 * @param start the given index
2037 * @return the number of occurrences of the given character in the given array, 0 if any
2038 * @throws NullPointerException if array is null
2039 * @throws ArrayIndexOutOfBoundsException if start is lower than 0
2041 public static final int occurencesOf(
2046 for (int i = start; i < array.length; i++)
2047 if (toBeFound == array[i])
2053 * Answers true if the given name starts with the given prefix, false otherwise.
2054 * The comparison is case sensitive.
2060 * prefix = { 'a' , 'b' }
2061 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2066 * prefix = { 'a' , 'c' }
2067 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2073 * @param prefix the given prefix
2074 * @param name the given name
2075 * @return true if the given name starts with the given prefix, false otherwise
2076 * @throws NullPointerException if the given name is null or if the given prefix is null
2078 public static final boolean prefixEquals(char[] prefix, char[] name) {
2080 int max = prefix.length;
2081 if (name.length < max)
2085 ) // assumes the prefix is not larger than the name
2086 if (prefix[i] != name[i])
2092 * Answers true if the given name starts with the given prefix, false otherwise.
2093 * isCaseSensitive is used to find out whether or not the comparison should be case sensitive.
2099 * prefix = { 'a' , 'B' }
2100 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2101 * isCaseSensitive = false
2106 * prefix = { 'a' , 'B' }
2107 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2108 * isCaseSensitive = true
2114 * @param prefix the given prefix
2115 * @param name the given name
2116 * @param isCaseSensitive to find out whether or not the comparison should be case sensitive
2117 * @return true if the given name starts with the given prefix, false otherwise
2118 * @throws NullPointerException if the given name is null or if the given prefix is null
2120 public static final boolean prefixEquals(
2123 boolean isCaseSensitive) {
2125 int max = prefix.length;
2126 if (name.length < max)
2128 if (isCaseSensitive) {
2131 ) // assumes the prefix is not larger than the name
2132 if (prefix[i] != name[i])
2139 ) // assumes the prefix is not larger than the name
2140 if (Character.toLowerCase(prefix[i])
2141 != Character.toLowerCase(name[i]))
2147 * Replace all occurrence of the character to be replaced with the remplacement character in the
2154 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2155 * toBeReplaced = 'b'
2156 * replacementChar = 'a'
2157 * result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
2161 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2162 * toBeReplaced = 'c'
2163 * replacementChar = 'a'
2164 * result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
2169 * @param array the given array
2170 * @param toBeReplaced the character to be replaced
2171 * @param replacementChar the replacement character
2172 * @throws NullPointerException if the given array is null
2174 public static final void replace(
2177 char replacementChar) {
2178 if (toBeReplaced != replacementChar) {
2179 for (int i = 0, max = array.length; i < max; i++) {
2180 if (array[i] == toBeReplaced)
2181 array[i] = replacementChar;
2187 * Answers a new array of characters with substitutions. No side-effect is operated on the original
2188 * array, in case no substitution happened, then the result is the same as the
2195 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2196 * toBeReplaced = { 'b' }
2197 * replacementChar = { 'a', 'a' }
2198 * result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
2202 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2203 * toBeReplaced = { 'c' }
2204 * replacementChar = { 'a' }
2205 * result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
2210 * @param array the given array
2211 * @param toBeReplaced characters to be replaced
2212 * @param replacementChars the replacement characters
2213 * @return a new array of characters with substitutions or the given array if none
2214 * @throws NullPointerException if the given array is null
2216 public static final char[] replace(
2218 char[] toBeReplaced,
2219 char[] replacementChars) {
2221 int max = array.length;
2222 int replacedLength = toBeReplaced.length;
2223 int replacementLength = replacementChars.length;
2225 int[] starts = new int[5];
2226 int occurrenceCount = 0;
2228 if (!equals(toBeReplaced, replacementChars)) {
2230 next : for (int i = 0; i < max; i++) {
2232 while (j < replacedLength) {
2235 if (array[i + j] != toBeReplaced[j++])
2238 if (occurrenceCount == starts.length) {
2242 starts = new int[occurrenceCount * 2],
2246 starts[occurrenceCount++] = i;
2249 if (occurrenceCount == 0)
2253 + occurrenceCount * (replacementLength - replacedLength)];
2254 int inStart = 0, outStart = 0;
2255 for (int i = 0; i < occurrenceCount; i++) {
2256 int offset = starts[i] - inStart;
2257 System.arraycopy(array, inStart, result, outStart, offset);
2266 inStart += replacedLength;
2267 outStart += replacementLength;
2269 System.arraycopy(array, inStart, result, outStart, max - inStart);
2274 * Return a new array which is the split of the given array using the given divider and triming each subarray to remove
2275 * whitespaces equals to ' '.
2282 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2283 * result => { { 'a' }, { }, { 'a' }, { 'a' } }
2288 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2289 * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2294 * array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
2295 * result => { { 'a' }, { }, { 'a' }, { 'a' } }
2300 * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
2301 * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2306 * @param divider the given divider
2307 * @param array the given array
2308 * @return a new array which is the split of the given array using the given divider and triming each subarray to remove
2309 * whitespaces equals to ' '
2311 public static final char[][] splitAndTrimOn(char divider, char[] array) {
2312 int length = array == null ? 0 : array.length;
2314 return NO_CHAR_CHAR;
2317 for (int i = 0; i < length; i++)
2318 if (array[i] == divider)
2320 char[][] split = new char[wordCount][];
2321 int last = 0, currentWord = 0;
2322 for (int i = 0; i < length; i++) {
2323 if (array[i] == divider) {
2324 int start = last, end = i - 1;
2325 while (start < i && array[start] == ' ')
2327 while (end > start && array[end] == ' ')
2329 split[currentWord] = new char[end - start + 1];
2333 split[currentWord++],
2339 int start = last, end = length - 1;
2340 while (start < length && array[start] == ' ')
2342 while (end > start && array[end] == ' ')
2344 split[currentWord] = new char[end - start + 1];
2348 split[currentWord++],
2355 * Return a new array which is the split of the given array using the given divider.
2362 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2363 * result => { { 'a' }, { }, { 'a' }, { 'a' } }
2368 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2369 * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2374 * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
2375 * result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
2380 * @param divider the given divider
2381 * @param array the given array
2382 * @return a new array which is the split of the given array using the given divider
2384 public static final char[][] splitOn(char divider, char[] array) {
2385 int length = array == null ? 0 : array.length;
2387 return NO_CHAR_CHAR;
2390 for (int i = 0; i < length; i++)
2391 if (array[i] == divider)
2393 char[][] split = new char[wordCount][];
2394 int last = 0, currentWord = 0;
2395 for (int i = 0; i < length; i++) {
2396 if (array[i] == divider) {
2397 split[currentWord] = new char[i - last];
2401 split[currentWord++],
2407 split[currentWord] = new char[length - last];
2408 System.arraycopy(array, last, split[currentWord], 0, length - last);
2413 * Return a new array which is the split of the given array using the given divider. The given end
2414 * is exclusive and the given start is inclusive.
2421 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2424 * result => { { }, { 'a' }, { } }
2429 * @param divider the given divider
2430 * @param array the given array
2431 * @param start the given starting index
2432 * @param end the given ending index
2433 * @return a new array which is the split of the given array using the given divider
2434 * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
2436 public static final char[][] splitOn(
2441 int length = array == null ? 0 : array.length;
2442 if (length == 0 || start > end)
2443 return NO_CHAR_CHAR;
2446 for (int i = start; i < end; i++)
2447 if (array[i] == divider)
2449 char[][] split = new char[wordCount][];
2450 int last = start, currentWord = 0;
2451 for (int i = start; i < end; i++) {
2452 if (array[i] == divider) {
2453 split[currentWord] = new char[i - last];
2457 split[currentWord++],
2463 split[currentWord] = new char[end - last];
2464 System.arraycopy(array, last, split[currentWord], 0, end - last);
2469 * Answers a new array which is a copy of the given array starting at the given start and
2470 * ending at the given end. The given start is inclusive and the given end is exclusive.
2471 * Answers null if start is greater than end, if start is lower than 0 or if end is greater
2472 * than the length of the given array. If end equals -1, it is converted to the array length.
2478 * array = { { 'a' } , { 'b' } }
2481 * result => { { 'a' } }
2485 * array = { { 'a' } , { 'b' } }
2488 * result => { { 'a' }, { 'b' } }
2493 * @param array the given array
2494 * @param start the given starting index
2495 * @param end the given ending index
2496 * @return a new array which is a copy of the given array starting at the given start and
2497 * ending at the given end
2498 * @throws NullPointerException if the given array is null
2500 public static final char[][] subarray(char[][] array, int start, int end) {
2507 if (end > array.length)
2510 char[][] result = new char[end - start][];
2511 System.arraycopy(array, start, result, 0, end - start);
2516 * Answers a new array which is a copy of the given array starting at the given start and
2517 * ending at the given end. The given start is inclusive and the given end is exclusive.
2518 * Answers null if start is greater than end, if start is lower than 0 or if end is greater
2519 * than the length of the given array. If end equals -1, it is converted to the array length.
2525 * array = { 'a' , 'b' }
2532 * array = { 'a', 'b' }
2535 * result => { 'a' , 'b' }
2540 * @param array the given array
2541 * @param start the given starting index
2542 * @param end the given ending index
2543 * @return a new array which is a copy of the given array starting at the given start and
2544 * ending at the given end
2545 * @throws NullPointerException if the given array is null
2547 public static final char[] subarray(char[] array, int start, int end) {
2554 if (end > array.length)
2557 char[] result = new char[end - start];
2558 System.arraycopy(array, start, result, 0, end - start);
2562 * Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null.
2564 * NOTE: If no conversion was necessary, then answers back the argument one.
2570 * chars = { 'a' , 'b' }
2571 * result => { 'a' , 'b' }
2575 * array = { 'A', 'b' }
2576 * result => { 'a' , 'b' }
2581 * @param chars the chars to convert
2582 * @return the result of a char[] conversion to lowercase
2584 final static public char[] toLowerCase(char[] chars) {
2587 int length = chars.length;
2588 char[] lowerChars = null;
2589 for (int i = 0; i < length; i++) {
2591 char lc = Character.toLowerCase(c);
2592 if ((c != lc) || (lowerChars != null)) {
2593 if (lowerChars == null) {
2597 lowerChars = new char[length],
2604 return lowerChars == null ? chars : lowerChars;
2608 * Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no
2609 * space characters to remove.
2615 * chars = { ' ', 'a' , 'b', ' ', ' ' }
2616 * result => { 'a' , 'b' }
2620 * array = { 'A', 'b' }
2621 * result => { 'A' , 'b' }
2626 * @param chars the given array
2627 * @return a new array removing leading and trailing spaces (' ')
2629 final static public char[] trim(char[] chars) {
2634 int start = 0, length = chars.length, end = length - 1;
2635 while (start < length && chars[start] == ' ') {
2638 while (end > start && chars[end] == ' ') {
2641 if (start != 0 || end != length - 1) {
2642 return subarray(chars, start, end + 1);
2648 * Answers a string which is the concatenation of the given array using the '.' as a separator.
2654 * array = { { 'a' } , { 'b' } }
2659 * array = { { ' ', 'a' } , { 'b' } }
2665 * @param array the given array
2666 * @return a string which is the concatenation of the given array using the '.' as a separator
2668 final static public String toString(char[][] array) {
2669 char[] result = concatWith(array, '.');
2670 return new String(result);
2673 * Answers an array of strings from the given array of char array.
2675 * @param array the given array
2676 * @return an array of strings
2679 final static public String[] toStrings(char[][] array) {
2680 int length = array.length;
2681 String[] result = new String[length];
2682 for (int i = 0; i < length; i++)
2683 result[i] = new String(array[i]);