Makefile fixup
[org.ibex.tool.git] / repo / org.ibex.tool / src / org / eclipse / jdt / core / compiler / CharOperation.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.core.compiler;
12
13 /**
14  * This class is a collection of helper methods to manipulate char arrays.
15  * 
16  * @since 2.1
17  */
18 public final class CharOperation {
19
20         /**
21          * Constant for an empty char array
22          */
23         public static final char[] NO_CHAR = new char[0];
24
25         /**
26          * Constant for an empty char array with two dimensions.
27          */
28         public static final char[][] NO_CHAR_CHAR = new char[0][];
29         
30         /**
31          * Answers a new array with appending the suffix character at the end of the array.
32          * <br>
33          * <br>
34          * For example:<br>
35          * <ol>
36          * <li><pre>
37          *    array = { 'a', 'b' }
38          *    suffix = 'c'
39          *    => result = { 'a', 'b' , 'c' }
40          * </pre>
41          * </li>
42          * <li><pre>
43          *    array = null
44          *    suffix = 'c'
45          *    => result = { 'c' }
46          * </pre></li>
47          * </ol>
48          * 
49          * @param array the array that is concanated with the suffix character
50          * @param suffix the suffix character
51          * @return the new array
52          */
53         public static final char[] append(char[] array, char suffix) {
54                 if (array == null)
55                         return new char[] { suffix };
56                 int length = array.length;
57                 System.arraycopy(array, 0, array = new char[length + 1], 0, length);
58                 array[length] = suffix;
59                 return array;
60         }
61         /**
62          * Append the given subarray to the target array starting at the given index in the target array.
63          * The start of the subarray is inclusive, the end is exclusive.
64          * Answers a new target array if it needs to grow, otherwise answers the same target array.
65          * <br>
66          * For example:<br>
67          * <ol>
68          * <li><pre>
69          *    target = { 'a', 'b', '0' }
70          *    index = 2
71          *    array = { 'c', 'd' }
72          *    start = 0
73          *    end = 1
74          *    => result = { 'a', 'b' , 'c' }
75          * </pre>
76          * </li>
77          * <li><pre>
78          *    target = { 'a', 'b' }
79          *    index = 2
80          *    array = { 'c', 'd' }
81          *    start = 0
82          *    end = 1
83          *    => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
84          * </pre></li>
85          * <li><pre>
86          *    target = { 'a', 'b', 'c' }
87          *    index = 1
88          *    array = { 'c', 'd', 'e', 'f' }
89          *    start = 1
90          *    end = 4
91          *    => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
92          * </pre></li>
93          * </ol>
94          * 
95          * @param target the given target
96          * @param index the given index
97          * @param array the given array
98          * @param start the given start index
99          * @param end the given end index
100          * 
101          * @return the new array
102          * @throws NullPointerException if the target array is null
103          */
104         public static final char[] append(char[] target, int index, char[] array, int start, int end) {
105                 int targetLength = target.length;
106                 int subLength = end-start;
107                 int newTargetLength = subLength+index;
108                 if (newTargetLength > targetLength) {
109                         System.arraycopy(target, 0, target = new char[newTargetLength*2], 0, index);
110                 }
111                 System.arraycopy(array, start, target, index, subLength);
112                 return target;
113         }
114
115         /**
116          * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
117          * If the first array is null, then the second array is returned.
118          * If the second array is null, then the first array is returned.
119          * <br>
120          * <br>
121          * For example:
122          * <ol>
123          * <li><pre>
124          *    first = null
125          *    second = null
126          *    => result = null
127          * </pre>
128          * </li>
129          * <li><pre>
130          *    first = { { ' a' } }
131          *    second = null
132          *    => result = { { ' a' } }
133          * </pre>
134          * </li>
135          * <li><pre>
136          *    first = null
137          *    second = { { ' a' } }
138          *    => result = { { ' a' } }
139          * </pre>
140          * </li>
141          * <li><pre>
142          *    first = { { ' b' } }
143          *    second = { { ' a' } }
144          *    => result = { { ' b' }, { ' a' } }
145          * </pre>
146          * </li>
147          * </ol>
148          * 
149          * @param first the first array to concatenate
150          * @param second the second array to concatenate
151          * @return the concatenation of the two arrays, or null if the two arrays are null.
152          */
153         public static final char[][] arrayConcat(char[][] first, char[][] second) {
154                 if (first == null)
155                         return second;
156                 if (second == null)
157                         return first;
158
159                 int length1 = first.length;
160                 int length2 = second.length;
161                 char[][] result = new char[length1 + length2][];
162                 System.arraycopy(first, 0, result, 0, length1);
163                 System.arraycopy(second, 0, result, length1, length2);
164                 return result;
165         }
166         /**
167          * Returns the char arrays as an array of Strings
168          * 
169          * @param charArrays the char array to convert
170          * @return the char arrays as an array of Strings or null if the given char arrays is null.
171          * @since 3.0
172          */
173         public static String[] charArrayToStringArray(char[][] charArrays) {
174                 if (charArrays == null) {
175                         return null;
176                 }
177                 String[] strings= new String[charArrays.length];
178                 for (int i= 0; i < charArrays.length; i++) {
179                         strings[i]= new String(charArrays[i]);
180                 }
181                 return strings;
182         }
183         /**
184          * Returns the char array as a String
185
186          * @param charArray the char array to convert
187          * @return the char array as a String or null if the given char array is null.
188          * @since 3.0
189          */
190         public static String charToString(char[] charArray) {
191                 if (charArray == null) return null;
192                 return new String(charArray);
193         }
194
195         /**
196          * Answers a new array adding the second array at the end of first array.
197          * It answers null if the first and second are null.
198          * If the first array is null, then a new array char[][] is created with second.
199          * If the second array is null, then the first array is returned.
200          * <br>
201          * <br>
202          * For example:
203          * <ol>
204          * <li><pre>
205          *    first = null
206          *    second = { 'a' }
207          *    => result = { { ' a' } }
208          * </pre>
209          * <li><pre>
210          *    first = { { ' a' } }
211          *    second = null
212          *    => result = { { ' a' } }
213          * </pre>
214          * </li>
215          * <li><pre>
216          *    first = { { ' a' } }
217          *    second = { ' b' }
218          *    => result = { { ' a' } , { ' b' } }
219          * </pre>
220          * </li>
221          * </ol>
222          * 
223          * @param first the first array to concatenate
224          * @param second the array to add at the end of the first array
225          * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
226          */
227         public static final char[][] arrayConcat(char[][] first, char[] second) {
228                 if (second == null)
229                         return first;
230                 if (first == null)
231                         return new char[][] { second };
232
233                 int length = first.length;
234                 char[][] result = new char[length + 1][];
235                 System.arraycopy(first, 0, result, 0, length);
236                 result[length] = second;
237                 return result;
238         }
239
240         /**
241          * Compares the contents of the two arrays array and prefix. Returns
242          * <ul>
243          * <li>zero if the array starts with the prefix contents</li>
244          * <li>the difference between the first two characters that are not equal </li>
245          * <li>one if array length is lower than the prefix length and that the prefix starts with the 
246          * array contents.</li>
247          * </ul>
248          * <p>
249          * For example:
250          * <ol>
251          * <li><pre>
252          *    array = null
253          *    prefix = null
254          *    => result = NullPointerException
255          * </pre>
256          * </li>
257          * <li><pre>
258          *    array = { 'a', 'b', 'c', 'd', 'e' }
259          *    prefix = { 'a', 'b', 'c'}
260          *    => result = 0
261          * </pre>
262          * </li>
263          * <li><pre>
264          *    array = { 'a', 'b', 'c', 'd', 'e' }
265          *    prefix = { 'a', 'B', 'c'}
266          *    => result = 32
267          * </pre>
268          * </li>
269          * <li><pre>
270          *    array = { 'd', 'b', 'c', 'd', 'e' }
271          *    prefix = { 'a', 'b', 'c'}
272          *    => result = 3
273          * </pre>
274          * </li>
275          * <li><pre>
276          *    array = { 'a', 'b', 'c', 'd', 'e' }
277          *    prefix = { 'd', 'b', 'c'}
278          *    => result = -3
279          * </pre>
280          * </li>
281          * <li><pre>
282          *    array = { 'a', 'a', 'c', 'd', 'e' }
283          *    prefix = { 'a', 'e', 'c'}
284          *    => result = -4
285          * </pre>
286          * </li>
287          * </ol>
288          * </p>
289          * 
290          * @param array the given array
291          * @param prefix the given prefix
292          * @return the result of the comparison (>=0 if array>prefix)
293          * @throws NullPointerException if either array or prefix is null
294          */
295         public static final int compareWith(char[] array, char[] prefix) {
296                 int arrayLength = array.length;
297                 int prefixLength = prefix.length;
298                 int min = Math.min(arrayLength, prefixLength);
299                 int i = 0;
300                 while (min-- != 0) {
301                         char c1 = array[i];
302                         char c2 = prefix[i++];
303                         if (c1 != c2)
304                                 return c1 - c2;
305                 }
306                 if (prefixLength == i)
307                         return 0;
308                 return -1;      // array is shorter than prefix (e.g. array:'ab' < prefix:'abc').
309         }
310
311         /**
312          * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
313          * If the first array is null, then the second array is returned.
314          * If the second array is null, then the first array is returned.
315          * <br>
316          * <br>
317          * For example:
318          * <ol>
319          * <li><pre>
320          *    first = null
321          *    second = { 'a' }
322          *    => result = { ' a' }
323          * </pre>
324          * </li>
325          * <li><pre>
326          *    first = { ' a' }
327          *    second = null
328          *    => result = { ' a' }
329          * </pre>
330          * </li>
331          * <li><pre>
332          *    first = { ' a' }
333          *    second = { ' b' }
334          *    => result = { ' a' , ' b' }
335          * </pre>
336          * </li>
337          * </ol>
338          * 
339          * @param first the first array to concatenate
340          * @param second the second array to concatenate
341          * @return the concatenation of the two arrays, or null if the two arrays are null.
342          */
343         public static final char[] concat(char[] first, char[] second) {
344                 if (first == null)
345                         return second;
346                 if (second == null)
347                         return first;
348
349                 int length1 = first.length;
350                 int length2 = second.length;
351                 char[] result = new char[length1 + length2];
352                 System.arraycopy(first, 0, result, 0, length1);
353                 System.arraycopy(second, 0, result, length1, length2);
354                 return result;
355         }
356
357         /**
358          * Answers the concatenation of the three arrays. It answers null if the three arrays are null.
359          * If first is null, it answers the concatenation of second and third.
360          * If second is null, it answers the concatenation of first and third.
361          * If third is null, it answers the concatenation of first and second.
362          * <br>
363          * <br>
364          * For example:
365          * <ol>
366          * <li><pre>
367          *    first = null
368          *    second = { 'a' }
369          *    third = { 'b' }
370          *    => result = { ' a', 'b' }
371          * </pre>
372          * </li>
373          * <li><pre>
374          *    first = { 'a' }
375          *    second = null
376          *    third = { 'b' }
377          *    => result = { ' a', 'b' }
378          * </pre>
379          * </li>
380          * <li><pre>
381          *    first = { 'a' }
382          *    second = { 'b' }
383          *    third = null
384          *    => result = { ' a', 'b' }
385          * </pre>
386          * </li>
387          * <li><pre>
388          *    first = null
389          *    second = null
390          *    third = null
391          *    => result = null
392          * </pre>
393          * </li>
394          * <li><pre>
395          *    first = { 'a' }
396          *    second = { 'b' }
397          *    third = { 'c' }
398          *    => result = { 'a', 'b', 'c' }
399          * </pre>
400          * </li>
401          * </ol>
402          * 
403          * @param first the first array to concatenate
404          * @param second the second array to concatenate
405          * @param third the third array to concatenate
406          * 
407          * @return the concatenation of the three arrays, or null if the three arrays are null.
408          */
409         public static final char[] concat(
410                 char[] first,
411                 char[] second,
412                 char[] third) {
413                 if (first == null)
414                         return concat(second, third);
415                 if (second == null)
416                         return concat(first, third);
417                 if (third == null)
418                         return concat(first, second);
419
420                 int length1 = first.length;
421                 int length2 = second.length;
422                 int length3 = third.length;
423                 char[] result = new char[length1 + length2 + length3];
424                 System.arraycopy(first, 0, result, 0, length1);
425                 System.arraycopy(second, 0, result, length1, length2);
426                 System.arraycopy(third, 0, result, length1 + length2, length3);
427                 return result;
428         }
429
430         /**
431          * Answers the concatenation of the two arrays inserting the separator character between the two arrays.
432          * It answers null if the two arrays are null.
433          * If the first array is null, then the second array is returned.
434          * If the second array is null, then the first array is returned.
435          * <br>
436          * <br>
437          * For example:
438          * <ol>
439          * <li><pre>
440          *    first = null
441          *    second = { 'a' }
442          *    separator = '/'
443          *    => result = { ' a' }
444          * </pre>
445          * </li>
446          * <li><pre>
447          *    first = { ' a' }
448          *    second = null
449          *    separator = '/'
450          *    => result = { ' a' }
451          * </pre>
452          * </li>
453          * <li><pre>
454          *    first = { ' a' }
455          *    second = { ' b' }
456          *    separator = '/'
457          *    => result = { ' a' , '/', 'b' }
458          * </pre>
459          * </li>
460          * </ol>
461          * 
462          * @param first the first array to concatenate
463          * @param second the second array to concatenate
464          * @param separator the character to insert
465          * @return the concatenation of the two arrays inserting the separator character 
466          * between the two arrays , or null if the two arrays are null.
467          */
468         public static final char[] concat(
469                 char[] first,
470                 char[] second,
471                 char separator) {
472                 if (first == null)
473                         return second;
474                 if (second == null)
475                         return first;
476
477                 int length1 = first.length;
478                 if (length1 == 0)
479                         return second;
480                 int length2 = second.length;
481                 if (length2 == 0)
482                         return first;
483
484                 char[] result = new char[length1 + length2 + 1];
485                 System.arraycopy(first, 0, result, 0, length1);
486                 result[length1] = separator;
487                 System.arraycopy(second, 0, result, length1 + 1, length2);
488                 return result;
489         }
490
491         /**
492          * Answers the concatenation of the three arrays inserting the sep1 character between the 
493          * two arrays and sep2 between the last two.
494          * It answers null if the three arrays are null.
495          * If the first array is null, then it answers the concatenation of second and third inserting
496          * the sep2 character between them.
497          * If the second array is null, then it answers the concatenation of first and third inserting
498          * the sep1 character between them.
499          * If the third array is null, then it answers the concatenation of first and second inserting
500          * the sep1 character between them.
501          * <br>
502          * <br>
503          * For example:
504          * <ol>
505          * <li><pre>
506          *    first = null
507          *    sep1 = '/'
508          *    second = { 'a' }
509          *    sep2 = ':'
510          *    third = { 'b' }
511          *    => result = { ' a' , ':', 'b' }
512          * </pre>
513          * </li>
514          * <li><pre>
515          *    first = { 'a' }
516          *    sep1 = '/'
517          *    second = null
518          *    sep2 = ':'
519          *    third = { 'b' }
520          *    => result = { ' a' , '/', 'b' }
521          * </pre>
522          * </li>
523          * <li><pre>
524          *    first = { 'a' }
525          *    sep1 = '/'
526          *    second = { 'b' }
527          *    sep2 = ':'
528          *    third = null
529          *    => result = { ' a' , '/', 'b' }
530          * </pre>
531          * </li>
532          * <li><pre>
533          *    first = { 'a' }
534          *    sep1 = '/'
535          *    second = { 'b' }
536          *    sep2 = ':'
537          *    third = { 'c' }
538          *    => result = { ' a' , '/', 'b' , ':', 'c' }
539          * </pre>
540          * </li>
541          * </ol>
542          * 
543          * @param first the first array to concatenate
544          * @param sep1 the character to insert
545          * @param second the second array to concatenate
546          * @param sep2 the character to insert
547          * @param third the second array to concatenate
548          * @return the concatenation of the three arrays inserting the sep1 character between the 
549          * two arrays and sep2 between the last two.
550          */
551         public static final char[] concat(
552                 char[] first,
553                 char sep1,
554                 char[] second,
555                 char sep2,
556                 char[] third) {
557                 if (first == null)
558                         return concat(second, third, sep2);
559                 if (second == null)
560                         return concat(first, third, sep1);
561                 if (third == null)
562                         return concat(first, second, sep1);
563
564                 int length1 = first.length;
565                 int length2 = second.length;
566                 int length3 = third.length;
567                 char[] result = new char[length1 + length2 + length3 + 2];
568                 System.arraycopy(first, 0, result, 0, length1);
569                 result[length1] = sep1;
570                 System.arraycopy(second, 0, result, length1 + 1, length2);
571                 result[length1 + length2 + 1] = sep2;
572                 System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
573                 return result;
574         }
575
576         /**
577          * Answers a new array with prepending the prefix character and appending the suffix 
578          * character at the end of the array. If array is null, it answers a new array containing the 
579          * prefix and the suffix characters.
580          * <br>
581          * <br>
582          * For example:<br>
583          * <ol>
584          * <li><pre>
585          *    prefix = 'a'
586          *    array = { 'b' }
587          *    suffix = 'c'
588          *    => result = { 'a', 'b' , 'c' }
589          * </pre>
590          * </li>
591          * <li><pre>
592          *    prefix = 'a'
593          *    array = null
594          *    suffix = 'c'
595          *    => result = { 'a', 'c' }
596          * </pre></li>
597          * </ol>
598          * 
599          * @param prefix the prefix character
600          * @param array the array that is concanated with the prefix and suffix characters
601          * @param suffix the suffix character
602          * @return the new array
603          */
604         public static final char[] concat(char prefix, char[] array, char suffix) {
605                 if (array == null)
606                         return new char[] { prefix, suffix };
607
608                 int length = array.length;
609                 char[] result = new char[length + 2];
610                 result[0] = prefix;
611                 System.arraycopy(array, 0, result, 1, length);
612                 result[length + 1] = suffix;
613                 return result;
614         }
615         
616         /**
617          * Answers the concatenation of the given array parts using the given separator between each
618          * part and appending the given name at the end.
619          * <br>
620          * <br>
621          * For example:<br>
622          * <ol>
623          * <li><pre>
624          *    name = { 'c' }
625          *    array = { { 'a' }, { 'b' } }
626          *    separator = '.'
627          *    => result = { 'a', '.', 'b' , '.', 'c' }
628          * </pre>
629          * </li>
630          * <li><pre>
631          *    name = null
632          *    array = { { 'a' }, { 'b' } }
633          *    separator = '.'
634          *    => result = { 'a', '.', 'b' }
635          * </pre></li>
636          * <li><pre>
637          *    name = { ' c' }
638          *    array = null
639          *    separator = '.'
640          *    => result = { 'c' }
641          * </pre></li>
642          * </ol>
643          * 
644          * @param name the given name
645          * @param array the given array
646          * @param separator the given separator
647          * @return the concatenation of the given array parts using the given separator between each
648          * part and appending the given name at the end
649          */
650         public static final char[] concatWith(
651                 char[] name,
652                 char[][] array,
653                 char separator) {
654                 int nameLength = name == null ? 0 : name.length;
655                 if (nameLength == 0)
656                         return concatWith(array, separator);
657
658                 int length = array == null ? 0 : array.length;
659                 if (length == 0)
660                         return name;
661
662                 int size = nameLength;
663                 int index = length;
664                 while (--index >= 0)
665                         if (array[index].length > 0)
666                                 size += array[index].length + 1;
667                 char[] result = new char[size];
668                 index = size;
669                 for (int i = length - 1; i >= 0; i--) {
670                         int subLength = array[i].length;
671                         if (subLength > 0) {
672                                 index -= subLength;
673                                 System.arraycopy(array[i], 0, result, index, subLength);
674                                 result[--index] = separator;
675                         }
676                 }
677                 System.arraycopy(name, 0, result, 0, nameLength);
678                 return result;
679         }
680
681         /**
682          * Answers the concatenation of the given array parts using the given separator between each
683          * part and appending the given name at the end.
684          * <br>
685          * <br>
686          * For example:<br>
687          * <ol>
688          * <li><pre>
689          *    name = { 'c' }
690          *    array = { { 'a' }, { 'b' } }
691          *    separator = '.'
692          *    => result = { 'a', '.', 'b' , '.', 'c' }
693          * </pre>
694          * </li>
695          * <li><pre>
696          *    name = null
697          *    array = { { 'a' }, { 'b' } }
698          *    separator = '.'
699          *    => result = { 'a', '.', 'b' }
700          * </pre></li>
701          * <li><pre>
702          *    name = { ' c' }
703          *    array = null
704          *    separator = '.'
705          *    => result = { 'c' }
706          * </pre></li>
707          * </ol>
708          * 
709          * @param array the given array
710          * @param name the given name
711          * @param separator the given separator
712          * @return the concatenation of the given array parts using the given separator between each
713          * part and appending the given name at the end
714          */
715         public static final char[] concatWith(
716                 char[][] array,
717                 char[] name,
718                 char separator) {
719                 int nameLength = name == null ? 0 : name.length;
720                 if (nameLength == 0)
721                         return concatWith(array, separator);
722
723                 int length = array == null ? 0 : array.length;
724                 if (length == 0)
725                         return name;
726
727                 int size = nameLength;
728                 int index = length;
729                 while (--index >= 0)
730                         if (array[index].length > 0)
731                                 size += array[index].length + 1;
732                 char[] result = new char[size];
733                 index = 0;
734                 for (int i = 0; i < length; i++) {
735                         int subLength = array[i].length;
736                         if (subLength > 0) {
737                                 System.arraycopy(array[i], 0, result, index, subLength);
738                                 index += subLength;
739                                 result[index++] = separator;
740                         }
741                 }
742                 System.arraycopy(name, 0, result, index, nameLength);
743                 return result;
744         }
745
746         /**
747          * Answers the concatenation of the given array parts using the given separator between each part.
748          * <br>
749          * <br>
750          * For example:<br>
751          * <ol>
752          * <li><pre>
753          *    array = { { 'a' }, { 'b' } }
754          *    separator = '.'
755          *    => result = { 'a', '.', 'b' }
756          * </pre>
757          * </li>
758          * <li><pre>
759          *    array = null
760          *    separator = '.'
761          *    => result = { }
762          * </pre></li>
763          * </ol>
764          * 
765          * @param array the given array
766          * @param separator the given separator
767          * @return the concatenation of the given array parts using the given separator between each part
768          */
769         public static final char[] concatWith(char[][] array, char separator) {
770                 int length = array == null ? 0 : array.length;
771                 if (length == 0)
772                         return CharOperation.NO_CHAR;
773
774                 int size = length - 1;
775                 int index = length;
776                 while (--index >= 0) {
777                         if (array[index].length == 0)
778                                 size--;
779                         else
780                                 size += array[index].length;
781                 }
782                 if (size <= 0)
783                         return CharOperation.NO_CHAR;
784                 char[] result = new char[size];
785                 index = length;
786                 while (--index >= 0) {
787                         length = array[index].length;
788                         if (length > 0) {
789                                 System.arraycopy(
790                                         array[index],
791                                         0,
792                                         result,
793                                         (size -= length),
794                                         length);
795                                 if (--size >= 0)
796                                         result[size] = separator;
797                         }
798                 }
799                 return result;
800         }
801         
802         /**
803          * Answers true if the array contains an occurrence of character, false otherwise.
804          * 
805          * <br>
806          * <br>
807          * For example:
808          * <ol>
809          * <li><pre>
810          *    character = 'c'
811          *    array = { { ' a' }, { ' b' } }
812          *    result => false
813          * </pre>
814          * </li>
815          * <li><pre>
816          *    character = 'a'
817          *    array = { { ' a' }, { ' b' } }
818          *    result => true
819          * </pre>
820          * </li>
821          * </ol>
822          * 
823          * @param character the character to search
824          * @param array the array in which the search is done
825          * @return true if the array contains an occurrence of character, false otherwise.
826          * @throws NullPointerException if array is null.
827          */
828         public static final boolean contains(char character, char[][] array) {
829                 for (int i = array.length; --i >= 0;) {
830                         char[] subarray = array[i];
831                         for (int j = subarray.length; --j >= 0;)
832                                 if (subarray[j] == character)
833                                         return true;
834                 }
835                 return false;
836         }
837
838         /**
839          * Answers true if the array contains an occurrence of character, false otherwise.
840          * 
841          * <br>
842          * <br>
843          * For example:
844          * <ol>
845          * <li><pre>
846          *    character = 'c'
847          *    array = { ' b'  }
848          *    result => false
849          * </pre>
850          * </li>
851          * <li><pre>
852          *    character = 'a'
853          *    array = { ' a' , ' b' }
854          *    result => true
855          * </pre>
856          * </li>
857          * </ol>
858          * 
859          * @param character the character to search
860          * @param array the array in which the search is done
861          * @return true if the array contains an occurrence of character, false otherwise.
862          * @throws NullPointerException if array is null.
863          */
864         public static final boolean contains(char character, char[] array) {
865                 for (int i = array.length; --i >= 0;)
866                         if (array[i] == character)
867                                 return true;
868                 return false;
869         }
870         
871         /**
872          * Answers a deep copy of the toCopy array.
873          * 
874          * @param toCopy the array to copy
875          * @return a deep copy of the toCopy array.
876          */
877         public static final char[][] deepCopy(char[][] toCopy) {
878                 int toCopyLength = toCopy.length;
879                 char[][] result = new char[toCopyLength][];
880                 for (int i = 0; i < toCopyLength; i++) {
881                         char[] toElement = toCopy[i];
882                         int toElementLength = toElement.length;
883                         char[] resultElement = new char[toElementLength];
884                         System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
885                         result[i] = resultElement;
886                 }
887                 return result;
888         }
889
890         /**
891          * Return true if array ends with the sequence of characters contained in toBeFound, 
892          * otherwise false.
893          * <br>
894          * <br>
895          * For example:
896          * <ol>
897          * <li><pre>
898          *    array = { 'a', 'b', 'c', 'd' }
899          *    toBeFound = { 'b', 'c' }
900          *    result => false
901          * </pre>
902          * </li>
903          * <li><pre>
904          *    array = { 'a', 'b', 'c' }
905          *    toBeFound = { 'b', 'c' }
906          *    result => true
907          * </pre>
908          * </li>
909          * </ol>
910          * 
911          * @param array the array to check
912          * @param toBeFound the array to find
913          * @return true if array ends with the sequence of characters contained in toBeFound, 
914          * otherwise false.
915          * @throws NullPointerException if array is null or toBeFound is null
916          */
917         public static final boolean endsWith(char[] array, char[] toBeFound) {
918                 int i = toBeFound.length;
919                 int j = array.length - i;
920
921                 if (j < 0)
922                         return false;
923                 while (--i >= 0)
924                         if (toBeFound[i] != array[i + j])
925                                 return false;
926                 return true;
927         }
928
929         /**
930          * Answers true if the two arrays are identical character by character, otherwise false.
931          * The equality is case sensitive.
932          * <br>
933          * <br>
934          * For example:
935          * <ol>
936          * <li><pre>
937          *    first = null
938          *    second = null
939          *    result => true
940          * </pre>
941          * </li>
942          * <li><pre>
943          *    first = { { } }
944          *    second = null
945          *    result => false
946          * </pre>
947          * </li>
948          * <li><pre>
949          *    first = { { 'a' } }
950          *    second = { { 'a' } }
951          *    result => true
952          * </pre>
953          * </li>
954          * <li><pre>
955          *    first = { { 'A' } }
956          *    second = { { 'a' } }
957          *    result => false
958          * </pre>
959          * </li>
960          * </ol>
961          * @param first the first array
962          * @param second the second array
963          * @return true if the two arrays are identical character by character, otherwise false
964          */
965         public static final boolean equals(char[][] first, char[][] second) {
966                 if (first == second)
967                         return true;
968                 if (first == null || second == null)
969                         return false;
970                 if (first.length != second.length)
971                         return false;
972
973                 for (int i = first.length; --i >= 0;)
974                         if (!equals(first[i], second[i]))
975                                 return false;
976                 return true;
977         }
978
979         /**
980          * If isCaseSensite is true, answers true if the two arrays are identical character
981          * by character, otherwise false.
982          * If it is false, answers true if the two arrays are identical character by 
983          * character without checking the case, otherwise false.
984          * <br>
985          * <br>
986          * For example:
987          * <ol>
988          * <li><pre>
989          *    first = null
990          *    second = null
991          *    isCaseSensitive = true
992          *    result => true
993          * </pre>
994          * </li>
995          * <li><pre>
996          *    first = { { } }
997          *    second = null
998          *    isCaseSensitive = true
999          *    result => false
1000          * </pre>
1001          * </li>
1002          * <li><pre>
1003          *    first = { { 'A' } }
1004          *    second = { { 'a' } }
1005          *    isCaseSensitive = true
1006          *    result => false
1007          * </pre>
1008          * </li>
1009          * <li><pre>
1010          *    first = { { 'A' } }
1011          *    second = { { 'a' } }
1012          *    isCaseSensitive = false
1013          *    result => true
1014          * </pre>
1015          * </li>
1016          * </ol>
1017          * 
1018          * @param first the first array
1019          * @param second the second array
1020          * @param isCaseSensitive check whether or not the equality should be case sensitive
1021          * @return true if the two arrays are identical character by character according to the value
1022          * of isCaseSensitive, otherwise false
1023          */
1024         public static final boolean equals(
1025                 char[][] first,
1026                 char[][] second,
1027                 boolean isCaseSensitive) {
1028
1029                 if (isCaseSensitive) {
1030                         return equals(first, second);
1031                 }
1032                 if (first == second)
1033                         return true;
1034                 if (first == null || second == null)
1035                         return false;
1036                 if (first.length != second.length)
1037                         return false;
1038
1039                 for (int i = first.length; --i >= 0;)
1040                         if (!equals(first[i], second[i], false))
1041                                 return false;
1042                 return true;
1043         }
1044
1045         /**
1046          * Answers true if the two arrays are identical character by character, otherwise false.
1047          * The equality is case sensitive.
1048          * <br>
1049          * <br>
1050          * For example:
1051          * <ol>
1052          * <li><pre>
1053          *    first = null
1054          *    second = null
1055          *    result => true
1056          * </pre>
1057          * </li>
1058          * <li><pre>
1059          *    first = { }
1060          *    second = null
1061          *    result => false
1062          * </pre>
1063          * </li>
1064          * <li><pre>
1065          *    first = { 'a' }
1066          *    second = { 'a' }
1067          *    result => true
1068          * </pre>
1069          * </li>
1070          * <li><pre>
1071          *    first = { 'a' }
1072          *    second = { 'A' }
1073          *    result => false
1074          * </pre>
1075          * </li>
1076          * </ol>
1077          * @param first the first array
1078          * @param second the second array
1079          * @return true if the two arrays are identical character by character, otherwise false
1080          */
1081         public static final boolean equals(char[] first, char[] second) {
1082                 if (first == second)
1083                         return true;
1084                 if (first == null || second == null)
1085                         return false;
1086                 if (first.length != second.length)
1087                         return false;
1088
1089                 for (int i = first.length; --i >= 0;)
1090                         if (first[i] != second[i])
1091                                 return false;
1092                 return true;
1093         }
1094         
1095         /**
1096          * Answers true if the first array is identical character by character to a portion of the second array
1097          * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false.
1098          * The equality is case sensitive.
1099          * <br>
1100          * <br>
1101          * For example:
1102          * <ol>
1103          * <li><pre>
1104          *    first = null
1105          *    second = null
1106          *    secondStart = 0
1107          *    secondEnd = 0
1108          *    result => true
1109          * </pre>
1110          * </li>
1111          * <li><pre>
1112          *    first = { }
1113          *    second = null
1114          *    secondStart = 0
1115          *    secondEnd = 0
1116          *    result => false
1117          * </pre>
1118          * </li>
1119          * <li><pre>
1120          *    first = { 'a' }
1121          *    second = { 'a' }
1122          *    secondStart = 0
1123          *    secondEnd = 1
1124          *    result => true
1125          * </pre>
1126          * </li>
1127          * <li><pre>
1128          *    first = { 'a' }
1129          *    second = { 'A' }
1130          *    secondStart = 0
1131          *    secondEnd = 1
1132          *    result => false
1133          * </pre>
1134          * </li>
1135          * </ol>
1136          * @param first the first array
1137          * @param second the second array
1138          * @param secondStart inclusive start position in the second array to compare
1139          * @param secondEnd exclusive end position in the second array to compare
1140          * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
1141          * @since 3.0
1142          */
1143         public static final boolean equals(char[] first, char[] second, int secondStart, int secondEnd) {
1144                 if (first == second)
1145                         return true;
1146                 if (first == null || second == null)
1147                         return false;
1148                 if (first.length != secondEnd - secondStart)
1149                         return false;
1150
1151                 for (int i = first.length; --i >= 0;)
1152                         if (first[i] != second[i+secondStart])
1153                                 return false;
1154                 return true;
1155         }
1156
1157         /**
1158          * If isCaseSensite is true, answers true if the two arrays are identical character
1159          * by character, otherwise false.
1160          * If it is false, answers true if the two arrays are identical character by 
1161          * character without checking the case, otherwise false.
1162          * <br>
1163          * <br>
1164          * For example:
1165          * <ol>
1166          * <li><pre>
1167          *    first = null
1168          *    second = null
1169          *    isCaseSensitive = true
1170          *    result => true
1171          * </pre>
1172          * </li>
1173          * <li><pre>
1174          *    first = { }
1175          *    second = null
1176          *    isCaseSensitive = true
1177          *    result => false
1178          * </pre>
1179          * </li>
1180          * <li><pre>
1181          *    first = { 'A' }
1182          *    second = { 'a' }
1183          *    isCaseSensitive = true
1184          *    result => false
1185          * </pre>
1186          * </li>
1187          * <li><pre>
1188          *    first = { 'A' }
1189          *    second = { 'a' }
1190          *    isCaseSensitive = false
1191          *    result => true
1192          * </pre>
1193          * </li>
1194          * </ol>
1195          * 
1196          * @param first the first array
1197          * @param second the second array
1198          * @param isCaseSensitive check whether or not the equality should be case sensitive
1199          * @return true if the two arrays are identical character by character according to the value
1200          * of isCaseSensitive, otherwise false
1201          */
1202         public static final boolean equals(
1203                 char[] first,
1204                 char[] second,
1205                 boolean isCaseSensitive) {
1206
1207                 if (isCaseSensitive) {
1208                         return equals(first, second);
1209                 }
1210                 if (first == second)
1211                         return true;
1212                 if (first == null || second == null)
1213                         return false;
1214                 if (first.length != second.length)
1215                         return false;
1216
1217                 for (int i = first.length; --i >= 0;)
1218                         if (Character.toLowerCase(first[i])
1219                                 != Character.toLowerCase(second[i]))
1220                                 return false;
1221                 return true;
1222         }
1223         /**
1224          * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive.
1225          * 
1226          * Answers true if the name contains the fragment at the starting index startIndex, otherwise false.
1227          * <br>
1228          * <br>
1229          * For example:
1230          * <ol>
1231          * <li><pre>
1232          *    fragment = { 'b', 'c' , 'd' }
1233          *    name = { 'a', 'b', 'c' , 'd' }
1234          *    startIndex = 1
1235          *    isCaseSensitive = true
1236          *    result => true
1237          * </pre>
1238          * </li>
1239          * <li><pre>
1240          *    fragment = { 'b', 'c' , 'd' }
1241          *    name = { 'a', 'b', 'C' , 'd' }
1242          *    startIndex = 1
1243          *    isCaseSensitive = true
1244          *    result => false
1245          * </pre>
1246          * </li>
1247          * <li><pre>
1248          *    fragment = { 'b', 'c' , 'd' }
1249          *    name = { 'a', 'b', 'C' , 'd' }
1250          *    startIndex = 0
1251          *    isCaseSensitive = false
1252          *    result => false
1253          * </pre>
1254          * </li>
1255          * <li><pre>
1256          *    fragment = { 'b', 'c' , 'd' }
1257          *    name = { 'a', 'b'}
1258          *    startIndex = 0
1259          *    isCaseSensitive = true
1260          *    result => false
1261          * </pre>
1262          * </li>
1263          * </ol>
1264          * 
1265          * @param fragment the fragment to check
1266          * @param name the array to check
1267          * @param startIndex the starting index
1268          * @param isCaseSensitive check whether or not the equality should be case sensitive
1269          * @return true if the name contains the fragment at the starting index startIndex according to the 
1270          * value of isCaseSensitive, otherwise false.
1271          * @throws NullPointerException if fragment or name is null.
1272          */
1273         public static final boolean fragmentEquals(
1274                 char[] fragment,
1275                 char[] name,
1276                 int startIndex,
1277                 boolean isCaseSensitive) {
1278
1279                 int max = fragment.length;
1280                 if (name.length < max + startIndex)
1281                         return false;
1282                 if (isCaseSensitive) {
1283                         for (int i = max;
1284                                 --i >= 0;
1285                                 ) // assumes the prefix is not larger than the name
1286                                 if (fragment[i] != name[i + startIndex])
1287                                         return false;
1288                         return true;
1289                 }
1290                 for (int i = max;
1291                         --i >= 0;
1292                         ) // assumes the prefix is not larger than the name
1293                         if (Character.toLowerCase(fragment[i])
1294                                 != Character.toLowerCase(name[i + startIndex]))
1295                                 return false;
1296                 return true;
1297         }
1298
1299         /**
1300          * Answers a hashcode for the array
1301          * 
1302          * @param array the array for which a hashcode is required
1303          * @return the hashcode
1304          * @throws NullPointerException if array is null
1305          */
1306         public static final int hashCode(char[] array) {
1307                 int hash = 0;
1308                 int offset = 0;
1309                 int length = array.length;
1310                 if (length < 16) {
1311                         for (int i = length; i > 0; i--)
1312                                 hash = (hash * 37) + array[offset++];
1313                 } else {
1314                         // only sample some characters
1315                         int skip = length / 8;
1316                         for (int i = length; i > 0; i -= skip, offset += skip)
1317                                 hash = (hash * 39) + array[offset];
1318                 }
1319                 return hash & 0x7FFFFFFF;
1320         }
1321         /**
1322          * Answers true if c is a whitespace according to the JLS (&#92;u000a, &#92;u000c, &#92;u000d, &#92;u0009), otherwise false.
1323          * <br>
1324          * <br>
1325          * For example:
1326          * <ol>
1327          * <li><pre>
1328          *    c = ' '
1329          *    result => true
1330          * </pre>
1331          * </li>
1332          * <li><pre>
1333          *    c = '&#92;u3000'
1334          *    result => false
1335          * </pre>
1336          * </li>
1337          * </ol>
1338          * 
1339          * @param c the character to check
1340          * @return true if c is a whitespace according to the JLS, otherwise false.
1341          */
1342         public static boolean isWhitespace(char c) {
1343                 switch (c) {
1344                         case 10 : /* \ u000a: LINE FEED               */
1345                         case 12 : /* \ u000c: FORM FEED               */
1346                         case 13 : /* \ u000d: CARRIAGE RETURN         */
1347                         case 32 : /* \ u0020: SPACE                   */
1348                         case 9 : /* \ u0009: HORIZONTAL TABULATION   */
1349                                 return true;
1350                         default :
1351                                 return false;
1352                 }
1353         }
1354         
1355         /**
1356          * Answers the first index in the array for which the corresponding character is
1357          * equal to toBeFound. Answers -1 if no occurrence of this character is found.
1358          * <br>
1359          * <br>
1360          * For example:
1361          * <ol>
1362          * <li><pre>
1363          *    toBeFound = 'c'
1364          *    array = { ' a', 'b', 'c', 'd' }
1365          *    result => 2
1366          * </pre>
1367          * </li>
1368          * <li><pre>
1369          *    toBeFound = 'e'
1370          *    array = { ' a', 'b', 'c', 'd' }
1371          *    result => -1
1372          * </pre>
1373          * </li>
1374          * </ol>
1375          * 
1376          * @param toBeFound the character to search
1377          * @param array the array to be searched
1378          * @return the first index in the array for which the corresponding character is
1379          * equal to toBeFound, -1 otherwise
1380          * @throws NullPointerException if array is null
1381          */
1382         public static final int indexOf(char toBeFound, char[] array) {
1383                 for (int i = 0; i < array.length; i++)
1384                         if (toBeFound == array[i])
1385                                 return i;
1386                 return -1;
1387         }
1388
1389         /**
1390          * Answers the first index in the array for which the corresponding character is
1391          * equal to toBeFound starting the search at index start.
1392          * Answers -1 if no occurrence of this character is found.
1393          * <br>
1394          * <br>
1395          * For example:
1396          * <ol>
1397          * <li><pre>
1398          *    toBeFound = 'c'
1399          *    array = { ' a', 'b', 'c', 'd' }
1400          *    start = 2
1401          *    result => 2
1402          * </pre>
1403          * </li>
1404          * <li><pre>
1405          *    toBeFound = 'c'
1406          *    array = { ' a', 'b', 'c', 'd' }
1407          *    start = 3
1408          *    result => -1
1409          * </pre>
1410          * </li>
1411          * <li><pre>
1412          *    toBeFound = 'e'
1413          *    array = { ' a', 'b', 'c', 'd' }
1414          *    start = 1
1415          *    result => -1
1416          * </pre>
1417          * </li>
1418          * </ol>
1419          * 
1420          * @param toBeFound the character to search
1421          * @param array the array to be searched
1422          * @param start the starting index
1423          * @return the first index in the array for which the corresponding character is
1424          * equal to toBeFound, -1 otherwise
1425          * @throws NullPointerException if array is null
1426          * @throws ArrayIndexOutOfBoundsException if  start is lower than 0
1427          */
1428         public static final int indexOf(char toBeFound, char[] array, int start) {
1429                 for (int i = start; i < array.length; i++)
1430                         if (toBeFound == array[i])
1431                                 return i;
1432                 return -1;
1433         }
1434
1435         /**
1436          * Answers the last index in the array for which the corresponding character is
1437          * equal to toBeFound starting from the end of the array.
1438          * Answers -1 if no occurrence of this character is found.
1439          * <br>
1440          * <br>
1441          * For example:
1442          * <ol>
1443          * <li><pre>
1444          *    toBeFound = 'c'
1445          *    array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
1446          *    result => 4
1447          * </pre>
1448          * </li>
1449          * <li><pre>
1450          *    toBeFound = 'e'
1451          *    array = { ' a', 'b', 'c', 'd' }
1452          *    result => -1
1453          * </pre>
1454          * </li>
1455          * </ol>
1456          *
1457          * @param toBeFound the character to search
1458          * @param array the array to be searched
1459          * @return the last index in the array for which the corresponding character is
1460          * equal to toBeFound starting from the end of the array, -1 otherwise
1461          * @throws NullPointerException if array is null
1462          */
1463         public static final int lastIndexOf(char toBeFound, char[] array) {
1464                 for (int i = array.length; --i >= 0;)
1465                         if (toBeFound == array[i])
1466                                 return i;
1467                 return -1;
1468         }
1469
1470         /**
1471          * Answers the last index in the array for which the corresponding character is
1472          * equal to toBeFound stopping at the index startIndex.
1473          * Answers -1 if no occurrence of this character is found.
1474          * <br>
1475          * <br>
1476          * For example:
1477          * <ol>
1478          * <li><pre>
1479          *    toBeFound = 'c'
1480          *    array = { ' a', 'b', 'c', 'd' }
1481          *    startIndex = 2
1482          *    result => 2
1483          * </pre>
1484          * </li>
1485          * <li><pre>
1486          *    toBeFound = 'c'
1487          *    array = { ' a', 'b', 'c', 'd', 'e' }
1488          *    startIndex = 3
1489          *    result => -1
1490          * </pre>
1491          * </li>
1492          * <li><pre>
1493          *    toBeFound = 'e'
1494          *    array = { ' a', 'b', 'c', 'd' }
1495          *    startIndex = 0
1496          *    result => -1
1497          * </pre>
1498          * </li>
1499          * </ol>
1500          *
1501          * @param toBeFound the character to search
1502          * @param array the array to be searched
1503          * @param startIndex the stopping index
1504          * @return the last index in the array for which the corresponding character is
1505          * equal to toBeFound stopping at the index startIndex, -1 otherwise
1506          * @throws NullPointerException if array is null
1507          * @throws ArrayIndexOutOfBoundsException if startIndex is lower than 0
1508          */
1509         public static final int lastIndexOf(
1510                 char toBeFound,
1511                 char[] array,
1512                 int startIndex) {
1513                 for (int i = array.length; --i >= startIndex;)
1514                         if (toBeFound == array[i])
1515                                 return i;
1516                 return -1;
1517         }
1518
1519         /**
1520          * Answers the last index in the array for which the corresponding character is
1521          * equal to toBeFound starting from endIndex to startIndex.
1522          * Answers -1 if no occurrence of this character is found.
1523          * <br>
1524          * <br>
1525          * For example:
1526          * <ol>
1527          * <li><pre>
1528          *    toBeFound = 'c'
1529          *    array = { ' a', 'b', 'c', 'd' }
1530          *    startIndex = 2
1531          *    endIndex = 2
1532          *    result => 2
1533          * </pre>
1534          * </li>
1535          * <li><pre>
1536          *    toBeFound = 'c'
1537          *    array = { ' a', 'b', 'c', 'd', 'e' }
1538          *    startIndex = 3
1539          *    endIndex = 4
1540          *    result => -1
1541          * </pre>
1542          * </li>
1543          * <li><pre>
1544          *    toBeFound = 'e'
1545          *    array = { ' a', 'b', 'c', 'd' }
1546          *    startIndex = 0
1547          *    endIndex = 3
1548          *    result => -1
1549          * </pre>
1550          * </li>
1551          * </ol>
1552          * 
1553          * @param toBeFound the character to search
1554          * @param array the array to be searched
1555          * @param startIndex the stopping index
1556          * @param endIndex the starting index
1557          * @return the last index in the array for which the corresponding character is
1558          * equal to toBeFound starting from endIndex to startIndex, -1 otherwise
1559          * @throws NullPointerException if array is null
1560          * @throws ArrayIndexOutOfBoundsException if endIndex is greater or equals to array length or starting is lower than 0
1561          */
1562         public static final int lastIndexOf(
1563                 char toBeFound,
1564                 char[] array,
1565                 int startIndex,
1566                 int endIndex) {
1567                 for (int i = endIndex; --i >= startIndex;)
1568                         if (toBeFound == array[i])
1569                                 return i;
1570                 return -1;
1571         }
1572         
1573         /**
1574          * Answers the last portion of a name given a separator.
1575          * <br>
1576          * <br>
1577          * For example,
1578          * <pre>
1579          *      lastSegment("java.lang.Object".toCharArray(),'.') --> Object
1580          * </pre>
1581          * 
1582          * @param array the array
1583          * @param separator the given separator
1584          * @return the last portion of a name given a separator
1585          * @throws NullPointerException if array is null
1586          */
1587         final static public char[] lastSegment(char[] array, char separator) {
1588                 int pos = lastIndexOf(separator, array);
1589                 if (pos < 0)
1590                         return array;
1591                 return subarray(array, pos + 1, array.length);
1592         }
1593
1594         /**
1595          * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching
1596          * accepts wild-cards '*' and '?'.
1597          *
1598          * When not case sensitive, the pattern is assumed to already be lowercased, the
1599          * name will be lowercased character per character as comparing.
1600          * If name is null, the answer is false.
1601          * If pattern is null, the answer is true if name is not null.
1602          * <br>
1603          * <br>
1604          * For example:
1605          * <ol>
1606          * <li><pre>
1607          *    pattern = { '?', 'b', '*' }
1608          *    name = { 'a', 'b', 'c' , 'd' }
1609          *    isCaseSensitive = true
1610          *    result => true
1611          * </pre>
1612          * </li>
1613          * <li><pre>
1614          *    pattern = { '?', 'b', '?' }
1615          *    name = { 'a', 'b', 'c' , 'd' }
1616          *    isCaseSensitive = true
1617          *    result => false
1618          * </pre>
1619          * </li>
1620          * <li><pre>
1621          *    pattern = { 'b', '*' }
1622          *    name = { 'a', 'b', 'c' , 'd' }
1623          *    isCaseSensitive = true
1624          *    result => false
1625          * </pre>
1626          * </li>
1627          * </ol>
1628          * 
1629          * @param pattern the given pattern
1630          * @param name the given name
1631          * @param isCaseSensitive flag to know whether or not the matching should be case sensitive
1632          * @return true if the pattern matches the given name, false otherwise
1633          */
1634         public static final boolean match(
1635                 char[] pattern,
1636                 char[] name,
1637                 boolean isCaseSensitive) {
1638
1639                 if (name == null)
1640                         return false; // null name cannot match
1641                 if (pattern == null)
1642                         return true; // null pattern is equivalent to '*'
1643
1644                 return match(
1645                         pattern,
1646                         0,
1647                         pattern.length,
1648                         name,
1649                         0,
1650                         name.length,
1651                         isCaseSensitive);
1652         }
1653
1654         /**
1655          * Answers true if the a sub-pattern matches the subpart of the given name, false otherwise.
1656          * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only subset of name/pattern.
1657          * end positions are non-inclusive.
1658          * The subpattern is defined by the patternStart and pattternEnd positions.
1659          * When not case sensitive, the pattern is assumed to already be lowercased, the
1660          * name will be lowercased character per character as comparing.
1661          * <br>
1662          * <br>
1663          * For example:
1664          * <ol>
1665          * <li><pre>
1666          *    pattern = { '?', 'b', '*' }
1667          *    patternStart = 1
1668          *    patternEnd = 3
1669          *    name = { 'a', 'b', 'c' , 'd' }
1670          *    nameStart = 1
1671          *    nameEnd = 4
1672          *    isCaseSensitive = true
1673          *    result => true
1674          * </pre>
1675          * </li>
1676          * <li><pre>
1677          *    pattern = { '?', 'b', '*' }
1678          *    patternStart = 1
1679          *    patternEnd = 2
1680          *    name = { 'a', 'b', 'c' , 'd' }
1681          *    nameStart = 1
1682          *    nameEnd = 2
1683          *    isCaseSensitive = true
1684          *    result => false
1685          * </pre>
1686          * </li>
1687          * </ol>
1688          * 
1689          * @param pattern the given pattern
1690          * @param patternStart the given pattern start
1691          * @param patternEnd the given pattern end
1692          * @param name the given name
1693          * @param nameStart the given name start
1694          * @param nameEnd the given name end
1695          * @param isCaseSensitive flag to know if the matching should be case sensitive
1696          * @return true if the a sub-pattern matches the subpart of the given name, false otherwise
1697          */
1698         public static final boolean match(
1699                 char[] pattern,
1700                 int patternStart,
1701                 int patternEnd,
1702                 char[] name,
1703                 int nameStart,
1704                 int nameEnd,
1705                 boolean isCaseSensitive) {
1706
1707                 if (name == null)
1708                         return false; // null name cannot match
1709                 if (pattern == null)
1710                         return true; // null pattern is equivalent to '*'
1711                 int iPattern = patternStart;
1712                 int iName = nameStart;
1713
1714                 if (patternEnd < 0)
1715                         patternEnd = pattern.length;
1716                 if (nameEnd < 0)
1717                         nameEnd = name.length;
1718
1719                 /* check first segment */
1720                 char patternChar = 0;
1721                 while ((iPattern < patternEnd)
1722                         && (patternChar = pattern[iPattern]) != '*') {
1723                         if (iName == nameEnd)
1724                                 return false;
1725                         if (patternChar
1726                                 != (isCaseSensitive
1727                                         ? name[iName]
1728                                         : Character.toLowerCase(name[iName]))
1729                                 && patternChar != '?') {
1730                                 return false;
1731                         }
1732                         iName++;
1733                         iPattern++;
1734                 }
1735                 /* check sequence of star+segment */
1736                 int segmentStart;
1737                 if (patternChar == '*') {
1738                         segmentStart = ++iPattern; // skip star
1739                 } else {
1740                         segmentStart = 0; // force iName check
1741                 }
1742                 int prefixStart = iName;
1743                 checkSegment : while (iName < nameEnd) {
1744                         if (iPattern == patternEnd) {
1745                                 iPattern = segmentStart; // mismatch - restart current segment
1746                                 iName = ++prefixStart;
1747                                 continue checkSegment;
1748                         }
1749                         /* segment is ending */
1750                         if ((patternChar = pattern[iPattern]) == '*') {
1751                                 segmentStart = ++iPattern; // skip start
1752                                 if (segmentStart == patternEnd) {
1753                                         return true;
1754                                 }
1755                                 prefixStart = iName;
1756                                 continue checkSegment;
1757                         }
1758                         /* check current name character */
1759                         if ((isCaseSensitive ? name[iName] : Character.toLowerCase(name[iName]))
1760                                                 != patternChar
1761                                         && patternChar != '?') {
1762                                 iPattern = segmentStart; // mismatch - restart current segment
1763                                 iName = ++prefixStart;
1764                                 continue checkSegment;
1765                         }
1766                         iName++;
1767                         iPattern++;
1768                 }
1769
1770                 return (segmentStart == patternEnd)
1771                         || (iName == nameEnd && iPattern == patternEnd)
1772                         || (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
1773         }
1774
1775         /**
1776          * Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
1777          * 
1778          * Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks
1779          * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
1780          * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
1781          * any folder combination.
1782          * Special rule: 
1783          * - foo\  is equivalent to foo\**   
1784          * When not case sensitive, the pattern is assumed to already be lowercased, the
1785          * name will be lowercased character per character as comparing.
1786          * 
1787          * @param pattern the given pattern
1788          * @param filepath the given path 
1789          * @param isCaseSensitive to find out whether or not the matching should be case sensitive
1790          * @param pathSeparator the given path separator
1791          * @return true if the pattern matches the filepath using the pathSepatator, false otherwise
1792          */
1793         public static final boolean pathMatch(
1794                 char[] pattern,
1795                 char[] filepath,
1796                 boolean isCaseSensitive,
1797                 char pathSeparator) {
1798
1799                 if (filepath == null)
1800                         return false; // null name cannot match
1801                 if (pattern == null)
1802                         return true; // null pattern is equivalent to '*'
1803
1804                 // offsets inside pattern
1805                 int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
1806                 int pLength = pattern.length;
1807                 int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart+1);
1808                 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1809
1810                 // special case: pattern foo\ is equivalent to foo\**
1811                 boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
1812
1813                 // offsets inside filepath
1814                 int fSegmentStart, fLength = filepath.length;
1815                 if (filepath[0] != pathSeparator){
1816                         fSegmentStart = 0;
1817                 } else {
1818                         fSegmentStart = 1;
1819                 }
1820                 if (fSegmentStart != pSegmentStart) {
1821                         return false; // both must start with a separator or none.
1822                 }
1823                 int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart+1);
1824                 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1825
1826                 // first segments
1827                 while (pSegmentStart < pLength
1828                         && !(pSegmentEnd == pLength && freeTrailingDoubleStar
1829                                         || (pSegmentEnd == pSegmentStart + 2
1830                                                         && pattern[pSegmentStart] == '*'
1831                                                         && pattern[pSegmentStart + 1] == '*'))) {
1832
1833                         if (fSegmentStart >= fLength)
1834                                 return false;
1835                         if (!CharOperation
1836                                 .match(
1837                                         pattern,
1838                                         pSegmentStart,
1839                                         pSegmentEnd,
1840                                         filepath,
1841                                         fSegmentStart,
1842                                         fSegmentEnd,
1843                                         isCaseSensitive)) {
1844                                 return false;
1845                         }
1846
1847                         // jump to next segment         
1848                         pSegmentEnd =
1849                                 CharOperation.indexOf(
1850                                         pathSeparator,
1851                                         pattern,
1852                                         pSegmentStart = pSegmentEnd + 1);
1853                         // skip separator
1854                         if (pSegmentEnd < 0)
1855                                 pSegmentEnd = pLength;
1856
1857                         fSegmentEnd =
1858                                 CharOperation.indexOf(
1859                                         pathSeparator,
1860                                         filepath,
1861                                         fSegmentStart = fSegmentEnd + 1);
1862                         // skip separator
1863                         if (fSegmentEnd < 0) fSegmentEnd = fLength;
1864                 }
1865
1866                 /* check sequence of doubleStar+segment */
1867                 int pSegmentRestart;
1868                 if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
1869                                 || (pSegmentEnd == pSegmentStart + 2
1870                                         && pattern[pSegmentStart] == '*'
1871                                         && pattern[pSegmentStart + 1] == '*')) {
1872                         pSegmentEnd =
1873                                 CharOperation.indexOf(
1874                                         pathSeparator,
1875                                         pattern,
1876                                         pSegmentStart = pSegmentEnd + 1);
1877                         // skip separator
1878                         if (pSegmentEnd < 0) pSegmentEnd = pLength;
1879                         pSegmentRestart = pSegmentStart;
1880                 } else {
1881                         if (pSegmentStart >= pLength) return fSegmentStart >= fLength; // true if filepath is done too.
1882                         pSegmentRestart = 0; // force fSegmentStart check
1883                 }
1884                 int fSegmentRestart = fSegmentStart;
1885                 checkSegment : while (fSegmentStart < fLength) {
1886                                 
1887                         if (pSegmentStart >= pLength) {
1888                                 if (freeTrailingDoubleStar) return true;
1889                                 // mismatch - restart current path segment
1890                                 pSegmentEnd =
1891                                         CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
1892                                 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1893
1894                                 fSegmentRestart = 
1895                                         CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
1896                                 // skip separator
1897                                 if (fSegmentRestart < 0) {
1898                                         fSegmentRestart = fLength;
1899                                 } else {
1900                                         fSegmentRestart++;
1901                                 }
1902                                 fSegmentEnd =
1903                                         CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
1904                                 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1905                                 continue checkSegment;
1906                         }
1907                         
1908                         /* path segment is ending */
1909                         if (pSegmentEnd == pSegmentStart + 2
1910                                 && pattern[pSegmentStart] == '*'
1911                                 && pattern[pSegmentStart + 1] == '*') {
1912                                 pSegmentEnd =
1913                                         CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
1914                                 // skip separator
1915                                 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1916                                 pSegmentRestart = pSegmentStart;
1917                                 fSegmentRestart = fSegmentStart;
1918                                 if (pSegmentStart >= pLength) return true;
1919                                 continue checkSegment;
1920                         }
1921                         /* chech current path segment */
1922                         if (!CharOperation.match(
1923                                                                 pattern,
1924                                                                 pSegmentStart,
1925                                                                 pSegmentEnd,
1926                                                                 filepath,
1927                                                                 fSegmentStart,
1928                                                                 fSegmentEnd,
1929                                                                 isCaseSensitive)) {
1930                                 // mismatch - restart current path segment
1931                                 pSegmentEnd =
1932                                         CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
1933                                 if (pSegmentEnd < 0) pSegmentEnd = pLength;
1934
1935                                 fSegmentRestart = 
1936                                         CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
1937                                 // skip separator
1938                                 if (fSegmentRestart < 0) {
1939                                         fSegmentRestart = fLength;
1940                                 } else {
1941                                         fSegmentRestart++;
1942                                 }
1943                                 fSegmentEnd =
1944                                         CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
1945                                 if (fSegmentEnd < 0) fSegmentEnd = fLength;
1946                                 continue checkSegment;
1947                         }
1948                         // jump to next segment         
1949                         pSegmentEnd =
1950                                 CharOperation.indexOf(
1951                                         pathSeparator,
1952                                         pattern,
1953                                         pSegmentStart = pSegmentEnd + 1);
1954                         // skip separator
1955                         if (pSegmentEnd < 0)
1956                                 pSegmentEnd = pLength;
1957
1958                         fSegmentEnd =
1959                                 CharOperation.indexOf(
1960                                         pathSeparator,
1961                                         filepath,
1962                                         fSegmentStart = fSegmentEnd + 1);
1963                         // skip separator
1964                         if (fSegmentEnd < 0)
1965                                 fSegmentEnd = fLength;
1966                 }
1967
1968                 return (pSegmentRestart >= pSegmentEnd)
1969                         || (fSegmentStart >= fLength && pSegmentStart >= pLength)
1970                         || (pSegmentStart == pLength - 2
1971                                 && pattern[pSegmentStart] == '*'
1972                                 && pattern[pSegmentStart + 1] == '*')
1973                         || (pSegmentStart == pLength && freeTrailingDoubleStar);
1974         }
1975
1976         /**
1977          * Answers the number of occurrences of the given character in the given array, 0 if any.
1978          * 
1979          * <br>
1980          * <br>
1981          * For example:
1982          * <ol>
1983          * <li><pre>
1984          *    toBeFound = 'b'
1985          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
1986          *    result => 3
1987          * </pre>
1988          * </li>
1989          * <li><pre>
1990          *    toBeFound = 'c'
1991          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
1992          *    result => 0
1993          * </pre>
1994          * </li>
1995          * </ol>
1996          * 
1997          * @param toBeFound the given character
1998          * @param array the given array
1999          * @return the number of occurrences of the given character in the given array, 0 if any
2000          * @throws NullPointerException if array is null
2001          */
2002         public static final int occurencesOf(char toBeFound, char[] array) {
2003                 int count = 0;
2004                 for (int i = 0; i < array.length; i++)
2005                         if (toBeFound == array[i])
2006                                 count++;
2007                 return count;
2008         }
2009
2010         /**
2011          * Answers the number of occurrences of the given character in the given array starting
2012          * at the given index, 0 if any.
2013          * 
2014          * <br>
2015          * <br>
2016          * For example:
2017          * <ol>
2018          * <li><pre>
2019          *    toBeFound = 'b'
2020          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2021          *    start = 2
2022          *    result => 2
2023          * </pre>
2024          * </li>
2025          * <li><pre>
2026          *    toBeFound = 'c'
2027          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2028          *    start = 0
2029          *    result => 0
2030          * </pre>
2031          * </li>
2032          * </ol>
2033          * 
2034          * @param toBeFound the given character
2035          * @param array the given array
2036          * @param start the given index
2037          * @return the number of occurrences of the given character in the given array, 0 if any
2038          * @throws NullPointerException if array is null
2039          * @throws ArrayIndexOutOfBoundsException if start is lower than 0
2040          */
2041         public static final int occurencesOf(
2042                 char toBeFound,
2043                 char[] array,
2044                 int start) {
2045                 int count = 0;
2046                 for (int i = start; i < array.length; i++)
2047                         if (toBeFound == array[i])
2048                                 count++;
2049                 return count;
2050         }
2051
2052         /**
2053          * Answers true if the given name starts with the given prefix, false otherwise.
2054          * The comparison is case sensitive.
2055          * <br>
2056          * <br>
2057          * For example:
2058          * <ol>
2059          * <li><pre>
2060          *    prefix = { 'a' , 'b' }
2061          *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2062          *    result => true
2063          * </pre>
2064          * </li>
2065          * <li><pre>
2066          *    prefix = { 'a' , 'c' }
2067          *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2068          *    result => false
2069          * </pre>
2070          * </li>
2071          * </ol>
2072          * 
2073          * @param prefix the given prefix
2074          * @param name the given name
2075          * @return true if the given name starts with the given prefix, false otherwise
2076          * @throws NullPointerException if the given name is null or if the given prefix is null
2077          */
2078         public static final boolean prefixEquals(char[] prefix, char[] name) {
2079
2080                 int max = prefix.length;
2081                 if (name.length < max)
2082                         return false;
2083                 for (int i = max;
2084                         --i >= 0;
2085                         ) // assumes the prefix is not larger than the name
2086                         if (prefix[i] != name[i])
2087                                 return false;
2088                 return true;
2089         }
2090
2091         /**
2092          * Answers true if the given name starts with the given prefix, false otherwise.
2093          * isCaseSensitive is used to find out whether or not the comparison should be case sensitive.
2094          * <br>
2095          * <br>
2096          * For example:
2097          * <ol>
2098          * <li><pre>
2099          *    prefix = { 'a' , 'B' }
2100          *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2101          *    isCaseSensitive = false
2102          *    result => true
2103          * </pre>
2104          * </li>
2105          * <li><pre>
2106          *    prefix = { 'a' , 'B' }
2107          *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2108          *    isCaseSensitive = true
2109          *    result => false
2110          * </pre>
2111          * </li>
2112          * </ol>
2113          * 
2114          * @param prefix the given prefix
2115          * @param name the given name
2116          * @param isCaseSensitive to find out whether or not the comparison should be case sensitive
2117          * @return true if the given name starts with the given prefix, false otherwise
2118          * @throws NullPointerException if the given name is null or if the given prefix is null
2119          */
2120         public static final boolean prefixEquals(
2121                 char[] prefix,
2122                 char[] name,
2123                 boolean isCaseSensitive) {
2124
2125                 int max = prefix.length;
2126                 if (name.length < max)
2127                         return false;
2128                 if (isCaseSensitive) {
2129                         for (int i = max;
2130                                 --i >= 0;
2131                                 ) // assumes the prefix is not larger than the name
2132                                 if (prefix[i] != name[i])
2133                                         return false;
2134                         return true;
2135                 }
2136
2137                 for (int i = max;
2138                         --i >= 0;
2139                         ) // assumes the prefix is not larger than the name
2140                         if (Character.toLowerCase(prefix[i])
2141                                 != Character.toLowerCase(name[i]))
2142                                 return false;
2143                 return true;
2144         }
2145
2146         /**
2147          * Replace all occurrence of the character to be replaced with the remplacement character in the
2148          * given array.
2149          * <br>
2150          * <br>
2151          * For example:
2152          * <ol>
2153          * <li><pre>
2154          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2155          *    toBeReplaced = 'b'
2156          *    replacementChar = 'a'
2157          *    result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
2158          * </pre>
2159          * </li>
2160          * <li><pre>
2161          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2162          *    toBeReplaced = 'c'
2163          *    replacementChar = 'a'
2164          *    result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
2165          * </pre>
2166          * </li>
2167          * </ol>
2168          * 
2169          * @param array the given array
2170          * @param toBeReplaced the character to be replaced
2171          * @param replacementChar the replacement character
2172          * @throws NullPointerException if the given array is null
2173          */
2174         public static final void replace(
2175                 char[] array,
2176                 char toBeReplaced,
2177                 char replacementChar) {
2178                 if (toBeReplaced != replacementChar) {
2179                         for (int i = 0, max = array.length; i < max; i++) {
2180                                 if (array[i] == toBeReplaced)
2181                                         array[i] = replacementChar;
2182                         }
2183                 }
2184         }
2185
2186         /**
2187          * Answers a new array of characters with substitutions. No side-effect is operated on the original
2188          * array, in case no substitution happened, then the result is the same as the
2189          * original one.
2190          * <br>
2191          * <br>
2192          * For example:
2193          * <ol>
2194          * <li><pre>
2195          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2196          *    toBeReplaced = { 'b' }
2197          *    replacementChar = { 'a', 'a' }
2198          *    result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
2199          * </pre>
2200          * </li>
2201          * <li><pre>
2202          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2203          *    toBeReplaced = { 'c' }
2204          *    replacementChar = { 'a' }
2205          *    result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
2206          * </pre>
2207          * </li>
2208          * </ol>
2209          * 
2210          * @param array the given array
2211          * @param toBeReplaced characters to be replaced
2212          * @param replacementChars the replacement characters
2213          * @return a new array of characters with substitutions or the given array if none
2214          * @throws NullPointerException if the given array is null
2215          */
2216         public static final char[] replace(
2217                 char[] array,
2218                 char[] toBeReplaced,
2219                 char[] replacementChars) {
2220
2221                 int max = array.length;
2222                 int replacedLength = toBeReplaced.length;
2223                 int replacementLength = replacementChars.length;
2224
2225                 int[] starts = new int[5];
2226                 int occurrenceCount = 0;
2227
2228                 if (!equals(toBeReplaced, replacementChars)) {
2229
2230                         next : for (int i = 0; i < max; i++) {
2231                                 int j = 0;
2232                                 while (j < replacedLength) {
2233                                         if (i + j == max)
2234                                                 continue next;
2235                                         if (array[i + j] != toBeReplaced[j++])
2236                                                 continue next;
2237                                 }
2238                                 if (occurrenceCount == starts.length) {
2239                                         System.arraycopy(
2240                                                 starts,
2241                                                 0,
2242                                                 starts = new int[occurrenceCount * 2],
2243                                                 0,
2244                                                 occurrenceCount);
2245                                 }
2246                                 starts[occurrenceCount++] = i;
2247                         }
2248                 }
2249                 if (occurrenceCount == 0)
2250                         return array;
2251                 char[] result =
2252                         new char[max
2253                                 + occurrenceCount * (replacementLength - replacedLength)];
2254                 int inStart = 0, outStart = 0;
2255                 for (int i = 0; i < occurrenceCount; i++) {
2256                         int offset = starts[i] - inStart;
2257                         System.arraycopy(array, inStart, result, outStart, offset);
2258                         inStart += offset;
2259                         outStart += offset;
2260                         System.arraycopy(
2261                                 replacementChars,
2262                                 0,
2263                                 result,
2264                                 outStart,
2265                                 replacementLength);
2266                         inStart += replacedLength;
2267                         outStart += replacementLength;
2268                 }
2269                 System.arraycopy(array, inStart, result, outStart, max - inStart);
2270                 return result;
2271         }
2272
2273         /**
2274          * Return a new array which is the split of the given array using the given divider and triming each subarray to remove
2275          * whitespaces equals to ' '.
2276          * <br>
2277          * <br>
2278          * For example:
2279          * <ol>
2280          * <li><pre>
2281          *    divider = 'b'
2282          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2283          *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
2284          * </pre>
2285          * </li>
2286          * <li><pre>
2287          *    divider = 'c'
2288          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2289          *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2290          * </pre>
2291          * </li>
2292          * <li><pre>
2293          *    divider = 'b'
2294          *    array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
2295          *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
2296          * </pre>
2297          * </li>
2298          * <li><pre>
2299          *    divider = 'c'
2300          *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
2301          *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2302          * </pre>
2303          * </li>
2304          * </ol>
2305          * 
2306          * @param divider the given divider
2307          * @param array the given array
2308          * @return a new array which is the split of the given array using the given divider and triming each subarray to remove
2309          * whitespaces equals to ' '
2310          */
2311         public static final char[][] splitAndTrimOn(char divider, char[] array) {
2312                 int length = array == null ? 0 : array.length;
2313                 if (length == 0)
2314                         return NO_CHAR_CHAR;
2315
2316                 int wordCount = 1;
2317                 for (int i = 0; i < length; i++)
2318                         if (array[i] == divider)
2319                                 wordCount++;
2320                 char[][] split = new char[wordCount][];
2321                 int last = 0, currentWord = 0;
2322                 for (int i = 0; i < length; i++) {
2323                         if (array[i] == divider) {
2324                                 int start = last, end = i - 1;
2325                                 while (start < i && array[start] == ' ')
2326                                         start++;
2327                                 while (end > start && array[end] == ' ')
2328                                         end--;
2329                                 split[currentWord] = new char[end - start + 1];
2330                                 System.arraycopy(
2331                                         array,
2332                                         start,
2333                                         split[currentWord++],
2334                                         0,
2335                                         end - start + 1);
2336                                 last = i + 1;
2337                         }
2338                 }
2339                 int start = last, end = length - 1;
2340                 while (start < length && array[start] == ' ')
2341                         start++;
2342                 while (end > start && array[end] == ' ')
2343                         end--;
2344                 split[currentWord] = new char[end - start + 1];
2345                 System.arraycopy(
2346                         array,
2347                         start,
2348                         split[currentWord++],
2349                         0,
2350                         end - start + 1);
2351                 return split;
2352         }
2353
2354         /**
2355          * Return a new array which is the split of the given array using the given divider.
2356          * <br>
2357          * <br>
2358          * For example:
2359          * <ol>
2360          * <li><pre>
2361          *    divider = 'b'
2362          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2363          *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
2364          * </pre>
2365          * </li>
2366          * <li><pre>
2367          *    divider = 'c'
2368          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2369          *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
2370          * </pre>
2371          * </li>
2372          * <li><pre>
2373          *    divider = 'c'
2374          *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
2375          *    result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
2376          * </pre>
2377          * </li>
2378          * </ol>
2379          * 
2380          * @param divider the given divider
2381          * @param array the given array
2382          * @return a new array which is the split of the given array using the given divider
2383          */
2384         public static final char[][] splitOn(char divider, char[] array) {
2385                 int length = array == null ? 0 : array.length;
2386                 if (length == 0)
2387                         return NO_CHAR_CHAR;
2388
2389                 int wordCount = 1;
2390                 for (int i = 0; i < length; i++)
2391                         if (array[i] == divider)
2392                                 wordCount++;
2393                 char[][] split = new char[wordCount][];
2394                 int last = 0, currentWord = 0;
2395                 for (int i = 0; i < length; i++) {
2396                         if (array[i] == divider) {
2397                                 split[currentWord] = new char[i - last];
2398                                 System.arraycopy(
2399                                         array,
2400                                         last,
2401                                         split[currentWord++],
2402                                         0,
2403                                         i - last);
2404                                 last = i + 1;
2405                         }
2406                 }
2407                 split[currentWord] = new char[length - last];
2408                 System.arraycopy(array, last, split[currentWord], 0, length - last);
2409                 return split;
2410         }
2411
2412         /**
2413          * Return a new array which is the split of the given array using the given divider. The given end 
2414          * is exclusive and the given start is inclusive.
2415          * <br>
2416          * <br>
2417          * For example:
2418          * <ol>
2419          * <li><pre>
2420          *    divider = 'b'
2421          *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2422          *    start = 2
2423          *    end = 5
2424          *    result => { {  }, { 'a' }, {  } }
2425          * </pre>
2426          * </li>
2427          * </ol>
2428          * 
2429          * @param divider the given divider
2430          * @param array the given array
2431          * @param start the given starting index
2432          * @param end the given ending index
2433          * @return a new array which is the split of the given array using the given divider
2434          * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
2435          */
2436         public static final char[][] splitOn(
2437                 char divider,
2438                 char[] array,
2439                 int start,
2440                 int end) {
2441                 int length = array == null ? 0 : array.length;
2442                 if (length == 0 || start > end)
2443                         return NO_CHAR_CHAR;
2444
2445                 int wordCount = 1;
2446                 for (int i = start; i < end; i++)
2447                         if (array[i] == divider)
2448                                 wordCount++;
2449                 char[][] split = new char[wordCount][];
2450                 int last = start, currentWord = 0;
2451                 for (int i = start; i < end; i++) {
2452                         if (array[i] == divider) {
2453                                 split[currentWord] = new char[i - last];
2454                                 System.arraycopy(
2455                                         array,
2456                                         last,
2457                                         split[currentWord++],
2458                                         0,
2459                                         i - last);
2460                                 last = i + 1;
2461                         }
2462                 }
2463                 split[currentWord] = new char[end - last];
2464                 System.arraycopy(array, last, split[currentWord], 0, end - last);
2465                 return split;
2466         }
2467
2468         /**
2469          * Answers a new array which is a copy of the given array starting at the given start and 
2470          * ending at the given end. The given start is inclusive and the given end is exclusive.
2471          * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
2472          * than the length of the given array. If end  equals -1, it is converted to the array length.
2473          * <br>
2474          * <br>
2475          * For example:
2476          * <ol>
2477          * <li><pre>
2478          *    array = { { 'a' } , { 'b' } }
2479          *    start = 0
2480          *    end = 1
2481          *    result => { { 'a' } }
2482          * </pre>
2483          * </li>
2484          * <li><pre>
2485          *    array = { { 'a' } , { 'b' } }
2486          *    start = 0
2487          *    end = -1
2488          *    result => { { 'a' }, { 'b' } }
2489          * </pre>
2490          * </li>
2491          * </ol>
2492          *  
2493          * @param array the given array
2494          * @param start the given starting index
2495          * @param end the given ending index
2496          * @return a new array which is a copy of the given array starting at the given start and 
2497          * ending at the given end
2498          * @throws NullPointerException if the given array is null
2499          */
2500         public static final char[][] subarray(char[][] array, int start, int end) {
2501                 if (end == -1)
2502                         end = array.length;
2503                 if (start > end)
2504                         return null;
2505                 if (start < 0)
2506                         return null;
2507                 if (end > array.length)
2508                         return null;
2509
2510                 char[][] result = new char[end - start][];
2511                 System.arraycopy(array, start, result, 0, end - start);
2512                 return result;
2513         }
2514
2515         /**
2516          * Answers a new array which is a copy of the given array starting at the given start and 
2517          * ending at the given end. The given start is inclusive and the given end is exclusive.
2518          * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
2519          * than the length of the given array. If end  equals -1, it is converted to the array length.
2520          * <br>
2521          * <br>
2522          * For example:
2523          * <ol>
2524          * <li><pre>
2525          *    array = { 'a' , 'b' }
2526          *    start = 0
2527          *    end = 1
2528          *    result => { 'a' }
2529          * </pre>
2530          * </li>
2531          * <li><pre>
2532          *    array = { 'a', 'b' }
2533          *    start = 0
2534          *    end = -1
2535          *    result => { 'a' , 'b' }
2536          * </pre>
2537          * </li>
2538          * </ol>
2539          *  
2540          * @param array the given array
2541          * @param start the given starting index
2542          * @param end the given ending index
2543          * @return a new array which is a copy of the given array starting at the given start and 
2544          * ending at the given end
2545          * @throws NullPointerException if the given array is null
2546          */
2547         public static final char[] subarray(char[] array, int start, int end) {
2548                 if (end == -1)
2549                         end = array.length;
2550                 if (start > end)
2551                         return null;
2552                 if (start < 0)
2553                         return null;
2554                 if (end > array.length)
2555                         return null;
2556
2557                 char[] result = new char[end - start];
2558                 System.arraycopy(array, start, result, 0, end - start);
2559                 return result;
2560         }
2561         /**
2562          * Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null.
2563          * <br>
2564          * NOTE: If no conversion was necessary, then answers back the argument one.
2565          * <br>
2566          * <br>
2567          * For example:
2568          * <ol>
2569          * <li><pre>
2570          *    chars = { 'a' , 'b' }
2571          *    result => { 'a' , 'b' }
2572          * </pre>
2573          * </li>
2574          * <li><pre>
2575          *    array = { 'A', 'b' }
2576          *    result => { 'a' , 'b' }
2577          * </pre>
2578          * </li>
2579          * </ol>
2580          * 
2581          * @param chars the chars to convert
2582          * @return the result of a char[] conversion to lowercase
2583          */
2584         final static public char[] toLowerCase(char[] chars) {
2585                 if (chars == null)
2586                         return null;
2587                 int length = chars.length;
2588                 char[] lowerChars = null;
2589                 for (int i = 0; i < length; i++) {
2590                         char c = chars[i];
2591                         char lc = Character.toLowerCase(c);
2592                         if ((c != lc) || (lowerChars != null)) {
2593                                 if (lowerChars == null) {
2594                                         System.arraycopy(
2595                                                 chars,
2596                                                 0,
2597                                                 lowerChars = new char[length],
2598                                                 0,
2599                                                 i);
2600                                 }
2601                                 lowerChars[i] = lc;
2602                         }
2603                 }
2604                 return lowerChars == null ? chars : lowerChars;
2605         }
2606
2607         /**
2608          * Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no
2609          * space characters to remove.
2610          * <br>
2611          * <br>
2612          * For example:
2613          * <ol>
2614          * <li><pre>
2615          *    chars = { ' ', 'a' , 'b', ' ',  ' ' }
2616          *    result => { 'a' , 'b' }
2617          * </pre>
2618          * </li>
2619          * <li><pre>
2620          *    array = { 'A', 'b' }
2621          *    result => { 'A' , 'b' }
2622          * </pre>
2623          * </li>
2624          * </ol>
2625          * 
2626          * @param chars the given array
2627          * @return a new array removing leading and trailing spaces (' ')
2628          */
2629         final static public char[] trim(char[] chars) {
2630
2631                 if (chars == null)
2632                         return null;
2633
2634                 int start = 0, length = chars.length, end = length - 1;
2635                 while (start < length && chars[start] == ' ') {
2636                         start++;
2637                 }
2638                 while (end > start && chars[end] == ' ') {
2639                         end--;
2640                 }
2641                 if (start != 0 || end != length - 1) {
2642                         return subarray(chars, start, end + 1);
2643                 }
2644                 return chars;
2645         }
2646
2647         /**
2648          * Answers a string which is the concatenation of the given array using the '.' as a separator.
2649          * <br>
2650          * <br>
2651          * For example:
2652          * <ol>
2653          * <li><pre>
2654          *    array = { { 'a' } , { 'b' } }
2655          *    result => "a.b"
2656          * </pre>
2657          * </li>
2658          * <li><pre>
2659          *    array = { { ' ',  'a' } , { 'b' } }
2660          *    result => " a.b"
2661          * </pre>
2662          * </li>
2663          * </ol>
2664          * 
2665          * @param array the given array
2666          * @return a string which is the concatenation of the given array using the '.' as a separator
2667          */
2668         final static public String toString(char[][] array) {
2669                 char[] result = concatWith(array, '.');
2670                 return new String(result);
2671         }
2672         /**
2673          * Answers an array of strings from the given array of char array.
2674          * 
2675          * @param array the given array
2676          * @return an array of strings
2677          * @since 3.0
2678          */
2679         final static public String[] toStrings(char[][] array) {
2680                 int length = array.length;
2681                 String[] result = new String[length];
2682                 for (int i = 0; i < length; i++)
2683                         result[i] = new String(array[i]);
2684                 return result;
2685         }
2686 }