KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > core > compiler > CharOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation 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
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  * Luiz-Otavio Zorzella <zorzella at gmail dot com> - Improve CamelCase algorithm
11  *******************************************************************************/

12 package org.eclipse.jdt.core.compiler;
13
14 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
15
16 /**
17  * This class is a collection of helper methods to manipulate char arrays.
18  * <p>
19  * This class is not intended to be instantiated or subclassed by clients.
20  * </p>
21  *
22  * @since 2.1
23  */

24 public final class CharOperation {
25
26     /**
27      * Constant for an empty char array
28      */

29     public static final char[] NO_CHAR = new char[0];
30
31     /**
32      * Constant for an empty char array with two dimensions.
33      */

34     public static final char[][] NO_CHAR_CHAR = new char[0][];
35     
36     /**
37      * Constant for an empty String array.
38      * @since 3.1
39      */

40     public static final String JavaDoc[] NO_STRINGS = new String JavaDoc[0];
41     
42 /**
43  * Answers a new array with appending the suffix character at the end of the array.
44  * <br>
45  * <br>
46  * For example:<br>
47  * <ol>
48  * <li><pre>
49  * array = { 'a', 'b' }
50  * suffix = 'c'
51  * => result = { 'a', 'b' , 'c' }
52  * </pre>
53  * </li>
54  * <li><pre>
55  * array = null
56  * suffix = 'c'
57  * => result = { 'c' }
58  * </pre></li>
59  * </ol>
60  *
61  * @param array the array that is concanated with the suffix character
62  * @param suffix the suffix character
63  * @return the new array
64  */

65 public static final char[] append(char[] array, char suffix) {
66     if (array == null)
67         return new char[] { suffix };
68     int length = array.length;
69     System.arraycopy(array, 0, array = new char[length + 1], 0, length);
70     array[length] = suffix;
71     return array;
72 }
73
74 /**
75  * Append the given subarray to the target array starting at the given index in the target array.
76  * The start of the subarray is inclusive, the end is exclusive.
77  * Answers a new target array if it needs to grow, otherwise answers the same target array.
78  * <br>
79  * For example:<br>
80  * <ol>
81  * <li><pre>
82  * target = { 'a', 'b', '0' }
83  * index = 2
84  * array = { 'c', 'd' }
85  * start = 0
86  * end = 1
87  * => result = { 'a', 'b' , 'c' }
88  * </pre>
89  * </li>
90  * <li><pre>
91  * target = { 'a', 'b' }
92  * index = 2
93  * array = { 'c', 'd' }
94  * start = 0
95  * end = 1
96  * => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
97  * </pre></li>
98  * <li><pre>
99  * target = { 'a', 'b', 'c' }
100  * index = 1
101  * array = { 'c', 'd', 'e', 'f' }
102  * start = 1
103  * end = 4
104  * => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
105  * </pre></li>
106  * </ol>
107  *
108  * @param target the given target
109  * @param index the given index
110  * @param array the given array
111  * @param start the given start index
112  * @param end the given end index
113  *
114  * @return the new array
115  * @throws NullPointerException if the target array is null
116  */

117 public static final char[] append(char[] target, int index, char[] array, int start, int end) {
118     int targetLength = target.length;
119     int subLength = end-start;
120     int newTargetLength = subLength+index;
121     if (newTargetLength > targetLength) {
122         System.arraycopy(target, 0, target = new char[newTargetLength*2], 0, index);
123     }
124     System.arraycopy(array, start, target, index, subLength);
125     return target;
126 }
127
128 /**
129  * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
130  * If the first array is null, then the second array is returned.
131  * If the second array is null, then the first array is returned.
132  * <br>
133  * <br>
134  * For example:
135  * <ol>
136  * <li><pre>
137  * first = null
138  * second = null
139  * => result = null
140  * </pre>
141  * </li>
142  * <li><pre>
143  * first = { { ' a' } }
144  * second = null
145  * => result = { { ' a' } }
146  * </pre>
147  * </li>
148  * <li><pre>
149  * first = null
150  * second = { { ' a' } }
151  * => result = { { ' a' } }
152  * </pre>
153  * </li>
154  * <li><pre>
155  * first = { { ' b' } }
156  * second = { { ' a' } }
157  * => result = { { ' b' }, { ' a' } }
158  * </pre>
159  * </li>
160  * </ol>
161  *
162  * @param first the first array to concatenate
163  * @param second the second array to concatenate
164  * @return the concatenation of the two arrays, or null if the two arrays are null.
165  */

166 public static final char[][] arrayConcat(char[][] first, char[][] second) {
167     if (first == null)
168         return second;
169     if (second == null)
170         return first;
171
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);
177     return result;
178 }
179
180 /**
181  * Answers true if the pattern matches the given name using CamelCase rules, or false otherwise.
182  * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
183  * <br>
184  * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
185  * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
186  * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
187  * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
188  * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
189  * names follow the lower CamelCase convention.
190  * <br>
191  * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
192  * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
193  * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
194  * <br><br>
195  * Examples:
196  * <ol>
197  * <li><pre>
198  * pattern = { 'N', 'P', 'E' }
199  * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
200  * result => true
201  * </pre>
202  * </li>
203  * <li><pre>
204  * pattern = { 'N', 'P', 'E' }
205  * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
206  * result => true
207  * </pre>
208  * </li>
209  * <li><pre>
210  * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
211  * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
212  * result => true
213  * </pre>
214  * </li>
215  * <li><pre>
216  * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
217  * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
218  * result => false
219  * </pre>
220  * </li>
221  * <li><pre>
222  * pattern = { 'n', p', 'e' }
223  * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
224  * result => false
225  * </pre>
226  * </li>
227  * </ol>
228  *
229  * @param pattern the given pattern
230  * @param name the given name
231  * @return true if the pattern matches the given name, false otherwise
232  * @since 3.2
233  */

234 public static final boolean camelCaseMatch(char[] pattern, char[] name) {
235     if (pattern == null)
236         return true; // null pattern is equivalent to '*'
237
if (name == null)
238         return false; // null name cannot match
239

240     return camelCaseMatch(pattern, 0, pattern.length, name, 0, name.length);
241 }
242
243 /**
244  * Answers true if a sub-pattern matches the subpart of the given name using CamelCase rules, or false otherwise.
245  * char[] CamelCase matching does NOT accept explicit wild-cards '*' and '?' and is inherently case sensitive.
246  * Can match only subset of name/pattern, considering end positions as non-inclusive.
247  * The subpattern is defined by the patternStart and patternEnd positions.
248  * <br>
249  * CamelCase denotes the convention of writing compound names without spaces, and capitalizing every term.
250  * This function recognizes both upper and lower CamelCase, depending whether the leading character is capitalized
251  * or not. The leading part of an upper CamelCase pattern is assumed to contain a sequence of capitals which are appearing
252  * in the matching name; e.g. 'NPE' will match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
253  * uses a lowercase first character. In Java, type names follow the upper CamelCase convention, whereas method or field
254  * names follow the lower CamelCase convention.
255  * <br>
256  * The pattern may contain lowercase characters, which will be match in a case sensitive way. These characters must
257  * appear in sequence in the name. For instance, 'NPExcep' will match 'NullPointerException', but not 'NullPointerExCEPTION'
258  * or 'NuPoEx' will match 'NullPointerException', but not 'NoPointerException'.
259  * <br><br>
260  * Examples:
261  * <ol>
262  * <li><pre>
263  * pattern = { 'N', 'P', 'E' }
264  * patternStart = 0
265  * patternEnd = 3
266  * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
267  * nameStart = 0
268  * nameEnd = 20
269  * result => true
270  * </pre>
271  * </li>
272  * <li><pre>
273  * pattern = { 'N', 'P', 'E' }
274  * patternStart = 0
275  * patternEnd = 3
276  * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
277  * nameStart = 0
278  * nameEnd = 21
279  * result => true
280  * </pre>
281  * </li>
282  * <li><pre>
283  * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
284  * patternStart = 0
285  * patternEnd = 6
286  * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
287  * nameStart = 0
288  * nameEnd = 20
289  * result => true
290  * </pre>
291  * </li>
292  * <li><pre>
293  * pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
294  * patternStart = 0
295  * patternEnd = 6
296  * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
297  * nameStart = 0
298  * nameEnd = 21
299  * result => false
300  * </pre>
301  * </li>
302  * <li><pre>
303  * pattern = { 'n', p', 'e' }
304  * patternStart = 0
305  * patternEnd = 3
306  * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
307  * nameStart = 0
308  * nameEnd = 20
309  * result => false
310  * </pre>
311  * </li>
312  * </ol>
313  *
314  * @param pattern the given pattern
315  * @param patternStart the start index of the pattern, inclusive
316  * @param patternEnd the end index of the pattern, exclusive
317  * @param name the given name
318  * @param nameStart the start index of the name, inclusive
319  * @param nameEnd the end index of the name, exclusive
320  * @return true if a sub-pattern matches the subpart of the given name, false otherwise
321  * @since 3.2
322  */

323 public static final boolean camelCaseMatch(char[] pattern, int patternStart, int patternEnd, char[] name, int nameStart, int nameEnd) {
324     if (name == null)
325         return false; // null name cannot match
326
if (pattern == null)
327         return true; // null pattern is equivalent to '*'
328
if (patternEnd < 0) patternEnd = pattern.length;
329     if (nameEnd < 0) nameEnd = name.length;
330
331     if (patternEnd <= patternStart) return nameEnd <= nameStart;
332     if (nameEnd <= nameStart) return false;
333     // check first pattern char
334
if (name[nameStart] != pattern[patternStart]) {
335         // first char must strictly match (upper/lower)
336
return false;
337     }
338
339     char patternChar, nameChar;
340     int iPattern = patternStart;
341     int iName = nameStart;
342
343     // Main loop is on pattern characters
344
while (true) {
345
346         iPattern++;
347         iName++;
348
349         if (iPattern == patternEnd) {
350             // We have exhausted pattern, so it's a match
351
return true;
352         }
353
354         if (iName == nameEnd){
355             // We have exhausted name (and not pattern), so it's not a match
356
return false;
357         }
358
359         // For as long as we're exactly matching, bring it on (even if it's a lower case character)
360
if ((patternChar = pattern[iPattern]) == name[iName]) {
361             continue;
362         }
363
364         // If characters are not equals, then it's not a match if patternChar is lowercase
365
if (patternChar < ScannerHelper.MAX_OBVIOUS) {
366             if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] & ScannerHelper.C_UPPER_LETTER) == 0) {
367                 return false;
368             }
369         }
370         else if (Character.isJavaIdentifierPart(patternChar) && !Character.isUpperCase(patternChar)) {
371             return false;
372         }
373
374         // patternChar is uppercase, so let's find the next uppercase in name
375
while (true) {
376             if (iName == nameEnd){
377                 // We have exhausted name (and not pattern), so it's not a match
378
return false;
379             }
380
381             nameChar = name[iName];
382             if (nameChar < ScannerHelper.MAX_OBVIOUS) {
383                 if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar] & (ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_SPECIAL | ScannerHelper.C_DIGIT)) != 0) {
384                     // nameChar is lowercase
385
iName++;
386                 // nameChar is uppercase...
387
} else if (patternChar != nameChar) {
388                     //.. and it does not match patternChar, so it's not a match
389
return false;
390                 } else {
391                     //.. and it matched patternChar. Back to the big loop
392
break;
393                 }
394             }
395             else if (Character.isJavaIdentifierPart(nameChar) && !Character.isUpperCase(nameChar)) {
396                 // nameChar is lowercase
397
iName++;
398             // nameChar is uppercase...
399
} else if (patternChar != nameChar) {
400                 //.. and it does not match patternChar, so it's not a match
401
return false;
402             } else {
403                 //.. and it matched patternChar. Back to the big loop
404
break;
405             }
406         }
407         // At this point, either name has been exhausted, or it is at an uppercase letter.
408
// Since pattern is also at an uppercase letter
409
}
410 }
411
412 /**
413  * Returns the char arrays as an array of Strings
414  *
415  * @param charArrays the char array to convert
416  * @return the char arrays as an array of Strings or null if the given char arrays is null.
417  * @since 3.0
418  */

419 public static String JavaDoc[] charArrayToStringArray(char[][] charArrays) {
420     if (charArrays == null)
421         return null;
422     int length = charArrays.length;
423     if (length == 0)
424         return NO_STRINGS;
425     String JavaDoc[] strings= new String JavaDoc[length];
426     for (int i= 0; i < length; i++)
427         strings[i]= new String JavaDoc(charArrays[i]);
428     return strings;
429 }
430
431 /**
432  * Returns the char array as a String
433
434  * @param charArray the char array to convert
435  * @return the char array as a String or null if the given char array is null.
436  * @since 3.0
437  */

