1
/*******************************************************************************
2
* Copyright (c) 2010 Alena Laskavaia and others.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* Alena Laskavaia - initial API and implementation
10
*******************************************************************************/
11
package org.eclipse.cdt.codan.internal.core;
14
* This class is a collection of helper methods to manipulate char arrays.
18
public final class CharOperation {
20
* Constant for an empty char array
22
public static final char[] NO_CHAR = new char[0];
24
* Constant for an empty char array with two dimensions.
26
public static final char[][] NO_CHAR_CHAR = new char[0][];
29
* Answers a new array with appending the suffix character at the end of the
36
* array = { 'a', 'b' }
38
* => result = { 'a', 'b' , 'c' }
49
* the array that is concanated with the suffix character
51
* the suffix character
52
* @return the new array
54
public static final char[] append(char[] array, char suffix) {
56
return new char[] { suffix };
57
int length = array.length;
58
System.arraycopy(array, 0, array = new char[length + 1], 0, length);
59
array[length] = suffix;
64
* Append the given subarray to the target array starting at the given index
65
* in the target array.
66
* The start of the subarray is inclusive, the end is exclusive.
67
* Answers a new target array if it needs to grow, otherwise answers the
73
* target = { 'a', 'b', '0' }
75
* array = { 'c', 'd' }
78
* => result = { 'a', 'b' , 'c' }
82
* target = { 'a', 'b' }
84
* array = { 'c', 'd' }
87
* => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
90
* target = { 'a', 'b', 'c' }
92
* array = { 'c', 'd', 'e', 'f' }
95
* => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
106
* the given start index
108
* the given end index
110
* @return the new array
111
* @throws NullPointerException
112
* if the target array is null
114
public static final char[] append(char[] target, int index, char[] array, int start, int end) {
115
int targetLength = target.length;
116
int subLength = end - start;
117
int newTargetLength = subLength + index;
118
if (newTargetLength > targetLength) {
119
System.arraycopy(target, 0, target = new char[newTargetLength * 2], 0, index);
121
System.arraycopy(array, start, target, index, subLength);
126
* Answers the concatenation of the two arrays. It answers null if the two
128
* If the first array is null, then the second array is returned.
129
* If the second array is null, then the first array is returned.
141
* first = { { ' a' } }
143
* => result = { { ' a' } }
148
* second = { { ' a' } }
149
* => result = { { ' a' } }
153
* first = { { ' b' } }
154
* second = { { ' a' } }
155
* => result = { { ' b' }, { ' a' } }
161
* the first array to concatenate
163
* the second array to concatenate
164
* @return the concatenation of the two arrays, or null if the two arrays
167
public static final char[][] arrayConcat(char[][] first, char[][] second) {
172
int length1 = first.length;
173
int length2 = second.length;
174
char[][] result = new char[length1 + length2][];
175
System.arraycopy(first, 0, result, 0, length1);
176
System.arraycopy(second, 0, result, length1, length2);
181
* Answers a new array adding the second array at the end of first array.
182
* It answers null if the first and second are null.
183
* If the first array is null, then a new array char[][] is created with
185
* If the second array is null, then the first array is returned.
193
* => result = { { ' a' } }
196
* first = { { ' a' } }
198
* => result = { { ' a' } }
202
* first = { { ' a' } }
204
* => result = { { ' a' } , { ' b' } }
210
* the first array to concatenate
212
* the array to add at the end of the first array
213
* @return a new array adding the second array at the end of first array, or
214
* null if the two arrays are null.
216
public static final char[][] arrayConcat(char[][] first, char[] second) {
220
return new char[][] { second };
221
int length = first.length;
222
char[][] result = new char[length + 1][];
223
System.arraycopy(first, 0, result, 0, length);
224
result[length] = second;
229
* Compares the contents of the two arrays array and prefix. Returns
231
* <li>zero if the array starts with the prefix contents</li>
232
* <li>the difference between the first two characters that are not equal
234
* <li>one if array length is lower than the prefix length and that the
235
* prefix starts with the
236
* array contents.</li>
244
* => result = NullPointerException
248
* array = { 'a', 'b', 'c', 'd', 'e' }
249
* prefix = { 'a', 'b', 'c'}
254
* array = { 'a', 'b', 'c', 'd', 'e' }
255
* prefix = { 'a', 'B', 'c'}
260
* array = { 'd', 'b', 'c', 'd', 'e' }
261
* prefix = { 'a', 'b', 'c'}
266
* array = { 'a', 'b', 'c', 'd', 'e' }
267
* prefix = { 'd', 'b', 'c'}
272
* array = { 'a', 'a', 'c', 'd', 'e' }
273
* prefix = { 'a', 'e', 'c'}
284
* @return the result of the comparison
285
* @exception NullPointerException
286
* if either array or prefix is null
288
public static final int compareWith(char[] array, char[] prefix) {
289
int arrayLength = array.length;
290
int prefixLength = prefix.length;
291
int min = Math.min(arrayLength, prefixLength);
295
char c2 = prefix[i++];
299
if (prefixLength == i)
305
* Answers the concatenation of the two arrays. It answers null if the two
307
* If the first array is null, then the second array is returned.
308
* If the second array is null, then the first array is returned.
316
* => result = { ' a' }
322
* => result = { ' a' }
328
* => result = { ' a' , ' b' }
334
* the first array to concatenate
336
* the second array to concatenate
337
* @return the concatenation of the two arrays, or null if the two arrays
340
public static final char[] concat(char[] first, char[] second) {
345
int length1 = first.length;
346
int length2 = second.length;
347
char[] result = new char[length1 + length2];
348
System.arraycopy(first, 0, result, 0, length1);
349
System.arraycopy(second, 0, result, length1, length2);
354
* Answers the concatenation of the three arrays. It answers null if the
355
* three arrays are null.
356
* If first is null, it answers the concatenation of second and third.
357
* If second is null, it answers the concatenation of first and third.
358
* If third is null, it answers the concatenation of first and second.
367
* => result = { ' a', 'b' }
374
* => result = { ' a', 'b' }
381
* => result = { ' a', 'b' }
395
* => result = { 'a', 'b', 'c' }
401
* the first array to concatenate
403
* the second array to concatenate
405
* the third array to concatenate
407
* @return the concatenation of the three arrays, or null if the three
410
public static final char[] concat(char[] first, char[] second, char[] third) {
412
return concat(second, third);
414
return concat(first, third);
416
return concat(first, second);
417
int length1 = first.length;
418
int length2 = second.length;
419
int length3 = third.length;
420
char[] result = new char[length1 + length2 + length3];
421
System.arraycopy(first, 0, result, 0, length1);
422
System.arraycopy(second, 0, result, length1, length2);
423
System.arraycopy(third, 0, result, length1 + length2, length3);
428
* Answers the concatenation of the two arrays inserting the separator
429
* character between the two arrays.
430
* It answers null if the two arrays are null.
431
* If the first array is null, then the second array is returned.
432
* If the second array is null, then the first array is returned.
441
* => result = { ' a' }
448
* => result = { ' a' }
455
* => result = { ' a' , '/', 'b' }
461
* the first array to concatenate
463
* the second array to concatenate
465
* the character to insert
466
* @return the concatenation of the two arrays inserting the separator
468
* between the two arrays , or null if the two arrays are null.
470
public static final char[] concat(char[] first, char[] second, char separator) {
475
int length1 = first.length;
478
int length2 = second.length;
481
char[] result = new char[length1 + length2 + 1];
482
System.arraycopy(first, 0, result, 0, length1);
483
result[length1] = separator;
484
System.arraycopy(second, 0, result, length1 + 1, length2);
489
* Answers the concatenation of the three arrays inserting the sep1
490
* character between the
491
* two arrays and sep2 between the last two.
492
* It answers null if the three arrays are null.
493
* If the first array is null, then it answers the concatenation of second
494
* and third inserting
495
* the sep2 character between them.
496
* If the second array is null, then it answers the concatenation of first
497
* and third inserting
498
* the sep1 character between them.
499
* If the third array is null, then it answers the concatenation of first
500
* and second inserting
501
* the sep1 character between them.
512
* => result = { ' a' , ':', 'b' }
521
* => result = { ' a' , '/', 'b' }
530
* => result = { ' a' , '/', 'b' }
539
* => result = { ' a' , '/', 'b' , ':', 'c' }
545
* the first array to concatenate
547
* the character to insert
549
* the second array to concatenate
551
* the character to insert
553
* the second array to concatenate
554
* @return the concatenation of the three arrays inserting the sep1
555
* character between the
556
* two arrays and sep2 between the last two.
558
public static final char[] concat(char[] first, char sep1, char[] second, char sep2, char[] third) {
560
return concat(second, third, sep2);
562
return concat(first, third, sep1);
564
return concat(first, second, sep1);
565
int length1 = first.length;
566
int length2 = second.length;
567
int length3 = third.length;
568
char[] result = new char[length1 + length2 + length3 + 2];
569
System.arraycopy(first, 0, result, 0, length1);
570
result[length1] = sep1;
571
System.arraycopy(second, 0, result, length1 + 1, length2);
572
result[length1 + length2 + 1] = sep2;
573
System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
578
* Answers a new array with prepending the prefix character and appending
580
* character at the end of the array. If array is null, it answers a new
581
* array containing the
582
* prefix and the suffix characters.
591
* => result = { 'a', 'b' , 'c' }
598
* => result = { 'a', 'c' }
603
* the prefix character
605
* the array that is concanated with the prefix and suffix
608
* 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 };
614
int length = array.length;
615
char[] result = new char[length + 2];
617
System.arraycopy(array, 0, result, 1, length);
618
result[length + 1] = suffix;
623
* Answers the concatenation of the given array parts using the given
624
* 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' }
656
* the given separator
657
* @return the concatenation of the given array parts using the given
658
* separator between each
659
* part and appending the given name at the end
661
public static final char[] concatWith(char[] name, char[][] array, char separator) {
662
int nameLength = name == null ? 0 : name.length;
664
return concatWith(array, separator);
667
final int length = array.length;
670
int size = nameLength;
673
if (array[index].length > 0)
674
size += array[index].length + 1;
675
char[] result = new char[size];
677
for (int i = length - 1; i >= 0; i--) {
678
int subLength = array[i].length;
681
System.arraycopy(array[i], 0, result, index, subLength);
682
result[--index] = separator;
685
System.arraycopy(name, 0, result, 0, nameLength);
690
* Answers the concatenation of the given array parts using the given
691
* separator between each
692
* part and appending the given name at the end.
699
* array = { { 'a' }, { 'b' } }
701
* => result = { 'a', '.', 'b' , '.', 'c' }
706
* array = { { 'a' }, { 'b' } }
708
* => result = { 'a', '.', 'b' }
714
* => result = { 'c' }
723
* the given separator
724
* @return the concatenation of the given array parts using the given
725
* separator between each
726
* part and appending the given name at the end
728
public static final char[] concatWith(char[][] array, char[] name, char separator) {
729
int nameLength = name == null ? 0 : name.length;
731
return concatWith(array, separator);
734
final int length = array.length;
737
int size = nameLength;
740
if (array[index].length > 0)
741
size += array[index].length + 1;
742
char[] result = new char[size];
744
for (int i = 0; i < length; i++) {
745
int subLength = array[i].length;
747
System.arraycopy(array[i], 0, result, index, subLength);
749
result[index++] = separator;
752
System.arraycopy(name, 0, result, index, nameLength);
757
* Answers the concatenation of the given array parts using the given
758
* separator between each part.
764
* array = { { 'a' }, { 'b' } }
766
* => result = { 'a', '.', 'b' }
779
* the given separator
780
* @return the concatenation of the given array parts using the given
781
* separator between each part
783
public static final char[] concatWith(char[][] array, char separator) {
785
return CharOperation.NO_CHAR;
786
int length = array.length;
788
return CharOperation.NO_CHAR;
789
int size = length - 1;
791
while (--index >= 0) {
792
if (array[index].length == 0)
795
size += array[index].length;
798
return CharOperation.NO_CHAR;
799
char[] result = new char[size];
801
while (--index >= 0) {
802
length = array[index].length;
804
System.arraycopy(array[index], 0, result, (size -= length), length);
806
result[size] = separator;
813
* Answers true if the array contains an occurrence of character, false
822
* array = { { ' a' }, { ' b' } }
828
* array = { { ' a' }, { ' b' } }
835
* the character to search
837
* the array in which the search is done
838
* @return true if the array contains an occurrence of character, false
840
* @exception NullPointerException
843
public static final boolean contains(char character, char[][] array) {
844
for (int i = array.length; --i >= 0;) {
845
char[] subarray = array[i];
846
for (int j = subarray.length; --j >= 0;)
847
if (subarray[j] == character)
854
* Answers true if the array contains an occurrence of character, false
869
* array = { ' a' , ' b' }
876
* the character to search
878
* the array in which the search is done
879
* @return true if the array contains an occurrence of character, false
881
* @exception NullPointerException
884
public static final boolean contains(char character, char[] array) {
885
for (int i = array.length; --i >= 0;)
886
if (array[i] == character)
892
* Answers a deep copy of the toCopy array.
896
* @return a deep copy of the toCopy array.
898
public static final char[][] deepCopy(char[][] toCopy) {
899
int toCopyLength = toCopy.length;
900
char[][] result = new char[toCopyLength][];
901
for (int i = 0; i < toCopyLength; i++) {
902
char[] toElement = toCopy[i];
903
int toElementLength = toElement.length;
904
char[] resultElement = new char[toElementLength];
905
System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
906
result[i] = resultElement;
912
* Return true if array ends with the sequence of characters contained in
920
* array = { 'a', 'b', 'c', 'd' }
921
* toBeFound = { 'b', 'c' }
926
* array = { 'a', 'b', 'c' }
927
* toBeFound = { 'b', 'c' }
937
* @return true if array ends with the sequence of characters contained in
940
* @exception NullPointerException
941
* if array is null or toBeFound is null
943
public static final boolean endsWith(char[] array, char[] toBeFound) {
944
int i = toBeFound.length;
945
int j = array.length - i;
949
if (toBeFound[i] != array[i + j])
955
* Answers true if the two arrays are identical character by character,
957
* The equality is case sensitive.
975
* first = { { 'a' } }
976
* second = { { 'a' } }
981
* first = { { 'A' } }
982
* second = { { 'a' } }
992
* @return true if the two arrays are identical character by character,
995
public static final boolean equals(char[][] first, char[][] second) {
998
if (first == null || second == null)
1000
if (first.length != second.length)
1002
for (int i = first.length; --i >= 0;)
1003
if (!equals(first[i], second[i]))
1009
* If isCaseSensite is true, answers true if the two arrays are identical
1011
* by character, otherwise false.
1012
* If it is false, answers true if the two arrays are identical character by
1013
* character without checking the case, otherwise false.
1021
* isCaseSensitive = true
1028
* isCaseSensitive = true
1033
* first = { { 'A' } }
1034
* second = { { 'a' } }
1035
* isCaseSensitive = true
1040
* first = { { 'A' } }
1041
* second = { { 'a' } }
1042
* isCaseSensitive = false
1052
* @param isCaseSensitive
1053
* check whether or not the equality should be case sensitive
1054
* @return true if the two arrays are identical character by character
1055
* according to the value
1056
* of isCaseSensitive, otherwise false
1058
public static final boolean equals(char[][] first, char[][] second, boolean isCaseSensitive) {
1059
if (isCaseSensitive) {
1060
return equals(first, second);
1062
if (first == second)
1064
if (first == null || second == null)
1066
if (first.length != second.length)
1068
for (int i = first.length; --i >= 0;)
1069
if (!equals(first[i], second[i], false))
1075
* Answers true if the two arrays are identical character by character,
1077
* The equality is case sensitive.
1112
* @return true if the two arrays are identical character by character,
1115
public static final boolean equals(char[] first, char[] second) {
1116
if (first == second)
1118
if (first == null || second == null)
1120
if (first.length != second.length)
1122
for (int i = first.length; --i >= 0;)
1123
if (first[i] != second[i])
1129
* If isCaseSensite is true, answers true if the two arrays are identical
1131
* by character, otherwise false.
1132
* If it is false, answers true if the two arrays are identical character by
1133
* character without checking the case, otherwise false.
1141
* isCaseSensitive = true
1148
* isCaseSensitive = true
1155
* isCaseSensitive = true
1162
* isCaseSensitive = false
1172
* @param isCaseSensitive
1173
* check whether or not the equality should be case sensitive
1174
* @return true if the two arrays are identical character by character
1175
* according to the value
1176
* of isCaseSensitive, otherwise false
1178
public static final boolean equals(char[] first, char[] second, boolean isCaseSensitive) {
1179
if (isCaseSensitive) {
1180
return equals(first, second);
1182
if (first == second)
1184
if (first == null || second == null)
1186
if (first.length != second.length)
1188
for (int i = first.length; --i >= 0;)
1189
if (Character.toLowerCase(first[i]) != Character.toLowerCase(second[i]))
1195
* If isCaseSensite is true, the equality is case sensitive, otherwise it is
1198
* Answers true if the name contains the fragment at the starting index
1199
* startIndex, otherwise false.
1205
* fragment = { 'b', 'c' , 'd' }
1206
* name = { 'a', 'b', 'c' , 'd' }
1208
* isCaseSensitive = true
1213
* fragment = { 'b', 'c' , 'd' }
1214
* name = { 'a', 'b', 'C' , 'd' }
1216
* isCaseSensitive = true
1221
* fragment = { 'b', 'c' , 'd' }
1222
* name = { 'a', 'b', 'C' , 'd' }
1224
* isCaseSensitive = false
1229
* fragment = { 'b', 'c' , 'd' }
1230
* name = { 'a', 'b'}
1232
* isCaseSensitive = true
1239
* the fragment to check
1241
* the array to check
1243
* the starting index
1244
* @param isCaseSensitive
1245
* check whether or not the equality should be case sensitive
1246
* @return true if the name contains the fragment at the starting index
1247
* startIndex according to the
1248
* value of isCaseSensitive, otherwise false.
1249
* @exception NullPointerException
1250
* if fragment or name is null.
1252
public static final boolean fragmentEquals(char[] fragment, char[] name, int startIndex, boolean isCaseSensitive) {
1253
int max = fragment.length;
1254
if (name.length < max + startIndex)
1256
if (isCaseSensitive) {
1257
for (int i = max; --i >= 0;)
1258
// assumes the prefix is not larger than the name
1259
if (fragment[i] != name[i + startIndex])
1263
for (int i = max; --i >= 0;)
1264
// assumes the prefix is not larger than the name
1265
if (Character.toLowerCase(fragment[i]) != Character.toLowerCase(name[i + startIndex]))
1271
* Answers a hashcode for the array
1274
* the array for which a hashcode is required
1275
* @return the hashcode
1276
* @exception NullPointerException
1279
public static final int hashCode(char[] array) {
1282
int length = array.length;
1284
for (int i = length; i > 0; i--)
1285
hash = (hash * 37) + array[offset++];
1287
// only sample some characters
1288
int skip = length / 8;
1289
for (int i = length; i > 0; i -= skip, offset += skip)
1290
hash = (hash * 39) + array[offset];
1292
return hash & 0x7FFFFFFF;
1296
* Answers true if c is a whitespace according to the JLS (\u000a,
1297
* \u000c, \u000d, \u0009), otherwise false.
1315
* the character to check
1316
* @return true if c is a whitespace according to the JLS, otherwise false.
1318
public static boolean isWhitespace(char c) {
1320
case 10: /* \ u000a: LINE FEED */
1321
case 12: /* \ u000c: FORM FEED */
1322
case 13: /* \ u000d: CARRIAGE RETURN */
1323
case 32: /* \ u0020: SPACE */
1324
case 9: /* \ u0009: HORIZONTAL TABULATION */
1332
* Answers the first index in the array for which the corresponding
1334
* equal to toBeFound. Answers -1 if no occurrence of this character is
1342
* array = { ' a', 'b', 'c', 'd' }
1348
* array = { ' a', 'b', 'c', 'd' }
1355
* the character to search
1357
* the array to be searched
1358
* @return the first index in the array for which the corresponding
1360
* equal to toBeFound, -1 otherwise
1361
* @exception NullPointerException
1364
public static final int indexOf(char toBeFound, char[] array) {
1365
for (int i = 0; i < array.length; i++)
1366
if (toBeFound == array[i])
1372
* Answers the first index in the array for which the corresponding
1374
* equal to toBeFound starting the search at index start.
1375
* Answers -1 if no occurrence of this character is found.
1382
* array = { ' a', 'b', 'c', 'd' }
1389
* array = { ' a', 'b', 'c', 'd' }
1396
* array = { ' a', 'b', 'c', 'd' }
1404
* the character to search
1406
* the array to be searched
1408
* the starting index
1409
* @return the first index in the array for which the corresponding
1411
* equal to toBeFound, -1 otherwise
1412
* @exception NullPointerException
1414
* @exception ArrayIndexOutOfBoundsException
1415
* if start is lower than 0
1417
public static final int indexOf(char toBeFound, char[] array, int start) {
1418
for (int i = start; i < array.length; i++)
1419
if (toBeFound == array[i])
1425
* Answers the last index in the array for which the corresponding character
1427
* equal to toBeFound starting from the end of the array.
1428
* Answers -1 if no occurrence of this character is found.
1435
* array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
1441
* array = { ' a', 'b', 'c', 'd' }
1448
* the character to search
1450
* the array to be searched
1451
* @return the last index in the array for which the corresponding character
1453
* equal to toBeFound starting from the end of the array, -1
1455
* @exception NullPointerException
1458
public static final int lastIndexOf(char toBeFound, char[] array) {
1459
for (int i = array.length; --i >= 0;)
1460
if (toBeFound == array[i])
1466
* Answers the last index in the array for which the corresponding character
1468
* equal to toBeFound stopping at the index startIndex.
1469
* Answers -1 if no occurrence of this character is found.
1476
* array = { ' a', 'b', 'c', 'd' }
1483
* array = { ' a', 'b', 'c', 'd', 'e' }
1490
* array = { ' a', 'b', 'c', 'd' }
1498
* the character to search
1500
* the array to be searched
1502
* the stopping index
1503
* @return the last index in the array for which the corresponding character
1505
* equal to toBeFound stopping at the index startIndex, -1 otherwise
1506
* @exception NullPointerException
1508
* @exception ArrayIndexOutOfBoundsException
1509
* if startIndex is lower than 0
1511
public static final int lastIndexOf(char toBeFound, char[] array, int startIndex) {
1512
for (int i = array.length; --i >= startIndex;)
1513
if (toBeFound == array[i])
1519
* Answers the last index in the array for which the corresponding character
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' }
1554
* the character to search
1556
* the array to be searched
1558
* the stopping index
1560
* the starting index
1561
* @return the last index in the array for which the corresponding character
1563
* equal to toBeFound starting from endIndex to startIndex, -1
1565
* @exception NullPointerException
1567
* @exception ArrayIndexOutOfBoundsException
1568
* if endIndex is greater or equals to array length or
1569
* starting is lower than 0
1571
public static final int lastIndexOf(char toBeFound, char[] array, int startIndex, int endIndex) {
1572
for (int i = endIndex; --i >= startIndex;)
1573
if (toBeFound == array[i])
1579
* Answers the last portion of a name given a separator.
1584
* lastSegment("java.lang.Object".toCharArray(),'.') --> Object
1590
* the given separator
1591
* @return the last portion of a name given a separator
1592
* @exception NullPointerException
1595
final static public char[] lastSegment(char[] array, char separator) {
1596
int pos = lastIndexOf(separator, array);
1599
return subarray(array, pos + 1, array.length);
1603
* Answers true if the pattern matches the given name, false otherwise. This
1604
* char[] pattern matching
1605
* accepts wild-cards '*' and '?'.
1607
* When not case sensitive, the pattern is assumed to already be lowercased,
1609
* name will be lowercased character per character as comparing.
1610
* If name is null, the answer is false.
1611
* If pattern is null, the answer is true if name is not null.
1617
* pattern = { '?', 'b', '*' }
1618
* name = { 'a', 'b', 'c' , 'd' }
1619
* isCaseSensitive = true
1624
* pattern = { '?', 'b', '?' }
1625
* name = { 'a', 'b', 'c' , 'd' }
1626
* isCaseSensitive = true
1631
* pattern = { 'b', '*' }
1632
* name = { 'a', 'b', 'c' , 'd' }
1633
* isCaseSensitive = true
1643
* @param isCaseSensitive
1644
* flag to know whether or not the matching should be case
1646
* @return true if the pattern matches the given name, false otherwise
1648
public static final boolean match(char[] pattern, char[] name, boolean isCaseSensitive) {
1650
return false; // null name cannot match
1651
if (pattern == null)
1652
return true; // null pattern is equivalent to '*'
1653
return match(pattern, 0, pattern.length, name, 0, name.length, isCaseSensitive, true);
1657
* Answers true if the a sub-pattern matches the subpart of the given name,
1659
* char[] pattern matching, accepting wild-cards '*' and '?'. Can match only
1660
* subset of name/pattern.
1661
* end positions are non-inclusive.
1662
* The subpattern is defined by the patternStart and pattternEnd positions.
1663
* When not case sensitive, the pattern is assumed to already be lowercased,
1665
* name will be lowercased character per character as comparing.
1671
* pattern = { '?', 'b', '*' }
1674
* name = { 'a', 'b', 'c' , 'd' }
1677
* isCaseSensitive = true
1682
* pattern = { '?', 'b', '*' }
1685
* name = { 'a', 'b', 'c' , 'd' }
1688
* isCaseSensitive = true
1696
* @param patternStart
1697
* the given pattern start
1699
* the given pattern end
1703
* the given name start
1705
* the given name end
1706
* @param isCaseSensitive
1707
* flag to know if the matching should be case sensitive
1708
* @return true if the a sub-pattern matches the subpart of the given name,
1711
public static final boolean match(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd,
1712
boolean isCaseSensitive) {
1713
return match(pattern, patternStart, patternEnd, name, nameStart, nameEnd, isCaseSensitive, false);
1716
public static final boolean match(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd,
1717
boolean isCaseSensitive, boolean allowEscaping) {
1719
return false; // null name cannot match
1720
if (pattern == null)
1721
return true; // null pattern is equivalent to '*'
1722
int iPattern = patternStart;
1723
int iName = nameStart;
1725
patternEnd = pattern.length;
1727
nameEnd = name.length;
1728
/* check first segment */
1729
char patternChar = 0;
1730
boolean isEscaped = false;
1731
while ((iPattern < patternEnd) && ((patternChar = pattern[iPattern]) != '*' || (patternChar == '*' && isEscaped))) {
1732
if (allowEscaping && pattern[iPattern] == '\\' && !isEscaped) {
1738
if (iName == nameEnd)
1740
if (patternChar != (isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName])) && patternChar != '?') {
1747
/* check sequence of star+segment */
1749
if (patternChar == '*') {
1750
segmentStart = ++iPattern; // skip star
1752
segmentStart = 0; // force iName check
1754
int prefixStart = iName;
1755
checkSegment: while (iName < nameEnd) {
1756
if (iPattern == patternEnd) {
1757
iPattern = segmentStart; // mismatch - restart current segment
1758
iName = ++prefixStart;
1759
continue checkSegment;
1761
/* segment is ending */
1762
if ((patternChar = pattern[iPattern]) == '*') {
1763
segmentStart = ++iPattern; // skip start
1764
if (segmentStart == patternEnd) {
1767
prefixStart = iName;
1768
continue checkSegment;
1770
/* check current name character */
1771
if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName])) != patternChar && patternChar != '?') {
1772
iPattern = segmentStart; // mismatch - restart current segment
1773
iName = ++prefixStart;
1774
continue checkSegment;
1779
return (segmentStart == patternEnd) || (iName == nameEnd && iPattern == patternEnd)
1780
|| (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
1784
* Answers true if the pattern matches the filepath using the pathSepatator,
1787
* Path char[] pattern matching, accepting wild-cards '**', '*' and '?'
1788
* (using Ant directory tasks
1789
* conventions, also see
1790
* "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
1791
* Path pattern matching is enhancing regular pattern matching in supporting
1792
* extra rule where '**' represent
1793
* any folder combination.
1795
* - foo\ is equivalent to foo\**
1796
* - *.java is equivalent to **\*.java
1797
* When not case sensitive, the pattern is assumed to already be lowercased,
1799
* name will be lowercased character per character as comparing.
1805
* @param isCaseSensitive
1806
* to find out whether or not the matching should be case
1808
* @param pathSeparator
1809
* the given path separator
1810
* @return true if the pattern matches the filepath using the pathSepatator,
1813
public static final boolean pathMatch(char[] pattern, char[] filepath, boolean isCaseSensitive, char pathSeparator) {
1814
if (filepath == null)
1815
return false; // null name cannot match
1816
if (pattern == null)
1817
return true; // null pattern is equivalent to '*'
1818
// special case: pattern foo is equivalent to **\foo (not absolute)
1819
boolean freeLeadingDoubleStar;
1820
// offsets inside pattern
1821
int pSegmentStart, pLength = pattern.length;
1822
freeLeadingDoubleStar = (pattern[0] != pathSeparator);
1823
if (freeLeadingDoubleStar) {
1828
int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart + 1);
1829
if (pSegmentEnd < 0)
1830
pSegmentEnd = pLength;
1831
// special case: pattern foo\ is equivalent to foo\**
1832
boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
1833
// offsets inside filepath
1834
int fSegmentStart, fLength = filepath.length;
1835
if (filepath[0] != pathSeparator) {
1840
if (fSegmentStart != pSegmentStart) {
1841
return false; // both must start with a separator or none.
1843
int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart + 1);
1844
if (fSegmentEnd < 0)
1845
fSegmentEnd = fLength;
1847
while (pSegmentStart < pLength
1848
&& !freeLeadingDoubleStar
1849
&& !(pSegmentEnd == pLength && freeTrailingDoubleStar || (pSegmentEnd == pSegmentStart + 2 && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*'))) {
1850
if (fSegmentStart >= fLength)
1852
if (!CharOperation.match(pattern, pSegmentStart, pSegmentEnd, filepath, fSegmentStart, fSegmentEnd, isCaseSensitive)) {
1855
// jump to next segment
1856
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
1858
if (pSegmentEnd < 0)
1859
pSegmentEnd = pLength;
1860
fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentEnd + 1);
1862
if (fSegmentEnd < 0)
1863
fSegmentEnd = fLength;
1865
/* check sequence of doubleStar+segment */
1866
int pSegmentRestart;
1867
if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
1868
|| (pSegmentEnd == pSegmentStart + 2 && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')) {
1869
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
1871
if (pSegmentEnd < 0)
1872
pSegmentEnd = pLength;
1873
pSegmentRestart = pSegmentStart;
1875
if (pSegmentStart >= pLength)
1876
return fSegmentStart >= fLength; // true if filepath is done too.
1877
pSegmentRestart = 0; // force fSegmentStart check
1879
int fSegmentRestart = fSegmentStart;
1880
checkSegment: while (fSegmentStart < fLength) {
1881
if (pSegmentStart >= pLength) {
1882
if (freeTrailingDoubleStar)
1884
// mismatch - restart current path segment
1885
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
1886
if (pSegmentEnd < 0)
1887
pSegmentEnd = pLength;
1888
fSegmentRestart = CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
1890
if (fSegmentRestart < 0) {
1891
fSegmentRestart = fLength;
1895
fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
1896
if (fSegmentEnd < 0)
1897
fSegmentEnd = fLength;
1898
continue checkSegment;
1900
/* path segment is ending */
1901
if (pSegmentEnd == pSegmentStart + 2 && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*') {
1902
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
1904
if (pSegmentEnd < 0)
1905
pSegmentEnd = pLength;
1906
pSegmentRestart = pSegmentStart;
1907
fSegmentRestart = fSegmentStart;
1908
if (pSegmentStart >= pLength)
1910
continue checkSegment;
1912
/* chech current path segment */
1913
if (!CharOperation.match(pattern, pSegmentStart, pSegmentEnd, filepath, fSegmentStart, fSegmentEnd, isCaseSensitive)) {
1914
// mismatch - restart current path segment
1915
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
1916
if (pSegmentEnd < 0)
1917
pSegmentEnd = pLength;
1918
fSegmentRestart = CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
1920
if (fSegmentRestart < 0) {
1921
fSegmentRestart = fLength;
1925
fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
1926
if (fSegmentEnd < 0)
1927
fSegmentEnd = fLength;
1928
continue checkSegment;
1930
// jump to next segment
1931
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
1933
if (pSegmentEnd < 0)
1934
pSegmentEnd = pLength;
1935
fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentEnd + 1);
1937
if (fSegmentEnd < 0)
1938
fSegmentEnd = fLength;
1940
return (pSegmentRestart >= pSegmentEnd) || (fSegmentStart >= fLength && pSegmentStart >= pLength)
1941
|| (pSegmentStart == pLength - 2 && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')
1942
|| (pSegmentStart == pLength && freeTrailingDoubleStar);
1946
* Answers the number of occurrences of the given character in the given
1955
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
1961
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
1968
* the given character
1971
* @return the number of occurrences of the given character in the given
1973
* @exception NullPointerException
1976
public static final int occurencesOf(char toBeFound, char[] array) {
1978
for (char element : array)
1979
if (toBeFound == element)
1985
* Answers the number of occurrences of the given character in the given
1987
* at the given index, 0 if any.
1995
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2002
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2010
* the given character
2013
* @return the number of occurrences of the given character in the given
2015
* @exception NullPointerException
2017
* @exception ArrayIndexOutOfBoundsException
2018
* if start is lower than 0
2020
public static final int occurencesOf(char toBeFound, char[] array, int start) {
2022
for (int i = start; i < array.length; i++)
2023
if (toBeFound == array[i])
2029
* Answers true if the given name starts with the given prefix, false
2031
* The comparison is case sensitive.
2037
* prefix = { 'a' , 'b' }
2038
* name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2043
* prefix = { 'a' , 'c' }
2044
* name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2054
* @return true if the given name starts with the given prefix, false
2056
* @exception NullPointerException
2057
* if the given name is null or if the given prefix is null
2059
public static final boolean prefixEquals(char[] prefix, char[] name) {
2060
int max = prefix.length;
2061
if (name.length < max)
2063
for (int i = max; --i >= 0;)
2064
// assumes the prefix is not larger than the name
2065
if (prefix[i] != name[i])
2071
* Answers true if the given name starts with the given prefix, false
2073
* isCaseSensitive is used to find out whether or not the comparison should
2074
* be case sensitive.
2080
* prefix = { 'a' , 'B' }
2081
* name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2082
* isCaseSensitive = false
2087
* prefix = { 'a' , 'B' }
2088
* name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2089
* isCaseSensitive = true
2099
* @param isCaseSensitive
2100
* to find out whether or not the comparison should be case
2102
* @return true if the given name starts with the given prefix, false
2104
* @exception NullPointerException
2105
* if the given name is null or if the given prefix is null
2107
public static final boolean prefixEquals(char[] prefix, char[] name, boolean isCaseSensitive) {
2108
int max = prefix.length;
2109
if (name.length < max)
2111
if (isCaseSensitive) {
2112
for (int i = max; --i >= 0;)
2113
// assumes the prefix is not larger than the name
2114
if (prefix[i] != name[i])
2118
for (int i = max; --i >= 0;)
2119
// assumes the prefix is not larger than the name
2120
if (Character.toLowerCase(prefix[i]) != Character.toLowerCase(name[i]))
2126
* Replace all occurrence of the character to be replaced with the
2127
* remplacement character in the
2134
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2135
* toBeReplaced = 'b'
2136
* replacementChar = 'a'
2137
* result => No returned value, but array is now equals to { 'a' , 'a', 'a',
2142
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2143
* toBeReplaced = 'c'
2144
* replacementChar = 'a'
2145
* result => No returned value, but array is now equals to { 'a' , 'b', 'b',
2153
* @param toBeReplaced
2154
* the character to be replaced
2155
* @param replacementChar
2156
* the replacement character
2157
* @exception NullPointerException
2158
* if the given array is null
2160
public static final void replace(char[] array, char toBeReplaced, char replacementChar) {
2161
if (toBeReplaced != replacementChar) {
2162
for (int i = 0, max = array.length; i < max; i++) {
2163
if (array[i] == toBeReplaced)
2164
array[i] = replacementChar;
2170
* Answers a new array of characters with substitutions. No side-effect is
2171
* operated on the original
2172
* array, in case no substitution happened, then the result is the same as
2180
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2181
* toBeReplaced = { 'b' }
2182
* replacementChar = { 'a', 'a' }
2183
* result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
2187
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2188
* toBeReplaced = { 'c' }
2189
* replacementChar = { 'a' }
2190
* result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
2197
* @param toBeReplaced
2198
* characters to be replaced
2199
* @param replacementChars
2200
* the replacement characters
2201
* @return a new array of characters with substitutions or the given array
2203
* @exception NullPointerException
2204
* if the given array is null
2206
public static final char[] replace(char[] array, char[] toBeReplaced, char[] replacementChars) {
2207
int max = array.length;
2208
int replacedLength = toBeReplaced.length;
2209
int replacementLength = replacementChars.length;
2210
int[] starts = new int[5];
2211
int occurrenceCount = 0;
2212
if (!equals(toBeReplaced, replacementChars)) {
2213
next: for (int i = 0; i < max; i++) {
2215
while (j < replacedLength) {
2218
if (array[i + j] != toBeReplaced[j++])
2221
if (occurrenceCount == starts.length) {
2222
System.arraycopy(starts, 0, starts = new int[occurrenceCount * 2], 0, occurrenceCount);
2224
starts[occurrenceCount++] = i;
2227
if (occurrenceCount == 0)
2229
char[] result = new char[max + occurrenceCount * (replacementLength - replacedLength)];
2230
int inStart = 0, outStart = 0;
2231
for (int i = 0; i < occurrenceCount; i++) {
2232
int offset = starts[i] - inStart;
2233
System.arraycopy(array, inStart, result, outStart, offset);
2236
System.arraycopy(replacementChars, 0, result, outStart, replacementLength);
2237
inStart += replacedLength;
2238
outStart += replacementLength;
2240
System.arraycopy(array, inStart, result, outStart, max - inStart);
2245
* Return a new array which is the split of the given array using the given
2246
* divider and triming each subarray to remove
2247
* whitespaces equals to ' '.
2254
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2255
* result => { { 'a' }, { }, { 'a' }, { 'a' } }
2260
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2261
* result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2266
* array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
2267
* result => { { 'a' }, { }, { 'a' }, { 'a' } }
2272
* array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
2273
* result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2282
* @return a new array which is the split of the given array using the given
2283
* divider and triming each subarray to remove
2284
* whitespaces equals to ' '
2286
public static final char[][] splitAndTrimOn(char divider, char[] array) {
2288
return NO_CHAR_CHAR;
2289
final int length = array.length;
2291
return NO_CHAR_CHAR;
2293
for (int i = 0; i < length; i++)
2294
if (array[i] == divider)
2296
char[][] split = new char[wordCount][];
2297
int last = 0, currentWord = 0;
2298
for (int i = 0; i < length; i++) {
2299
if (array[i] == divider) {
2300
int start = last, end = i - 1;
2301
while (start < i && array[start] == ' ')
2303
while (end > start && array[end] == ' ')
2305
split[currentWord] = new char[end - start + 1];
2306
System.arraycopy(array, start, split[currentWord++], 0, end - start + 1);
2310
int start = last, end = length - 1;
2311
while (start < length && array[start] == ' ')
2313
while (end > start && array[end] == ' ')
2315
split[currentWord] = new char[end - start + 1];
2316
System.arraycopy(array, start, split[currentWord++], 0, end - start + 1);
2321
* Return a new array which is the split of the given array using the given
2329
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2330
* result => { { 'a' }, { }, { 'a' }, { 'a' } }
2335
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2336
* result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2341
* array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
2342
* result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
2351
* @return a new array which is the split of the given array using the given
2354
public static final char[][] splitOn(char divider, char[] array) {
2356
return NO_CHAR_CHAR;
2357
final int length = array.length;
2359
return NO_CHAR_CHAR;
2361
for (int i = 0; i < length; i++)
2362
if (array[i] == divider)
2364
char[][] split = new char[wordCount][];
2365
int last = 0, currentWord = 0;
2366
for (int i = 0; i < length; i++) {
2367
if (array[i] == divider) {
2368
split[currentWord] = new char[i - last];
2369
System.arraycopy(array, last, split[currentWord++], 0, i - last);
2373
split[currentWord] = new char[length - last];
2374
System.arraycopy(array, last, split[currentWord], 0, length - last);
2379
* Return a new array which is the split of the given array using the given
2380
* divider. The given end
2381
* is exclusive and the given start is inclusive.
2388
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2391
* result => { { }, { }, { 'a' } }
2401
* the given starting index
2403
* the given ending index
2404
* @return a new array which is the split of the given array using the given
2406
* @exception ArrayIndexOutOfBoundsException
2407
* if start is lower than 0 or end is greater than the array
2410
public static final char[][] splitOn(char divider, char[] array, int start, int end) {
2412
return NO_CHAR_CHAR;
2413
final int length = array.length;
2414
if (length == 0 || start > end)
2415
return NO_CHAR_CHAR;
2417
for (int i = start; i < end; i++)
2418
if (array[i] == divider)
2420
char[][] split = new char[wordCount][];
2421
int last = start, currentWord = 0;
2422
for (int i = start; i < end; i++) {
2423
if (array[i] == divider) {
2424
split[currentWord] = new char[i - last];
2425
System.arraycopy(array, last, split[currentWord++], 0, i - last);
2429
split[currentWord] = new char[end - last];
2430
System.arraycopy(array, last, split[currentWord], 0, end - last);
2435
* Answers a new array which is a copy of the given array starting at the
2437
* ending at the given end. The given start is inclusive and the given end
2439
* Answers null if start is greater than end, if start is lower than 0 or if
2441
* than the length of the given array. If end equals -1, it is converted to
2448
* array = { { 'a' } , { 'b' } }
2451
* result => { { 'a' } }
2455
* array = { { 'a' } , { 'b' } }
2458
* result => { { 'a' }, { 'b' } }
2466
* the given starting index
2468
* the given ending index
2469
* @return a new array which is a copy of the given array starting at the
2471
* ending at the given end
2472
* @exception NullPointerException
2473
* if the given array is null
2475
public static final char[][] subarray(char[][] array, int start, int end) {
2482
if (end > array.length)
2484
char[][] result = new char[end - start][];
2485
System.arraycopy(array, start, result, 0, end - start);
2490
* Answers a new array which is a copy of the given array starting at the
2492
* ending at the given end. The given start is inclusive and the given end
2494
* Answers null if start is greater than end, if start is lower than 0 or if
2496
* than the length of the given array. If end equals -1, it is converted to
2503
* array = { 'a' , 'b' }
2510
* array = { 'a', 'b' }
2513
* result => { 'a' , 'b' }
2521
* the given starting index
2523
* the given ending index
2524
* @return a new array which is a copy of the given array starting at the
2526
* ending at the given end
2527
* @exception NullPointerException
2528
* if the given array is null
2530
public static final char[] subarray(char[] array, int start, int end) {
2537
if (end > array.length)
2539
char[] result = new char[end - start];
2540
System.arraycopy(array, start, result, 0, end - start);
2545
* Answers the result of a char[] conversion to lowercase. Answers null if
2546
* the given chars array is null.
2548
* NOTE: If no conversion was necessary, then answers back the argument one.
2554
* chars = { 'a' , 'b' }
2555
* result => { 'a' , 'b' }
2559
* array = { 'A', 'b' }
2560
* result => { 'a' , 'b' }
2566
* the chars to convert
2567
* @return the result of a char[] conversion to lowercase
2569
final static public char[] toLowerCase(char[] chars) {
2572
int length = chars.length;
2573
char[] lowerChars = null;
2574
for (int i = 0; i < length; i++) {
2576
char lc = Character.toLowerCase(c);
2577
if ((c != lc) || (lowerChars != null)) {
2578
if (lowerChars == null) {
2579
System.arraycopy(chars, 0, lowerChars = new char[length], 0, i);
2584
return lowerChars == null ? chars : lowerChars;
2588
* Answers a new array removing leading and trailing spaces (' '). Answers
2589
* the given array if there is no
2590
* space characters to remove.
2596
* chars = { ' ', 'a' , 'b', ' ', ' ' }
2597
* result => { 'a' , 'b' }
2601
* array = { 'A', 'b' }
2602
* result => { 'A' , 'b' }
2609
* @return a new array removing leading and trailing spaces (' ')
2611
final static public char[] trim(char[] chars) {
2614
int start = 0, length = chars.length, end = length - 1;
2615
while (start < length && chars[start] == ' ') {
2618
while (end > start && chars[end] == ' ') {
2621
if (start != 0 || end != length - 1) {
2622
return subarray(chars, start, end + 1);
2628
* Answers a string which is the concatenation of the given array using the
2629
* '.' as a separator.
2635
* array = { { 'a' } , { 'b' } }
2640
* array = { { ' ', 'a' } , { 'b' } }
2648
* @return a string which is the concatenation of the given array using the
2649
* '.' as a separator
2651
final static public String toString(char[][] array) {
2652
char[] result = concatWith(array, '.');
2653
return new String(result);