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