438 public static String JavaDoc charToString(char[] charArray) {
439     if (charArray == null) return null;
440     return new String JavaDoc(charArray);
441 }
442
443 /**
444  * Answers a new array adding the second array at the end of first array.
445  * It answers null if the first and second are null.
446  * If the first array is null, then a new array char[][] is created with second.
447  * If the second array is null, then the first array is returned.
448  * <br>
449  * <br>
450  * For example:
451  * <ol>
452  * <li><pre>
453  * first = null
454  * second = { 'a' }
455  * => result = { { ' a' } }
456  * </pre>
457  * <li><pre>
458  * first = { { ' a' } }
459  * second = null
460  * => result = { { ' a' } }
461  * </pre>
462  * </li>
463  * <li><pre>
464  * first = { { ' a' } }
465  * second = { ' b' }
466  * => result = { { ' a' } , { ' b' } }
467  * </pre>
468  * </li>
469  * </ol>
470  *
471  * @param first the first array to concatenate
472  * @param second the array to add at the end of the first array
473  * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
474  */

475 public static final char[][] arrayConcat(char[][] first, char[] second) {
476     if (second == null)
477         return first;
478     if (first == null)
479         return new char[][] { second };
480
481     int length = first.length;
482     char[][] result = new char[length + 1][];
483     System.arraycopy(first, 0, result, 0, length);
484     result[length] = second;
485     return result;
486 }
487 /**
488  * Compares the two char arrays lexicographically.
489  *
490  * Returns a negative integer if array1 lexicographically precedes the array2,
491  * a positive integer if this array1 lexicographically follows the array2, or
492  * zero if both arrays are equal.
493  *
494  * @param array1 the first given array
495  * @param array2 the second given array
496  * @return the returned value of the comparison between array1 and array2
497  * @throws NullPointerException if one of the arrays is null
498  * @since 3.3
499  */

500 public static final int compareTo(char[] array1, char[] array2) {
501     int length1 = array1.length;
502     int length2 = array2.length;
503     int min = Math.min(length1, length2);
504     for (int i = 0; i < min; i++) {
505         if (array1[i] != array2[i]) {
506             return array1[i] - array2[i];
507         }
508     }
509     return length1 - length2;
510 }
511 /**
512  * Compares the contents of the two arrays array and prefix. Returns
513  * <ul>
514  * <li>zero if the array starts with the prefix contents</li>
515  * <li>the difference between the first two characters that are not equal </li>
516  * <li>one if array length is lower than the prefix length and that the prefix starts with the
517  * array contents.</li>
518  * </ul>
519  * <p>
520  * For example:
521  * <ol>
522  * <li><pre>
523  * array = null
524  * prefix = null
525  * => result = NullPointerException
526  * </pre>
527  * </li>
528  * <li><pre>
529  * array = { 'a', 'b', 'c', 'd', 'e' }
530  * prefix = { 'a', 'b', 'c'}
531  * => result = 0
532  * </pre>
533  * </li>
534  * <li><pre>
535  * array = { 'a', 'b', 'c', 'd', 'e' }
536  * prefix = { 'a', 'B', 'c'}
537  * => result = 32
538  * </pre>
539  * </li>
540  * <li><pre>
541  * array = { 'd', 'b', 'c', 'd', 'e' }
542  * prefix = { 'a', 'b', 'c'}
543  * => result = 3
544  * </pre>
545  * </li>
546  * <li><pre>
547  * array = { 'a', 'b', 'c', 'd', 'e' }
548  * prefix = { 'd', 'b', 'c'}
549  * => result = -3
550  * </pre>
551  * </li>
552  * <li><pre>
553  * array = { 'a', 'a', 'c', 'd', 'e' }
554  * prefix = { 'a', 'e', 'c'}
555  * => result = -4
556  * </pre>
557  * </li>
558  * </ol>
559  * </p>
560  *
561  * @param array the given array
562  * @param prefix the given prefix
563  * @return the result of the comparison (>=0 if array>prefix)
564  * @throws NullPointerException if either array or prefix is null
565  */

566 public static final int compareWith(char[] array, char[] prefix) {
567     int arrayLength = array.length;
568     int prefixLength = prefix.length;
569     int min = Math.min(arrayLength, prefixLength);
570     int i = 0;
571     while (min-- != 0) {
572         char c1 = array[i];
573         char c2 = prefix[i++];
574         if (c1 != c2)
575             return c1 - c2;
576     }
577     if (prefixLength == i)
578         return 0;
579     return -1; // array is shorter than prefix (e.g. array:'ab' < prefix:'abc').
580
}
581
582 /**
583  * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
584  * If the first array is null, then the second array is returned.
585  * If the second array is null, then the first array is returned.
586  * <br>
587  * <br>
588  * For example:
589  * <ol>
590  * <li><pre>
591  * first = null
592  * second = { 'a' }
593  * => result = { ' a' }
594  * </pre>
595  * </li>
596  * <li><pre>
597  * first = { ' a' }
598  * second = null
599  * => result = { ' a' }
600  * </pre>
601  * </li>
602  * <li><pre>
603  * first = { ' a' }
604  * second = { ' b' }
605  * => result = { ' a' , ' b' }
606  * </pre>
607  * </li>
608  * </ol>
609  *
610  * @param first the first array to concatenate
611  * @param second the second array to concatenate
612  * @return the concatenation of the two arrays, or null if the two arrays are null.
613  */

614 public static final char[] concat(char[] first, char[] second) {
615     if (first == null)
616         return second;
617     if (second == null)
618         return first;
619
620     int length1 = first.length;
621     int length2 = second.length;
622     char[] result = new char[length1 + length2];
623     System.arraycopy(first, 0, result, 0, length1);
624     System.arraycopy(second, 0, result, length1, length2);
625     return result;
626 }
627
628 /**
629  * Answers the concatenation of the three arrays. It answers null if the three arrays are null.
630  * If first is null, it answers the concatenation of second and third.
631  * If second is null, it answers the concatenation of first and third.
632  * If third is null, it answers the concatenation of first and second.
633  * <br>
634  * <br>
635  * For example:
636  * <ol>
637  * <li><pre>
638  * first = null
639  * second = { 'a' }
640  * third = { 'b' }
641  * => result = { ' a', 'b' }
642  * </pre>
643  * </li>
644  * <li><pre>
645  * first = { 'a' }
646  * second = null
647  * third = { 'b' }
648  * => result = { ' a', 'b' }
649  * </pre>
650  * </li>
651  * <li><pre>
652  * first = { 'a' }
653  * second = { 'b' }
654  * third = null
655  * => result = { ' a', 'b' }
656  * </pre>
657  * </li>
658  * <li><pre>
659  * first = null
660  * second = null
661  * third = null
662  * => result = null
663  * </pre>
664  * </li>
665  * <li><pre>
666  * first = { 'a' }
667  * second = { 'b' }
668  * third = { 'c' }
669  * => result = { 'a', 'b', 'c' }
670  * </pre>
671  * </li>
672  * </ol>
673  *
674  * @param first the first array to concatenate
675  * @param second the second array to concatenate
676  * @param third the third array to concatenate
677  *
678  * @return the concatenation of the three arrays, or null if the three arrays are null.
679  */

680 public static final char[] concat(
681     char[] first,
682     char[] second,
683     char[] third) {
684     if (first == null)
685         return concat(second, third);
686     if (second == null)
687         return concat(first, third);
688     if (third == null)
689         return concat(first, second);
690
691     int length1 = first.length;
692     int length2 = second.length;
693     int length3 = third.length;
694     char[] result = new char[length1 + length2 + length3];
695     System.arraycopy(first, 0, result, 0, length1);
696     System.arraycopy(second, 0, result, length1, length2);
697     System.arraycopy(third, 0, result, length1 + length2, length3);
698     return result;
699 }
700
701 /**
702  * Answers the concatenation of the two arrays inserting the separator character between the two arrays.
703  * It answers null if the two arrays are null.
704  * If the first array is null, then the second array is returned.
705  * If the second array is null, then the first array is returned.
706  * <br>
707  * <br>
708  * For example:
709  * <ol>
710  * <li><pre>
711  * first = null
712  * second = { 'a' }
713  * separator = '/'
714  * => result = { ' a' }
715  * </pre>
716  * </li>
717  * <li><pre>
718  * first = { ' a' }
719  * second = null
720  * separator = '/'
721  * => result = { ' a' }
722  * </pre>
723  * </li>
724  * <li><pre>
725  * first = { ' a' }
726  * second = { ' b' }
727  * separator = '/'
728  * => result = { ' a' , '/', 'b' }
729  * </pre>
730  * </li>
731  * </ol>
732  *
733  * @param first the first array to concatenate
734  * @param second the second array to concatenate
735  * @param separator the character to insert
736  * @return the concatenation of the two arrays inserting the separator character
737  * between the two arrays , or null if the two arrays are null.
738  */

739 public static final char[] concat(
740     char[] first,
741     char[] second,
742     char separator) {
743     if (first == null)
744         return second;
745     if (second == null)
746         return first;
747
748     int length1 = first.length;
749     if (length1 == 0)
750         return second;
751     int length2 = second.length;
752     if (length2 == 0)
753         return first;
754
755     char[] result = new char[length1 + length2 + 1];
756     System.arraycopy(first, 0, result, 0, length1);
757     result[length1] = separator;
758     System.arraycopy(second, 0, result, length1 + 1, length2);
759     return result;
760 }
761
762 /**
763  * Answers the concatenation of the three arrays inserting the sep1 character between the
764  * first two arrays and sep2 between the last two.
765  * It answers null if the three arrays are null.
766  * If the first array is null, then it answers the concatenation of second and third inserting
767  * the sep2 character between them.
768  * If the second array is null, then it answers the concatenation of first and third inserting
769  * the sep1 character between them.
770  * If the third array is null, then it answers the concatenation of first and second inserting
771  * the sep1 character between them.
772  * <br>
773  * <br>
774  * For example:
775  * <ol>
776  * <li><pre>
777  * first = null
778  * sep1 = '/'
779  * second = { 'a' }
780  * sep2 = ':'
781  * third = { 'b' }
782  * => result = { ' a' , ':', 'b' }
783  * </pre>
784  * </li>
785  * <li><pre>
786  * first = { 'a' }
787  * sep1 = '/'
788  * second = null
789  * sep2 = ':'
790  * third = { 'b' }
791  * => result = { ' a' , '/', 'b' }
792  * </pre>
793  * </li>
794  * <li><pre>
795  * first = { 'a' }
796  * sep1 = '/'
797  * second = { 'b' }
798  * sep2 = ':'
799  * third = null
800  * => result = { ' a' , '/', 'b' }
801  * </pre>
802  * </li>
803  * <li><pre>
804  * first = { 'a' }
805  * sep1 = '/'
806  * second = { 'b' }
807  * sep2 = ':'
808  * third = { 'c' }
809  * => result = { ' a' , '/', 'b' , ':', 'c' }
810  * </pre>
811  * </li>
812  * </ol>
813  *
814  * @param first the first array to concatenate
815  * @param sep1 the character to insert
816  * @param second the second array to concatenate
817  * @param sep2 the character to insert
818  * @param third the second array to concatenate
819  * @return the concatenation of the three arrays inserting the sep1 character between the
820  * two arrays and sep2 between the last two.
821  */

822 public static final char[] concat(
823     char[] first,
824     char sep1,
825     char[] second,
826     char sep2,
827     char[] third) {
828     if (first == null)
829         return concat(second, third, sep2);
830     if (second == null)
831         return concat(first, third, sep1);
832     if (third == null)
833         return concat(first, second, sep1);
834
835     int length1 = first.length;
836     int length2 = second.length;
837     int length3 = third.length;
838     char[] result = new char[length1 + length2 + length3 + 2];
839     System.arraycopy(first, 0, result, 0, length1);
840     result[length1] = sep1;
841     System.arraycopy(second, 0, result, length1 + 1, length2);
842     result[length1 + length2 + 1] = sep2;
843     System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
844     return result;
845 }
846
847 /**
848  * Answers a new array with prepending the prefix character and appending the suffix
849  * character at the end of the array. If array is null, it answers a new array containing the
850  * prefix and the suffix characters.
851  * <br>
852  * <br>
853  * For example:<br>
854  * <ol>
855  * <li><pre>
856  * prefix = 'a'
857  * array = { 'b' }
858  * suffix = 'c'
859  * => result = { 'a', 'b' , 'c' }
860  * </pre>
861  * </li>
862  * <li><pre>
863  * prefix = 'a'
864  * array = null
865  * suffix = 'c'
866  * => result = { 'a', 'c' }
867  * </pre></li>
868  * </ol>
869  *
870  * @param prefix the prefix character
871  * @param array the array that is concanated with the prefix and suffix characters
872  * @param suffix the suffix character
873  * @return the new array
874  */

