Source Code Cross Referenced for CharOperation.java in  » IDE-Eclipse » jdt » org » eclipse » jdt » core » compiler » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Eclipse » jdt » org.eclipse.jdt.core.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*******************************************************************************
0002:         * Copyright (c) 2000, 2007 IBM Corporation and others.
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         *     IBM Corporation - initial API and implementation
0010:         *     Luiz-Otavio Zorzella <zorzella at gmail dot com> - Improve CamelCase algorithm
0011:         *******************************************************************************/package org.eclipse.jdt.core.compiler;
0012:
0013:        import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
0014:
0015:        /**
0016:         * This class is a collection of helper methods to manipulate char arrays.
0017:         * <p>
0018:         * This class is not intended to be instantiated or subclassed by clients.
0019:         * </p>
0020:         * 
0021:         * @since 2.1
0022:         */
0023:        public final class CharOperation {
0024:
0025:            /**
0026:             * Constant for an empty char array
0027:             */
0028:            public static final char[] NO_CHAR = new char[0];
0029:
0030:            /**
0031:             * Constant for an empty char array with two dimensions.
0032:             */
0033:            public static final char[][] NO_CHAR_CHAR = new char[0][];
0034:
0035:            /**
0036:             * Constant for an empty String array.
0037:             * @since 3.1
0038:             */
0039:            public static final String[] NO_STRINGS = new String[0];
0040:
0041:            /**
0042:             * Answers a new array with appending the suffix character at the end of the array.
0043:             * <br>
0044:             * <br>
0045:             * For example:<br>
0046:             * <ol>
0047:             * <li><pre>
0048:             *    array = { 'a', 'b' }
0049:             *    suffix = 'c'
0050:             *    => result = { 'a', 'b' , 'c' }
0051:             * </pre>
0052:             * </li>
0053:             * <li><pre>
0054:             *    array = null
0055:             *    suffix = 'c'
0056:             *    => result = { 'c' }
0057:             * </pre></li>
0058:             * </ol>
0059:             * 
0060:             * @param array the array that is concatenated with the suffix character
0061:             * @param suffix the suffix character
0062:             * @return the new array
0063:             */
0064:            public static final char[] append(char[] array, char suffix) {
0065:                if (array == null)
0066:                    return new char[] { suffix };
0067:                int length = array.length;
0068:                System.arraycopy(array, 0, array = new char[length + 1], 0,
0069:                        length);
0070:                array[length] = suffix;
0071:                return array;
0072:            }
0073:
0074:            /**
0075:             * Append the given sub-array to the target array starting at the given index in the target array.
0076:             * The start of the sub-array is inclusive, the end is exclusive.
0077:             * Answers a new target array if it needs to grow, otherwise answers the same target array.
0078:             * <br>
0079:             * For example:<br>
0080:             * <ol>
0081:             * <li><pre>
0082:             *    target = { 'a', 'b', '0' }
0083:             *    index = 2
0084:             *    array = { 'c', 'd' }
0085:             *    start = 0
0086:             *    end = 1
0087:             *    => result = { 'a', 'b' , 'c' }
0088:             * </pre>
0089:             * </li>
0090:             * <li><pre>
0091:             *    target = { 'a', 'b' }
0092:             *    index = 2
0093:             *    array = { 'c', 'd' }
0094:             *    start = 0
0095:             *    end = 1
0096:             *    => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
0097:             * </pre></li>
0098:             * <li><pre>
0099:             *    target = { 'a', 'b', 'c' }
0100:             *    index = 1
0101:             *    array = { 'c', 'd', 'e', 'f' }
0102:             *    start = 1
0103:             *    end = 4
0104:             *    => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
0105:             * </pre></li>
0106:             * </ol>
0107:             * 
0108:             * @param target the given target
0109:             * @param index the given index
0110:             * @param array the given array
0111:             * @param start the given start index
0112:             * @param end the given end index
0113:             * 
0114:             * @return the new array
0115:             * @throws NullPointerException if the target array is null
0116:             */
0117:            public static final char[] append(char[] target, int index,
0118:                    char[] array, int start, int end) {
0119:                int targetLength = target.length;
0120:                int subLength = end - start;
0121:                int newTargetLength = subLength + index;
0122:                if (newTargetLength > targetLength) {
0123:                    System.arraycopy(target, 0,
0124:                            target = new char[newTargetLength * 2], 0, index);
0125:                }
0126:                System.arraycopy(array, start, target, index, subLength);
0127:                return target;
0128:            }
0129:
0130:            /**
0131:             * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
0132:             * If the first array is null, then the second array is returned.
0133:             * If the second array is null, then the first array is returned.
0134:             * <br>
0135:             * <br>
0136:             * For example:
0137:             * <ol>
0138:             * <li><pre>
0139:             *    first = null
0140:             *    second = null
0141:             *    => result = null
0142:             * </pre>
0143:             * </li>
0144:             * <li><pre>
0145:             *    first = { { ' a' } }
0146:             *    second = null
0147:             *    => result = { { ' a' } }
0148:             * </pre>
0149:             * </li>
0150:             * <li><pre>
0151:             *    first = null
0152:             *    second = { { ' a' } }
0153:             *    => result = { { ' a' } }
0154:             * </pre>
0155:             * </li>
0156:             * <li><pre>
0157:             *    first = { { ' b' } }
0158:             *    second = { { ' a' } }
0159:             *    => result = { { ' b' }, { ' a' } }
0160:             * </pre>
0161:             * </li>
0162:             * </ol>
0163:             * 
0164:             * @param first the first array to concatenate
0165:             * @param second the second array to concatenate
0166:             * @return the concatenation of the two arrays, or null if the two arrays are null.
0167:             */
0168:            public static final char[][] arrayConcat(char[][] first,
0169:                    char[][] second) {
0170:                if (first == null)
0171:                    return second;
0172:                if (second == null)
0173:                    return first;
0174:
0175:                int length1 = first.length;
0176:                int length2 = second.length;
0177:                char[][] result = new char[length1 + length2][];
0178:                System.arraycopy(first, 0, result, 0, length1);
0179:                System.arraycopy(second, 0, result, length1, length2);
0180:                return result;
0181:            }
0182:
0183:            /**
0184:             * Answers true if the pattern matches the given name using CamelCase rules, or
0185:             * false otherwise. char[] CamelCase matching does NOT accept explicit wild-cards
0186:             * '*' and '?' and is inherently case sensitive.
0187:             * <p>
0188:             * CamelCase denotes the convention of writing compound names without spaces,
0189:             * and capitalizing every term. This function recognizes both upper and lower
0190:             * CamelCase, depending whether the leading character is capitalized or not.
0191:             * The leading part of an upper CamelCase pattern is assumed to contain a
0192:             * sequence of capitals which are appearing in the matching name; e.g. 'NPE' will
0193:             * match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
0194:             * uses a lowercase first character. In Java, type names follow the upper
0195:             * CamelCase convention, whereas method or field names follow the lower
0196:             * CamelCase convention.
0197:             * <p>
0198:             * The pattern may contain lowercase characters, which will be matched in a case
0199:             * sensitive way. These characters must appear in sequence in the name.
0200:             * For instance, 'NPExcep' will match 'NullPointerException', but not
0201:             * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not
0202:             * 'NoPointerException'.
0203:             * <p>
0204:             * Digit characters are treated in a special way. They can be used in the pattern
0205:             * but are not always considered as leading character. For instance, both
0206:             * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
0207:             * <p>
0208:             * This method allows prefix match in Camel Case (see
0209:             * {@link #camelCaseMatch(char[], char[], boolean)}).
0210:             * <p>
0211:             * <pre>
0212:             * Examples:<ol>
0213:             * <li> pattern = { 'N', 'P', 'E' }
0214:             * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0215:             * result => true</li>
0216:             * <li> pattern = { 'N', 'P', 'E' }
0217:             * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0218:             * result => true</li>
0219:             * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
0220:             * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0221:             * result => true</li>
0222:             * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
0223:             * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0224:             * result => false</li>
0225:             * <li> pattern = { 'n', p', 'e' }
0226:             * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0227:             * result => false</li>
0228:             * <li> pattern = { 'I', 'P', 'L', '3' }
0229:             * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
0230:             * result => true</li>
0231:             * <li> pattern = { 'H', M' }
0232:             * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
0233:             * result => true</li>
0234:             * <li>pattern = { 'H', M', 'a', 'p' }
0235:             * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
0236:             * result => true</li>
0237:             * </ol></pre>
0238:             * 
0239:             * @param pattern the given pattern
0240:             * @param name the given name
0241:             * @return true if the pattern matches the given name, false otherwise
0242:             * @since 3.2
0243:             */
0244:            public static final boolean camelCaseMatch(char[] pattern,
0245:                    char[] name) {
0246:                if (pattern == null)
0247:                    return true; // null pattern is equivalent to '*'
0248:                if (name == null)
0249:                    return false; // null name cannot match
0250:
0251:                return camelCaseMatch(pattern, 0, pattern.length, name, 0,
0252:                        name.length, true/*prefix match*/);
0253:            }
0254:
0255:            /**
0256:             * Answers true if the pattern matches the given name using CamelCase rules, or
0257:             * false otherwise. char[] CamelCase matching does NOT accept explicit wild-cards
0258:             * '*' and '?' and is inherently case sensitive.
0259:             * <p>
0260:             * CamelCase denotes the convention of writing compound names without spaces,
0261:             * and capitalizing every term. This function recognizes both upper and lower
0262:             * CamelCase, depending whether the leading character is capitalized or not.
0263:             * The leading part of an upper CamelCase pattern is assumed to contain a
0264:             * sequence of capitals which are appearing in the matching name; e.g. 'NPE' will
0265:             * match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
0266:             * uses a lowercase first character. In Java, type names follow the upper
0267:             * CamelCase convention, whereas method or field names follow the lower
0268:             * CamelCase convention.
0269:             * <p>
0270:             * The pattern may contain lowercase characters, which will be matched in a case
0271:             * sensitive way. These characters must appear in sequence in the name.
0272:             * For instance, 'NPExcep' will match 'NullPointerException', but not
0273:             * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not
0274:             * 'NoPointerException'.
0275:             * <p>
0276:             * Digit characters are treated in a special way. They can be used in the pattern
0277:             * but are not always considered as leading character. For instance, both
0278:             * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
0279:             * <p>
0280:             * CamelCase may or may not match prefixes depending on the given parameter.
0281:             * When the prefix match parameter is <code>true</code>, the given pattern can
0282:             * match only a prefix of the given name. For instance, 'HM' , 'HaMa' and  'HMap'
0283:             * patterns will all match 'HashMap', 'HatMapper' <b>and</b> 'HashMapEntry'.
0284:             * <br>
0285:             * Reversely, if the prefix match parameter is <code>false</code>, then pattern
0286:             * and name must have <b>exactly</b> the same number of parts, and their last
0287:             * parts must be identical if they contain lowercase characters.
0288:             * For instance, 'HMap' and 'HaMap' patterns will match 'HashMap' but neither
0289:             * 'HashMapEntry' nor 'HatMapper'. Note that when the last part does not contain
0290:             * lowercase characters, then the name may end with lowercase characters.
0291:             * So, 'HM' pattern will match both 'HashMap' <b>and</b> 'HatMapper' but will not
0292:             * match 'HashMapEntry'.
0293:             * <p>
0294:             * <pre>
0295:             * Examples:<ol>
0296:             * <li> pattern = { 'N', 'P', 'E' }
0297:             * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0298:             * result => true</li>
0299:             * <li> pattern = { 'N', 'P', 'E' }
0300:             * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0301:             * result => true</li>
0302:             * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
0303:             * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0304:             * result => true</li>
0305:             * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
0306:             * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0307:             * result => false</li>
0308:             * <li> pattern = { 'n', p', 'e' }
0309:             * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0310:             * result => false</li>
0311:             * <li> pattern = { 'I', 'P', 'L', '3' }
0312:             * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
0313:             * result => true</li>
0314:             * <li> pattern = { 'H', M' }
0315:             * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
0316:             * result => (prefixMatch == true)</li>
0317:             * <li> pattern = { 'H', M', 'a', 'p' }
0318:             * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
0319:             * result => (prefixMatch == true)</li>
0320:             * </ol></pre>
0321:             * 
0322:             * @param pattern the given pattern
0323:             * @param name the given name
0324:             * @param prefixMatch flag telling whether the pattern can match name prefix or not.
0325:             * 	<ul>
0326:             * 		<li>For example, when it's <code>true</code>:<br>
0327:             * 			- 'HM' type string pattern will match  'HashMap' and 'HtmlMapper' types,
0328:             * 			  but not 'HashMapEntry'<br>
0329:             * 			- 'HMap' type string pattern will match  'HashMap' type but not 'HtmlMapper'.
0330:             * 		</li>
0331:             * 		<li>and, when it's <code>false</code>:<br>
0332:             * 			- 'HM' type string pattern will match both   'HashMap' and 'HtmlMapper'
0333:             * 			  and 'HashMapEntry'<br>
0334:             * 			- 'HMap' type string pattern will match both 'HashMap' and 'HtmlMapper'
0335:             * 			  types.
0336:             * 		</li>
0337:             * 	</ul>
0338:             * @return true if the pattern matches the given name, false otherwise
0339:             * @since 3.4
0340:             */
0341:            public static final boolean camelCaseMatch(char[] pattern,
0342:                    char[] name, boolean prefixMatch) {
0343:                if (pattern == null)
0344:                    return true; // null pattern is equivalent to '*'
0345:                if (name == null)
0346:                    return false; // null name cannot match
0347:
0348:                return camelCaseMatch(pattern, 0, pattern.length, name, 0,
0349:                        name.length, prefixMatch);
0350:            }
0351:
0352:            /**
0353:             * Answers true if a sub-pattern matches the sub-part of the given name using
0354:             * CamelCase rules, or false otherwise.  char[] CamelCase matching does NOT
0355:             * accept explicit wild-cards '*' and '?' and is inherently case sensitive. 
0356:             * Can match only subset of name/pattern, considering end positions as non-inclusive.
0357:             * The sub-pattern is defined by the patternStart and patternEnd positions.
0358:             * <p>
0359:             * CamelCase denotes the convention of writing compound names without spaces,
0360:             * and capitalizing every term. This function recognizes both upper and lower
0361:             * CamelCase, depending whether the leading character is capitalized or not.
0362:             * The leading part of an upper CamelCase pattern is assumed to contain a
0363:             * sequence of capitals which are appearing in the matching name; e.g. 'NPE' will
0364:             * match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
0365:             * uses a lowercase first character. In Java, type names follow the upper
0366:             * CamelCase convention, whereas method or field names follow the lower
0367:             * CamelCase convention.
0368:             * <p>
0369:             * The pattern may contain lowercase characters, which will be matched in a case
0370:             * sensitive way. These characters must appear in sequence in the name.
0371:             * For instance, 'NPExcep' will match 'NullPointerException', but not
0372:             * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not
0373:             * 'NoPointerException'.
0374:             * <p>
0375:             * Digit characters are treated in a special way. They can be used in the pattern
0376:             * but are not always considered as leading character. For instance, both
0377:             * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
0378:             * <p>
0379:             * Digit characters are treated in a special way. They can be used in the pattern
0380:             * but are not always considered as leading character. For instance, both
0381:             * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
0382:             * <p>
0383:             * This method allows prefix match in Camel Case (see
0384:             * {@link #camelCaseMatch(char[], int, int, char[], int, int, boolean)}).
0385:             * <p>
0386:             * Examples:
0387:             * <ol>
0388:             * <li><pre>
0389:             *    pattern = { 'N', 'P', 'E' }
0390:             *    patternStart = 0
0391:             *    patternEnd = 3
0392:             *    name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0393:             *    nameStart = 0
0394:             *    nameEnd = 20
0395:             *    result => true
0396:             * </pre>
0397:             * </li>
0398:             * <li><pre>
0399:             *    pattern = { 'N', 'P', 'E' }
0400:             *    patternStart = 0
0401:             *    patternEnd = 3
0402:             *    name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0403:             *    nameStart = 0
0404:             *    nameEnd = 21
0405:             *    result => true
0406:             * </pre>
0407:             * </li>
0408:             * <li><pre>
0409:             *    pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
0410:             *    patternStart = 0
0411:             *    patternEnd = 6
0412:             *    name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0413:             *    nameStart = 0
0414:             *    nameEnd = 20
0415:             *    result => true
0416:             * </pre>
0417:             * </li>
0418:             * <li><pre>
0419:             *    pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
0420:             *    patternStart = 0
0421:             *    patternEnd = 6
0422:             *    name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0423:             *    nameStart = 0
0424:             *    nameEnd = 21
0425:             *    result => false
0426:             * </pre>
0427:             * </li>
0428:             * <li><pre>
0429:             *    pattern = { 'n', p', 'e' }
0430:             *    patternStart = 0
0431:             *    patternEnd = 3
0432:             *    name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0433:             *    nameStart = 0
0434:             *    nameEnd = 20
0435:             *    result => false
0436:             * </pre>
0437:             * </li>
0438:             * <li><pre>
0439:             *    pattern = { 'I', 'P', 'L', '3' }
0440:             *    patternStart = 0
0441:             *    patternEnd = 4
0442:             *    name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
0443:             *    nameStart = 0
0444:             *    nameEnd = 21
0445:             *    result => true
0446:             * </pre>
0447:             * </li>
0448:             * </ol>
0449:             * 
0450:             * @param pattern the given pattern
0451:             * @param patternStart the start index of the pattern, inclusive
0452:             * @param patternEnd the end index of the pattern, exclusive
0453:             * @param name the given name
0454:             * @param nameStart the start index of the name, inclusive
0455:             * @param nameEnd the end index of the name, exclusive
0456:             * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
0457:             * @since 3.2
0458:             */
0459:            public static final boolean camelCaseMatch(char[] pattern,
0460:                    int patternStart, int patternEnd, char[] name,
0461:                    int nameStart, int nameEnd) {
0462:                return camelCaseMatch(pattern, patternStart, patternEnd, name,
0463:                        nameStart, nameEnd, true/*prefix match*/);
0464:            }
0465:
0466:            /**
0467:             * Answers true if a sub-pattern matches the sub-part of the given name using 
0468:             * CamelCase rules, or false otherwise.  char[] CamelCase matching does NOT
0469:             * accept explicit wild-cards '*' and '?' and is inherently case sensitive. 
0470:             * Can match only subset of name/pattern, considering end positions as
0471:             * non-inclusive. The sub-pattern is defined by the patternStart and patternEnd
0472:             * positions.
0473:             * <p>
0474:             * CamelCase denotes the convention of writing compound names without spaces,
0475:             * and capitalizing every term. This function recognizes both upper and lower
0476:             * CamelCase, depending whether the leading character is capitalized or not.
0477:             * The leading part of an upper CamelCase pattern is assumed to contain
0478:             * a sequence of capitals which are appearing in the matching name; e.g. 'NPE' will
0479:             * match 'NullPointerException', but not 'NewPerfData'. A lower CamelCase pattern
0480:             * uses a lowercase first character. In Java, type names follow the upper
0481:             * CamelCase convention, whereas method or field names follow the lower
0482:             * CamelCase convention.
0483:             * <p>
0484:             * The pattern may contain lowercase characters, which will be matched in a case
0485:             * sensitive way. These characters must appear in sequence in the name.
0486:             * For instance, 'NPExcep' will match 'NullPointerException', but not
0487:             * 'NullPointerExCEPTION' or 'NuPoEx' will match 'NullPointerException', but not
0488:             * 'NoPointerException'.
0489:             * <p>
0490:             * Digit characters are treated in a special way. They can be used in the pattern
0491:             * but are not always considered as leading character. For instance, both
0492:             * 'UTF16DSS' and 'UTFDSS' patterns will match 'UTF16DocumentScannerSupport'.
0493:             * <p>
0494:             * CamelCase may or may not match prefixes depending on the given parameter.
0495:             * When the prefix match parameter is <code>true</code>, the given pattern can
0496:             * match only a prefix of the given name. For instance, 'HM' , 'HaMa' and  'HMap'
0497:             * patterns will all match 'HashMap', 'HatMapper' <b>and</b> 'HashMapEntry'.
0498:             * <br>
0499:             * Reversely, if the prefix match parameter is <code>false</code>, then pattern
0500:             * and name must have <b>exactly</b> the same number of parts, and their last
0501:             * parts must be identical if they contain lowercase characters.
0502:             * For instance, 'HMap' and 'HaMap' patterns will match 'HashMap' but neither
0503:             * 'HashMapEntry' nor 'HatMapper'. Note that when the last part does not contain
0504:             * lowercase characters, then the name may end with lowercase characters.
0505:             * So, 'HM' pattern will match both 'HashMap' <b>and</b> 'HatMapper' but will not
0506:             * match 'HashMapEntry'.
0507:             * <p>
0508:             * <pre>
0509:             * Examples:
0510:             * <ol>
0511:             * <li> pattern = { 'N', 'P', 'E' }
0512:             * patternStart = 0
0513:             * patternEnd = 3
0514:             * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0515:             * nameStart = 0
0516:             * nameEnd = 20
0517:             * result => true</li>
0518:             * <li> pattern = { 'N', 'P', 'E' }
0519:             * patternStart = 0
0520:             * patternEnd = 3
0521:             * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0522:             * nameStart = 0
0523:             * nameEnd = 21
0524:             * result => true</li>
0525:             * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
0526:             * patternStart = 0
0527:             * patternEnd = 6
0528:             * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0529:             * nameStart = 0
0530:             * nameEnd = 20
0531:             * result => true</li>
0532:             * <li> pattern = { 'N', 'u', 'P', 'o', 'E', 'x' }
0533:             * patternStart = 0
0534:             * patternEnd = 6
0535:             * name = { 'N', 'o', 'P', 'e', 'r', 'm', 'i', 's', 's', 'i', 'o', 'n', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0536:             * nameStart = 0
0537:             * nameEnd = 21
0538:             * result => false</li>
0539:             * <li> pattern = { 'n', p', 'e' }
0540:             * patternStart = 0
0541:             * patternEnd = 3
0542:             * name = { 'N', 'u','l', 'l', 'P', 'o', 'i', 'n', 't', 'e', 'r', 'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n' }
0543:             * nameStart = 0
0544:             * nameEnd = 20
0545:             * result => false</li>
0546:             * <li> pattern = { 'I', 'P', 'L', '3' }
0547:             * patternStart = 0
0548:             * patternEnd = 4
0549:             * name = { 'I', 'P', 'e', 'r', 's', 'p', 'e', 'c', 't', 'i', 'v', 'e', 'L', 'i', 's', 't', 'e', 'n', 'e', 'r', '3' }
0550:             * nameStart = 0
0551:             * nameEnd = 21
0552:             * result => true</li>
0553:             * <li> pattern = { 'H', M' }
0554:             * patternStart = 0
0555:             * patternEnd = 2
0556:             * name = { 'H', 'a', 's', 'h', 'M', 'a', 'p', 'E', 'n', 't', 'r', 'y' }
0557:             * nameStart = 0
0558:             * nameEnd = 12
0559:             * result => (exactMode == false)</li>
0560:             * <li> pattern = { 'H', M', 'a', 'p' }
0561:             * patternStart = 0
0562:             * patternEnd = 4
0563:             * name = { 'H', 'a', 't', 'M', 'a', 'p', 'p', 'e', 'r' }
0564:             * nameStart = 0
0565:             * nameEnd = 9
0566:             * result => (exactMode == false)</li>
0567:             * </ol>
0568:             * </pre>
0569:             * 
0570:             * @param pattern the given pattern
0571:             * @param patternStart the start index of the pattern, inclusive
0572:             * @param patternEnd the end index of the pattern, exclusive
0573:             * @param name the given name
0574:             * @param nameStart the start index of the name, inclusive
0575:             * @param nameEnd the end index of the name, exclusive
0576:             * @param prefixMatch flag telling whether the pattern can match name prefix or not.
0577:             * 	<ul>
0578:             * 		<li>For example, when it's <code>true</code>:<br>
0579:             * 			- 'HM' type string pattern will match  'HashMap' and 'HtmlMapper' types,
0580:             * 			  but not 'HashMapEntry'<br>
0581:             * 			- 'HMap' type string pattern will match  'HashMap' type but not 'HtmlMapper'.
0582:             * 		</li>
0583:             * 		<li>and, when it's <code>false</code>:<br>
0584:             * 			- 'HM' type string pattern will match both   'HashMap' and 'HtmlMapper'
0585:             * 			  and 'HashMapEntry'<br>
0586:             * 			- 'HMap' type string pattern will match both 'HashMap' and 'HtmlMapper'
0587:             * 			  types.
0588:             * 		</li>
0589:             * 	</ul>
0590:             * @return true if a sub-pattern matches the sub-part of the given name, false otherwise
0591:             * @since 3.4
0592:             */
0593:            public static final boolean camelCaseMatch(char[] pattern,
0594:                    int patternStart, int patternEnd, char[] name,
0595:                    int nameStart, int nameEnd, boolean prefixMatch) {
0596:                if (name == null)
0597:                    return false; // null name cannot match
0598:                if (pattern == null)
0599:                    return true; // null pattern is equivalent to '*'
0600:                if (patternEnd < 0)
0601:                    patternEnd = pattern.length;
0602:                if (nameEnd < 0)
0603:                    nameEnd = name.length;
0604:
0605:                if (patternEnd <= patternStart)
0606:                    return nameEnd <= nameStart;
0607:                if (nameEnd <= nameStart)
0608:                    return false;
0609:                // check first pattern char
0610:                if (name[nameStart] != pattern[patternStart]) {
0611:                    // first char must strictly match (upper/lower)
0612:                    return false;
0613:                }
0614:
0615:                char patternChar, nameChar;
0616:                int iPattern = patternStart;
0617:                int iName = nameStart;
0618:
0619:                // Main loop is on pattern characters
0620:                while (true) {
0621:
0622:                    iPattern++;
0623:                    iName++;
0624:
0625:                    if (iPattern == patternEnd) { // we have exhausted pattern...
0626:                        // it's a match if not exact mode or name is also exhausted
0627:                        if (prefixMatch || iName == nameEnd)
0628:                            return true;
0629:
0630:                        // it's not a match if last pattern character is a lowercase
0631:                        if ((patternChar = pattern[iPattern - 1]) < ScannerHelper.MAX_OBVIOUS) {
0632:                            if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_DIGIT)) == 0) {
0633:                                return false;
0634:                            }
0635:                        } else if (Character.isJavaIdentifierPart(patternChar)
0636:                                && !Character.isUpperCase(patternChar)
0637:                                && !Character.isDigit(patternChar)) {
0638:                            return false;
0639:                        }
0640:
0641:                        // it's a match only if name has no more uppercase characters (exact mode)
0642:                        while (true) {
0643:                            if (iName == nameEnd) {
0644:                                // we have exhausted name, so it's a match
0645:                                return true;
0646:                            }
0647:                            nameChar = name[iName];
0648:                            if (nameChar < ScannerHelper.MAX_OBVIOUS) {
0649:                                if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar] & ScannerHelper.C_UPPER_LETTER) != 0) {
0650:                                    // nameChar is uppercase, so it's not a match
0651:                                    return false;
0652:                                }
0653:                            } else if (!Character
0654:                                    .isJavaIdentifierPart(nameChar)
0655:                                    || Character.isUpperCase(nameChar)) {
0656:                                return false;
0657:                            }
0658:                            iName++;
0659:                        }
0660:                    }
0661:
0662:                    if (iName == nameEnd) {
0663:                        // We have exhausted name (and not pattern), so it's not a match 
0664:                        return false;
0665:                    }
0666:
0667:                    // For as long as we're exactly matching, bring it on (even if it's a lower case character)
0668:                    if ((patternChar = pattern[iPattern]) == name[iName]) {
0669:                        continue;
0670:                    }
0671:
0672:                    // If characters are not equals, then it's not a match if patternChar is lowercase
0673:                    if (patternChar < ScannerHelper.MAX_OBVIOUS) {
0674:                        if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[patternChar] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_DIGIT)) == 0) {
0675:                            return false;
0676:                        }
0677:                    } else if (Character.isJavaIdentifierPart(patternChar)
0678:                            && !Character.isUpperCase(patternChar)
0679:                            && !Character.isDigit(patternChar)) {
0680:                        return false;
0681:                    }
0682:
0683:                    // patternChar is uppercase, so let's find the next uppercase in name
0684:                    while (true) {
0685:                        if (iName == nameEnd) {
0686:                            //	We have exhausted name (and not pattern), so it's not a match
0687:                            return false;
0688:                        }
0689:
0690:                        nameChar = name[iName];
0691:                        if (nameChar < ScannerHelper.MAX_OBVIOUS) {
0692:                            int charNature = ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[nameChar];
0693:                            if ((charNature & (ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_SPECIAL)) != 0) {
0694:                                // nameChar is lowercase    
0695:                                iName++;
0696:                            } else if ((charNature & ScannerHelper.C_DIGIT) != 0) {
0697:                                // nameChar is digit => break if the digit is current pattern character otherwise consume it
0698:                                if (patternChar == nameChar)
0699:                                    break;
0700:                                iName++;
0701:                                // nameChar is uppercase...
0702:                            } else if (patternChar != nameChar) {
0703:                                //.. and it does not match patternChar, so it's not a match
0704:                                return false;
0705:                            } else {
0706:                                //.. and it matched patternChar. Back to the big loop
0707:                                break;
0708:                            }
0709:                        }
0710:                        // Same tests for non-obvious characters
0711:                        else if (Character.isJavaIdentifierPart(nameChar)
0712:                                && !Character.isUpperCase(nameChar)) {
0713:                            iName++;
0714:                        } else if (Character.isDigit(nameChar)) {
0715:                            if (patternChar == nameChar)
0716:                                break;
0717:                            iName++;
0718:                        } else if (patternChar != nameChar) {
0719:                            return false;
0720:                        } else {
0721:                            break;
0722:                        }
0723:                    }
0724:                    // At this point, either name has been exhausted, or it is at an uppercase letter.
0725:                    // Since pattern is also at an uppercase letter
0726:                }
0727:            }
0728:
0729:            /**
0730:             * Returns the char arrays as an array of Strings
0731:             * 
0732:             * @param charArrays the char array to convert
0733:             * @return the char arrays as an array of Strings or null if the given char arrays is null.
0734:             * @since 3.0
0735:             */
0736:            public static String[] charArrayToStringArray(char[][] charArrays) {
0737:                if (charArrays == null)
0738:                    return null;
0739:                int length = charArrays.length;
0740:                if (length == 0)
0741:                    return NO_STRINGS;
0742:                String[] strings = new String[length];
0743:                for (int i = 0; i < length; i++)
0744:                    strings[i] = new String(charArrays[i]);
0745:                return strings;
0746:            }
0747:
0748:            /**
0749:             * Returns the char array as a String
0750:
0751:             * @param charArray the char array to convert
0752:             * @return the char array as a String or null if the given char array is null.
0753:             * @since 3.0
0754:             */
0755:            public static String charToString(char[] charArray) {
0756:                if (charArray == null)
0757:                    return null;
0758:                return new String(charArray);
0759:            }
0760:
0761:            /**
0762:             * Answers a new array adding the second array at the end of first array.
0763:             * It answers null if the first and second are null.
0764:             * If the first array is null, then a new array char[][] is created with second.
0765:             * If the second array is null, then the first array is returned.
0766:             * <br>
0767:             * <br>
0768:             * For example:
0769:             * <ol>
0770:             * <li><pre>
0771:             *    first = null
0772:             *    second = { 'a' }
0773:             *    => result = { { ' a' } }
0774:             * </pre>
0775:             * <li><pre>
0776:             *    first = { { ' a' } }
0777:             *    second = null
0778:             *    => result = { { ' a' } }
0779:             * </pre>
0780:             * </li>
0781:             * <li><pre>
0782:             *    first = { { ' a' } }
0783:             *    second = { ' b' }
0784:             *    => result = { { ' a' } , { ' b' } }
0785:             * </pre>
0786:             * </li>
0787:             * </ol>
0788:             * 
0789:             * @param first the first array to concatenate
0790:             * @param second the array to add at the end of the first array
0791:             * @return a new array adding the second array at the end of first array, or null if the two arrays are null.
0792:             */
0793:            public static final char[][] arrayConcat(char[][] first,
0794:                    char[] second) {
0795:                if (second == null)
0796:                    return first;
0797:                if (first == null)
0798:                    return new char[][] { second };
0799:
0800:                int length = first.length;
0801:                char[][] result = new char[length + 1][];
0802:                System.arraycopy(first, 0, result, 0, length);
0803:                result[length] = second;
0804:                return result;
0805:            }
0806:
0807:            /**
0808:             * Compares the two char arrays lexicographically.
0809:             *
0810:             * Returns a negative integer if array1 lexicographically precedes the array2,
0811:             * a positive integer if this array1 lexicographically follows the array2, or 
0812:             * zero if both arrays are equal. 
0813:             * 
0814:             * @param array1 the first given array
0815:             * @param array2 the second given array
0816:             * @return the returned value of the comparison between array1 and array2
0817:             * @throws NullPointerException if one of the arrays is null
0818:             * @since 3.3
0819:             */
0820:            public static final int compareTo(char[] array1, char[] array2) {
0821:                int length1 = array1.length;
0822:                int length2 = array2.length;
0823:                int min = Math.min(length1, length2);
0824:                for (int i = 0; i < min; i++) {
0825:                    if (array1[i] != array2[i]) {
0826:                        return array1[i] - array2[i];
0827:                    }
0828:                }
0829:                return length1 - length2;
0830:            }
0831:
0832:            /**
0833:             * Compares the contents of the two arrays array and prefix. Returns
0834:             * <ul>
0835:             * <li>zero if the array starts with the prefix contents</li>
0836:             * <li>the difference between the first two characters that are not equal </li>
0837:             * <li>one if array length is lower than the prefix length and that the prefix starts with the 
0838:             * array contents.</li>
0839:             * </ul>
0840:             * <p>
0841:             * For example:
0842:             * <ol>
0843:             * <li><pre>
0844:             *    array = null
0845:             *    prefix = null
0846:             *    => result = NullPointerException
0847:             * </pre>
0848:             * </li>
0849:             * <li><pre>
0850:             *    array = { 'a', 'b', 'c', 'd', 'e' }
0851:             *    prefix = { 'a', 'b', 'c'}
0852:             *    => result = 0
0853:             * </pre>
0854:             * </li>
0855:             * <li><pre>
0856:             *    array = { 'a', 'b', 'c', 'd', 'e' }
0857:             *    prefix = { 'a', 'B', 'c'}
0858:             *    => result = 32
0859:             * </pre>
0860:             * </li>
0861:             * <li><pre>
0862:             *    array = { 'd', 'b', 'c', 'd', 'e' }
0863:             *    prefix = { 'a', 'b', 'c'}
0864:             *    => result = 3
0865:             * </pre>
0866:             * </li>
0867:             * <li><pre>
0868:             *    array = { 'a', 'b', 'c', 'd', 'e' }
0869:             *    prefix = { 'd', 'b', 'c'}
0870:             *    => result = -3
0871:             * </pre>
0872:             * </li>
0873:             * <li><pre>
0874:             *    array = { 'a', 'a', 'c', 'd', 'e' }
0875:             *    prefix = { 'a', 'e', 'c'}
0876:             *    => result = -4
0877:             * </pre>
0878:             * </li>
0879:             * </ol>
0880:             * </p>
0881:             * 
0882:             * @param array the given array
0883:             * @param prefix the given prefix
0884:             * @return the result of the comparison (>=0 if array>prefix)
0885:             * @throws NullPointerException if either array or prefix is null
0886:             */
0887:            public static final int compareWith(char[] array, char[] prefix) {
0888:                int arrayLength = array.length;
0889:                int prefixLength = prefix.length;
0890:                int min = Math.min(arrayLength, prefixLength);
0891:                int i = 0;
0892:                while (min-- != 0) {
0893:                    char c1 = array[i];
0894:                    char c2 = prefix[i++];
0895:                    if (c1 != c2)
0896:                        return c1 - c2;
0897:                }
0898:                if (prefixLength == i)
0899:                    return 0;
0900:                return -1; // array is shorter than prefix (e.g. array:'ab' < prefix:'abc').
0901:            }
0902:
0903:            /**
0904:             * Answers the concatenation of the two arrays. It answers null if the two arrays are null.
0905:             * If the first array is null, then the second array is returned.
0906:             * If the second array is null, then the first array is returned.
0907:             * <br>
0908:             * <br>
0909:             * For example:
0910:             * <ol>
0911:             * <li><pre>
0912:             *    first = null
0913:             *    second = { 'a' }
0914:             *    => result = { ' a' }
0915:             * </pre>
0916:             * </li>
0917:             * <li><pre>
0918:             *    first = { ' a' }
0919:             *    second = null
0920:             *    => result = { ' a' }
0921:             * </pre>
0922:             * </li>
0923:             * <li><pre>
0924:             *    first = { ' a' }
0925:             *    second = { ' b' }
0926:             *    => result = { ' a' , ' b' }
0927:             * </pre>
0928:             * </li>
0929:             * </ol>
0930:             * 
0931:             * @param first the first array to concatenate
0932:             * @param second the second array to concatenate
0933:             * @return the concatenation of the two arrays, or null if the two arrays are null.
0934:             */
0935:            public static final char[] concat(char[] first, char[] second) {
0936:                if (first == null)
0937:                    return second;
0938:                if (second == null)
0939:                    return first;
0940:
0941:                int length1 = first.length;
0942:                int length2 = second.length;
0943:                char[] result = new char[length1 + length2];
0944:                System.arraycopy(first, 0, result, 0, length1);
0945:                System.arraycopy(second, 0, result, length1, length2);
0946:                return result;
0947:            }
0948:
0949:            /**
0950:             * Answers the concatenation of the three arrays. It answers null if the three arrays are null.
0951:             * If first is null, it answers the concatenation of second and third.
0952:             * If second is null, it answers the concatenation of first and third.
0953:             * If third is null, it answers the concatenation of first and second.
0954:             * <br>
0955:             * <br>
0956:             * For example:
0957:             * <ol>
0958:             * <li><pre>
0959:             *    first = null
0960:             *    second = { 'a' }
0961:             *    third = { 'b' }
0962:             *    => result = { ' a', 'b' }
0963:             * </pre>
0964:             * </li>
0965:             * <li><pre>
0966:             *    first = { 'a' }
0967:             *    second = null
0968:             *    third = { 'b' }
0969:             *    => result = { ' a', 'b' }
0970:             * </pre>
0971:             * </li>
0972:             * <li><pre>
0973:             *    first = { 'a' }
0974:             *    second = { 'b' }
0975:             *    third = null
0976:             *    => result = { ' a', 'b' }
0977:             * </pre>
0978:             * </li>
0979:             * <li><pre>
0980:             *    first = null
0981:             *    second = null
0982:             *    third = null
0983:             *    => result = null
0984:             * </pre>
0985:             * </li>
0986:             * <li><pre>
0987:             *    first = { 'a' }
0988:             *    second = { 'b' }
0989:             *    third = { 'c' }
0990:             *    => result = { 'a', 'b', 'c' }
0991:             * </pre>
0992:             * </li>
0993:             * </ol>
0994:             * 
0995:             * @param first the first array to concatenate
0996:             * @param second the second array to concatenate
0997:             * @param third the third array to concatenate
0998:             * 
0999:             * @return the concatenation of the three arrays, or null if the three arrays are null.
1000:             */
1001:            public static final char[] concat(char[] first, char[] second,
1002:                    char[] third) {
1003:                if (first == null)
1004:                    return concat(second, third);
1005:                if (second == null)
1006:                    return concat(first, third);
1007:                if (third == null)
1008:                    return concat(first, second);
1009:
1010:                int length1 = first.length;
1011:                int length2 = second.length;
1012:                int length3 = third.length;
1013:                char[] result = new char[length1 + length2 + length3];
1014:                System.arraycopy(first, 0, result, 0, length1);
1015:                System.arraycopy(second, 0, result, length1, length2);
1016:                System.arraycopy(third, 0, result, length1 + length2, length3);
1017:                return result;
1018:            }
1019:
1020:            /**
1021:             * Answers the concatenation of the two arrays inserting the separator character between the two arrays.
1022:             * It answers null if the two arrays are null.
1023:             * If the first array is null, then the second array is returned.
1024:             * If the second array is null, then the first array is returned.
1025:             * <br>
1026:             * <br>
1027:             * For example:
1028:             * <ol>
1029:             * <li><pre>
1030:             *    first = null
1031:             *    second = { 'a' }
1032:             *    separator = '/'
1033:             *    => result = { ' a' }
1034:             * </pre>
1035:             * </li>
1036:             * <li><pre>
1037:             *    first = { ' a' }
1038:             *    second = null
1039:             *    separator = '/'
1040:             *    => result = { ' a' }
1041:             * </pre>
1042:             * </li>
1043:             * <li><pre>
1044:             *    first = { ' a' }
1045:             *    second = { ' b' }
1046:             *    separator = '/'
1047:             *    => result = { ' a' , '/', 'b' }
1048:             * </pre>
1049:             * </li>
1050:             * </ol>
1051:             * 
1052:             * @param first the first array to concatenate
1053:             * @param second the second array to concatenate
1054:             * @param separator the character to insert
1055:             * @return the concatenation of the two arrays inserting the separator character 
1056:             * between the two arrays , or null if the two arrays are null.
1057:             */
1058:            public static final char[] concat(char[] first, char[] second,
1059:                    char separator) {
1060:                if (first == null)
1061:                    return second;
1062:                if (second == null)
1063:                    return first;
1064:
1065:                int length1 = first.length;
1066:                if (length1 == 0)
1067:                    return second;
1068:                int length2 = second.length;
1069:                if (length2 == 0)
1070:                    return first;
1071:
1072:                char[] result = new char[length1 + length2 + 1];
1073:                System.arraycopy(first, 0, result, 0, length1);
1074:                result[length1] = separator;
1075:                System.arraycopy(second, 0, result, length1 + 1, length2);
1076:                return result;
1077:            }
1078:
1079:            /**
1080:             * Answers the concatenation of the three arrays inserting the sep1 character between the 
1081:             * first two arrays and sep2 between the last two.
1082:             * It answers null if the three arrays are null.
1083:             * If the first array is null, then it answers the concatenation of second and third inserting
1084:             * the sep2 character between them.
1085:             * If the second array is null, then it answers the concatenation of first and third inserting
1086:             * the sep1 character between them.
1087:             * If the third array is null, then it answers the concatenation of first and second inserting
1088:             * the sep1 character between them.
1089:             * <br>
1090:             * <br>
1091:             * For example:
1092:             * <ol>
1093:             * <li><pre>
1094:             *    first = null
1095:             *    sep1 = '/'
1096:             *    second = { 'a' }
1097:             *    sep2 = ':'
1098:             *    third = { 'b' }
1099:             *    => result = { ' a' , ':', 'b' }
1100:             * </pre>
1101:             * </li>
1102:             * <li><pre>
1103:             *    first = { 'a' }
1104:             *    sep1 = '/'
1105:             *    second = null
1106:             *    sep2 = ':'
1107:             *    third = { 'b' }
1108:             *    => result = { ' a' , '/', 'b' }
1109:             * </pre>
1110:             * </li>
1111:             * <li><pre>
1112:             *    first = { 'a' }
1113:             *    sep1 = '/'
1114:             *    second = { 'b' }
1115:             *    sep2 = ':'
1116:             *    third = null
1117:             *    => result = { ' a' , '/', 'b' }
1118:             * </pre>
1119:             * </li>
1120:             * <li><pre>
1121:             *    first = { 'a' }
1122:             *    sep1 = '/'
1123:             *    second = { 'b' }
1124:             *    sep2 = ':'
1125:             *    third = { 'c' }
1126:             *    => result = { ' a' , '/', 'b' , ':', 'c' }
1127:             * </pre>
1128:             * </li>
1129:             * </ol>
1130:             * 
1131:             * @param first the first array to concatenate
1132:             * @param sep1 the character to insert
1133:             * @param second the second array to concatenate
1134:             * @param sep2 the character to insert
1135:             * @param third the second array to concatenate
1136:             * @return the concatenation of the three arrays inserting the sep1 character between the 
1137:             * two arrays and sep2 between the last two.
1138:             */
1139:            public static final char[] concat(char[] first, char sep1,
1140:                    char[] second, char sep2, char[] third) {
1141:                if (first == null)
1142:                    return concat(second, third, sep2);
1143:                if (second == null)
1144:                    return concat(first, third, sep1);
1145:                if (third == null)
1146:                    return concat(first, second, sep1);
1147:
1148:                int length1 = first.length;
1149:                int length2 = second.length;
1150:                int length3 = third.length;
1151:                char[] result = new char[length1 + length2 + length3 + 2];
1152:                System.arraycopy(first, 0, result, 0, length1);
1153:                result[length1] = sep1;
1154:                System.arraycopy(second, 0, result, length1 + 1, length2);
1155:                result[length1 + length2 + 1] = sep2;
1156:                System.arraycopy(third, 0, result, length1 + length2 + 2,
1157:                        length3);
1158:                return result;
1159:            }
1160:
1161:            /**
1162:             * Answers a new array with prepending the prefix character and appending the suffix 
1163:             * character at the end of the array. If array is null, it answers a new array containing the 
1164:             * prefix and the suffix characters.
1165:             * <br>
1166:             * <br>
1167:             * For example:<br>
1168:             * <ol>
1169:             * <li><pre>
1170:             *    prefix = 'a'
1171:             *    array = { 'b' }
1172:             *    suffix = 'c'
1173:             *    => result = { 'a', 'b' , 'c' }
1174:             * </pre>
1175:             * </li>
1176:             * <li><pre>
1177:             *    prefix = 'a'
1178:             *    array = null
1179:             *    suffix = 'c'
1180:             *    => result = { 'a', 'c' }
1181:             * </pre></li>
1182:             * </ol>
1183:             * 
1184:             * @param prefix the prefix character
1185:             * @param array the array that is concatenated with the prefix and suffix characters
1186:             * @param suffix the suffix character
1187:             * @return the new array
1188:             */
1189:            public static final char[] concat(char prefix, char[] array,
1190:                    char suffix) {
1191:                if (array == null)
1192:                    return new char[] { prefix, suffix };
1193:
1194:                int length = array.length;
1195:                char[] result = new char[length + 2];
1196:                result[0] = prefix;
1197:                System.arraycopy(array, 0, result, 1, length);
1198:                result[length + 1] = suffix;
1199:                return result;
1200:            }
1201:
1202:            /**
1203:             * Answers the concatenation of the given array parts using the given separator between each
1204:             * part and appending the given name at the end.
1205:             * <br>
1206:             * <br>
1207:             * For example:<br>
1208:             * <ol>
1209:             * <li><pre>
1210:             *    name = { 'c' }
1211:             *    array = { { 'a' }, { 'b' } }
1212:             *    separator = '.'
1213:             *    => result = { 'a', '.', 'b' , '.', 'c' }
1214:             * </pre>
1215:             * </li>
1216:             * <li><pre>
1217:             *    name = null
1218:             *    array = { { 'a' }, { 'b' } }
1219:             *    separator = '.'
1220:             *    => result = { 'a', '.', 'b' }
1221:             * </pre></li>
1222:             * <li><pre>
1223:             *    name = { ' c' }
1224:             *    array = null
1225:             *    separator = '.'
1226:             *    => result = { 'c' }
1227:             * </pre></li>
1228:             * </ol>
1229:             * 
1230:             * @param name the given name
1231:             * @param array the given array
1232:             * @param separator the given separator
1233:             * @return the concatenation of the given array parts using the given separator between each
1234:             * part and appending the given name at the end
1235:             */
1236:            public static final char[] concatWith(char[] name, char[][] array,
1237:                    char separator) {
1238:                int nameLength = name == null ? 0 : name.length;
1239:                if (nameLength == 0)
1240:                    return concatWith(array, separator);
1241:
1242:                int length = array == null ? 0 : array.length;
1243:                if (length == 0)
1244:                    return name;
1245:
1246:                int size = nameLength;
1247:                int index = length;
1248:                while (--index >= 0)
1249:                    if (array[index].length > 0)
1250:                        size += array[index].length + 1;
1251:                char[] result = new char[size];
1252:                index = size;
1253:                for (int i = length - 1; i >= 0; i--) {
1254:                    int subLength = array[i].length;
1255:                    if (subLength > 0) {
1256:                        index -= subLength;
1257:                        System.arraycopy(array[i], 0, result, index, subLength);
1258:                        result[--index] = separator;
1259:                    }
1260:                }
1261:                System.arraycopy(name, 0, result, 0, nameLength);
1262:                return result;
1263:            }
1264:
1265:            /**
1266:             * Answers the concatenation of the given array parts using the given separator between each
1267:             * part and appending the given name at the end.
1268:             * <br>
1269:             * <br>
1270:             * For example:<br>
1271:             * <ol>
1272:             * <li><pre>
1273:             *    name = { 'c' }
1274:             *    array = { { 'a' }, { 'b' } }
1275:             *    separator = '.'
1276:             *    => result = { 'a', '.', 'b' , '.', 'c' }
1277:             * </pre>
1278:             * </li>
1279:             * <li><pre>
1280:             *    name = null
1281:             *    array = { { 'a' }, { 'b' } }
1282:             *    separator = '.'
1283:             *    => result = { 'a', '.', 'b' }
1284:             * </pre></li>
1285:             * <li><pre>
1286:             *    name = { ' c' }
1287:             *    array = null
1288:             *    separator = '.'
1289:             *    => result = { 'c' }
1290:             * </pre></li>
1291:             * </ol>
1292:             * 
1293:             * @param array the given array
1294:             * @param name the given name
1295:             * @param separator the given separator
1296:             * @return the concatenation of the given array parts using the given separator between each
1297:             * part and appending the given name at the end
1298:             */
1299:            public static final char[] concatWith(char[][] array, char[] name,
1300:                    char separator) {
1301:                int nameLength = name == null ? 0 : name.length;
1302:                if (nameLength == 0)
1303:                    return concatWith(array, separator);
1304:
1305:                int length = array == null ? 0 : array.length;
1306:                if (length == 0)
1307:                    return name;
1308:
1309:                int size = nameLength;
1310:                int index = length;
1311:                while (--index >= 0)
1312:                    if (array[index].length > 0)
1313:                        size += array[index].length + 1;
1314:                char[] result = new char[size];
1315:                index = 0;
1316:                for (int i = 0; i < length; i++) {
1317:                    int subLength = array[i].length;
1318:                    if (subLength > 0) {
1319:                        System.arraycopy(array[i], 0, result, index, subLength);
1320:                        index += subLength;
1321:                        result[index++] = separator;
1322:                    }
1323:                }
1324:                System.arraycopy(name, 0, result, index, nameLength);
1325:                return result;
1326:            }
1327:
1328:            /**
1329:             * Answers the concatenation of the given array parts using the given separator between each part.
1330:             * <br>
1331:             * <br>
1332:             * For example:<br>
1333:             * <ol>
1334:             * <li><pre>
1335:             *    array = { { 'a' }, { 'b' } }
1336:             *    separator = '.'
1337:             *    => result = { 'a', '.', 'b' }
1338:             * </pre>
1339:             * </li>
1340:             * <li><pre>
1341:             *    array = null
1342:             *    separator = '.'
1343:             *    => result = { }
1344:             * </pre></li>
1345:             * </ol>
1346:             * 
1347:             * @param array the given array
1348:             * @param separator the given separator
1349:             * @return the concatenation of the given array parts using the given separator between each part
1350:             */
1351:            public static final char[] concatWith(char[][] array, char separator) {
1352:                int length = array == null ? 0 : array.length;
1353:                if (length == 0)
1354:                    return CharOperation.NO_CHAR;
1355:
1356:                int size = length - 1;
1357:                int index = length;
1358:                while (--index >= 0) {
1359:                    if (array[index].length == 0)
1360:                        size--;
1361:                    else
1362:                        size += array[index].length;
1363:                }
1364:                if (size <= 0)
1365:                    return CharOperation.NO_CHAR;
1366:                char[] result = new char[size];
1367:                index = length;
1368:                while (--index >= 0) {
1369:                    length = array[index].length;
1370:                    if (length > 0) {
1371:                        System.arraycopy(array[index], 0, result,
1372:                                (size -= length), length);
1373:                        if (--size >= 0)
1374:                            result[size] = separator;
1375:                    }
1376:                }
1377:                return result;
1378:            }
1379:
1380:            /**
1381:             * Answers true if the array contains an occurrence of character, false otherwise.
1382:             * 
1383:             * <br>
1384:             * <br>
1385:             * For example:
1386:             * <ol>
1387:             * <li><pre>
1388:             *    character = 'c'
1389:             *    array = { { ' a' }, { ' b' } }
1390:             *    result => false
1391:             * </pre>
1392:             * </li>
1393:             * <li><pre>
1394:             *    character = 'a'
1395:             *    array = { { ' a' }, { ' b' } }
1396:             *    result => true
1397:             * </pre>
1398:             * </li>
1399:             * </ol>
1400:             * 
1401:             * @param character the character to search
1402:             * @param array the array in which the search is done
1403:             * @return true if the array contains an occurrence of character, false otherwise.
1404:             * @throws NullPointerException if array is null.
1405:             */
1406:            public static final boolean contains(char character, char[][] array) {
1407:                for (int i = array.length; --i >= 0;) {
1408:                    char[] subarray = array[i];
1409:                    for (int j = subarray.length; --j >= 0;)
1410:                        if (subarray[j] == character)
1411:                            return true;
1412:                }
1413:                return false;
1414:            }
1415:
1416:            /**
1417:             * Answers true if the array contains an occurrence of character, false otherwise.
1418:             * 
1419:             * <br>
1420:             * <br>
1421:             * For example:
1422:             * <ol>
1423:             * <li><pre>
1424:             *    character = 'c'
1425:             *    array = { ' b'  }
1426:             *    result => false
1427:             * </pre>
1428:             * </li>
1429:             * <li><pre>
1430:             *    character = 'a'
1431:             *    array = { ' a' , ' b' }
1432:             *    result => true
1433:             * </pre>
1434:             * </li>
1435:             * </ol>
1436:             * 
1437:             * @param character the character to search
1438:             * @param array the array in which the search is done
1439:             * @return true if the array contains an occurrence of character, false otherwise.
1440:             * @throws NullPointerException if array is null.
1441:             */
1442:            public static final boolean contains(char character, char[] array) {
1443:                for (int i = array.length; --i >= 0;)
1444:                    if (array[i] == character)
1445:                        return true;
1446:                return false;
1447:            }
1448:
1449:            /**
1450:             * Answers true if the array contains an occurrence of one of the characters, false otherwise.
1451:             * 
1452:             * <br>
1453:             * <br>
1454:             * For example:
1455:             * <ol>
1456:             * <li><pre>
1457:             *    characters = { 'c', 'd' }
1458:             *    array = { 'a', ' b'  }
1459:             *    result => false
1460:             * </pre>
1461:             * </li>
1462:             * <li><pre>
1463:             *    characters = { 'c', 'd' }
1464:             *    array = { 'a', ' b', 'c'  }
1465:             *    result => true
1466:             * </pre>
1467:             * </li>
1468:             * </ol>
1469:             * 
1470:             * @param characters the characters to search
1471:             * @param array the array in which the search is done
1472:             * @return true if the array contains an occurrence of one of the characters, false otherwise.
1473:             * @throws NullPointerException if array is null.
1474:             * @since 3.1
1475:             */
1476:            public static final boolean contains(char[] characters, char[] array) {
1477:                for (int i = array.length; --i >= 0;)
1478:                    for (int j = characters.length; --j >= 0;)
1479:                        if (array[i] == characters[j])
1480:                            return true;
1481:                return false;
1482:            }
1483:
1484:            /**
1485:             * Answers a deep copy of the toCopy array.
1486:             * 
1487:             * @param toCopy the array to copy
1488:             * @return a deep copy of the toCopy array.
1489:             */
1490:
1491:            public static final char[][] deepCopy(char[][] toCopy) {
1492:                int toCopyLength = toCopy.length;
1493:                char[][] result = new char[toCopyLength][];
1494:                for (int i = 0; i < toCopyLength; i++) {
1495:                    char[] toElement = toCopy[i];
1496:                    int toElementLength = toElement.length;
1497:                    char[] resultElement = new char[toElementLength];
1498:                    System.arraycopy(toElement, 0, resultElement, 0,
1499:                            toElementLength);
1500:                    result[i] = resultElement;
1501:                }
1502:                return result;
1503:            }
1504:
1505:            /**
1506:             * Return true if array ends with the sequence of characters contained in toBeFound, 
1507:             * otherwise false.
1508:             * <br>
1509:             * <br>
1510:             * For example:
1511:             * <ol>
1512:             * <li><pre>
1513:             *    array = { 'a', 'b', 'c', 'd' }
1514:             *    toBeFound = { 'b', 'c' }
1515:             *    result => false
1516:             * </pre>
1517:             * </li>
1518:             * <li><pre>
1519:             *    array = { 'a', 'b', 'c' }
1520:             *    toBeFound = { 'b', 'c' }
1521:             *    result => true
1522:             * </pre>
1523:             * </li>
1524:             * </ol>
1525:             * 
1526:             * @param array the array to check
1527:             * @param toBeFound the array to find
1528:             * @return true if array ends with the sequence of characters contained in toBeFound, 
1529:             * otherwise false.
1530:             * @throws NullPointerException if array is null or toBeFound is null
1531:             */
1532:            public static final boolean endsWith(char[] array, char[] toBeFound) {
1533:                int i = toBeFound.length;
1534:                int j = array.length - i;
1535:
1536:                if (j < 0)
1537:                    return false;
1538:                while (--i >= 0)
1539:                    if (toBeFound[i] != array[i + j])
1540:                        return false;
1541:                return true;
1542:            }
1543:
1544:            /**
1545:             * Answers true if the two arrays are identical character by character, otherwise false.
1546:             * The equality is case sensitive.
1547:             * <br>
1548:             * <br>
1549:             * For example:
1550:             * <ol>
1551:             * <li><pre>
1552:             *    first = null
1553:             *    second = null
1554:             *    result => true
1555:             * </pre>
1556:             * </li>
1557:             * <li><pre>
1558:             *    first = { { } }
1559:             *    second = null
1560:             *    result => false
1561:             * </pre>
1562:             * </li>
1563:             * <li><pre>
1564:             *    first = { { 'a' } }
1565:             *    second = { { 'a' } }
1566:             *    result => true
1567:             * </pre>
1568:             * </li>
1569:             * <li><pre>
1570:             *    first = { { 'A' } }
1571:             *    second = { { 'a' } }
1572:             *    result => false
1573:             * </pre>
1574:             * </li>
1575:             * </ol>
1576:             * @param first the first array
1577:             * @param second the second array
1578:             * @return true if the two arrays are identical character by character, otherwise false
1579:             */
1580:            public static final boolean equals(char[][] first, char[][] second) {
1581:                if (first == second)
1582:                    return true;
1583:                if (first == null || second == null)
1584:                    return false;
1585:                if (first.length != second.length)
1586:                    return false;
1587:
1588:                for (int i = first.length; --i >= 0;)
1589:                    if (!equals(first[i], second[i]))
1590:                        return false;
1591:                return true;
1592:            }
1593:
1594:            /**
1595:             * If isCaseSensite is true, answers true if the two arrays are identical character
1596:             * by character, otherwise false.
1597:             * If it is false, answers true if the two arrays are identical character by 
1598:             * character without checking the case, otherwise false.
1599:             * <br>
1600:             * <br>
1601:             * For example:
1602:             * <ol>
1603:             * <li><pre>
1604:             *    first = null
1605:             *    second = null
1606:             *    isCaseSensitive = true
1607:             *    result => true
1608:             * </pre>
1609:             * </li>
1610:             * <li><pre>
1611:             *    first = { { } }
1612:             *    second = null
1613:             *    isCaseSensitive = true
1614:             *    result => false
1615:             * </pre>
1616:             * </li>
1617:             * <li><pre>
1618:             *    first = { { 'A' } }
1619:             *    second = { { 'a' } }
1620:             *    isCaseSensitive = true
1621:             *    result => false
1622:             * </pre>
1623:             * </li>
1624:             * <li><pre>
1625:             *    first = { { 'A' } }
1626:             *    second = { { 'a' } }
1627:             *    isCaseSensitive = false
1628:             *    result => true
1629:             * </pre>
1630:             * </li>
1631:             * </ol>
1632:             * 
1633:             * @param first the first array
1634:             * @param second the second array
1635:             * @param isCaseSensitive check whether or not the equality should be case sensitive
1636:             * @return true if the two arrays are identical character by character according to the value
1637:             * of isCaseSensitive, otherwise false
1638:             */
1639:            public static final boolean equals(char[][] first, char[][] second,
1640:                    boolean isCaseSensitive) {
1641:
1642:                if (isCaseSensitive) {
1643:                    return equals(first, second);
1644:                }
1645:                if (first == second)
1646:                    return true;
1647:                if (first == null || second == null)
1648:                    return false;
1649:                if (first.length != second.length)
1650:                    return false;
1651:
1652:                for (int i = first.length; --i >= 0;)
1653:                    if (!equals(first[i], second[i], false))
1654:                        return false;
1655:                return true;
1656:            }
1657:
1658:            /**
1659:             * Answers true if the two arrays are identical character by character, otherwise false.
1660:             * The equality is case sensitive.
1661:             * <br>
1662:             * <br>
1663:             * For example:
1664:             * <ol>
1665:             * <li><pre>
1666:             *    first = null
1667:             *    second = null
1668:             *    result => true
1669:             * </pre>
1670:             * </li>
1671:             * <li><pre>
1672:             *    first = { }
1673:             *    second = null
1674:             *    result => false
1675:             * </pre>
1676:             * </li>
1677:             * <li><pre>
1678:             *    first = { 'a' }
1679:             *    second = { 'a' }
1680:             *    result => true
1681:             * </pre>
1682:             * </li>
1683:             * <li><pre>
1684:             *    first = { 'a' }
1685:             *    second = { 'A' }
1686:             *    result => false
1687:             * </pre>
1688:             * </li>
1689:             * </ol>
1690:             * @param first the first array
1691:             * @param second the second array
1692:             * @return true if the two arrays are identical character by character, otherwise false
1693:             */
1694:            public static final boolean equals(char[] first, char[] second) {
1695:                if (first == second)
1696:                    return true;
1697:                if (first == null || second == null)
1698:                    return false;
1699:                if (first.length != second.length)
1700:                    return false;
1701:
1702:                for (int i = first.length; --i >= 0;)
1703:                    if (first[i] != second[i])
1704:                        return false;
1705:                return true;
1706:            }
1707:
1708:            /**
1709:             * Answers true if the first array is identical character by character to a portion of the second array
1710:             * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false.
1711:             * The equality is case sensitive.
1712:             * <br>
1713:             * <br>
1714:             * For example:
1715:             * <ol>
1716:             * <li><pre>
1717:             *    first = null
1718:             *    second = null
1719:             *    secondStart = 0
1720:             *    secondEnd = 0
1721:             *    result => true
1722:             * </pre>
1723:             * </li>
1724:             * <li><pre>
1725:             *    first = { }
1726:             *    second = null
1727:             *    secondStart = 0
1728:             *    secondEnd = 0
1729:             *    result => false
1730:             * </pre>
1731:             * </li>
1732:             * <li><pre>
1733:             *    first = { 'a' }
1734:             *    second = { 'a' }
1735:             *    secondStart = 0
1736:             *    secondEnd = 1
1737:             *    result => true
1738:             * </pre>
1739:             * </li>
1740:             * <li><pre>
1741:             *    first = { 'a' }
1742:             *    second = { 'A' }
1743:             *    secondStart = 0
1744:             *    secondEnd = 1
1745:             *    result => false
1746:             * </pre>
1747:             * </li>
1748:             * </ol>
1749:             * @param first the first array
1750:             * @param second the second array
1751:             * @param secondStart inclusive start position in the second array to compare
1752:             * @param secondEnd exclusive end position in the second array to compare
1753:             * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
1754:             * @since 3.0
1755:             */
1756:            public static final boolean equals(char[] first, char[] second,
1757:                    int secondStart, int secondEnd) {
1758:                return equals(first, second, secondStart, secondEnd, true);
1759:            }
1760:
1761:            /**
1762:             * <p>Answers true if the first array is identical character by character to a portion of the second array
1763:             * delimited from position secondStart (inclusive) to secondEnd(exclusive), otherwise false. The equality could be either 
1764:             * case sensitive or case insensitive according to the value of the <code>isCaseSensitive</code> parameter.
1765:             * </p>
1766:             * <p>For example:</p>
1767:             * <ol>
1768:             * <li><pre>
1769:             *    first = null
1770:             *    second = null
1771:             *    secondStart = 0
1772:             *    secondEnd = 0
1773:             *    isCaseSensitive = false
1774:             *    result => true
1775:             * </pre>
1776:             * </li>
1777:             * <li><pre>
1778:             *    first = { }
1779:             *    second = null
1780:             *    secondStart = 0
1781:             *    secondEnd = 0
1782:             *    isCaseSensitive = false
1783:             *    result => false
1784:             * </pre>
1785:             * </li>
1786:             * <li><pre>
1787:             *    first = { 'a' }
1788:             *    second = { 'a' }
1789:             *    secondStart = 0
1790:             *    secondEnd = 1
1791:             *    isCaseSensitive = true
1792:             *    result => true
1793:             * </pre>
1794:             * </li>
1795:             * <li><pre>
1796:             *    first = { 'a' }
1797:             *    second = { 'A' }
1798:             *    secondStart = 0
1799:             *    secondEnd = 1
1800:             *    isCaseSensitive = true
1801:             *    result => false
1802:             * </pre>
1803:             * </li>
1804:             * <li><pre>
1805:             *    first = { 'a' }
1806:             *    second = { 'A' }
1807:             *    secondStart = 0
1808:             *    secondEnd = 1
1809:             *    isCaseSensitive = false
1810:             *    result => true
1811:             * </pre>
1812:             * </li>
1813:             * </ol>
1814:             * @param first the first array
1815:             * @param second the second array
1816:             * @param secondStart inclusive start position in the second array to compare
1817:             * @param secondEnd exclusive end position in the second array to compare
1818:             * @param isCaseSensitive check whether or not the equality should be case sensitive
1819:             * @return true if the first array is identical character by character to fragment of second array ranging from secondStart to secondEnd-1, otherwise false
1820:             * @since 3.2
1821:             */
1822:            public static final boolean equals(char[] first, char[] second,
1823:                    int secondStart, int secondEnd, boolean isCaseSensitive) {
1824:                if (first == second)
1825:                    return true;
1826:                if (first == null || second == null)
1827:                    return false;
1828:                if (first.length != secondEnd - secondStart)
1829:                    return false;
1830:                if (isCaseSensitive) {
1831:                    for (int i = first.length; --i >= 0;)
1832:                        if (first[i] != second[i + secondStart])
1833:                            return false;
1834:                } else {
1835:                    for (int i = first.length; --i >= 0;)
1836:                        if (ScannerHelper.toLowerCase(first[i]) != ScannerHelper
1837:                                .toLowerCase(second[i + secondStart]))
1838:                            return false;
1839:                }
1840:                return true;
1841:            }
1842:
1843:            /**
1844:             * If isCaseSensite is true, answers true if the two arrays are identical character
1845:             * by character, otherwise false.
1846:             * If it is false, answers true if the two arrays are identical character by 
1847:             * character without checking the case, otherwise false.
1848:             * <br>
1849:             * <br>
1850:             * For example:
1851:             * <ol>
1852:             * <li><pre>
1853:             *    first = null
1854:             *    second = null
1855:             *    isCaseSensitive = true
1856:             *    result => true
1857:             * </pre>
1858:             * </li>
1859:             * <li><pre>
1860:             *    first = { }
1861:             *    second = null
1862:             *    isCaseSensitive = true
1863:             *    result => false
1864:             * </pre>
1865:             * </li>
1866:             * <li><pre>
1867:             *    first = { 'A' }
1868:             *    second = { 'a' }
1869:             *    isCaseSensitive = true
1870:             *    result => false
1871:             * </pre>
1872:             * </li>
1873:             * <li><pre>
1874:             *    first = { 'A' }
1875:             *    second = { 'a' }
1876:             *    isCaseSensitive = false
1877:             *    result => true
1878:             * </pre>
1879:             * </li>
1880:             * </ol>
1881:             * 
1882:             * @param first the first array
1883:             * @param second the second array
1884:             * @param isCaseSensitive check whether or not the equality should be case sensitive
1885:             * @return true if the two arrays are identical character by character according to the value
1886:             * of isCaseSensitive, otherwise false
1887:             */
1888:            public static final boolean equals(char[] first, char[] second,
1889:                    boolean isCaseSensitive) {
1890:
1891:                if (isCaseSensitive) {
1892:                    return equals(first, second);
1893:                }
1894:                if (first == second)
1895:                    return true;
1896:                if (first == null || second == null)
1897:                    return false;
1898:                if (first.length != second.length)
1899:                    return false;
1900:
1901:                for (int i = first.length; --i >= 0;)
1902:                    if (ScannerHelper.toLowerCase(first[i]) != ScannerHelper
1903:                            .toLowerCase(second[i]))
1904:                        return false;
1905:                return true;
1906:            }
1907:
1908:            /**
1909:             * If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive.
1910:             * 
1911:             * Answers true if the name contains the fragment at the starting index startIndex, otherwise false.
1912:             * <br>
1913:             * <br>
1914:             * For example:
1915:             * <ol>
1916:             * <li><pre>
1917:             *    fragment = { 'b', 'c' , 'd' }
1918:             *    name = { 'a', 'b', 'c' , 'd' }
1919:             *    startIndex = 1
1920:             *    isCaseSensitive = true
1921:             *    result => true
1922:             * </pre>
1923:             * </li>
1924:             * <li><pre>
1925:             *    fragment = { 'b', 'c' , 'd' }
1926:             *    name = { 'a', 'b', 'C' , 'd' }
1927:             *    startIndex = 1
1928:             *    isCaseSensitive = true
1929:             *    result => false
1930:             * </pre>
1931:             * </li>
1932:             * <li><pre>
1933:             *    fragment = { 'b', 'c' , 'd' }
1934:             *    name = { 'a', 'b', 'C' , 'd' }
1935:             *    startIndex = 0
1936:             *    isCaseSensitive = false
1937:             *    result => false
1938:             * </pre>
1939:             * </li>
1940:             * <li><pre>
1941:             *    fragment = { 'b', 'c' , 'd' }
1942:             *    name = { 'a', 'b'}
1943:             *    startIndex = 0
1944:             *    isCaseSensitive = true
1945:             *    result => false
1946:             * </pre>
1947:             * </li>
1948:             * </ol>
1949:             * 
1950:             * @param fragment the fragment to check
1951:             * @param name the array to check
1952:             * @param startIndex the starting index
1953:             * @param isCaseSensitive check whether or not the equality should be case sensitive
1954:             * @return true if the name contains the fragment at the starting index startIndex according to the 
1955:             * value of isCaseSensitive, otherwise false.
1956:             * @throws NullPointerException if fragment or name is null.
1957:             */
1958:            public static final boolean fragmentEquals(char[] fragment,
1959:                    char[] name, int startIndex, boolean isCaseSensitive) {
1960:
1961:                int max = fragment.length;
1962:                if (name.length < max + startIndex)
1963:                    return false;
1964:                if (isCaseSensitive) {
1965:                    for (int i = max; --i >= 0;)
1966:                        // assumes the prefix is not larger than the name
1967:                        if (fragment[i] != name[i + startIndex])
1968:                            return false;
1969:                    return true;
1970:                }
1971:                for (int i = max; --i >= 0;)
1972:                    // assumes the prefix is not larger than the name
1973:                    if (ScannerHelper.toLowerCase(fragment[i]) != ScannerHelper
1974:                            .toLowerCase(name[i + startIndex]))
1975:                        return false;
1976:                return true;
1977:            }
1978:
1979:            /**
1980:             * Answers a hashcode for the array
1981:             * 
1982:             * @param array the array for which a hashcode is required
1983:             * @return the hashcode
1984:             * @throws NullPointerException if array is null
1985:             */
1986:            public static final int hashCode(char[] array) {
1987:                int length = array.length;
1988:                int hash = length == 0 ? 31 : array[0];
1989:                if (length < 8) {
1990:                    for (int i = length; --i > 0;)
1991:                        hash = (hash * 31) + array[i];
1992:                } else {
1993:                    // 8 characters is enough to compute a decent hash code, don't waste time examining every character
1994:                    for (int i = length - 1, last = i > 16 ? i - 16 : 0; i > last; i -= 2)
1995:                        hash = (hash * 31) + array[i];
1996:                }
1997:                return hash & 0x7FFFFFFF;
1998:            }
1999:
2000:            /**
2001:             * Answers true if c is a whitespace according to the JLS (&#92;u000a, &#92;u000c, &#92;u000d, &#92;u0009), otherwise false.
2002:             * <br>
2003:             * <br>
2004:             * For example:
2005:             * <ol>
2006:             * <li><pre>
2007:             *    c = ' '
2008:             *    result => true
2009:             * </pre>
2010:             * </li>
2011:             * <li><pre>
2012:             *    c = '&#92;u3000'
2013:             *    result => false
2014:             * </pre>
2015:             * </li>
2016:             * </ol>
2017:             * 
2018:             * @param c the character to check
2019:             * @return true if c is a whitespace according to the JLS, otherwise false.
2020:             */
2021:            public static boolean isWhitespace(char c) {
2022:                return c < ScannerHelper.MAX_OBVIOUS
2023:                        && ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_JLS_SPACE) != 0);
2024:            }
2025:
2026:            /**
2027:             * Answers the first index in the array for which the corresponding character is
2028:             * equal to toBeFound. Answers -1 if no occurrence of this character is found.
2029:             * <br>
2030:             * <br>
2031:             * For example:
2032:             * <ol>
2033:             * <li><pre>
2034:             *    toBeFound = 'c'
2035:             *    array = { ' a', 'b', 'c', 'd' }
2036:             *    result => 2
2037:             * </pre>
2038:             * </li>
2039:             * <li><pre>
2040:             *    toBeFound = 'e'
2041:             *    array = { ' a', 'b', 'c', 'd' }
2042:             *    result => -1
2043:             * </pre>
2044:             * </li>
2045:             * </ol>
2046:             * 
2047:             * @param toBeFound the character to search
2048:             * @param array the array to be searched
2049:             * @return the first index in the array for which the corresponding character is
2050:             * equal to toBeFound, -1 otherwise
2051:             * @throws NullPointerException if array is null
2052:             */
2053:            public static final int indexOf(char toBeFound, char[] array) {
2054:                return indexOf(toBeFound, array, 0);
2055:            }
2056:
2057:            /**
2058:             * Answers the first index in the array for which the toBeFound array is a matching
2059:             * subarray following the case rule. Answers -1 if no match is found.
2060:             * <br>
2061:             * <br>
2062:             * For example:
2063:             * <ol>
2064:             * <li><pre>
2065:             *    toBeFound = { 'c' }
2066:             *    array = { ' a', 'b', 'c', 'd' }
2067:             *    result => 2
2068:             * </pre>
2069:             * </li>
2070:             * <li><pre>
2071:             *    toBeFound = { 'e' }
2072:             *    array = { ' a', 'b', 'c', 'd' }
2073:             *    result => -1
2074:             * </pre>
2075:             * </li>
2076:             * </ol>
2077:             * 
2078:             * @param toBeFound the subarray to search
2079:             * @param array the array to be searched
2080:             * @param isCaseSensitive flag to know if the matching should be case sensitive
2081:             * @return the first index in the array for which the toBeFound array is a matching
2082:             * subarray following the case rule, -1 otherwise
2083:             * @throws NullPointerException if array is null or toBeFound is null
2084:             * @since 3.2
2085:             */
2086:            public static final int indexOf(char[] toBeFound, char[] array,
2087:                    boolean isCaseSensitive) {
2088:                return indexOf(toBeFound, array, isCaseSensitive, 0);
2089:            }
2090:
2091:            /**
2092:             * Answers the first index in the array for which the toBeFound array is a matching
2093:             * subarray following the case rule starting at the index start. Answers -1 if no match is found.
2094:             * <br>
2095:             * <br>
2096:             * For example:
2097:             * <ol>
2098:             * <li><pre>
2099:             *    toBeFound = { 'c' }
2100:             *    array = { ' a', 'b', 'c', 'd' }
2101:             *    result => 2
2102:             * </pre>
2103:             * </li>
2104:             * <li><pre>
2105:             *    toBeFound = { 'e' }
2106:             *    array = { ' a', 'b', 'c', 'd' }
2107:             *    result => -1
2108:             * </pre>
2109:             * </li>
2110:             * </ol>
2111:             * 
2112:             * @param toBeFound the subarray to search
2113:             * @param array the array to be searched
2114:             * @param isCaseSensitive flag to know if the matching should be case sensitive
2115:             * @param start the starting index 
2116:             * @return the first index in the array for which the toBeFound array is a matching
2117:             * subarray following the case rule starting at the index start, -1 otherwise
2118:             * @throws NullPointerException if array is null or toBeFound is null
2119:             * @since 3.2
2120:             */
2121:            public static final int indexOf(final char[] toBeFound,
2122:                    final char[] array, final boolean isCaseSensitive,
2123:                    final int start) {
2124:                return indexOf(toBeFound, array, isCaseSensitive, start,
2125:                        array.length);
2126:            }
2127:
2128:            /**
2129:             * Answers the first index in the array for which the toBeFound array is a matching
2130:             * subarray following the case rule starting at the index start. Answers -1 if no match is found.
2131:             * <br>
2132:             * <br>
2133:             * For example:
2134:             * <ol>
2135:             * <li><pre>
2136:             *    toBeFound = { 'c' }
2137:             *    array = { ' a', 'b', 'c', 'd' }
2138:             *    result => 2
2139:             * </pre>
2140:             * </li>
2141:             * <li><pre>
2142:             *    toBeFound = { 'e' }
2143:             *    array = { ' a', 'b', 'c', 'd' }
2144:             *    result => -1
2145:             * </pre>
2146:             * </li>
2147:             * </ol>
2148:             * 
2149:             * @param toBeFound the subarray to search
2150:             * @param array the array to be searched
2151:             * @param isCaseSensitive flag to know if the matching should be case sensitive
2152:             * @param start the starting index (inclusive)
2153:             * @param end the end index (exclusive)
2154:             * @return the first index in the array for which the toBeFound array is a matching
2155:             * subarray following the case rule starting at the index start, -1 otherwise
2156:             * @throws NullPointerException if array is null or toBeFound is null
2157:             * @since 3.2
2158:             */
2159:            public static final int indexOf(final char[] toBeFound,
2160:                    final char[] array, final boolean isCaseSensitive,
2161:                    final int start, final int end) {
2162:                final int arrayLength = end;
2163:                final int toBeFoundLength = toBeFound.length;
2164:                if (toBeFoundLength > arrayLength)
2165:                    return -1;
2166:                if (toBeFoundLength == 0)
2167:                    return 0;
2168:                if (toBeFoundLength == arrayLength) {
2169:                    if (isCaseSensitive) {
2170:                        for (int i = start; i < arrayLength; i++) {
2171:                            if (array[i] != toBeFound[i])
2172:                                return -1;
2173:                        }
2174:                        return 0;
2175:                    } else {
2176:                        for (int i = start; i < arrayLength; i++) {
2177:                            if (ScannerHelper.toLowerCase(array[i]) != ScannerHelper
2178:                                    .toLowerCase(toBeFound[i]))
2179:                                return -1;
2180:                        }
2181:                        return 0;
2182:                    }
2183:                }
2184:                if (isCaseSensitive) {
2185:                    arrayLoop: for (int i = start, max = arrayLength
2186:                            - toBeFoundLength + 1; i < max; i++) {
2187:                        if (array[i] == toBeFound[0]) {
2188:                            for (int j = 1; j < toBeFoundLength; j++) {
2189:                                if (array[i + j] != toBeFound[j])
2190:                                    continue arrayLoop;
2191:                            }
2192:                            return i;
2193:                        }
2194:                    }
2195:                } else {
2196:                    arrayLoop: for (int i = start, max = arrayLength
2197:                            - toBeFoundLength + 1; i < max; i++) {
2198:                        if (ScannerHelper.toLowerCase(array[i]) == ScannerHelper
2199:                                .toLowerCase(toBeFound[0])) {
2200:                            for (int j = 1; j < toBeFoundLength; j++) {
2201:                                if (ScannerHelper.toLowerCase(array[i + j]) != ScannerHelper
2202:                                        .toLowerCase(toBeFound[j]))
2203:                                    continue arrayLoop;
2204:                            }
2205:                            return i;
2206:                        }
2207:                    }
2208:                }
2209:                return -1;
2210:            }
2211:
2212:            /**
2213:             * Answers the first index in the array for which the corresponding character is
2214:             * equal to toBeFound starting the search at index start.
2215:             * Answers -1 if no occurrence of this character is found.
2216:             * <br>
2217:             * <br>
2218:             * For example:
2219:             * <ol>
2220:             * <li><pre>
2221:             *    toBeFound = 'c'
2222:             *    array = { ' a', 'b', 'c', 'd' }
2223:             *    start = 2
2224:             *    result => 2
2225:             * </pre>
2226:             * </li>
2227:             * <li><pre>
2228:             *    toBeFound = 'c'
2229:             *    array = { ' a', 'b', 'c', 'd' }
2230:             *    start = 3
2231:             *    result => -1
2232:             * </pre>
2233:             * </li>
2234:             * <li><pre>
2235:             *    toBeFound = 'e'
2236:             *    array = { ' a', 'b', 'c', 'd' }
2237:             *    start = 1
2238:             *    result => -1
2239:             * </pre>
2240:             * </li>
2241:             * </ol>
2242:             * 
2243:             * @param toBeFound the character to search
2244:             * @param array the array to be searched
2245:             * @param start the starting index
2246:             * @return the first index in the array for which the corresponding character is
2247:             * equal to toBeFound, -1 otherwise
2248:             * @throws NullPointerException if array is null
2249:             * @throws ArrayIndexOutOfBoundsException if  start is lower than 0
2250:             */
2251:            public static final int indexOf(char toBeFound, char[] array,
2252:                    int start) {
2253:                for (int i = start; i < array.length; i++)
2254:                    if (toBeFound == array[i])
2255:                        return i;
2256:                return -1;
2257:            }
2258:
2259:            /**
2260:             * Answers the first index in the array for which the corresponding character is
2261:             * equal to toBeFound starting the search at index start and before the ending index.
2262:             * Answers -1 if no occurrence of this character is found.
2263:             * <br>
2264:             * <br>
2265:             * For example:
2266:             * <ol>
2267:             * <li><pre>
2268:             *    toBeFound = 'c'
2269:             *    array = { ' a', 'b', 'c', 'd' }
2270:             *    start = 2
2271:             *    result => 2
2272:             * </pre>
2273:             * </li>
2274:             * <li><pre>
2275:             *    toBeFound = 'c'
2276:             *    array = { ' a', 'b', 'c', 'd' }
2277:             *    start = 3
2278:             *    result => -1
2279:             * </pre>
2280:             * </li>
2281:             * <li><pre>
2282:             *    toBeFound = 'e'
2283:             *    array = { ' a', 'b', 'c', 'd' }
2284:             *    start = 1
2285:             *    result => -1
2286:             * </pre>
2287:             * </li>
2288:             * </ol>
2289:             * 
2290:             * @param toBeFound the character to search
2291:             * @param array the array to be searched
2292:             * @param start the starting index (inclusive)
2293:             * @param end the ending index (exclusive)
2294:             * @return the first index in the array for which the corresponding character is
2295:             * equal to toBeFound, -1 otherwise
2296:             * @throws NullPointerException if array is null
2297:             * @throws ArrayIndexOutOfBoundsException if  start is lower than 0 or ending greater than array length
2298:             * @since 3.2
2299:             */
2300:            public static final int indexOf(char toBeFound, char[] array,
2301:                    int start, int end) {
2302:                for (int i = start; i < end; i++)
2303:                    if (toBeFound == array[i])
2304:                        return i;
2305:                return -1;
2306:            }
2307:
2308:            /**
2309:             * Answers the last index in the array for which the corresponding character is
2310:             * equal to toBeFound starting from the end of the array.
2311:             * Answers -1 if no occurrence of this character is found.
2312:             * <br>
2313:             * <br>
2314:             * For example:
2315:             * <ol>
2316:             * <li><pre>
2317:             *    toBeFound = 'c'
2318:             *    array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
2319:             *    result => 4
2320:             * </pre>
2321:             * </li>
2322:             * <li><pre>
2323:             *    toBeFound = 'e'
2324:             *    array = { ' a', 'b', 'c', 'd' }
2325:             *    result => -1
2326:             * </pre>
2327:             * </li>
2328:             * </ol>
2329:             *
2330:             * @param toBeFound the character to search
2331:             * @param array the array to be searched
2332:             * @return the last index in the array for which the corresponding character is
2333:             * equal to toBeFound starting from the end of the array, -1 otherwise
2334:             * @throws NullPointerException if array is null
2335:             */
2336:            public static final int lastIndexOf(char toBeFound, char[] array) {
2337:                for (int i = array.length; --i >= 0;)
2338:                    if (toBeFound == array[i])
2339:                        return i;
2340:                return -1;
2341:            }
2342:
2343:            /**
2344:             * Answers the last index in the array for which the corresponding character is
2345:             * equal to toBeFound stopping at the index startIndex.
2346:             * Answers -1 if no occurrence of this character is found.
2347:             * <br>
2348:             * <br>
2349:             * For example:
2350:             * <ol>
2351:             * <li><pre>
2352:             *    toBeFound = 'c'
2353:             *    array = { ' a', 'b', 'c', 'd' }
2354:             *    startIndex = 2
2355:             *    result => 2
2356:             * </pre>
2357:             * </li>
2358:             * <li><pre>
2359:             *    toBeFound = 'c'
2360:             *    array = { ' a', 'b', 'c', 'd', 'e' }
2361:             *    startIndex = 3
2362:             *    result => -1
2363:             * </pre>
2364:             * </li>
2365:             * <li><pre>
2366:             *    toBeFound = 'e'
2367:             *    array = { ' a', 'b', 'c', 'd' }
2368:             *    startIndex = 0
2369:             *    result => -1
2370:             * </pre>
2371:             * </li>
2372:             * </ol>
2373:             *
2374:             * @param toBeFound the character to search
2375:             * @param array the array to be searched
2376:             * @param startIndex the stopping index
2377:             * @return the last index in the array for which the corresponding character is
2378:             * equal to toBeFound stopping at the index startIndex, -1 otherwise
2379:             * @throws NullPointerException if array is null
2380:             * @throws ArrayIndexOutOfBoundsException if startIndex is lower than 0
2381:             */
2382:            public static final int lastIndexOf(char toBeFound, char[] array,
2383:                    int startIndex) {
2384:                for (int i = array.length; --i >= startIndex;)
2385:                    if (toBeFound == array[i])
2386:                        return i;
2387:                return -1;
2388:            }
2389:
2390:            /**
2391:             * Answers the last index in the array for which the corresponding character is
2392:             * equal to toBeFound starting from endIndex to startIndex.
2393:             * Answers -1 if no occurrence of this character is found.
2394:             * <br>
2395:             * <br>
2396:             * For example:
2397:             * <ol>
2398:             * <li><pre>
2399:             *    toBeFound = 'c'
2400:             *    array = { ' a', 'b', 'c', 'd' }
2401:             *    startIndex = 2
2402:             *    endIndex = 2
2403:             *    result => 2
2404:             * </pre>
2405:             * </li>
2406:             * <li><pre>
2407:             *    toBeFound = 'c'
2408:             *    array = { ' a', 'b', 'c', 'd', 'e' }
2409:             *    startIndex = 3
2410:             *    endIndex = 4
2411:             *    result => -1
2412:             * </pre>
2413:             * </li>
2414:             * <li><pre>
2415:             *    toBeFound = 'e'
2416:             *    array = { ' a', 'b', 'c', 'd' }
2417:             *    startIndex = 0
2418:             *    endIndex = 3
2419:             *    result => -1
2420:             * </pre>
2421:             * </li>
2422:             * </ol>
2423:             * 
2424:             * @param toBeFound the character to search
2425:             * @param array the array to be searched
2426:             * @param startIndex the stopping index
2427:             * @param endIndex the starting index
2428:             * @return the last index in the array for which the corresponding character is
2429:             * equal to toBeFound starting from endIndex to startIndex, -1 otherwise
2430:             * @throws NullPointerException if array is null
2431:             * @throws ArrayIndexOutOfBoundsException if endIndex is greater or equals to array length or starting is lower than 0
2432:             */
2433:            public static final int lastIndexOf(char toBeFound, char[] array,
2434:                    int startIndex, int endIndex) {
2435:                for (int i = endIndex; --i >= startIndex;)
2436:                    if (toBeFound == array[i])
2437:                        return i;
2438:                return -1;
2439:            }
2440:
2441:            /**
2442:             * Answers the last portion of a name given a separator.
2443:             * <br>
2444:             * <br>
2445:             * For example,
2446:             * <pre>
2447:             * 	lastSegment("java.lang.Object".toCharArray(),'.') --> Object
2448:             * </pre>
2449:             * 
2450:             * @param array the array
2451:             * @param separator the given separator
2452:             * @return the last portion of a name given a separator
2453:             * @throws NullPointerException if array is null
2454:             */
2455:            final static public char[] lastSegment(char[] array, char separator) {
2456:                int pos = lastIndexOf(separator, array);
2457:                if (pos < 0)
2458:                    return array;
2459:                return subarray(array, pos + 1, array.length);
2460:            }
2461:
2462:            /**
2463:             * Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching
2464:             * accepts wild-cards '*' and '?'.
2465:             *
2466:             * When not case sensitive, the pattern is assumed to already be lowercased, the
2467:             * name will be lowercased character per character as comparing.
2468:             * If name is null, the answer is false.
2469:             * If pattern is null, the answer is true if name is not null.
2470:             * <br>
2471:             * <br>
2472:             * For example:
2473:             * <ol>
2474:             * <li><pre>
2475:             *    pattern = { '?', 'b', '*' }
2476:             *    name = { 'a', 'b', 'c' , 'd' }
2477:             *    isCaseSensitive = true
2478:             *    result => true
2479:             * </pre>
2480:             * </li>
2481:             * <li><pre>
2482:             *    pattern = { '?', 'b', '?' }
2483:             *    name = { 'a', 'b', 'c' , 'd' }
2484:             *    isCaseSensitive = true
2485:             *    result => false
2486:             * </pre>
2487:             * </li>
2488:             * <li><pre>
2489:             *    pattern = { 'b', '*' }
2490:             *    name = { 'a', 'b', 'c' , 'd' }
2491:             *    isCaseSensitive = true
2492:             *    result => false
2493:             * </pre>
2494:             * </li>
2495:             * </ol>
2496:             * 
2497:             * @param pattern the given pattern
2498:             * @param name the given name
2499:             * @param isCaseSensitive flag to know whether or not the matching should be case sensitive
2500:             * @return true if the pattern matches the given name, false otherwise
2501:             */
2502:            public static final boolean match(char[] pattern, char[] name,
2503:                    boolean isCaseSensitive) {
2504:
2505:                if (name == null)
2506:                    return false; // null name cannot match
2507:                if (pattern == null)
2508:                    return true; // null pattern is equivalent to '*'
2509:
2510:                return match(pattern, 0, pattern.length, name, 0, name.length,
2511:                        isCaseSensitive);
2512:            }
2513:
2514:            /**
2515:             * Answers true if a sub-pattern matches the subpart of the given name, false otherwise.
2516:             * char[] pattern matching, accepting wild-cards '*' and '?'. Can match only subset of name/pattern.
2517:             * end positions are non-inclusive.
2518:             * The subpattern is defined by the patternStart and pattternEnd positions.
2519:             * When not case sensitive, the pattern is assumed to already be lowercased, the
2520:             * name will be lowercased character per character as comparing.
2521:             * <br>
2522:             * <br>
2523:             * For example:
2524:             * <ol>
2525:             * <li><pre>
2526:             *    pattern = { '?', 'b', '*' }
2527:             *    patternStart = 1
2528:             *    patternEnd = 3
2529:             *    name = { 'a', 'b', 'c' , 'd' }
2530:             *    nameStart = 1
2531:             *    nameEnd = 4
2532:             *    isCaseSensitive = true
2533:             *    result => true
2534:             * </pre>
2535:             * </li>
2536:             * <li><pre>
2537:             *    pattern = { '?', 'b', '*' }
2538:             *    patternStart = 1
2539:             *    patternEnd = 2
2540:             *    name = { 'a', 'b', 'c' , 'd' }
2541:             *    nameStart = 1
2542:             *    nameEnd = 2
2543:             *    isCaseSensitive = true
2544:             *    result => false
2545:             * </pre>
2546:             * </li>
2547:             * </ol>
2548:             * 
2549:             * @param pattern the given pattern
2550:             * @param patternStart the given pattern start
2551:             * @param patternEnd the given pattern end
2552:             * @param name the given name
2553:             * @param nameStart the given name start
2554:             * @param nameEnd the given name end
2555:             * @param isCaseSensitive flag to know if the matching should be case sensitive
2556:             * @return true if a sub-pattern matches the subpart of the given name, false otherwise
2557:             */
2558:            public static final boolean match(char[] pattern, int patternStart,
2559:                    int patternEnd, char[] name, int nameStart, int nameEnd,
2560:                    boolean isCaseSensitive) {
2561:
2562:                if (name == null)
2563:                    return false; // null name cannot match
2564:                if (pattern == null)
2565:                    return true; // null pattern is equivalent to '*'
2566:                int iPattern = patternStart;
2567:                int iName = nameStart;
2568:
2569:                if (patternEnd < 0)
2570:                    patternEnd = pattern.length;
2571:                if (nameEnd < 0)
2572:                    nameEnd = name.length;
2573:
2574:                /* check first segment */
2575:                char patternChar = 0;
2576:                while ((iPattern < patternEnd)
2577:                        && (patternChar = pattern[iPattern]) != '*') {
2578:                    if (iName == nameEnd)
2579:                        return false;
2580:                    if (patternChar != (isCaseSensitive ? name[iName]
2581:                            : ScannerHelper.toLowerCase(name[iName]))
2582:                            && patternChar != '?') {
2583:                        return false;
2584:                    }
2585:                    iName++;
2586:                    iPattern++;
2587:                }
2588:                /* check sequence of star+segment */
2589:                int segmentStart;
2590:                if (patternChar == '*') {
2591:                    segmentStart = ++iPattern; // skip star
2592:                } else {
2593:                    segmentStart = 0; // force iName check
2594:                }
2595:                int prefixStart = iName;
2596:                checkSegment: while (iName < nameEnd) {
2597:                    if (iPattern == patternEnd) {
2598:                        iPattern = segmentStart; // mismatch - restart current segment
2599:                        iName = ++prefixStart;
2600:                        continue checkSegment;
2601:                    }
2602:                    /* segment is ending */
2603:                    if ((patternChar = pattern[iPattern]) == '*') {
2604:                        segmentStart = ++iPattern; // skip start
2605:                        if (segmentStart == patternEnd) {
2606:                            return true;
2607:                        }
2608:                        prefixStart = iName;
2609:                        continue checkSegment;
2610:                    }
2611:                    /* check current name character */
2612:                    if ((isCaseSensitive ? name[iName] : ScannerHelper
2613:                            .toLowerCase(name[iName])) != patternChar
2614:                            && patternChar != '?') {
2615:                        iPattern = segmentStart; // mismatch - restart current segment
2616:                        iName = ++prefixStart;
2617:                        continue checkSegment;
2618:                    }
2619:                    iName++;
2620:                    iPattern++;
2621:                }
2622:
2623:                return (segmentStart == patternEnd)
2624:                        || (iName == nameEnd && iPattern == patternEnd)
2625:                        || (iPattern == patternEnd - 1 && pattern[iPattern] == '*');
2626:            }
2627:
2628:            /**
2629:             * Answers true if the pattern matches the filepath using the pathSepatator, false otherwise.
2630:             * 
2631:             * Path char[] pattern matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks
2632:             * conventions, also see "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes").
2633:             * Path pattern matching is enhancing regular pattern matching in supporting extra rule where '**' represent
2634:             * any folder combination.
2635:             * Special rule: 
2636:             * - foo\  is equivalent to foo\**   
2637:             * When not case sensitive, the pattern is assumed to already be lowercased, the
2638:             * name will be lowercased character per character as comparing.
2639:             * 
2640:             * @param pattern the given pattern
2641:             * @param filepath the given path 
2642:             * @param isCaseSensitive to find out whether or not the matching should be case sensitive
2643:             * @param pathSeparator the given path separator
2644:             * @return true if the pattern matches the filepath using the pathSepatator, false otherwise
2645:             */
2646:            public static final boolean pathMatch(char[] pattern,
2647:                    char[] filepath, boolean isCaseSensitive, char pathSeparator) {
2648:
2649:                if (filepath == null)
2650:                    return false; // null name cannot match
2651:                if (pattern == null)
2652:                    return true; // null pattern is equivalent to '*'
2653:
2654:                // offsets inside pattern
2655:                int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
2656:                int pLength = pattern.length;
2657:                int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
2658:                        pSegmentStart + 1);
2659:                if (pSegmentEnd < 0)
2660:                    pSegmentEnd = pLength;
2661:
2662:                // special case: pattern foo\ is equivalent to foo\**
2663:                boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
2664:
2665:                // offsets inside filepath
2666:                int fSegmentStart, fLength = filepath.length;
2667:                if (filepath[0] != pathSeparator) {
2668:                    fSegmentStart = 0;
2669:                } else {
2670:                    fSegmentStart = 1;
2671:                }
2672:                if (fSegmentStart != pSegmentStart) {
2673:                    return false; // both must start with a separator or none.
2674:                }
2675:                int fSegmentEnd = CharOperation.indexOf(pathSeparator,
2676:                        filepath, fSegmentStart + 1);
2677:                if (fSegmentEnd < 0)
2678:                    fSegmentEnd = fLength;
2679:
2680:                // first segments
2681:                while (pSegmentStart < pLength
2682:                        && !(pSegmentEnd == pLength && freeTrailingDoubleStar || (pSegmentEnd == pSegmentStart + 2
2683:                                && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*'))) {
2684:
2685:                    if (fSegmentStart >= fLength)
2686:                        return false;
2687:                    if (!CharOperation.match(pattern, pSegmentStart,
2688:                            pSegmentEnd, filepath, fSegmentStart, fSegmentEnd,
2689:                            isCaseSensitive)) {
2690:                        return false;
2691:                    }
2692:
2693:                    // jump to next segment		
2694:                    pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
2695:                            pSegmentStart = pSegmentEnd + 1);
2696:                    // skip separator
2697:                    if (pSegmentEnd < 0)
2698:                        pSegmentEnd = pLength;
2699:
2700:                    fSegmentEnd = CharOperation.indexOf(pathSeparator,
2701:                            filepath, fSegmentStart = fSegmentEnd + 1);
2702:                    // skip separator
2703:                    if (fSegmentEnd < 0)
2704:                        fSegmentEnd = fLength;
2705:                }
2706:
2707:                /* check sequence of doubleStar+segment */
2708:                int pSegmentRestart;
2709:                if ((pSegmentStart >= pLength && freeTrailingDoubleStar)
2710:                        || (pSegmentEnd == pSegmentStart + 2
2711:                                && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')) {
2712:                    pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
2713:                            pSegmentStart = pSegmentEnd + 1);
2714:                    // skip separator
2715:                    if (pSegmentEnd < 0)
2716:                        pSegmentEnd = pLength;
2717:                    pSegmentRestart = pSegmentStart;
2718:                } else {
2719:                    if (pSegmentStart >= pLength)
2720:                        return fSegmentStart >= fLength; // true if filepath is done too.
2721:                    pSegmentRestart = 0; // force fSegmentStart check
2722:                }
2723:                int fSegmentRestart = fSegmentStart;
2724:                checkSegment: while (fSegmentStart < fLength) {
2725:
2726:                    if (pSegmentStart >= pLength) {
2727:                        if (freeTrailingDoubleStar)
2728:                            return true;
2729:                        // mismatch - restart current path segment
2730:                        pSegmentEnd = CharOperation.indexOf(pathSeparator,
2731:                                pattern, pSegmentStart = pSegmentRestart);
2732:                        if (pSegmentEnd < 0)
2733:                            pSegmentEnd = pLength;
2734:
2735:                        fSegmentRestart = CharOperation.indexOf(pathSeparator,
2736:                                filepath, fSegmentRestart + 1);
2737:                        // skip separator
2738:                        if (fSegmentRestart < 0) {
2739:                            fSegmentRestart = fLength;
2740:                        } else {
2741:                            fSegmentRestart++;
2742:                        }
2743:                        fSegmentEnd = CharOperation.indexOf(pathSeparator,
2744:                                filepath, fSegmentStart = fSegmentRestart);
2745:                        if (fSegmentEnd < 0)
2746:                            fSegmentEnd = fLength;
2747:                        continue checkSegment;
2748:                    }
2749:
2750:                    /* path segment is ending */
2751:                    if (pSegmentEnd == pSegmentStart + 2
2752:                            && pattern[pSegmentStart] == '*'
2753:                            && pattern[pSegmentStart + 1] == '*') {
2754:                        pSegmentEnd = CharOperation.indexOf(pathSeparator,
2755:                                pattern, pSegmentStart = pSegmentEnd + 1);
2756:                        // skip separator
2757:                        if (pSegmentEnd < 0)
2758:                            pSegmentEnd = pLength;
2759:                        pSegmentRestart = pSegmentStart;
2760:                        fSegmentRestart = fSegmentStart;
2761:                        if (pSegmentStart >= pLength)
2762:                            return true;
2763:                        continue checkSegment;
2764:                    }
2765:                    /* chech current path segment */
2766:                    if (!CharOperation.match(pattern, pSegmentStart,
2767:                            pSegmentEnd, filepath, fSegmentStart, fSegmentEnd,
2768:                            isCaseSensitive)) {
2769:                        // mismatch - restart current path segment
2770:                        pSegmentEnd = CharOperation.indexOf(pathSeparator,
2771:                                pattern, pSegmentStart = pSegmentRestart);
2772:                        if (pSegmentEnd < 0)
2773:                            pSegmentEnd = pLength;
2774:
2775:                        fSegmentRestart = CharOperation.indexOf(pathSeparator,
2776:                                filepath, fSegmentRestart + 1);
2777:                        // skip separator
2778:                        if (fSegmentRestart < 0) {
2779:                            fSegmentRestart = fLength;
2780:                        } else {
2781:                            fSegmentRestart++;
2782:                        }
2783:                        fSegmentEnd = CharOperation.indexOf(pathSeparator,
2784:                                filepath, fSegmentStart = fSegmentRestart);
2785:                        if (fSegmentEnd < 0)
2786:                            fSegmentEnd = fLength;
2787:                        continue checkSegment;
2788:                    }
2789:                    // jump to next segment		
2790:                    pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern,
2791:                            pSegmentStart = pSegmentEnd + 1);
2792:                    // skip separator
2793:                    if (pSegmentEnd < 0)
2794:                        pSegmentEnd = pLength;
2795:
2796:                    fSegmentEnd = CharOperation.indexOf(pathSeparator,
2797:                            filepath, fSegmentStart = fSegmentEnd + 1);
2798:                    // skip separator
2799:                    if (fSegmentEnd < 0)
2800:                        fSegmentEnd = fLength;
2801:                }
2802:
2803:                return (pSegmentRestart >= pSegmentEnd)
2804:                        || (fSegmentStart >= fLength && pSegmentStart >= pLength)
2805:                        || (pSegmentStart == pLength - 2
2806:                                && pattern[pSegmentStart] == '*' && pattern[pSegmentStart + 1] == '*')
2807:                        || (pSegmentStart == pLength && freeTrailingDoubleStar);
2808:            }
2809:
2810:            /**
2811:             * Answers the number of occurrences of the given character in the given array, 0 if any.
2812:             * 
2813:             * <br>
2814:             * <br>
2815:             * For example:
2816:             * <ol>
2817:             * <li><pre>
2818:             *    toBeFound = 'b'
2819:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2820:             *    result => 3
2821:             * </pre>
2822:             * </li>
2823:             * <li><pre>
2824:             *    toBeFound = 'c'
2825:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2826:             *    result => 0
2827:             * </pre>
2828:             * </li>
2829:             * </ol>
2830:             * 
2831:             * @param toBeFound the given character
2832:             * @param array the given array
2833:             * @return the number of occurrences of the given character in the given array, 0 if any
2834:             * @throws NullPointerException if array is null
2835:             */
2836:            public static final int occurencesOf(char toBeFound, char[] array) {
2837:                int count = 0;
2838:                for (int i = 0; i < array.length; i++)
2839:                    if (toBeFound == array[i])
2840:                        count++;
2841:                return count;
2842:            }
2843:
2844:            /**
2845:             * Answers the number of occurrences of the given character in the given array starting
2846:             * at the given index, 0 if any.
2847:             * 
2848:             * <br>
2849:             * <br>
2850:             * For example:
2851:             * <ol>
2852:             * <li><pre>
2853:             *    toBeFound = 'b'
2854:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2855:             *    start = 2
2856:             *    result => 2
2857:             * </pre>
2858:             * </li>
2859:             * <li><pre>
2860:             *    toBeFound = 'c'
2861:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2862:             *    start = 0
2863:             *    result => 0
2864:             * </pre>
2865:             * </li>
2866:             * </ol>
2867:             * 
2868:             * @param toBeFound the given character
2869:             * @param array the given array
2870:             * @param start the given index
2871:             * @return the number of occurrences of the given character in the given array, 0 if any
2872:             * @throws NullPointerException if array is null
2873:             * @throws ArrayIndexOutOfBoundsException if start is lower than 0
2874:             */
2875:            public static final int occurencesOf(char toBeFound, char[] array,
2876:                    int start) {
2877:                int count = 0;
2878:                for (int i = start; i < array.length; i++)
2879:                    if (toBeFound == array[i])
2880:                        count++;
2881:                return count;
2882:            }
2883:
2884:            /**
2885:             * Answers true if the given name starts with the given prefix, false otherwise.
2886:             * The comparison is case sensitive.
2887:             * <br>
2888:             * <br>
2889:             * For example:
2890:             * <ol>
2891:             * <li><pre>
2892:             *    prefix = { 'a' , 'b' }
2893:             *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2894:             *    result => true
2895:             * </pre>
2896:             * </li>
2897:             * <li><pre>
2898:             *    prefix = { 'a' , 'c' }
2899:             *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2900:             *    result => false
2901:             * </pre>
2902:             * </li>
2903:             * </ol>
2904:             * 
2905:             * @param prefix the given prefix
2906:             * @param name the given name
2907:             * @return true if the given name starts with the given prefix, false otherwise
2908:             * @throws NullPointerException if the given name is null or if the given prefix is null
2909:             */
2910:            public static final boolean prefixEquals(char[] prefix, char[] name) {
2911:
2912:                int max = prefix.length;
2913:                if (name.length < max)
2914:                    return false;
2915:                for (int i = max; --i >= 0;)
2916:                    // assumes the prefix is not larger than the name
2917:                    if (prefix[i] != name[i])
2918:                        return false;
2919:                return true;
2920:            }
2921:
2922:            /**
2923:             * Answers true if the given name starts with the given prefix, false otherwise.
2924:             * isCaseSensitive is used to find out whether or not the comparison should be case sensitive.
2925:             * <br>
2926:             * <br>
2927:             * For example:
2928:             * <ol>
2929:             * <li><pre>
2930:             *    prefix = { 'a' , 'B' }
2931:             *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2932:             *    isCaseSensitive = false
2933:             *    result => true
2934:             * </pre>
2935:             * </li>
2936:             * <li><pre>
2937:             *    prefix = { 'a' , 'B' }
2938:             *    name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2939:             *    isCaseSensitive = true
2940:             *    result => false
2941:             * </pre>
2942:             * </li>
2943:             * </ol>
2944:             * 
2945:             * @param prefix the given prefix
2946:             * @param name the given name
2947:             * @param isCaseSensitive to find out whether or not the comparison should be case sensitive
2948:             * @return true if the given name starts with the given prefix, false otherwise
2949:             * @throws NullPointerException if the given name is null or if the given prefix is null
2950:             */
2951:            public static final boolean prefixEquals(char[] prefix,
2952:                    char[] name, boolean isCaseSensitive) {
2953:
2954:                int max = prefix.length;
2955:                if (name.length < max)
2956:                    return false;
2957:                if (isCaseSensitive) {
2958:                    for (int i = max; --i >= 0;)
2959:                        // assumes the prefix is not larger than the name
2960:                        if (prefix[i] != name[i])
2961:                            return false;
2962:                    return true;
2963:                }
2964:
2965:                for (int i = max; --i >= 0;)
2966:                    // assumes the prefix is not larger than the name
2967:                    if (ScannerHelper.toLowerCase(prefix[i]) != ScannerHelper
2968:                            .toLowerCase(name[i]))
2969:                        return false;
2970:                return true;
2971:            }
2972:
2973:            /**
2974:             * Answers a new array removing a given character. Answers the given array if there is
2975:             * no occurrence of the character to remove.
2976:             * <br>
2977:             * <br>
2978:             * For example:
2979:             * <ol>
2980:             * <li><pre>
2981:             *    array = { 'a' , 'b', 'b', 'c', 'b', 'a' }
2982:             *    toBeRemoved = 'b'
2983:             *    return { 'a' , 'c', 'a' }
2984:             * </pre>
2985:             * </li>
2986:             * <li><pre>
2987:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
2988:             *    toBeRemoved = 'c'
2989:             *    return array
2990:             * </pre>
2991:             * </li>
2992:             * </ol>
2993:             * 
2994:             * @param array the given array
2995:             * @param toBeRemoved the character to be removed
2996:             * @return a new array removing given character
2997:             * @since 3.2
2998:             */
2999:            public static final char[] remove(char[] array, char toBeRemoved) {
3000:
3001:                if (array == null)
3002:                    return null;
3003:                int length = array.length;
3004:                if (length == 0)
3005:                    return array;
3006:                char[] result = null;
3007:                int count = 0;
3008:                for (int i = 0; i < length; i++) {
3009:                    char c = array[i];
3010:                    if (c == toBeRemoved) {
3011:                        if (result == null) {
3012:                            result = new char[length];
3013:                            System.arraycopy(array, 0, result, 0, i);
3014:                            count = i;
3015:                        }
3016:                    } else if (result != null) {
3017:                        result[count++] = c;
3018:                    }
3019:                }
3020:                if (result == null)
3021:                    return array;
3022:                System.arraycopy(result, 0, result = new char[count], 0, count);
3023:                return result;
3024:            }
3025:
3026:            /**
3027:             * Replace all occurrence of the character to be replaced with the replacement character in the
3028:             * given array.
3029:             * <br>
3030:             * <br>
3031:             * For example:
3032:             * <ol>
3033:             * <li><pre>
3034:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3035:             *    toBeReplaced = 'b'
3036:             *    replacementChar = 'a'
3037:             *    result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
3038:             * </pre>
3039:             * </li>
3040:             * <li><pre>
3041:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3042:             *    toBeReplaced = 'c'
3043:             *    replacementChar = 'a'
3044:             *    result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
3045:             * </pre>
3046:             * </li>
3047:             * </ol>
3048:             * 
3049:             * @param array the given array
3050:             * @param toBeReplaced the character to be replaced
3051:             * @param replacementChar the replacement character
3052:             * @throws NullPointerException if the given array is null
3053:             */
3054:            public static final void replace(char[] array, char toBeReplaced,
3055:                    char replacementChar) {
3056:                if (toBeReplaced != replacementChar) {
3057:                    for (int i = 0, max = array.length; i < max; i++) {
3058:                        if (array[i] == toBeReplaced)
3059:                            array[i] = replacementChar;
3060:                    }
3061:                }
3062:            }
3063:
3064:            /**
3065:             * Replace all occurrences of characters to be replaced with the replacement character in the
3066:             * given array.
3067:             * <br>
3068:             * <br>
3069:             * For example:
3070:             * <ol>
3071:             * <li><pre>
3072:             *    array = { 'a' , 'b', 'b', 'c', 'a', 'b', 'c', 'a' }
3073:             *    toBeReplaced = { 'b', 'c' }
3074:             *    replacementChar = 'a'
3075:             *    result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
3076:             * </pre>
3077:             * </li>
3078:             * </ol>
3079:             * 
3080:             * @param array the given array
3081:             * @param toBeReplaced characters to be replaced
3082:             * @param replacementChar the replacement character
3083:             * @throws NullPointerException if arrays are null.
3084:             * @since 3.1
3085:             */
3086:            public static final void replace(char[] array, char[] toBeReplaced,
3087:                    char replacementChar) {
3088:                replace(array, toBeReplaced, replacementChar, 0, array.length);
3089:            }
3090:
3091:            /**
3092:             * Replace all occurrences of characters to be replaced with the replacement character in the
3093:             * given array from the start position (inclusive) to the end position (exclusive).
3094:             * <br>
3095:             * <br>
3096:             * For example:
3097:             * <ol>
3098:             * <li><pre>
3099:             *    array = { 'a' , 'b', 'b', 'c', 'a', 'b', 'c', 'a' }
3100:             *    toBeReplaced = { 'b', 'c' }
3101:             *    replacementChar = 'a'
3102:             *    start = 4
3103:             *    end = 8
3104:             *    result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'c', 'a', 'a', 'a', 'a' }
3105:             * </pre>
3106:             * </li>
3107:             * </ol>
3108:             * 
3109:             * @param array the given array
3110:             * @param toBeReplaced characters to be replaced
3111:             * @param replacementChar the replacement character
3112:             * @param start the given start position (inclusive)
3113:             * @param end  the given end position (exclusive)
3114:             * @throws NullPointerException if arrays are null.
3115:             * @since 3.2
3116:             */
3117:            public static final void replace(char[] array, char[] toBeReplaced,
3118:                    char replacementChar, int start, int end) {
3119:                for (int i = end; --i >= start;)
3120:                    for (int j = toBeReplaced.length; --j >= 0;)
3121:                        if (array[i] == toBeReplaced[j])
3122:                            array[i] = replacementChar;
3123:            }
3124:
3125:            /**
3126:             * Answers a new array of characters with substitutions. No side-effect is operated on the original
3127:             * array, in case no substitution happened, then the result is the same as the
3128:             * original one.
3129:             * <br>
3130:             * <br>
3131:             * For example:
3132:             * <ol>
3133:             * <li><pre>
3134:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3135:             *    toBeReplaced = { 'b' }
3136:             *    replacementChar = { 'a', 'a' }
3137:             *    result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
3138:             * </pre>
3139:             * </li>
3140:             * <li><pre>
3141:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3142:             *    toBeReplaced = { 'c' }
3143:             *    replacementChar = { 'a' }
3144:             *    result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
3145:             * </pre>
3146:             * </li>
3147:             * </ol>
3148:             * 
3149:             * @param array the given array
3150:             * @param toBeReplaced characters to be replaced
3151:             * @param replacementChars the replacement characters
3152:             * @return a new array of characters with substitutions or the given array if none
3153:             * @throws NullPointerException if the given array is null
3154:             */
3155:            public static final char[] replace(char[] array,
3156:                    char[] toBeReplaced, char[] replacementChars) {
3157:
3158:                int max = array.length;
3159:                int replacedLength = toBeReplaced.length;
3160:                int replacementLength = replacementChars.length;
3161:
3162:                int[] starts = new int[5];
3163:                int occurrenceCount = 0;
3164:
3165:                if (!equals(toBeReplaced, replacementChars)) {
3166:
3167:                    next: for (int i = 0; i < max;) {
3168:                        int index = indexOf(toBeReplaced, array, true, i);
3169:                        if (index == -1) {
3170:                            i++;
3171:                            continue next;
3172:                        }
3173:                        if (occurrenceCount == starts.length) {
3174:                            System.arraycopy(starts, 0,
3175:                                    starts = new int[occurrenceCount * 2], 0,
3176:                                    occurrenceCount);
3177:                        }
3178:                        starts[occurrenceCount++] = index;
3179:                        i = index + replacedLength;
3180:                    }
3181:                }
3182:                if (occurrenceCount == 0)
3183:                    return array;
3184:                char[] result = new char[max + occurrenceCount
3185:                        * (replacementLength - replacedLength)];
3186:                int inStart = 0, outStart = 0;
3187:                for (int i = 0; i < occurrenceCount; i++) {
3188:                    int offset = starts[i] - inStart;
3189:                    System.arraycopy(array, inStart, result, outStart, offset);
3190:                    inStart += offset;
3191:                    outStart += offset;
3192:                    System.arraycopy(replacementChars, 0, result, outStart,
3193:                            replacementLength);
3194:                    inStart += replacedLength;
3195:                    outStart += replacementLength;
3196:                }
3197:                System.arraycopy(array, inStart, result, outStart, max
3198:                        - inStart);
3199:                return result;
3200:            }
3201:
3202:            /**
3203:             * Replace all occurrence of the character to be replaced with the replacement character 
3204:             * in a copy of the given array. Returns the given array if no occurrences of the character
3205:             * to be replaced are found.
3206:             * <br>
3207:             * <br>
3208:             * For example:
3209:             * <ol>
3210:             * <li><pre>
3211:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3212:             *    toBeReplaced = 'b'
3213:             *    replacementChar = 'a'
3214:             *    result => A new array that is equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
3215:             * </pre>
3216:             * </li>
3217:             * <li><pre>
3218:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3219:             *    toBeReplaced = 'c'
3220:             *    replacementChar = 'a'
3221:             *    result => The original array that remains unchanged.
3222:             * </pre>
3223:             * </li>
3224:             * </ol>
3225:             * 
3226:             * @param array the given array
3227:             * @param toBeReplaced the character to be replaced
3228:             * @param replacementChar the replacement character
3229:             * @throws NullPointerException if the given array is null
3230:             * @since 3.1
3231:             */
3232:            public static final char[] replaceOnCopy(char[] array,
3233:                    char toBeReplaced, char replacementChar) {
3234:
3235:                char[] result = null;
3236:                for (int i = 0, length = array.length; i < length; i++) {
3237:                    char c = array[i];
3238:                    if (c == toBeReplaced) {
3239:                        if (result == null) {
3240:                            result = new char[length];
3241:                            System.arraycopy(array, 0, result, 0, i);
3242:                        }
3243:                        result[i] = replacementChar;
3244:                    } else if (result != null) {
3245:                        result[i] = c;
3246:                    }
3247:                }
3248:                if (result == null)
3249:                    return array;
3250:                return result;
3251:            }
3252:
3253:            /**
3254:             * Return a new array which is the split of the given array using the given divider and trimming each subarray to remove
3255:             * whitespaces equals to ' '.
3256:             * <br>
3257:             * <br>
3258:             * For example:
3259:             * <ol>
3260:             * <li><pre>
3261:             *    divider = 'b'
3262:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3263:             *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
3264:             * </pre>
3265:             * </li>
3266:             * <li><pre>
3267:             *    divider = 'c'
3268:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3269:             *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
3270:             * </pre>
3271:             * </li>
3272:             * <li><pre>
3273:             *    divider = 'b'
3274:             *    array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
3275:             *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
3276:             * </pre>
3277:             * </li>
3278:             * <li><pre>
3279:             *    divider = 'c'
3280:             *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
3281:             *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
3282:             * </pre>
3283:             * </li>
3284:             * </ol>
3285:             * 
3286:             * @param divider the given divider
3287:             * @param array the given array
3288:             * @return a new array which is the split of the given array using the given divider and trimming each subarray to remove
3289:             * whitespaces equals to ' '
3290:             */
3291:            public static final char[][] splitAndTrimOn(char divider,
3292:                    char[] array) {
3293:                int length = array == null ? 0 : array.length;
3294:                if (length == 0)
3295:                    return NO_CHAR_CHAR;
3296:
3297:                int wordCount = 1;
3298:                for (int i = 0; i < length; i++)
3299:                    if (array[i] == divider)
3300:                        wordCount++;
3301:                char[][] split = new char[wordCount][];
3302:                int last = 0, currentWord = 0;
3303:                for (int i = 0; i < length; i++) {
3304:                    if (array[i] == divider) {
3305:                        int start = last, end = i - 1;
3306:                        while (start < i && array[start] == ' ')
3307:                            start++;
3308:                        while (end > start && array[end] == ' ')
3309:                            end--;
3310:                        split[currentWord] = new char[end - start + 1];
3311:                        System.arraycopy(array, start, split[currentWord++], 0,
3312:                                end - start + 1);
3313:                        last = i + 1;
3314:                    }
3315:                }
3316:                int start = last, end = length - 1;
3317:                while (start < length && array[start] == ' ')
3318:                    start++;
3319:                while (end > start && array[end] == ' ')
3320:                    end--;
3321:                split[currentWord] = new char[end - start + 1];
3322:                System.arraycopy(array, start, split[currentWord++], 0, end
3323:                        - start + 1);
3324:                return split;
3325:            }
3326:
3327:            /**
3328:             * Return a new array which is the split of the given array using the given divider.
3329:             * <br>
3330:             * <br>
3331:             * For example:
3332:             * <ol>
3333:             * <li><pre>
3334:             *    divider = 'b'
3335:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3336:             *    result => { { 'a' }, {  }, { 'a' }, { 'a' } }
3337:             * </pre>
3338:             * </li>
3339:             * <li><pre>
3340:             *    divider = 'c'
3341:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3342:             *    result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
3343:             * </pre>
3344:             * </li>
3345:             * <li><pre>
3346:             *    divider = 'c'
3347:             *    array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
3348:             *    result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
3349:             * </pre>
3350:             * </li>
3351:             * </ol>
3352:             * 
3353:             * @param divider the given divider
3354:             * @param array the given array
3355:             * @return a new array which is the split of the given array using the given divider
3356:             */
3357:            public static final char[][] splitOn(char divider, char[] array) {
3358:                int length = array == null ? 0 : array.length;
3359:                if (length == 0)
3360:                    return NO_CHAR_CHAR;
3361:
3362:                int wordCount = 1;
3363:                for (int i = 0; i < length; i++)
3364:                    if (array[i] == divider)
3365:                        wordCount++;
3366:                char[][] split = new char[wordCount][];
3367:                int last = 0, currentWord = 0;
3368:                for (int i = 0; i < length; i++) {
3369:                    if (array[i] == divider) {
3370:                        split[currentWord] = new char[i - last];
3371:                        System.arraycopy(array, last, split[currentWord++], 0,
3372:                                i - last);
3373:                        last = i + 1;
3374:                    }
3375:                }
3376:                split[currentWord] = new char[length - last];
3377:                System.arraycopy(array, last, split[currentWord], 0, length
3378:                        - last);
3379:                return split;
3380:            }
3381:
3382:            /**
3383:             * Return a new array which is the split of the given array using the given divider. The given end 
3384:             * is exclusive and the given start is inclusive.
3385:             * <br>
3386:             * <br>
3387:             * For example:
3388:             * <ol>
3389:             * <li><pre>
3390:             *    divider = 'b'
3391:             *    array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
3392:             *    start = 2
3393:             *    end = 5
3394:             *    result => { {  }, { 'a' }, {  } }
3395:             * </pre>
3396:             * </li>
3397:             * </ol>
3398:             * 
3399:             * @param divider the given divider
3400:             * @param array the given array
3401:             * @param start the given starting index
3402:             * @param end the given ending index
3403:             * @return a new array which is the split of the given array using the given divider
3404:             * @throws ArrayIndexOutOfBoundsException if start is lower than 0 or end is greater than the array length
3405:             */
3406:            public static final char[][] splitOn(char divider, char[] array,
3407:                    int start, int end) {
3408:                int length = array == null ? 0 : array.length;
3409:                if (length == 0 || start > end)
3410:                    return NO_CHAR_CHAR;
3411:
3412:                int wordCount = 1;
3413:                for (int i = start; i < end; i++)
3414:                    if (array[i] == divider)
3415:                        wordCount++;
3416:                char[][] split = new char[wordCount][];
3417:                int last = start, currentWord = 0;
3418:                for (int i = start; i < end; i++) {
3419:                    if (array[i] == divider) {
3420:                        split[currentWord] = new char[i - last];
3421:                        System.arraycopy(array, last, split[currentWord++], 0,
3422:                                i - last);
3423:                        last = i + 1;
3424:                    }
3425:                }
3426:                split[currentWord] = new char[end - last];
3427:                System
3428:                        .arraycopy(array, last, split[currentWord], 0, end
3429:                                - last);
3430:                return split;
3431:            }
3432:
3433:            /**
3434:             * Answers a new array which is a copy of the given array starting at the given start and 
3435:             * ending at the given end. The given start is inclusive and the given end is exclusive.
3436:             * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
3437:             * than the length of the given array. If end  equals -1, it is converted to the array length.
3438:             * <br>
3439:             * <br>
3440:             * For example:
3441:             * <ol>
3442:             * <li><pre>
3443:             *    array = { { 'a' } , { 'b' } }
3444:             *    start = 0
3445:             *    end = 1
3446:             *    result => { { 'a' } }
3447:             * </pre>
3448:             * </li>
3449:             * <li><pre>
3450:             *    array = { { 'a' } , { 'b' } }
3451:             *    start = 0
3452:             *    end = -1
3453:             *    result => { { 'a' }, { 'b' } }
3454:             * </pre>
3455:             * </li>
3456:             * </ol>
3457:             *  
3458:             * @param array the given array
3459:             * @param start the given starting index
3460:             * @param end the given ending index
3461:             * @return a new array which is a copy of the given array starting at the given start and 
3462:             * ending at the given end
3463:             * @throws NullPointerException if the given array is null
3464:             */
3465:            public static final char[][] subarray(char[][] array, int start,
3466:                    int end) {
3467:                if (end == -1)
3468:                    end = array.length;
3469:                if (start > end)
3470:                    return null;
3471:                if (start < 0)
3472:                    return null;
3473:                if (end > array.length)
3474:                    return null;
3475:
3476:                char[][] result = new char[end - start][];
3477:                System.arraycopy(array, start, result, 0, end - start);
3478:                return result;
3479:            }
3480:
3481:            /**
3482:             * Answers a new array which is a copy of the given array starting at the given start and 
3483:             * ending at the given end. The given start is inclusive and the given end is exclusive.
3484:             * Answers null if start is greater than end, if start is lower than 0 or if end is greater 
3485:             * than the length of the given array. If end  equals -1, it is converted to the array length.
3486:             * <br>
3487:             * <br>
3488:             * For example:
3489:             * <ol>
3490:             * <li><pre>
3491:             *    array = { 'a' , 'b' }
3492:             *    start = 0
3493:             *    end = 1
3494:             *    result => { 'a' }
3495:             * </pre>
3496:             * </li>
3497:             * <li><pre>
3498:             *    array = { 'a', 'b' }
3499:             *    start = 0
3500:             *    end = -1
3501:             *    result => { 'a' , 'b' }
3502:             * </pre>
3503:             * </li>
3504:             * </ol>
3505:             *  
3506:             * @param array the given array
3507:             * @param start the given starting index
3508:             * @param end the given ending index
3509:             * @return a new array which is a copy of the given array starting at the given start and 
3510:             * ending at the given end
3511:             * @throws NullPointerException if the given array is null
3512:             */
3513:            public static final char[] subarray(char[] array, int start, int end) {
3514:                if (end == -1)
3515:                    end = array.length;
3516:                if (start > end)
3517:                    return null;
3518:                if (start < 0)
3519:                    return null;
3520:                if (end > array.length)
3521:                    return null;
3522:
3523:                char[] result = new char[end - start];
3524:                System.arraycopy(array, start, result, 0, end - start);
3525:                return result;
3526:            }
3527:
3528:            /**
3529:             * Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null.
3530:             * <br>
3531:             * NOTE: If no conversion was necessary, then answers back the argument one.
3532:             * <br>
3533:             * <br>
3534:             * For example:
3535:             * <ol>
3536:             * <li><pre>
3537:             *    chars = { 'a' , 'b' }
3538:             *    result => { 'a' , 'b' }
3539:             * </pre>
3540:             * </li>
3541:             * <li><pre>
3542:             *    array = { 'A', 'b' }
3543:             *    result => { 'a' , 'b' }
3544:             * </pre>
3545:             * </li>
3546:             * </ol>
3547:             * 
3548:             * @param chars the chars to convert
3549:             * @return the result of a char[] conversion to lowercase
3550:             */
3551:            final static public char[] toLowerCase(char[] chars) {
3552:                if (chars == null)
3553:                    return null;
3554:                int length = chars.length;
3555:                char[] lowerChars = null;
3556:                for (int i = 0; i < length; i++) {
3557:                    char c = chars[i];
3558:                    char lc = ScannerHelper.toLowerCase(c);
3559:                    if ((c != lc) || (lowerChars != null)) {
3560:                        if (lowerChars == null) {
3561:                            System.arraycopy(chars, 0,
3562:                                    lowerChars = new char[length], 0, i);
3563:                        }
3564:                        lowerChars[i] = lc;
3565:                    }
3566:                }
3567:                return lowerChars == null ? chars : lowerChars;
3568:            }
3569:
3570:            /**
3571:             * Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no
3572:             * space characters to remove.
3573:             * <br>
3574:             * <br>
3575:             * For example:
3576:             * <ol>
3577:             * <li><pre>
3578:             *    chars = { ' ', 'a' , 'b', ' ',  ' ' }
3579:             *    result => { 'a' , 'b' }
3580:             * </pre>
3581:             * </li>
3582:             * <li><pre>
3583:             *    array = { 'A', 'b' }
3584:             *    result => { 'A' , 'b' }
3585:             * </pre>
3586:             * </li>
3587:             * </ol>
3588:             * 
3589:             * @param chars the given array
3590:             * @return a new array removing leading and trailing spaces (' ')
3591:             */
3592:            final static public char[] trim(char[] chars) {
3593:
3594:                if (chars == null)
3595:                    return null;
3596:
3597:                int start = 0, length = chars.length, end = length - 1;
3598:                while (start < length && chars[start] == ' ') {
3599:                    start++;
3600:                }
3601:                while (end > start && chars[end] == ' ') {
3602:                    end--;
3603:                }
3604:                if (start != 0 || end != length - 1) {
3605:                    return subarray(chars, start, end + 1);
3606:                }
3607:                return chars;
3608:            }
3609:
3610:            /**
3611:             * Answers a string which is the concatenation of the given array using the '.' as a separator.
3612:             * <br>
3613:             * <br>
3614:             * For example:
3615:             * <ol>
3616:             * <li><pre>
3617:             *    array = { { 'a' } , { 'b' } }
3618:             *    result => "a.b"
3619:             * </pre>
3620:             * </li>
3621:             * <li><pre>
3622:             *    array = { { ' ',  'a' } , { 'b' } }
3623:             *    result => " a.b"
3624:             * </pre>
3625:             * </li>
3626:             * </ol>
3627:             * 
3628:             * @param array the given array
3629:             * @return a string which is the concatenation of the given array using the '.' as a separator
3630:             */
3631:            final static public String toString(char[][] array) {
3632:                char[] result = concatWith(array, '.');
3633:                return new String(result);
3634:            }
3635:
3636:            /**
3637:             * Answers an array of strings from the given array of char array.
3638:             * 
3639:             * @param array the given array
3640:             * @return an array of strings
3641:             * @since 3.0
3642:             */
3643:            final static public String[] toStrings(char[][] array) {
3644:                if (array == null)
3645:                    return NO_STRINGS;
3646:                int length = array.length;
3647:                if (length == 0)
3648:                    return NO_STRINGS;
3649:                String[] result = new String[length];
3650:                for (int i = 0; i < length; i++)
3651:                    result[i] = new String(array[i]);
3652:                return result;
3653:            }
3654:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.