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