875 public static final char[] concat(char prefix, char[] array, char suffix) {
876     if (array == null)
877         return new char[] { prefix, suffix };
878
879     int length = array.length;
880     char[] result = new char[length + 2];
881     result[0] = prefix;
882     System.arraycopy(array, 0, result, 1, length);
883     result[length + 1] = suffix;
884     return result;
885 }
886
887 /**
888  * Answers the concatenation of the given array parts using the given separator between each
889  * part and appending the given name at the end.
890  * <br>
891  * <br>
892  * For example:<br>
893  * <ol>
894  * <li><pre>
895  * name = { 'c' }
896  * array = { { 'a' }, { 'b' } }
897  * separator = '.'
898  * => result = { 'a', '.', 'b' , '.', 'c' }
899  * </pre>
900  * </li>
901  * <li><pre>
902  * name = null
903  * array = { { 'a' }, { 'b' } }
904  * separator = '.'
905  * => result = { 'a', '.', 'b' }
906  * </pre></li>
907  * <li><pre>
908  * name = { ' c' }
909  * array = null
910  * separator = '.'
911  * => result = { 'c' }
912  * </pre></li>
913  * </ol>
914  *
915  * @param name the given name
916  * @param array the given array
917  * @param separator the given separator
918  * @return the concatenation of the given array parts using the given separator between each
919  * part and appending the given name at the end
920  */

921 public static final char[] concatWith(
922     char[] name,
923     char[][] array,
924     char separator) {
925     int nameLength = name == null ? 0 : name.length;
926     if (nameLength == 0)
927         return concatWith(array, separator);
928
929     int length = array == null ? 0 : array.length;
930     if (length == 0)
931         return name;
932
933     int size = nameLength;
934     int index = length;
935     while (--index >= 0)
936         if (array[index].length > 0)
937             size += array[index].length + 1;
938     char[] result = new char[size];
939     index = size;
940     for (int i = length - 1; i >= 0; i--) {
941         int subLength = array[i].length;
942         if (subLength > 0) {
943             index -= subLength;
944             System.arraycopy(array[i], 0, result, index, subLength);
945             result[--index] = separator;
946         }
947     }
948     System.arraycopy(name, 0, result, 0, nameLength);
949     return result;
950 }
951
952 /**
953  * Answers the concatenation of the given array parts using the given separator between each
954  * part and appending the given name at the end.
955  * <br>
956  * <br>
957  * For example:<br>
958  * <ol>
959  * <li><pre>
960  * name = { 'c' }
961  * array = { { 'a' }, { 'b' } }
962  * separator = '.'
963  * => result = { 'a', '.', 'b' , '.', 'c' }
964  * </pre>
965  * </li>
966  * <li><pre>
967  * name = null
968  * array = { { 'a' }, { 'b' } }
969  * separator = '.'
970  * => result = { 'a', '.', 'b' }
971  * </pre></li>
972  * <li><pre>
973  * name = { ' c' }
974  * array = null
975  * separator = '.'
976  * => result = { 'c' }
977  * </pre></li>
978  * </ol>
979  *
980  * @param array the given array
981  * @param name the given name
982  * @param separator the given separator
983  * @return the concatenation of the given array parts using the given separator between each
984  * part and appending the given name at the end
985  */

986 public static final char[] concatWith(
987     char[][] array,
988     char[] name,
989     char separator) {
990     int nameLength = name == null ? 0 : name.length;
991     if (nameLength == 0)
992         return concatWith(array, separator);
993
994     int length = array == null ? 0 : array.length;
995     if (length == 0)
996         return name;
997
998     int size = nameLength;
999     int index = length;
1000    while (--index >= 0)
1001        if (array[index].length > 0)
1002            size += array[index].length + 1;
1003    char[] result = new char[size];
1004    index = 0;
1005    for (int i = 0; i < length; i++) {
1006        int subLength = array[i].length;
1007        if (subLength > 0) {
1008            System.arraycopy(array[i], 0, result, index, subLength);
1009            index += subLength;
1010            result[index++] = separator;
1011        }
1012    }
1013    System.arraycopy(name, 0, result, index, nameLength);
1014    return result;
1015}
1016
1017/**
1018 * Answers the concatenation of the given array parts using the given separator between each part.
1019 * <br>
1020 * <br>
1021 * For example:<br>
1022 * <ol>
1023 * <li><pre>
1024 * array = { { 'a' }, { 'b' } }
1025 * separator = '.'
1026 * => result = { 'a', '.', 'b' }
1027 * </pre>
1028 * </li>
1029 * <li><pre>
1030 * array = null
1031 * separator = '.'
1032 * => result = { }
1033 * </pre></li>
1034 * </ol>
1035 *
1036 * @param array the given array
1037 * @param separator the given separator
1038 * @return the concatenation of the given array parts using the given separator between each part
1039 */

1040public static final char[] concatWith(char[][] array, char separator) {
1041    int length = array == null ? 0 : array.length;
1042    if (length == 0)
1043        return CharOperation.NO_CHAR;
1044
1045    int size = length - 1;
1046    int index = length;
1047    while (--index >= 0) {
1048        if (array[index].length == 0)
1049            size--;
1050        else
1051            size += array[index].length;
1052    }
1053    if (size <= 0)
1054        return CharOperation.NO_CHAR;
1055    char[] result = new char[size];
1056    index = length;
1057    while (--index >= 0) {
1058        length = array[index].length;
1059        if (length > 0) {
1060            System.arraycopy(
1061                array[index],
1062                0,
1063                result,
1064                (size -= length),
1065                length);
1066            if (--size >= 0)
1067                result[size] = separator;
1068        }
1069    }
1070    return result;
1071}
1072
1073/**
1074 * Answers true if the array contains an occurrence of character, false otherwise.
1075 *
1076 * <br>
1077 * <br>
1078 * For example:
1079 * <ol>
1080 * <li><pre>
1081 * character = 'c'
1082 * array = { { ' a' }, { ' b' } }
1083 * result => false
1084 * </pre>
1085 * </li>
1086 * <li><pre>
1087 * character = 'a'
1088 * array = { { ' a' }, { ' b' } }
1089 * result => true
1090 * </pre>
1091 * </li>
1092 * </ol>
1093 *
1094 * @param character the character to search
1095 * @param array the array in which the search is done
1096 * @return true if the array contains an occurrence of character, false otherwise.
1097 * @throws NullPointerException if array is null.
1098 */

1099public static final boolean contains(char character, char[][] array) {
1100    for (int i = array.length; --i >= 0;) {
1101        char[] subarray = array[i];
1102        for (int j = subarray.length; --j >= 0;)
1103            if (subarray[j] == character)
1104                return true;
1105    }
1106    return false;
1107}
1108
1109/**
1110 * Answers true if the array contains an occurrence of character, false otherwise.
1111 *
1112 * <br>
1113 * <br>
1114 * For example:
1115 * <ol>
1116 * <li><pre>
1117 * character = 'c'
1118 * array = { ' b' }
1119 * result => false
1120 * </pre>
1121 * </li>
1122 * <li><pre>
1123 * character = 'a'
1124 * array = { ' a' , ' b' }
1125 * result => true
1126 * </pre>
1127 * </li>
1128 * </ol>
1129 *
1130 * @param character the character to search
1131 * @param array the array in which the search is done
1132 * @return true if the array contains an occurrence of character, false otherwise.
1133 * @throws NullPointerException if array is null.
1134 */

1135public static final boolean contains(char character, char[] array) {
1136    for (int i = array.length; --i >= 0;)
1137        if (array[i] == character)
1138            return true;
1139    return false;
1140}
1141
1142/**
1143 * Answers true if the array contains an occurrence of one of the characters, false otherwise.
1144 *
1145 * <br>
1146 * <br>
1147 * For example:
1148 * <ol>
1149 * <li><pre>
1150 * characters = { 'c', 'd' }
1151 * array = { 'a', ' b' }
1152 * result => false
1153 * </pre>
1154 * </li>
1155 * <li><pre>
1156 * characters = { 'c', 'd' }
1157 * array = { 'a', ' b', 'c' }
1158 * result => true
1159 * </pre>
1160 * </li>
1161 * </ol>
1162 *
1163 * @param characters the characters to search
1164 * @param array the array in which the search is done
1165 * @return true if the array contains an occurrence of one of the characters, false otherwise.
1166 * @throws NullPointerException if array is null.
1167 * @since 3.1
1168 */

1169public static final boolean contains(char[] characters, char[] array) {
1170    for (int i = array.length; --i >= 0;)
1171        for (int j = characters.length; --j >= 0;)
1172            if (array[i] == characters[j])
1173                return true;
1174    return false;
1175}
1176
1177/**
1178 * Answers a deep copy of the toCopy array.
1179 *
1180 * @param toCopy the array to copy
1181 * @return a deep copy of the toCopy array.
1182 */

1183
1184public static final char[][] deepCopy(char[][] toCopy) {
1185    int toCopyLength = toCopy.length;
1186    char[][] result = new char[toCopyLength][];
1187    for (int i = 0; i < toCopyLength; i++) {
1188        char[] toElement = toCopy[i];
1189        int toElementLength = toElement.length;
1190        char[] resultElement = new char[toElementLength];
1191        System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
1192        result[i] = resultElement;
1193    }
1194    return result;
1195}
1196
1197/**
1198 * Return true if array ends with the sequence of characters contained in toBeFound,
1199 * otherwise false.
1200 * <br>
1201 * <br>
1202 * For example:
1203 * <ol>
1204 * <li><pre>
1205 * array = { 'a', 'b', 'c', 'd' }
1206 * toBeFound = { 'b', 'c' }
1207 * result => false
1208 * </pre>
1209 * </li>
1210 * <li><pre>
1211 * array = { 'a', 'b', 'c' }
1212 * toBeFound = { 'b', 'c' }
1213 * result => true
1214 * </pre>
1215 * </li>
1216 * </ol>
1217 *
1218 * @param array the array to check
1219 * @param toBeFound the array to find
1220 * @return true if array ends with the sequence of characters contained in toBeFound,
1221 * otherwise false.
1222 * @throws NullPointerException if array is null or toBeFound is null
1223 */

1224public static final boolean endsWith(char[] array, char[] toBeFound) {
1225    int i = toBeFound.length;
1226    int j = array.length - i;
1227
1228    if (j < 0)
1229        return false;
1230    while (--i >= 0)
1231        if (toBeFound[i] != array[i + j])
1232            return false;
1233    return true;
1234}
1235
1236/**
1237 * Answers true if the two arrays are identical character by character, otherwise false.
1238 * The equality is case sensitive.
1239 * <br>
1240 * <br>
1241 * For example:
1242 * <ol>
1243 * <li><pre>
1244 * first = null
1245 * second = null
1246 * result => true
1247 * </pre>
1248 * </li>
1249 * <li><pre>
1250 * first = { { } }
1251 * second = null
1252 * result => false
1253 * </pre>
1254 * </li>
1255 * <li><pre>
1256 * first = { { 'a' } }
1257 * second = { { 'a' } }
1258 * result => true
1259 * </pre>
1260 * </li>
1261 * <li><pre>
1262 * first = { { 'A' } }
1263 * second = { { 'a' } }
1264 * result => false
1265 * </pre>
1266 * </li>
1267 * </ol>
1268 * @param first the first array
1269 * @param second the second array
1270 * @return true if the two arrays are identical character by character, otherwise false
1271 */

1272public static final boolean equals(char[][] first, char[][] second) {
1273    if (first == second)
1274        return true;
1275    if (first == null || second == null)
1276        return false;
1277    if (first.length != second.length)
1278        return false;
1279
1280    for (int i = first.length; --i >= 0;)
1281        if (!equals(first[i], second[i]))
1282            return false;
1283    return true;
1284}
1285
1286/**
1287 * If isCaseSensite is true, answers true if the two arrays are identical character
1288 * by character, otherwise false.
1289 * If it is false, answers true if the two arrays are identical character by
1290 * character without checking the case, otherwise false.
1291 * <br>
1292 * <br>
1293 * For example:
1294 * <ol>
1295 * <li><pre>
1296 * first = null
1297 * second = null
1298 * isCaseSensitive = true
1299 * result => true
1300 * </pre>
1301 * </li>
1302 * <li><pre>
1303 * first = { { } }
1304 * second = null
1305 * isCaseSensitive = true
1306 * result => false
1307 * </pre>
1308 * </li>
1309 * <li><pre>
1310 * first = { { 'A' } }
1311 * second = { { 'a' } }
1312 * isCaseSensitive = true
1313 * result => false
1314 * </pre>
1315 * </li>
1316 * <li><pre>
1317 * first = { { 'A' } }
1318 * second = { { 'a' } }
1319 * isCaseSensitive = false
1320 * result => true
1321 * </pre>
1322 * </li>
1323 * </ol>
1324 *
1325 * @param first the first array
1326 * @param second the second array
1327 * @param isCaseSensitive check whether or not the equality should be case sensitive
1328 * @return true if the two arrays are identical character by character according to the value
1329 * of isCaseSensitive, otherwise false
1330 */

1331public static final boolean equals(
1332    char[][] first,
1333    char[][] second,
1334    boolean isCaseSensitive) {
1335
1336    if (isCaseSensitive) {
1337        return equals(first, second);
1338    }
1339    if (first == second)
1340        return true;
1341    if (first == null || second == null)
1342        return false;
1343    if (first.length != second.length)
1344        return false;
1345
1346    for (int i = first.length; --i >= 0;)
1347        if (!equals(first[i], second[i], false))
1348            return false;
1349    return true;
1350}
1351
1352/**
1353 * Answers true if the two arrays are identical character by character, otherwise false.
1354 * The equality is case sensitive.
1355 * <br>
1356 * <br>
1357 * For example:
1358 * <ol>
1359 * <li><pre>
1360 * first = null
1361 * second = null
1362 * result => true
1363 * </pre>
1364 * </li>
1365 * <li><pre>
1366 * first = { }
1367 * second = null
1368 * result => false
1369 * </pre>
1370 * </li>
1371 * <li><pre>
1372 * first = { 'a' }
1373 * second = { 'a' }
1374 * result => true
1375 * </pre>
1376 * </li>
1377 * <li><pre>
1378 * first = { 'a' }
1379 * second = { 'A' }
1380 * result => false
1381 * </pre>
1382 * </li>
1383 * </ol>
1384 * @param first the first array
1385 * @param second the second array
1386 * @return true if the two arrays are identical character by character, otherwise false
1387 */

1388public static final boolean equals(char[] first, char[] second) {
1389    if (first == second)
1390        return true;
1391    if (first == null || second == null)
1392        return false;
1393    if (first.length != second.length)
1394        return false;
1395
1396    for (int i = first.length; --i >= 0;)
1397        if (first[i] != second[i])
1398            return false;
1399    return true;
1400}
1401
1402/**
1403 * Answers true if the first array is identical character by character to a portion of the second array
1404 * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false.
1405 * The equality is case sensitive.
1406 * <br>
1407 * <br>
1408 * For example:
1409 * <ol>
1410 * <li><pre>
1411 * first = null
1412 * second = null
1413 * secondStart = 0
1414 * secondEnd = 0
1415 * result => true
1416 * </pre>
1417 * </li>
1418 * <li><pre>
1419 * first = { }
1420 * second = null
1421 * secondStart = 0
1422 * secondEnd = 0
1423 * result => false
1424 * </pre>
1425 * </li>
1426 * <li><pre>
1427 * first = { 'a' }
1428 * second = { 'a' }
1429 * secondStart = 0
1430 * secondEnd = 1
1431 * result => true
1432 * </pre>
1433 * </li>
1434 * <li><pre>
1435 * first = { 'a' }
1436 * second = { 'A' }
1437 * secondStart = 0
1438 * secondEnd = 1
1439 * result => false
1440 * </pre>
1441 * </li>
1442 * </ol>
1443 * @param first the first array
1444 * @param second the second array
1445 * @param secondStart inclusive start position in the second array to compare
1446 * @param secondEnd exclusive end position in the second array to compare
1447 * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
1448 * @since 3.0
1449 */

1450public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd) {
1451    return equals(first, second, secondStart, secondEnd, true);
1452}
1453/**
1454 * <p>Answers true if the first array is identical character by character to a portion of the second array
1455 * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false. The equality could be either
1456 * case sensitive or case insensitive according to the value of the <code>isCaseSensitive</code> parameter.
1457 * </p>
1458 * <p>For example:</p>
1459 * <ol>
1460 * <li><pre>
1461 * first = null
1462 * second = null
1463 * secondStart = 0
1464 * secondEnd = 0
1465 * isCaseSensitive = false
1466 * result => true
1467 * </pre>
1468 * </li>
1469 * <li><pre>
1470 * first = { }
1471 * second = null
1472 * secondStart = 0
1473 * secondEnd = 0
1474 * isCaseSensitive = false
1475 * result => false
1476 * </pre>
1477 * </li>
1478 * <li><pre>
1479 * first = { 'a' }
1480 * second = { 'a' }
1481 * secondStart = 0
1482 * secondEnd = 1
1483 * isCaseSensitive = true
1484 * result => true
1485 * </pre>
1486 * </li>
1487 * <li><pre>
1488 * first = { 'a' }
1489 * second = { 'A' }
1490 * secondStart = 0
1491 * secondEnd = 1
1492 * isCaseSensitive = true
1493 * result => false
1494 * </pre>
1495 * </li>
1496 * <li><pre>
1497 * first = { 'a' }
1498 * second = { 'A' }
1499 * secondStart = 0
1500 * secondEnd = 1
1501 * isCaseSensitive = false
1502 * result => true
1503 * </pre>
1504 * </li>
1505 * </ol>
1506 * @param first the first array
1507 * @param second the second array
1508 * @param secondStart inclusive start position in the second array to compare
1509 * @param secondEnd exclusive end position in the second array to compare
1510 * @param isCaseSensitive check whether or not the equality should be case sensitive
1511 * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
1512 * @since 3.2
1513 */

1514public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd, boolean isCaseSensitive) {
1515    if (first == second)
1516        return true;
1517    if (first == null || second == null)
1518        return false;
1519    if (first.length != secondEnd - secondStart)
1520        return false;
1521    if (isCaseSensitive) {
1522        for (int i = first.length; --i >= 0;)
1523            if (first[i] != second[i+secondStart])
1524                return false;
1525    } else {
1526        for (int i = first.length; --i >= 0;)
1527            if (ScannerHelper.toLowerCase(first[i]) != ScannerHelper.toLowerCase(second[i+secondStart]))
1528                return false;
1529    }
1530    return true;
1531}
1532
1533/**
1534 * If isCaseSensite is true, answers true if the two arrays are identical character
1535 * by character, otherwise false.
1536 * If it is false, answers true if the two arrays are identical character by
1537 * character without checking the case, otherwise false.
1538 * <br>
1539 * <br>
1540 * For example:
1541 * <ol>
1542 * <li><pre>
1543 * first = null
1544 * second = null
1545 * isCaseSensitive = true
1546 * result => true
1547 * </pre>
1548 * </li>
1549 * <li><pre>
1550 * first = { }
1551 * second = null
1552 * isCaseSensitive = true
1553 * result => false
1554 * </pre>
1555 * </li>
1556 * <li><pre>
1557 * first = { 'A' }
1558 * second = { 'a' }
1559 * isCaseSensitive = true
1560 * result => false
1561 * </pre>
1562 * </li>
1563 * <li><pre>
1564 * first = { 'A' }
1565 * second = { 'a' }
1566 * isCaseSensitive = false
1567 * result => true
1568 * </pre>
1569 * </li>
1570 * </ol>
1571 *
1572 * @param first the first array
1573 * @param second the second array
1574 * @param isCaseSensitive check whether or not the equality should be case sensitive
1575 * @return true if the two arrays are identical character by character according to the value
1576 * of isCaseSensitive, otherwise false
1577 */

1578public static final boolean equals(
1579    char[] first,
1580    char[] second,
1581    boolean isCaseSensitive) {
1582
1583    if (isCaseSensitive) {
1584        return equals(first, second);
1585    }
1586    if (first == second)
1587        return true;
1588    if (first == null || second == null)
1589        return false;
1590    if (first.length != second.length)
1591        return false;
1592
1593    for (int i = first.length; --i >= 0;)
1594        if (ScannerHelper.toLowerCase(first[i])
1595            != ScannerHelper.toLowerCase(second[i]))
1596            return false;
1597    return true;
1598}
1599
1600/**
1601 * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive.
1602 *
1603 * Answers true if the name contains the fragment at the starting index startIndex, otherwise false.
1604 * <br>
1605 * <br>
1606 * For example:
1607 * <ol>
1608 * <li><pre>
1609 * fragment = { 'b', 'c' , 'd' }
1610 * name = { 'a', 'b', 'c' , 'd' }
1611 * startIndex = 1
1612 * isCaseSensitive = true
1613 * result => true
1614 * </pre>
1615 * </li>
1616 * <li><pre>
1617 * fragment = { 'b', 'c' , 'd' }
1618 * name = { 'a', 'b', 'C' , 'd' }
1619 * startIndex = 1
1620 * isCaseSensitive = true
1621 * result => false
1622 * </pre>
1623 * </li>
1624 * <li><pre>
1625 * fragment = { 'b', 'c' , 'd' }
1626 * name = { 'a', 'b', 'C' , 'd' }
1627 * startIndex = 0
1628 * isCaseSensitive = false
1629 * result => false
1630 * </pre>
1631 * </li>
1632 * <li><pre>
1633 * fragment = { 'b', 'c' , 'd' }
1634 * name = { 'a', 'b'}
1635 * startIndex = 0
1636 * isCaseSensitive = true
1637 * result => false
1638 * </pre>
1639 * </li>
1640 * </ol>
1641 *
1642 * @param fragment the fragment to check
1643 * @param name the array to check
1644 * @param startIndex the starting index
1645 * @param isCaseSensitive check whether or not the equality should be case sensitive
1646 * @return true if the name contains the fragment at the starting index startIndex according to the
1647 * value of isCaseSensitive, otherwise false.
1648 * @throws NullPointerException if fragment or name is null.
1649 */

1650public static final boolean fragmentEquals(
1651    char[] fragment,
1652    char[] name,
1653    int startIndex,
1654    boolean isCaseSensitive) {
1655
1656    int max = fragment.length;
1657    if (name.length < max + startIndex)
1658        return false;
1659    if (isCaseSensitive) {
1660        for (int i = max;
1661            --i >= 0;
1662            ) // assumes the prefix is not larger than the name
1663
if (fragment[i] != name[i + startIndex])
1664                return false;
1665        return true;
1666    }
1667    for (int i = max;
1668        --i >= 0;
1669        ) // assumes the prefix is not larger than the name
1670
if (ScannerHelper.toLowerCase(fragment[i])
1671            != ScannerHelper.toLowerCase(name[i + startIndex]))
1672            return false;
1673    return true;
1674}
1675
1676/**
1677 * Answers a hashcode for the array
1678 *
1679 * @param array the array for which a hashcode is required
1680 * @return the hashcode
1681 * @throws NullPointerException if array is null
1682 */

1683public static final int hashCode(char[] array) {
1684    int length = array.length;
1685    int hash = length == 0 ? 31 : array[0];
1686    if (length < 8) {
1687        for (int i = length; --i > 0;)
1688            hash = (hash * 31) + array[i];
1689    } else {
1690        // 8 characters is enough to compute a decent hash code, don't waste time examining every character
1691
for (int i = length - 1, last = i > 16 ? i - 16 : 0; i > last; i -= 2)
1692            hash = (hash * 31) + array[i];
1693    }
1694    return hash & 0x7FFFFFFF;
1695}
1696
1697/**
1698 * Answers true if c is a whitespace according to the JLS (&#92;u000a, &#92;u000c, &#92;u000d, &#92;u0009), otherwise false.
1699 * <br>
1700 * <br>
1701 * For example:
1702 * <ol>
1703 * <li><pre>
1704 * c = ' '
1705 * result => true
1706 * </pre>
1707 * </li>
1708 * <li><pre>
1709 * c = '&#92;u3000'
1710 * result => false
1711 * </pre>
1712 * </li>
1713 * </ol>
1714 *
1715 * @param c the character to check
1716 * @return true if c is a whitespace according to the JLS, otherwise false.
1717 */

1718public static boolean isWhitespace(char c) {
1719    return c < ScannerHelper.MAX_OBVIOUS && ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_JLS_SPACE) != 0);
1720}
1721
1722/**
1723 * Answers the first index in the array for which the corresponding character is
1724 * equal to toBeFound. Answers -1 if no occurrence of this character is found.
1725 * <br>
1726 * <br>
1727 * For example:
1728 * <ol>
1729 * <li><pre>
1730 * toBeFound = 'c'
1731 * array = { ' a', 'b', 'c', 'd' }
1732 * result => 2
1733 * </pre>
1734 * </li>
1735 * <li><pre>
1736 * toBeFound = 'e'
1737 * array = { ' a', 'b', 'c', 'd' }
1738 * result => -1
1739 * </pre>
1740 * </li>
1741 * </ol>
1742 *
1743 * @param toBeFound the character to search
1744 * @param array the array to be searched
1745 * @return the first index in the array for which the corresponding character is
1746 * equal to toBeFound, -1 otherwise
1747 * @throws NullPointerException if array is null
1748 */

1749public static final int indexOf(char toBeFound, char[] array) {
1750    return indexOf(toBeFound, array, 0);
1751}
1752
1753/**
1754 * Answers the first index in the array for which the toBeFound array is a matching
1755 * subarray following the case rule. Answers -1 if no match is found.
1756 * <br>
1757 * <br>
1758 * For example:
1759 * <ol>
1760 * <li><pre>
1761 * toBeFound = { 'c' }
1762 * array = { ' a', 'b', 'c', 'd' }
1763 * result => 2
1764 * </pre>
1765 * </li>
1766 * <li><pre>
1767 * toBeFound = { 'e' }
1768 * array = { ' a', 'b', 'c', 'd' }
1769 * result => -1
1770 * </pre>
1771 * </li>
1772 * </ol>
1773 *
1774 * @param toBeFound the subarray to search
1775 * @param array the array to be searched
1776 * @param isCaseSensitive flag to know if the matching should be case sensitive
1777 * @return the first index in the array for which the toBeFound array is a matching
1778 * subarray following the case rule, -1 otherwise
1779 * @throws NullPointerException if array is null or toBeFound is null
1780 * @since 3.2
1781 */

1782public static final int indexOf(char[] toBeFound, char[] array, boolean isCaseSensitive) {
1783    return indexOf(toBeFound, array, isCaseSensitive, 0);
1784}
1785
1786/**
1787 * Answers the first index in the array for which the toBeFound array is a matching
1788 * subarray following the case rule starting at the index start. Answers -1 if no match is found.
1789 * <br>
1790 * <br>
1791 * For example:
1792 * <ol>
1793 * <li><pre>
1794 * toBeFound = { 'c' }
1795 * array = { ' a', 'b', 'c', 'd' }
1796 * result => 2
1797 * </pre>
1798 * </li>
1799 * <li><pre>
1800 * toBeFound = { 'e' }
1801 * array = { ' a', 'b', 'c', 'd' }
1802 * result => -1
1803 * </pre>
1804 * </li>
1805 * </ol>
1806 *
1807 * @param toBeFound the subarray to search
1808 * @param array the array to be searched
1809 * @param isCaseSensitive flag to know if the matching should be case sensitive
1810 * @param start the starting index
1811 * @return the first index in the array for which the toBeFound array is a matching
1812 * subarray following the case rule starting at the index start, -1 otherwise
1813 * @throws NullPointerException if array is null or toBeFound is null
1814 * @since 3.2
1815 */

1816public static final int indexOf(final char[] toBeFound, final char[] array, final boolean isCaseSensitive, final int start) {
1817    return indexOf(toBeFound, array, isCaseSensitive, start, array.length);
1818}
1819
1820/**
1821 * Answers the first index in the array for which the toBeFound array is a matching
1822 * subarray following the case rule starting at the index start. Answers -1 if no match is found.
1823 * <br>
1824 * <br>
1825 * For example:
1826 * <ol>
1827 * <li><pre>
1828 * toBeFound = { 'c' }
1829 * array = { ' a', 'b', 'c', 'd' }
1830 * result => 2
1831 * </pre>
1832 * </li>
1833 * <li><pre>
1834 * toBeFound = { 'e' }
1835 * array = { ' a', 'b', 'c', 'd' }
1836 * result => -1
1837 * </pre>
1838 * </li>
1839 * </ol>
1840 *
1841 * @param toBeFound the subarray to search
1842 * @param array the array to be searched
1843 * @param isCaseSensitive flag to know if the matching should be case sensitive
1844 * @param start the starting index (inclusive)
1845 * @param end the end index (exclusive)
1846 * @return the first index in the array for which the toBeFound array is a matching
1847 * subarray following the case rule starting at the index start, -1 otherwise
1848 * @throws NullPointerException if array is null or toBeFound is null
1849 * @since 3.2
1850 */

1851public static final int indexOf(final char[] toBeFound, final char[] array, final boolean isCaseSensitive, final int start, final int end) {
1852    final int arrayLength = end;
1853    final int toBeFoundLength = toBeFound.length;
1854    if (toBeFoundLength > arrayLength) return -1;
1855    if (toBeFoundLength == 0) return 0;
1856    if (toBeFoundLength == arrayLength) {
1857        if (isCaseSensitive) {
1858            for (int i = start; i < arrayLength; i++) {
1859                if (array[i] != toBeFound[i]) return -1;
1860            }
1861            return 0;
1862        } else {
1863            for (int i = start; i < arrayLength; i++) {
1864                if (ScannerHelper.toLowerCase(array[i]) != ScannerHelper.toLowerCase(toBeFound[i])) return -1;
1865            }
1866            return 0;
1867        }
1868    }
1869    if (isCaseSensitive) {
1870        arrayLoop: for (int i = start, max = arrayLength - toBeFoundLength + 1; i < max; i++) {
1871            if (array[i] == toBeFound[0]) {
1872                for (int j = 1; j < toBeFoundLength; j++) {
1873                    if (array[i + j] != toBeFound[j]) continue arrayLoop;
1874                }
1875                return i;
1876            }
1877        }
1878    } else {
1879        arrayLoop: for (int i = start, max = arrayLength - toBeFoundLength + 1; i < max; i++) {
1880            if (ScannerHelper.toLowerCase(array[i]) == ScannerHelper.toLowerCase(toBeFound[0])) {
1881                for (int j = 1; j < toBeFoundLength; j++) {
1882                    if (ScannerHelper.toLowerCase(array[i + j]) != ScannerHelper.toLowerCase(toBeFound[j])) continue arrayLoop;
1883                }
1884                return i;
1885            }
1886        }
1887    }
1888    return -1;
1889}
1890
1891/**
1892 * Answers the first index in the array for which the corresponding character is
1893 * equal to toBeFound starting the search at index start.
1894 * Answers -1 if no occurrence of this character is found.
1895 * <br>
1896 * <br>
1897 * For example:
1898 * <ol>
1899 * <li><pre>
1900 * toBeFound = 'c'
1901 * array = { ' a', 'b', 'c', 'd' }
1902 * start = 2
1903 * result => 2
1904 * </pre>
1905 * </li>
1906 * <li><pre>
1907 * toBeFound = 'c'
1908 * array = { ' a', 'b', 'c', 'd' }
1909 * start = 3
1910 * result => -1
1911 * </pre>
1912 * </li>
1913 * <li><pre>
1914 * toBeFound = 'e'
1915 * array = { ' a', 'b', 'c', 'd' }
1916 * start = 1
1917 * result => -1
1918 * </pre>
1919 * </li>
1920 * </ol>
1921 *
1922 * @param toBeFound the character to search
1923 * @param array the array to be searched
1924 * @param start the starting index
1925 * @return the first index in the array for which the corresponding character is
1926 * equal to toBeFound, -1 otherwise
1927 * @throws NullPointerException if array is null
1928 * @throws ArrayIndexOutOfBoundsException if start is lower than 0
1929 */

1930public static final int indexOf(char toBeFound, char[] array, int start) {
1931    for (int i = start; i < array.length; i++)
1932        if (toBeFound == array[i])
1933            return i;
1934    return -1;
1935}
1936
1937/**
1938 * Answers the first index in the array for which the corresponding character is
1939 * equal to toBeFound starting the search at index start and before the ending index.
1940 * Answers -1 if no occurrence of this character is found.
1941 * <br>
1942 * <br>
1943 * For example:
1944 * <ol>
1945 * <li><pre>
1946 * toBeFound = 'c'
1947 * array = { ' a', 'b', 'c', 'd' }
1948 * start = 2
1949 * result => 2
1950 * </pre>
1951 * </li>
1952 * <li><pre>
1953 * toBeFound = 'c'
1954 * array = { ' a', 'b', 'c', 'd' }
1955 * start = 3
1956 * result => -1
1957 * </pre>
1958 * </li>
1959 * <li><pre>
1960 * toBeFound = 'e'
1961 * array = { ' a', 'b', 'c', 'd' }
1962 * start = 1
1963 * result => -1
1964 * </pre>
1965 * </li>
1966 * </ol>
1967 *
1968 * @param toBeFound the character to search
1969 * @param array the array to be searched
1970 * @param start the starting index (inclusive)
1971 * @param end the ending index (exclusive)
1972 * @return the first index in the array for which the corresponding character is
1973 * equal to toBeFound, -1 otherwise
1974 * @throws NullPointerException if array is null
1975 * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or ending greater than array length
1976 * @since 3.2
1977 */

1978public static final int indexOf(char toBeFound, char[] array, int start, int end) {
1979    for (int i = start; i < end; i++)
1980        if (toBeFound == array[i])
1981            return i;
1982    return -1;
1983}
1984
1985/**
1986 * Answers the last index in the array for which the corresponding character is
1987 * equal to toBeFound starting from the end of the array.
1988 * Answers -1 if no occurrence of this character is found.
1989 * <br>
1990 * <br>
1991 * For example:
1992 * <ol>
1993 * <li><pre>
1994 * toBeFound = 'c'
1995 * array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
1996 * result => 4
1997 * </pre>
1998 * </li>
1999 * <li><pre>
2000 * toBeFound = 'e'
2001 * array = { ' a', 'b', 'c', 'd' }
2002 * result => -1
2003 * </pre>
2004 * </li>
2005 * </ol>
2006 *
2007 * @param toBeFound the character to search
2008 * @param array the array to be searched
2009 * @return the last index in the array for which the corresponding character is
2010 * equal to toBeFound starting from the end of the array, -1 otherwise
2011 * @throws NullPointerException if array is null
2012 */

2013public static final int lastIndexOf(char toBeFound, char[] array) {
2014    for (int i = array.length; --i >= 0;)
2015        if (toBeFound == array[i])
2016            return i;
2017    return -1;
2018}
2019
2020/**
2021 * Answers the last index in the array for which the corresponding character is
2022 * equal to toBeFound stopping at the index startIndex.
2023 * Answers -1 if no occurrence of this character is found.
2024 * <br>
2025 * <br>
2026 * For example:
2027 * <ol>
2028 * <li><pre>
2029 * toBeFound = 'c'
2030 * array = { ' a', 'b', 'c', 'd' }
2031 * startIndex = 2
2032 * result => 2
2033 * </pre>
2034 * </li>
2035 * <li><pre>
2036 * toBeFound = 'c'
2037 * array = { ' a', 'b', 'c', 'd', 'e' }
2038 * startIndex = 3
2039 * result => -1
2040 * </pre>
2041 * </li>
2042 * <li><pre>
2043 * toBeFound = 'e'
2044 * array = { ' a', 'b', 'c', 'd' }
2045 * startIndex = 0
2046 * result => -1
2047 * </pre>
2048 * </li>
2049 * </ol>
2050 *
2051 * @param toBeFound the character to search
2052 * @param array the array to be searched
2053 * @param startIndex the stopping index
2054 * @return the last index in the array for which the corresponding character is
2055 * equal to toBeFound stopping at the index startIndex, -1 otherwise
2056 * @throws NullPointerException if array is null
2057 * @throws ArrayIndexOutOfBoundsException if startIndex is lower than 0
2058 */

2059public static final int lastIndexOf(
2060    char toBeFound,
2061    char[] array,
2062    int startIndex) {
2063    for (int i = array.length; --i >= startIndex;)
2064        if (toBeFound == array[i])
2065            return i;
2066    return -1;
2067}
2068
2069/**
2070 * Answers the last index in the array for which the corresponding character is
2071 * equal to toBeFound starting from endIndex to startIndex.
2072 * Answers -1 if no occurrence of this character is found.
2073 * <br>
2074 * <br>
2075 * For example:
2076 * <ol>
2077 * <li><pre>
2078 * toBeFound = 'c'
2079 * array = { ' a', 'b', 'c', 'd' }
2080 * startIndex = 2
2081 * endIndex = 2
2082 * result => 2
2083 * </pre>
2084 * </li>
2085 * <li><pre>
2086 * toBeFound = 'c'
2087 * array = { ' a', 'b', 'c', 'd', 'e' }
2088 * startIndex = 3
2089 * endIndex = 4
2090 * result => -1
2091 * </pre>
2092 * </li>
2093 * <li><pre>
2094 * toBeFound = 'e'
2095 * array = { ' a', 'b', 'c', 'd' }
2096 * startIndex = 0
2097 * endIndex = 3
2098 * result => -1
2099 * </pre>
2100 * </li>
2101 * </ol>
2102 *
2103 * @param toBeFound the character to search
2104 * @param array the array to be searched
2105 * @param startIndex the stopping index
2106 * @param endIndex the starting index
2107 * @return the last index in the array for which the corresponding character is
2108 * equal to toBeFound starting from endIndex to startIndex, -1 otherwise
2109 * @throws NullPointerException if array is null
2110 * @throws ArrayIndexOutOfBoundsException if endIndex is greater or equals to array length or starting is lower than 0
2111 */

2112public static final int lastIndexOf(
2113    char toBeFound,
2114    char[] array,
2115    int startIndex,
2116    int endIndex) {
2117    for (int i = endIndex; --i >= startIndex;)
2118        if (toBeFound == array[i])
2119            return i;
2120    return -1;
2121}
2122
2123/**
2124 * Answers the last portion of a name given a separator.
2125 * <br>
2126 * <br>
2127 * For example,
2128 * <pre>
2129 * lastSegment("java.lang.Object".toCharArray(),'.') --> Object
2130 * </pre>
2131 *
2132 * @param array the array
2133 * @param separator the given separator
2134 * @return the last portion of a name given a separator
2135 * @throws NullPointerException if array is null
2136 */

2137final static public char[] lastSegment(char[] array, char separator) {
2138    int pos = lastIndexOf(separator, array);
2139    if (pos < 0)
2140        return array;
2141    return subarray(array, pos + 1, array.length);
2142}
2143
2144/**
2145 * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching
2146 * accepts wild-cards '*' and '?'.
2147 *
2148 * When not case sensitive, the pattern is assumed to already be lowercased, the
2149 * name will be lowercased character per character as comparing.
2150 * If name is null, the answer is false.
2151 * If pattern is null, the answer is true if name is not null.
2152 * <br>
2153 * <br>
2154 * For example:
2155 * <ol>
2156 * <li><pre>
2157 * pattern = { '?', 'b', '*' }
2158 * name = { 'a', 'b', 'c' , 'd' }
2159 * isCaseSensitive = true
2160 * result => true
2161 * </pre>
2162 * </li>
2163 * <li><pre>
2164 * pattern = { '?', 'b', '?' }
2165 * name = { 'a', 'b', 'c' , 'd' }
2166 * isCaseSensitive = true
2167 * result => false
2168 * </pre>
2169 * </li>
2170 * <li><pre>
2171 * pattern = { 'b', '*' }
2172 * name = { 'a', 'b', 'c' , 'd' }
2173 * isCaseSensitive = true
2174 * result => false
2175 * </pre>
2176 * </li>
2177 * </ol>
2178 *
2179 * @param pattern the given pattern
2180 * @param name the given name
2181 * @param isCaseSensitive flag to know whether or not the matching should be case sensitive
2182 * @return true if the pattern matches the given name, false otherwise
2183 */

2184public static final boolean match(
2185    char[] pattern,
2186    char[] name,
2187    boolean isCaseSensitive) {
2188
2189    if (name == null)
2190        return false; // null name cannot match
2191
if (pattern == null)
2192        return true; // null pattern is equivalent to '*'
2193

2194    return match(
2195        pattern,
2196        0,
2197        pattern.length,
2198        name,
2199        0,
2200        name.length,
2201        isCaseSensitive);
2202}
2203
2204/**
2205 * Answers true if a sub-pattern matches the subpart of the given name, false otherwise.
2206 * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only subset of name/pattern.
2207 * end positions are non-inclusive.
2208 * The subpattern is defined by the patternStart and pattternEnd positions.
2209 * When not case sensitive, the pattern is assumed to already be lowercased, the
2210 * name will be lowercased character per character as comparing.
2211 * <br>
2212 * <br>
2213 * For example:
2214 * <ol>
2215 * <li><pre>
2216 * pattern = { '?', 'b', '*' }
2217 * patternStart = 1
2218 * patternEnd = 3
2219 * name = { 'a', 'b', 'c' , 'd' }
2220 * nameStart = 1
2221 * nameEnd = 4
2222 * isCaseSensitive = true
2223 * result => true
2224 * </pre>
2225 * </li>
2226 * <li><pre>
2227 * pattern = { '?', 'b', '*' }
2228 * patternStart = 1
2229 * patternEnd = 2
2230 * name = { 'a', 'b', 'c' , 'd' }
2231 * nameStart = 1
2232 * nameEnd = 2
2233 * isCaseSensitive = true
2234 * result => false
2235 * </pre>
2236 * </li>
2237 * </ol>
2238 *
2239 * @param pattern the given pattern
2240 * @param patternStart the given pattern start
2241 * @param patternEnd the given pattern end
2242 * @param name the given name
2243 * @param nameStart the given name start
2244 * @param nameEnd the given name end
2245 * @param isCaseSensitive flag to know if the matching should be case sensitive
2246 * @return true if a sub-pattern matches the subpart of the given name, false otherwise
2247 */

2248public static final boolean match(
2249    char[] pattern,
2250    int patternStart,
2251    int patternEnd,
2252    char[] name,
2253    int nameStart,
2254    int nameEnd,
2255    boolean isCaseSensitive) {
2256
2257    if (name == null)
2258        return false; // null name cannot match
2259
if (pattern == null)
2260        return true; // null pattern is equivalent to '*'
2261
int iPattern = patternStart;
2262    int iName = nameStart;
2263
2264    if (patternEnd < 0)
2265        patternEnd = pattern.length;
2266    if (nameEnd < 0)
2267        nameEnd = name.length;
2268
2269    /* check first segment */
2270    char patternChar = 0;
2271    while ((iPattern < patternEnd)
2272        && (patternChar = pattern[iPattern]) != '*') {
2273        if (iName == nameEnd)
2274            return false;
2275        if (patternChar
2276            != (isCaseSensitive
2277                ? name[iName]
2278                : ScannerHelper.toLowerCase(name[iName]))
2279            && patternChar != '?') {
2280            return false;
2281        }
2282        iName++;
2283        iPattern++;
2284    }
2285    /* check sequence of star+segment */
2286    int segmentStart;
2287    if (patternChar == '*') {
2288        segmentStart = ++iPattern; // skip star
2289
} else {
2290        segmentStart = 0; // force iName check
2291
}
2292    int prefixStart = iName;
2293    checkSegment : while (iName < nameEnd) {
2294        if (iPattern == patternEnd) {
2295            iPattern = segmentStart; // mismatch - restart current segment
2296
iName = ++prefixStart;
2297            continue checkSegment;
2298        }
2299        /* segment is ending */
2300        if ((patternChar = pattern[iPattern]) == '*') {
2301            segmentStart = ++iPattern; // skip start
2302
if (segmentStart == patternEnd) {
2303                return true;
2304            }
2305            prefixStart = iName;
2306            continue checkSegment;
2307        }
2308        /* check current name character */
2309        if ((isCaseSensitive ? name[iName] : ScannerHelper.toLowerCase(name[iName]))
2310                    != patternChar
2311                && patternChar != '?') {
2312            iPattern = segmentStart; // mismatch - restart current segment
2313
iName = ++prefixStart;
2314            continue checkSegment;
2315        }
2316        iName++;
2317        iPattern++;
2318    }
2319
2320    return (segmentStart == patternEnd)
2321        || (iName == nameEnd && iPattern == patternEnd)
2322        || (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
2323}
2324
2325/**
2326 * Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
2327 *
2328 * Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks
2329 * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
2330 * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
2331 * any folder combination.
2332 * Special rule:
2333 * - foo\ is equivalent to foo\**
2334 * When not case sensitive, the pattern is assumed to already be lowercased, the
2335 * name will be lowercased character per character as comparing.
2336 *
2337 * @param pattern the given pattern
2338 * @param filepath the given path
2339 * @param isCaseSensitive to find out whether or not the matching should be case sensitive
2340 * @param pathSeparator the given path separator
2341 * @return true if the pattern matches the filepath using the pathSepatator, false otherwise
2342 */

2343public static final boolean pathMatch(
2344    char[] pattern,
2345    char[] filepath,
2346    boolean isCaseSensitive,
2347    char pathSeparator) {
2348
2349    if (filepath == null)
2350        return false; // null name cannot match
2351
if (pattern == null)
2352        return true; // null pattern is equivalent to '*'
2353

2354    // offsets inside pattern
2355
int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
2356    int pLength = pattern.length;
2357    int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart+1);
2358    if (pSegmentEnd < 0) pSegmentEnd = pLength;
2359
2360    // special case: pattern foo\ is equivalent to foo\**
2361
boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
2362
2363    // offsets inside filepath
2364
int fSegmentStart, fLength = filepath.length;
2365    if (filepath[0] != pathSeparator){
2366        fSegmentStart = 0;
2367    } else {
2368        fSegmentStart = 1;
2369    }
2370    if (fSegmentStart != pSegmentStart) {
2371        return false; // both must start with a separator or none.
2372
}
2373    int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart+1);
2374    if (fSegmentEnd < 0) fSegmentEnd = fLength;
2375
2376    // first segments
2377
while (pSegmentStart < pLength
2378        && !(pSegmentEnd == pLength && freeTrailingDoubleStar
2379                || (pSegmentEnd == pSegmentStart + 2
2380                        && pattern[pSegmentStart] == '*'
2381                        && pattern[pSegmentStart + 1] == '*'))) {
2382
2383        if (fSegmentStart >= fLength)
2384            return false;
2385        if (!CharOperation
2386            .match(
2387                pattern,
2388                pSegmentStart,
2389                pSegmentEnd,
2390                filepath,
2391                fSegmentStart,
2392                fSegmentEnd,
2393                isCaseSensitive)) {
2394            return false;
2395        }
2396
2397        // jump to next segment
2398
pSegmentEnd =
2399            CharOperation.indexOf(
2400                pathSeparator,
2401                pattern,
2402                pSegmentStart = pSegmentEnd + 1);
2403        // skip separator
2404
if (pSegmentEnd < 0)
2405            pSegmentEnd = pLength;
2406
2407        fSegmentEnd =
2408            CharOperation.indexOf(
2409                pathSeparator,
2410                filepath,
2411                fSegmentStart = fSegmentEnd + 1);
2412        // skip separator
2413
if (fSegmentEnd < 0) fSegmentEnd = fLength;
2414    }
2415
2416    /* check sequence of doubleStar+segment */
2417    int pSegmentRestart;
2418    if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
2419            || (pSegmentEnd == pSegmentStart + 2
2420                && pattern[pSegmentStart] == '*'
2421                && pattern[pSegmentStart + 1] == '*')) {
2422        pSegmentEnd =
2423            CharOperation.indexOf(
2424                pathSeparator,
2425                pattern,
2426                pSegmentStart = pSegmentEnd + 1);
2427        // skip separator
2428
if (pSegmentEnd < 0) pSegmentEnd = pLength;
2429        pSegmentRestart = pSegmentStart;
2430    } else {
2431        if (pSegmentStart >= pLength) return fSegmentStart >= fLength; // true if filepath is done too.
2432
pSegmentRestart = 0; // force fSegmentStart check
2433
}
2434    int fSegmentRestart = fSegmentStart;
2435    checkSegment : while (fSegmentStart < fLength) {
2436            
2437        if (pSegmentStart >= pLength) {
2438            if (freeTrailingDoubleStar) return true;
2439            // mismatch - restart current path segment
2440
pSegmentEnd =
2441                CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
2442            if (pSegmentEnd < 0) pSegmentEnd = pLength;
2443
2444            fSegmentRestart =
2445                CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
2446            // skip separator
2447
if (fSegmentRestart < 0) {
2448                fSegmentRestart = fLength;
2449            } else {
2450                fSegmentRestart++;
2451            }
2452            fSegmentEnd =
2453                CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
2454            if (fSegmentEnd < 0) fSegmentEnd = fLength;
2455            continue checkSegment;
2456        }
2457        
2458        /* path segment is ending */
2459        if (pSegmentEnd == pSegmentStart + 2
2460            && pattern[pSegmentStart] == '*'
2461            && pattern[pSegmentStart + 1] == '*') {
2462            pSegmentEnd =
2463                CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
2464            // skip separator
2465
if (pSegmentEnd < 0) pSegmentEnd = pLength;
2466            pSegmentRestart = pSegmentStart;
2467            fSegmentRestart = fSegmentStart;
2468            if (pSegmentStart >= pLength) return true;
2469            continue checkSegment;
2470        }
2471        /* chech current path segment */
2472        if (!CharOperation.match(
2473                            pattern,
2474                            pSegmentStart,
2475                            pSegmentEnd,
2476                            filepath,
2477                            fSegmentStart,
2478                            fSegmentEnd,
2479                            isCaseSensitive)) {
2480            // mismatch - restart current path segment
2481
pSegmentEnd =
2482                CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
2483            if (pSegmentEnd < 0) pSegmentEnd = pLength;
2484
2485            fSegmentRestart =
2486                CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
2487            // skip separator
2488
if (fSegmentRestart < 0) {
2489                fSegmentRestart = fLength;
2490            } else {
2491                fSegmentRestart++;
2492            }
2493            fSegmentEnd =
2494                CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
2495            if (fSegmentEnd < 0) fSegmentEnd = fLength;
2496            continue checkSegment;
2497        }
2498        // jump to next segment
2499
pSegmentEnd =
2500            CharOperation.indexOf(
2501                pathSeparator,
2502                pattern,
2503                pSegmentStart = pSegmentEnd + 1);
2504        // skip separator
2505
if (pSegmentEnd < 0)
2506            pSegmentEnd = pLength;
2507
2508        fSegmentEnd =
2509            CharOperation.indexOf(
2510                pathSeparator,
2511                filepath,
2512                fSegmentStart = fSegmentEnd + 1);
2513        // skip separator
2514
if (fSegmentEnd < 0)
2515            fSegmentEnd = fLength;
2516    }
2517
2518    return (pSegmentRestart >= pSegmentEnd)
2519        || (fSegmentStart >= fLength && pSegmentStart >= pLength)
2520        || (pSegmentStart == pLength - 2
2521            && pattern[pSegmentStart] == '*'
2522            && pattern[pSegmentStart + 1] == '*')
2523        || (pSegmentStart == pLength && freeTrailingDoubleStar);
2524}
2525
2526/**
2527 * Answers the number of occurrences of the given character in the given array, 0 if any.
2528 *
2529 * <br>
2530 * <br>
2531 * For example:
2532 * <ol>
2533 * <li><pre>
2534 * toBeFound = 'b'
2535 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2536 * result => 3
2537 * </pre>
2538 * </li>
2539 * <li><pre>
2540 * toBeFound = 'c'
2541 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2542 * result => 0
2543 * </pre>
2544 * </li>
2545 * </ol>
2546 *
2547 * @param toBeFound the given character
2548 * @param array the given array
2549 * @return the number of occurrences of the given character in the given array, 0 if any
2550 * @throws NullPointerException if array is null
2551 */

2552public static final int occurencesOf(char toBeFound, char[] array) {
2553    int count = 0;
2554    for (int i = 0; i < array.length; i++)
2555        if (toBeFound == array[i])
2556            count++;
2557    return count;
2558}
2559
2560/**
2561 * Answers the number of occurrences of the given character in the given array starting
2562 * at the given index, 0 if any.
2563 *
2564 * <br>
2565 * <br>
2566 * For example:
2567 * <ol>
2568 * <li><pre>
2569 * toBeFound = 'b'
2570 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2571 * start = 2
2572 * result => 2
2573 * </pre>
2574 * </li>
2575 * <li><pre>
2576 * toBeFound = 'c'
2577 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2578 * start = 0
2579 * result => 0
2580 * </pre>
2581 * </li>
2582 * </ol>
2583 *
2584 * @param toBeFound the given character
2585 * @param array the given array
2586 * @param start the given index
2587 * @return the number of occurrences of the given character in the given array, 0 if any
2588 * @throws NullPointerException if array is null
2589 * @throws ArrayIndexOutOfBoundsException if start is lower than 0
2590 */

2591public static final int occurencesOf(
2592    char toBeFound,
2593    char[] array,
2594    int start) {
2595    int count = 0;
2596    for (int i = start; i < array.length; i++)
2597        if (toBeFound == array[i])
2598            count++;
2599    return count;
2600}
2601
2602/**
2603 * Answers true if the given name starts with the given prefix, false otherwise.
2604 * The comparison is case sensitive.
2605 * <br>
2606 * <br>
2607 * For example:
2608 * <ol>
2609 * <li><pre>
2610 * prefix = { 'a' , 'b' }
2611 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2612 * result => true
2613 * </pre>
2614 * </li>
2615 * <li><pre>
2616 * prefix = { 'a' , 'c' }
2617 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2618 * result => false
2619 * </pre>
2620 * </li>
2621 * </ol>
2622 *
2623 * @param prefix the given prefix
2624 * @param name the given name
2625 * @return true if the given name starts with the given prefix, false otherwise
2626 * @throws NullPointerException if the given name is null or if the given prefix is null
2627 */

2628public static final boolean prefixEquals(char[] prefix, char[] name) {
2629
2630    int max = prefix.length;
2631    if (name.length < max)
2632        return false;
2633    for (int i = max;
2634        --i >= 0;
2635        ) // assumes the prefix is not larger than the name
2636
if (prefix[i] != name[i])
2637            return false;
2638    return true;
2639}
2640
2641/**
2642 * Answers true if the given name starts with the given prefix, false otherwise.
2643 * isCaseSensitive is used to find out whether or not the comparison should be case sensitive.
2644 * <br>
2645 * <br>
2646 * For example:
2647 * <ol>
2648 * <li><pre>
2649 * prefix = { 'a' , 'B' }
2650 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2651 * isCaseSensitive = false
2652 * result => true
2653 * </pre>
2654 * </li>
2655 * <li><pre>
2656 * prefix = { 'a' , 'B' }
2657 * name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2658 * isCaseSensitive = true
2659 * result => false
2660 * </pre>
2661 * </li>
2662 * </ol>
2663 *
2664 * @param prefix the given prefix
2665 * @param name the given name
2666 * @param isCaseSensitive to find out whether or not the comparison should be case sensitive
2667 * @return true if the given name starts with the given prefix, false otherwise
2668 * @throws NullPointerException if the given name is null or if the given prefix is null
2669 */

2670public static final boolean prefixEquals(
2671    char[] prefix,
2672    char[] name,
2673    boolean isCaseSensitive) {
2674
2675    int max = prefix.length;
2676    if (name.length < max)
2677        return false;
2678    if (isCaseSensitive) {
2679        for (int i = max;
2680            --i >= 0;
2681            ) // assumes the prefix is not larger than the name
2682
if (prefix[i] != name[i])
2683                return false;
2684        return true;
2685    }
2686
2687    for (int i = max;
2688        --i >= 0;
2689        ) // assumes the prefix is not larger than the name
2690
if (ScannerHelper.toLowerCase(prefix[i])
2691            != ScannerHelper.toLowerCase(name[i]))
2692            return false;
2693    return true;
2694}
2695
2696/**
2697 * Answers a new array removing a given character. Answers the given array if there is
2698 * no occurence of the character to remove.
2699 * <br>
2700 * <br>
2701 * For example:
2702 * <ol>
2703 * <li><pre>
2704 * array = { 'a' , 'b', 'b', 'c', 'b', 'a' }
2705 * toBeRemoved = 'b'
2706 * return { 'a' , 'c', 'a' }
2707 * </pre>
2708 * </li>
2709 * <li><pre>
2710 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2711 * toBeRemoved = 'c'
2712 * return array
2713 * </pre>
2714 * </li>
2715 * </ol>
2716 *
2717 * @param array the given array
2718 * @param toBeRemoved the character to be removed
2719 * @return a new array removing given character
2720 * @since 3.2
2721 */

2722public static final char[] remove(char[] array, char toBeRemoved) {
2723
2724    if (array == null) return null;
2725    int length = array.length;
2726    if (length == 0) return array;
2727    char[] result = null;
2728    int count = 0;
2729    for (int i = 0; i < length; i++) {
2730        char c = array[i];
2731        if (c == toBeRemoved) {
2732            if (result == null) {
2733                result = new char[length];
2734                System.arraycopy(array, 0, result, 0, i);
2735                count = i;
2736            }
2737        } else if (result != null) {
2738            result[count++] = c;
2739        }
2740    }
2741    if (result == null) return array;
2742    System.arraycopy(result, 0, result = new char[count], 0, count);
2743    return result;
2744}
2745
2746/**
2747 * Replace all occurrence of the character to be replaced with the remplacement character in the
2748 * given array.
2749 * <br>
2750 * <br>
2751 * For example:
2752 * <ol>
2753 * <li><pre>
2754 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2755 * toBeReplaced = 'b'
2756 * replacementChar = 'a'
2757 * result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
2758 * </pre>
2759 * </li>
2760 * <li><pre>
2761 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2762 * toBeReplaced = 'c'
2763 * replacementChar = 'a'
2764 * result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
2765 * </pre>
2766 * </li>
2767 * </ol>
2768 *
2769 * @param array the given array
2770 * @param toBeReplaced the character to be replaced
2771 * @param replacementChar the replacement character
2772 * @throws NullPointerException if the given array is null
2773 */

2774public static final void replace(
2775    char[] array,
2776    char toBeReplaced,
2777    char replacementChar) {
2778    if (toBeReplaced != replacementChar) {
2779        for (int i = 0, max = array.length; i < max; i++) {
2780            if (array[i] == toBeReplaced)
2781                array[i] = replacementChar;
2782        }
2783    }
2784}
2785
2786/**
2787 * Replace all occurrences of characters to be replaced with the remplacement character in the
2788 * given array.
2789 * <br>
2790 * <br>
2791 * For example:
2792 * <ol>
2793 * <li><pre>
2794 * array = { 'a' , 'b', 'b', 'c', 'a', 'b', 'c', 'a' }
2795 * toBeReplaced = { 'b', 'c' }
2796 * replacementChar = 'a'
2797 * result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
2798 * </pre>
2799 * </li>
2800 * </ol>
2801 *
2802 * @param array the given array
2803 * @param toBeReplaced characters to be replaced
2804 * @param replacementChar the replacement character
2805 * @throws NullPointerException if arrays are null.
2806 * @since 3.1
2807 */

2808public static final void replace(char[] array, char[] toBeReplaced, char replacementChar) {
2809    replace(array, toBeReplaced, replacementChar, 0, array.length);
2810}
2811
2812/**
2813 * Replace all occurrences of characters to be replaced with the remplacement character in the
2814 * given array from the start position (inclusive) to the end position (exclusive).
2815 * <br>
2816 * <br>
2817 * For example:
2818 * <ol>
2819 * <li><pre>
2820 * array = { 'a' , 'b', 'b', 'c', 'a', 'b', 'c', 'a' }
2821 * toBeReplaced = { 'b', 'c' }
2822 * replacementChar = 'a'
2823 * start = 4
2824 * end = 8
2825 * result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'c', 'a', 'a', 'a', 'a' }
2826 * </pre>
2827 * </li>
2828 * </ol>
2829 *
2830 * @param array the given array
2831 * @param toBeReplaced characters to be replaced
2832 * @param replacementChar the replacement character
2833 * @param start the given start position (inclusive)
2834 * @param end the given end position (exclusive)
2835 * @throws NullPointerException if arrays are null.
2836 * @since 3.2
2837 */

2838public static final void replace(char[] array, char[] toBeReplaced, char replacementChar, int start, int end) {
2839    for (int i = end; --i >= start;)
2840        for (int j = toBeReplaced.length; --j >= 0;)
2841            if (array[i] == toBeReplaced[j])
2842                array[i] = replacementChar;
2843}
2844/**
2845 * Answers a new array of characters with substitutions. No side-effect is operated on the original
2846 * array, in case no substitution happened, then the result is the same as the
2847 * original one.
2848 * <br>
2849 * <br>
2850 * For example:
2851 * <ol>
2852 * <li><pre>
2853 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2854 * toBeReplaced = { 'b' }
2855 * replacementChar = { 'a', 'a' }
2856 * result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
2857 * </pre>
2858 * </li>
2859 * <li><pre>
2860 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2861 * toBeReplaced = { 'c' }
2862 * replacementChar = { 'a' }
2863 * result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
2864 * </pre>
2865 * </li>
2866 * </ol>
2867 *
2868 * @param array the given array
2869 * @param toBeReplaced characters to be replaced
2870 * @param replacementChars the replacement characters
2871 * @return a new array of characters with substitutions or the given array if none
2872 * @throws NullPointerException if the given array is null
2873 */

2874public static final char[] replace(
2875    char[] array,
2876    char[] toBeReplaced,
2877    char[] replacementChars) {
2878
2879    int max = array.length;
2880    int replacedLength = toBeReplaced.length;
2881    int replacementLength = replacementChars.length;
2882
2883    int[] starts = new int[5];
2884    int occurrenceCount = 0;
2885
2886    if (!equals(toBeReplaced, replacementChars)) {
2887
2888        next : for (int i = 0; i < max;) {
2889            int index = indexOf(toBeReplaced, array, true, i);
2890            if (index == -1) {
2891                i++;
2892                continue next;
2893            }
2894            if (occurrenceCount == starts.length) {
2895                System.arraycopy(
2896                    starts,
2897                    0,
2898                    starts = new int[occurrenceCount * 2],
2899                    0,
2900                    occurrenceCount);
2901            }
2902            starts[occurrenceCount++] = index;
2903            i = index + replacedLength;
2904        }
2905    }
2906    if (occurrenceCount == 0)
2907        return array;
2908    char[] result =
2909        new char[max
2910            + occurrenceCount * (replacementLength - replacedLength)];
2911    int inStart = 0, outStart = 0;
2912    for (int i = 0; i < occurrenceCount; i++) {
2913        int offset = starts[i] - inStart;
2914        System.arraycopy(array, inStart, result, outStart, offset);
2915        inStart += offset;
2916        outStart += offset;
2917        System.arraycopy(
2918            replacementChars,
2919            0,
2920            result,
2921            outStart,
2922            replacementLength);
2923        inStart += replacedLength;
2924        outStart += replacementLength;
2925    }
2926    System.arraycopy(array, inStart, result, outStart, max - inStart);
2927    return result;
2928}
2929
2930/**
2931 * Replace all occurrence of the character to be replaced with the remplacement character
2932 * in a copy of the given array. Returns the given array if no occurrences of the character
2933 * to be replaced are found.
2934 * <br>
2935 * <br>
2936 * For example:
2937 * <ol>
2938 * <li><pre>
2939 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2940 * toBeReplaced = 'b'
2941 * replacementChar = 'a'
2942 * result => A new array that is equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
2943 * </pre>
2944 * </li>
2945 * <li><pre>
2946 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2947 * toBeReplaced = 'c'
2948 * replacementChar = 'a'
2949 * result => The original array that remains unchanged.
2950 * </pre>
2951 * </li>
2952 * </ol>
2953 *
2954 * @param array the given array
2955 * @param toBeReplaced the character to be replaced
2956 * @param replacementChar the replacement character
2957 * @throws NullPointerException if the given array is null
2958 * @since 3.1
2959 */

2960public static final char[] replaceOnCopy(
2961    char[] array,
2962    char toBeReplaced,
2963    char replacementChar) {
2964    
2965    char[] result = null;
2966    for (int i = 0, length = array.length; i < length; i++) {
2967        char c = array[i];
2968        if (c == toBeReplaced) {
2969            if (result == null) {
2970                result = new char[length];
2971                System.arraycopy(array, 0, result, 0, i);
2972            }
2973            result[i] = replacementChar;
2974        } else if (result != null) {
2975            result[i] = c;
2976        }
2977    }
2978    if (result == null) return array;
2979    return result;
2980}
2981
2982/**
2983 * Return a new array which is the split of the given array using the given divider and triming each subarray to remove
2984 * whitespaces equals to ' '.
2985 * <br>
2986 * <br>
2987 * For example:
2988 * <ol>
2989 * <li><pre>
2990 * divider = 'b'
2991 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2992 * result => { { 'a' }, { }, { 'a' }, { 'a' } }
2993 * </pre>
2994 * </li>
2995 * <li><pre>
2996 * divider = 'c'
2997 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2998 * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2999 * </pre>
3000 * </li>
3001 * <li><pre>
3002 * divider = 'b'
3003 * array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
3004 * result => { { 'a' }, { }, { 'a' }, { 'a' } }
3005 * </pre>
3006 * </li>
3007 * <li><pre>
3008 * divider = 'c'
3009 * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
3010 * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
3011 * </pre>
3012 * </li>
3013 * </ol>
3014 *
3015 * @param divider the given divider
3016 * @param array the given array
3017 * @return a new array which is the split of the given array using the given divider and triming each subarray to remove
3018 * whitespaces equals to ' '
3019 */

3020public static final char[][] splitAndTrimOn(char divider, char[] array) {
3021    int length = array == null ? 0 : array.length;
3022    if (length == 0)
3023        return NO_CHAR_CHAR;
3024
3025    int wordCount = 1;
3026    for (int i = 0; i < length; i++)
3027        if (array[i] == divider)
3028            wordCount++;
3029    char[][] split = new char[wordCount][];
3030    int last = 0, currentWord = 0;
3031    for (int i = 0; i < length; i++) {
3032        if (array[i] == divider) {
3033            int start = last, end = i - 1;
3034            while (start < i && array[start] == ' ')
3035                start++;
3036            while (end > start && array[end] == ' ')
3037                end--;
3038            split[currentWord] = new char[end - start + 1];
3039            System.arraycopy(
3040                array,
3041                start,
3042                split[currentWord++],
3043                0,
3044                end - start + 1);
3045            last = i + 1;
3046        }
3047    }
3048    int start = last, end = length - 1;
3049    while (start < length && array[start] == ' ')
3050        start++;
3051    while (end > start && array[end] == ' ')
3052        end--;
3053    split[currentWord] = new char[end - start + 1];
3054    System.arraycopy(
3055        array,
3056        start,
3057        split[currentWord++],
3058        0,
3059        end - start + 1);
3060    return split;
3061}
3062
3063/**
3064 * Return a new array which is the split of the given array using the given divider.
3065 * <br>
3066 * <br>
3067 * For example:
3068 * <ol>
3069 * <li><pre>
3070 * divider = 'b'
3071 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3072 * result => { { 'a' }, { }, { 'a' }, { 'a' } }
3073 * </pre>
3074 * </li>
3075 * <li><pre>
3076 * divider = 'c'
3077 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3078 * result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
3079 * </pre>
3080 * </li>
3081 * <li><pre>
3082 * divider = 'c'
3083 * array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
3084 * result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
3085 * </pre>
3086 * </li>
3087 * </ol>
3088 *
3089 * @param divider the given divider
3090 * @param array the given array
3091 * @return a new array which is the split of the given array using the given divider
3092 */

3093public static final char[][] splitOn(char divider, char[] array) {
3094    int length = array == null ? 0 : array.length;
3095    if (length == 0)
3096        return NO_CHAR_CHAR;
3097
3098    int wordCount = 1;
3099    for (int i = 0; i < length; i++)
3100        if (array[i] == divider)
3101            wordCount++;
3102    char[][] split = new char[wordCount][];
3103    int last = 0, currentWord = 0;
3104    for (int i = 0; i < length; i++) {
3105        if (array[i] == divider) {
3106            split[currentWord] = new char[i - last];
3107            System.arraycopy(
3108                array,
3109                last,
3110                split[currentWord++],
3111                0,
3112                i - last);
3113            last = i + 1;
3114        }
3115    }
3116    split[currentWord] = new char[length - last];
3117    System.arraycopy(array, last, split[currentWord], 0, length - last);
3118    return split;
3119}
3120
3121/**
3122 * Return a new array which is the split of the given array using the given divider. The given end
3123 * is exclusive and the given start is inclusive.
3124 * <br>
3125 * <br>
3126 * For example:
3127 * <ol>
3128 * <li><pre>
3129 * divider = 'b'
3130 * array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3131 * start = 2
3132 * end = 5
3133 * result => { { }, { 'a' }, { } }
3134 * </pre>
3135 * </li>
3136 * </ol>
3137 *
3138 * @param divider the given divider
3139 * @param array the given array
3140 * @param start the given starting index
3141 * @param end the given ending index
3142 * @return a new array which is the split of the given array using the given divider
3143 * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
3144 */

3145public static final char[][] splitOn(
3146    char divider,
3147    char[] array,
3148    int start,
3149    int end) {
3150    int length = array == null ? 0 : array.length;
3151    if (length == 0 || start > end)
3152        return NO_CHAR_CHAR;
3153
3154    int wordCount = 1;
3155    for (int i = start; i < end; i++)
3156        if (array[i] == divider)
3157            wordCount++;
3158    char[][] split = new char[wordCount][];
3159    int last = start, currentWord = 0;
3160    for (int i = start; i < end; i++) {
3161        if (array[i] == divider) {
3162            split[currentWord] = new char[i - last];
3163            System.arraycopy(
3164                array,
3165                last,
3166                split[currentWord++],
3167                0,
3168                i - last);
3169            last = i + 1;
3170        }
3171    }
3172    split[currentWord] = new char[end - last];
3173    System.arraycopy(array, last, split[currentWord], 0, end - last);
3174    return split;
3175}
3176
3177/**
3178 * Answers a new array which is a copy of the given array starting at the given start and
3179 * ending at the given end. The given start is inclusive and the given end is exclusive.
3180 * Answers null if start is greater than end, if start is lower than 0 or if end is greater
3181 * than the length of the given array. If end equals -1, it is converted to the array length.
3182 * <br>
3183 * <br>
3184 * For example:
3185 * <ol>
3186 * <li><pre>
3187 * array = { { 'a' } , { 'b' } }
3188 * start = 0
3189 * end = 1
3190 * result => { { 'a' } }
3191 * </pre>
3192 * </li>
3193 * <li><pre>
3194 * array = { { 'a' } , { 'b' } }
3195 * start = 0
3196 * end = -1
3197 * result => { { 'a' }, { 'b' } }
3198 * </pre>
3199 * </li>
3200 * </ol>
3201 *
3202 * @param array the given array
3203 * @param start the given starting index
3204 * @param end the given ending index
3205 * @return a new array which is a copy of the given array starting at the given start and
3206 * ending at the given end
3207 * @throws NullPointerException if the given array is null
3208 */

3209public static final char[][] subarray(char[][] array, int start, int end) {
3210    if (end == -1)
3211        end = array.length;
3212    if (start > end)
3213        return null;
3214    if (start < 0)
3215        return null;
3216    if (end > array.length)
3217        return null;
3218
3219    char[][] result = new char[end - start][];
3220    System.arraycopy(array, start, result, 0, end - start);
3221    return result;
3222}
3223
3224/**
3225 * Answers a new array which is a copy of the given array starting at the given start and
3226 * ending at the given end. The given start is inclusive and the given end is exclusive.
3227 * Answers null if start is greater than end, if start is lower than 0 or if end is greater
3228 * than the length of the given array. If end equals -1, it is converted to the array length.
3229 * <br>
3230 * <br>
3231 * For example:
3232 * <ol>
3233 * <li><pre>
3234 * array = { 'a' , 'b' }
3235 * start = 0
3236 * end = 1
3237 * result => { 'a' }
3238 * </pre>
3239 * </li>
3240 * <li><pre>
3241 * array = { 'a', 'b' }
3242 * start = 0
3243 * end = -1
3244 * result => { 'a' , 'b' }
3245 * </pre>
3246 * </li>
3247 * </ol>
3248 *
3249 * @param array the given array
3250 * @param start the given starting index
3251 * @param end the given ending index
3252 * @return a new array which is a copy of the given array starting at the given start and
3253 * ending at the given end
3254 * @throws NullPointerException if the given array is null
3255 */

3256public static final char[] subarray(char[] array, int start, int end) {
3257    if (end == -1)
3258        end = array.length;
3259    if (start > end)
3260        return null;
3261    if (start < 0)
3262        return null;
3263    if (end > array.length)
3264        return null;
3265
3266    char[] result = new char[end - start];
3267    System.arraycopy(array, start, result, 0, end - start);
3268    return result;
3269}
3270
3271/**
3272 * Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null.
3273 * <br>
3274 * NOTE: If no conversion was necessary, then answers back the argument one.
3275 * <br>
3276 * <br>
3277 * For example:
3278 * <ol>
3279 * <li><pre>
3280 * chars = { 'a' , 'b' }
3281 * result => { 'a' , 'b' }
3282 * </pre>
3283 * </li>
3284 * <li><pre>
3285 * array = { 'A', 'b' }
3286 * result => { 'a' , 'b' }
3287 * </pre>
3288 * </li>
3289 * </ol>
3290 *
3291 * @param chars the chars to convert
3292 * @return the result of a char[] conversion to lowercase
3293 */

3294final static public char[] toLowerCase(char[] chars) {
3295    if (chars == null)
3296        return null;
3297    int length = chars.length;
3298    char[] lowerChars = null;
3299    for (int i = 0; i < length; i++) {
3300        char c = chars[i];
3301        char lc = ScannerHelper.toLowerCase(c);
3302        if ((c != lc) || (lowerChars != null)) {
3303            if (lowerChars == null) {
3304                System.arraycopy(
3305                    chars,
3306                    0,
3307                    lowerChars = new char[length],
3308                    0,
3309                    i);
3310            }
3311            lowerChars[i] = lc;
3312        }
3313    }
3314    return lowerChars == null ? chars : lowerChars;
3315}
3316
3317/**
3318 * Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no
3319 * space characters to remove.
3320 * <br>
3321 * <br>
3322 * For example:
3323 * <ol>
3324 * <li><pre>
3325 * chars = { ' ', 'a' , 'b', ' ', ' ' }
3326 * result => { 'a' , 'b' }
3327 * </pre>
3328 * </li>
3329 * <li><pre>
3330 * array = { 'A', 'b' }
3331 * result => { 'A' , 'b' }
3332 * </pre>
3333 * </li>
3334 * </ol>
3335 *
3336 * @param chars the given array
3337 * @return a new array removing leading and trailing spaces (' ')
3338 */

3339final static public char[] trim(char[] chars) {
3340
3341    if (chars == null)
3342        return null;
3343
3344    int start = 0, length = chars.length, end = length - 1;
3345    while (start < length && chars[start] == ' ') {
3346        start++;
3347    }
3348    while (end > start && chars[end] == ' ') {
3349        end--;
3350    }
3351    if (start != 0 || end != length - 1) {
3352        return subarray(chars, start, end + 1);
3353    }
3354    return chars;
3355}
3356
3357/**
3358 * Answers a string which is the concatenation of the given array using the '.' as a separator.
3359 * <br>
3360 * <br>
3361 * For example:
3362 * <ol>
3363 * <li><pre>
3364 * array = { { 'a' } , { 'b' } }
3365 * result => "a.b"
3366 * </pre>
3367 * </li>
3368 * <li><pre>
3369 * array = { { ' ', 'a' } , { 'b' } }
3370 * result => " a.b"
3371 * </pre>
3372 * </li>
3373 * </ol>
3374 *
3375 * @param array the given array
3376 * @return a string which is the concatenation of the given array using the '.' as a separator
3377 */

3378final static public String JavaDoc toString(char[][] array) {
3379    char[] result = concatWith(array, '.');
3380    return new String JavaDoc(result);
3381}
3382
3383/**
3384 * Answers an array of strings from the given array of char array.
3385 *
3386 * @param array the given array
3387 * @return an array of strings
3388 * @since 3.0
3389 */

3390final static public String JavaDoc[] toStrings(char[][] array) {
3391    if (array == null) return NO_STRINGS;
3392    int length = array.length;
3393    if (length == 0) return NO_STRINGS;
3394    String JavaDoc[] result = new String JavaDoc[length];
3395    for (int i = 0; i < length; i++)
3396        result[i] = new String JavaDoc(array[i]);
3397    return result;
3398}
3399}
3400
Popular Tags