/*
* #%~
* org.overture.ide.debug
* %%
* Copyright (C) 2008 - 2014 Overture
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #~%
*/
package org.overture.ide.debug.utils;
/**
* This class is a collection of helper methods to manipulate char arrays.
*/
public final class CharOperation
{
/**
* Constant for an empty char array
*/
public static final char[] NO_CHAR = new char[0];
/**
* Constant for an empty char array with two dimensions.
*/
public static final char[][] NO_CHAR_CHAR = new char[0][];
/**
* Constant for an empty String array.
*/
public static final String[] NO_STRINGS = new String[0];
// private static final char MAX_OBVIOUS = 128;
/**
* Answers a new array with appending the suffix character at the end of the array. <br>
* <br>
* For example:<br>
* <ol>
* <li>
*
* <pre>
* array = { 'a', 'b' }
* suffix = 'c'
* => result = { 'a', 'b' , 'c' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = null
* suffix = 'c'
* => result = { 'c' }
* </pre>
*
* </li>
* </ol>
*
* @param array
* the array that is concanated with the suffix character
* @param suffix
* the suffix character
* @return the new array
*/
public static final char[] append(char[] array, char suffix)
{
if (array == null)
{
return new char[] { suffix };
}
int length = array.length;
System.arraycopy(array, 0, array = new char[length + 1], 0, length);
array[length] = suffix;
return array;
}
/**
* Append the given subarray to the target array starting at the given index in the target array. The start of the
* subarray is inclusive, the end is exclusive. Answers a new target array if it needs to grow, otherwise answers
* the same target array. <br>
* For example:<br>
* <ol>
* <li>
*
* <pre>
* target = { 'a', 'b', '0' }
* index = 2
* array = { 'c', 'd' }
* start = 0
* end = 1
* => result = { 'a', 'b' , 'c' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* target = { 'a', 'b' }
* index = 2
* array = { 'c', 'd' }
* start = 0
* end = 1
* => result = { 'a', 'b' , 'c', '0', '0' , '0' } (new array)
* </pre>
*
* </li>
* <li>
*
* <pre>
* target = { 'a', 'b', 'c' }
* index = 1
* array = { 'c', 'd', 'e', 'f' }
* start = 1
* end = 4
* => result = { 'a', 'd' , 'e', 'f', '0', '0', '0', '0' } (new array)
* </pre>
*
* </li>
* </ol>
*
* @param target
* the given target
* @param index
* the given index
* @param array
* the given array
* @param start
* the given start index
* @param end
* the given end index
* @return the new array
* @throws NullPointerException
* if the target array is null
*/
public static final char[] append(char[] target, int index, char[] array,
int start, int end)
{
int targetLength = target.length;
int subLength = end - start;
int newTargetLength = subLength + index;
if (newTargetLength > targetLength)
{
System.arraycopy(target, 0, target = new char[newTargetLength * 2], 0, index);
}
System.arraycopy(array, start, target, index, subLength);
return target;
}
/**
* Answers the concatenation of the two arrays. It answers null if the two arrays are null. If the first array is
* null, then the second array is returned. If the second array is null, then the first array is returned. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = null
* => result = null
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { { ' a' } }
* second = null
* => result = { { ' a' } }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = null
* second = { { ' a' } }
* => result = { { ' a' } }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { { ' b' } }
* second = { { ' a' } }
* => result = { { ' b' }, { ' a' } }
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array to concatenate
* @param second
* the second array to concatenate
* @return the concatenation of the two arrays, or null if the two arrays are null.
*/
public static final char[][] arrayConcat(char[][] first, char[][] second)
{
if (first == null)
{
return second;
}
if (second == null)
{
return first;
}
int length1 = first.length;
int length2 = second.length;
char[][] result = new char[length1 + length2][];
System.arraycopy(first, 0, result, 0, length1);
System.arraycopy(second, 0, result, length1, length2);
return result;
}
/**
* Returns the char arrays as an array of Strings
*
* @param charArrays
* the char array to convert
* @return the char arrays as an array of Strings or null if the given char arrays is null.
*/
public static String[] charArrayToStringArray(char[][] charArrays)
{
if (charArrays == null)
{
return null;
}
int length = charArrays.length;
if (length == 0)
{
return NO_STRINGS;
}
String[] strings = new String[length];
for (int i = 0; i < length; i++)
{
strings[i] = new String(charArrays[i]);
}
return strings;
}
/**
* Returns the char array as a String
*
* @param charArray
* the char array to convert
* @return the char array as a String or null if the given char array is null.
*/
public static String charToString(char[] charArray)
{
if (charArray == null)
{
return null;
}
return new String(charArray);
}
/**
* Answers a new array adding the second array at the end of first array. It answers null if the first and second
* are null. If the first array is null, then a new array char[][] is created with second. If the second array is
* null, then the first array is returned. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = { 'a' }
* => result = { { ' a' } }
* </pre>
* <li>
*
* <pre>
* first = { { ' a' } }
* second = null
* => result = { { ' a' } }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { { ' a' } }
* second = { ' b' }
* => result = { { ' a' } , { ' b' } }
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array to concatenate
* @param second
* the array to add at the end of the first array
* @return a new array adding the second array at the end of first array, or null if the two arrays are null.
*/
public static final char[][] arrayConcat(char[][] first, char[] second)
{
if (second == null)
{
return first;
}
if (first == null)
{
return new char[][] { second };
}
int length = first.length;
char[][] result = new char[length + 1][];
System.arraycopy(first, 0, result, 0, length);
result[length] = second;
return result;
}
/**
* Compares the contents of the two arrays array and prefix. Returns
* <ul>
* <li>zero if the array starts with the prefix contents</li>
* <li>the difference between the first two characters that are not equal</li>
* <li>one if array length is lower than the prefix length and that the prefix starts with the array contents.</li>
* </ul>
* <p>
* For example:
* <ol>
* <li>
*
* <pre>
* array = null
* prefix = null
* => result = NullPointerException
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'a', 'b', 'c', 'd', 'e' }
* prefix = { 'a', 'b', 'c'}
* => result = 0
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'a', 'b', 'c', 'd', 'e' }
* prefix = { 'a', 'B', 'c'}
* => result = 32
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'd', 'b', 'c', 'd', 'e' }
* prefix = { 'a', 'b', 'c'}
* => result = 3
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'a', 'b', 'c', 'd', 'e' }
* prefix = { 'd', 'b', 'c'}
* => result = -3
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'a', 'a', 'c', 'd', 'e' }
* prefix = { 'a', 'e', 'c'}
* => result = -4
* </pre>
*
* </li>
* </ol>
* </p>
*
* @param array
* the given array
* @param prefix
* the given prefix
* @return the result of the comparison (>=0 if array>prefix)
* @throws NullPointerException
* if either array or prefix is null
*/
public static final int compareWith(char[] array, char[] prefix)
{
int arrayLength = array.length;
int prefixLength = prefix.length;
int min = Math.min(arrayLength, prefixLength);
int i = 0;
while (min-- != 0)
{
char c1 = array[i];
char c2 = prefix[i++];
if (c1 != c2)
{
return c1 - c2;
}
}
if (prefixLength == i)
{
return 0;
}
return -1; // array is shorter than prefix (e.g. array:'ab' <
// prefix:'abc').
}
/**
* Answers the concatenation of the two arrays. It answers null if the two arrays are null. If the first array is
* null, then the second array is returned. If the second array is null, then the first array is returned. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = { 'a' }
* => result = { ' a' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { ' a' }
* second = null
* => result = { ' a' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { ' a' }
* second = { ' b' }
* => result = { ' a' , ' b' }
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array to concatenate
* @param second
* the second array to concatenate
* @return the concatenation of the two arrays, or null if the two arrays are null.
*/
public static final char[] concat(char[] first, char[] second)
{
if (first == null)
{
return second;
}
if (second == null)
{
return first;
}
int length1 = first.length;
int length2 = second.length;
char[] result = new char[length1 + length2];
System.arraycopy(first, 0, result, 0, length1);
System.arraycopy(second, 0, result, length1, length2);
return result;
}
/**
* Answers the concatenation of the three arrays. It answers null if the three arrays are null. If first is null, it
* answers the concatenation of second and third. If second is null, it answers the concatenation of first and
* third. If third is null, it answers the concatenation of first and second. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = { 'a' }
* third = { 'b' }
* => result = { ' a', 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* second = null
* third = { 'b' }
* => result = { ' a', 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* second = { 'b' }
* third = null
* => result = { ' a', 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = null
* second = null
* third = null
* => result = null
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* second = { 'b' }
* third = { 'c' }
* => result = { 'a', 'b', 'c' }
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array to concatenate
* @param second
* the second array to concatenate
* @param third
* the third array to concatenate
* @return the concatenation of the three arrays, or null if the three arrays are null.
*/
public static final char[] concat(char[] first, char[] second, char[] third)
{
if (first == null)
{
return concat(second, third);
}
if (second == null)
{
return concat(first, third);
}
if (third == null)
{
return concat(first, second);
}
int length1 = first.length;
int length2 = second.length;
int length3 = third.length;
char[] result = new char[length1 + length2 + length3];
System.arraycopy(first, 0, result, 0, length1);
System.arraycopy(second, 0, result, length1, length2);
System.arraycopy(third, 0, result, length1 + length2, length3);
return result;
}
/**
* Answers the concatenation of the two arrays inserting the separator character between the two arrays. It answers
* null if the two arrays are null. If the first array is null, then the second array is returned. If the second
* array is null, then the first array is returned. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = { 'a' }
* separator = '/'
* => result = { ' a' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { ' a' }
* second = null
* separator = '/'
* => result = { ' a' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { ' a' }
* second = { ' b' }
* separator = '/'
* => result = { ' a' , '/', 'b' }
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array to concatenate
* @param second
* the second array to concatenate
* @param separator
* the character to insert
* @return the concatenation of the two arrays inserting the separator character between the two arrays , or null if
* the two arrays are null.
*/
public static final char[] concat(char[] first, char[] second,
char separator)
{
if (first == null)
{
return second;
}
if (second == null)
{
return first;
}
int length1 = first.length;
if (length1 == 0)
{
return second;
}
int length2 = second.length;
if (length2 == 0)
{
return first;
}
char[] result = new char[length1 + length2 + 1];
System.arraycopy(first, 0, result, 0, length1);
result[length1] = separator;
System.arraycopy(second, 0, result, length1 + 1, length2);
return result;
}
public static final char[] concatWithSeparator(char[] first, char[] second,
char[] separator)
{
if (first == null)
{
return second;
}
if (second == null)
{
return first;
}
int length1 = first.length;
if (length1 == 0)
{
return second;
}
int length2 = second.length;
if (length2 == 0)
{
return first;
}
int length3 = separator.length;
char[] result = new char[length1 + length2 + length3];
System.arraycopy(first, 0, result, 0, length1);
System.arraycopy(separator, 0, result, length1, length3);
System.arraycopy(second, 0, result, length1 + length3, length2);
return result;
}
/**
* Answers the concatenation of the three arrays inserting the sep1 character between the first two arrays and sep2
* between the last two. It answers null if the three arrays are null. If the first array is null, then it answers
* the concatenation of second and third inserting the sep2 character between them. If the second array is null,
* then it answers the concatenation of first and third inserting the sep1 character between them. If the third
* array is null, then it answers the concatenation of first and second inserting the sep1 character between them. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* sep1 = '/'
* second = { 'a' }
* sep2 = ':'
* third = { 'b' }
* => result = { ' a' , ':', 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* sep1 = '/'
* second = null
* sep2 = ':'
* third = { 'b' }
* => result = { ' a' , '/', 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* sep1 = '/'
* second = { 'b' }
* sep2 = ':'
* third = null
* => result = { ' a' , '/', 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* sep1 = '/'
* second = { 'b' }
* sep2 = ':'
* third = { 'c' }
* => result = { ' a' , '/', 'b' , ':', 'c' }
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array to concatenate
* @param sep1
* the character to insert
* @param second
* the second array to concatenate
* @param sep2
* the character to insert
* @param third
* the second array to concatenate
* @return the concatenation of the three arrays inserting the sep1 character between the two arrays and sep2
* between the last two.
*/
public static final char[] concat(char[] first, char sep1, char[] second,
char sep2, char[] third)
{
if (first == null)
{
return concat(second, third, sep2);
}
if (second == null)
{
return concat(first, third, sep1);
}
if (third == null)
{
return concat(first, second, sep1);
}
int length1 = first.length;
int length2 = second.length;
int length3 = third.length;
char[] result = new char[length1 + length2 + length3 + 2];
System.arraycopy(first, 0, result, 0, length1);
result[length1] = sep1;
System.arraycopy(second, 0, result, length1 + 1, length2);
result[length1 + length2 + 1] = sep2;
System.arraycopy(third, 0, result, length1 + length2 + 2, length3);
return result;
}
/**
* Answers a new array with prepending the prefix character and appending the suffix character at the end of the
* array. If array is null, it answers a new array containing the prefix and the suffix characters. <br>
* <br>
* For example:<br>
* <ol>
* <li>
*
* <pre>
* prefix = 'a'
* array = { 'b' }
* suffix = 'c'
* => result = { 'a', 'b' , 'c' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* prefix = 'a'
* array = null
* suffix = 'c'
* => result = { 'a', 'c' }
* </pre>
*
* </li>
* </ol>
*
* @param prefix
* the prefix character
* @param array
* the array that is concanated with the prefix and suffix characters
* @param suffix
* the suffix character
* @return the new array
*/
public static final char[] concat(char prefix, char[] array, char suffix)
{
if (array == null)
{
return new char[] { prefix, suffix };
}
int length = array.length;
char[] result = new char[length + 2];
result[0] = prefix;
System.arraycopy(array, 0, result, 1, length);
result[length + 1] = suffix;
return result;
}
/**
* Answers the concatenation of the given array parts using the given separator between each part and appending the
* given name at the end. <br>
* <br>
* For example:<br>
* <ol>
* <li>
*
* <pre>
* name = { 'c' }
* array = { { 'a' }, { 'b' } }
* separator = '.'
* => result = { 'a', '.', 'b' , '.', 'c' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* name = null
* array = { { 'a' }, { 'b' } }
* separator = '.'
* => result = { 'a', '.', 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* name = { ' c' }
* array = null
* separator = '.'
* => result = { 'c' }
* </pre>
*
* </li>
* </ol>
*
* @param name
* the given name
* @param array
* the given array
* @param separator
* the given separator
* @return the concatenation of the given array parts using the given separator between each part and appending the
* given name at the end
*/
public static final char[] concatWith(char[] name, char[][] array,
char separator)
{
int nameLength = name == null ? 0 : name.length;
if (nameLength == 0)
{
return concatWith(array, separator);
}
int length = array == null ? 0 : array.length;
if (length == 0)
{
return name;
}
int size = nameLength;
int index = length;
while (--index >= 0)
{
if (array[index].length > 0)
{
size += array[index].length + 1;
}
}
char[] result = new char[size];
index = size;
for (int i = length - 1; i >= 0; i--)
{
int subLength = array[i].length;
if (subLength > 0)
{
index -= subLength;
System.arraycopy(array[i], 0, result, index, subLength);
result[--index] = separator;
}
}
System.arraycopy(name, 0, result, 0, nameLength);
return result;
}
/**
* Answers the concatenation of the given array parts using the given separator between each part and appending the
* given name at the end. <br>
* <br>
* For example:<br>
* <ol>
* <li>
*
* <pre>
* name = { 'c' }
* array = { { 'a' }, { 'b' } }
* separator = '.'
* => result = { 'a', '.', 'b' , '.', 'c' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* name = null
* array = { { 'a' }, { 'b' } }
* separator = '.'
* => result = { 'a', '.', 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* name = { ' c' }
* array = null
* separator = '.'
* => result = { 'c' }
* </pre>
*
* </li>
* </ol>
*
* @param array
* the given array
* @param name
* the given name
* @param separator
* the given separator
* @return the concatenation of the given array parts using the given separator between each part and appending the
* given name at the end
*/
public static final char[] concatWith(char[][] array, char[] name,
char separator)
{
int nameLength = name == null ? 0 : name.length;
if (nameLength == 0)
{
return concatWith(array, separator);
}
int length = array == null ? 0 : array.length;
if (length == 0)
{
return name;
}
int size = nameLength;
int index = length;
while (--index >= 0)
{
if (array[index].length > 0)
{
size += array[index].length + 1;
}
}
char[] result = new char[size];
index = 0;
for (int i = 0; i < length; i++)
{
int subLength = array[i].length;
if (subLength > 0)
{
System.arraycopy(array[i], 0, result, index, subLength);
index += subLength;
result[index++] = separator;
}
}
System.arraycopy(name, 0, result, index, nameLength);
return result;
}
/**
* Answers the concatenation of the given array parts using the given separator between each part. <br>
* <br>
* For example:<br>
* <ol>
* <li>
*
* <pre>
* array = { { 'a' }, { 'b' } }
* separator = '.'
* => result = { 'a', '.', 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = null
* separator = '.'
* => result = { }
* </pre>
*
* </li>
* </ol>
*
* @param array
* the given array
* @param separator
* the given separator
* @return the concatenation of the given array parts using the given separator between each part
*/
public static final char[] concatWith(char[][] array, char separator)
{
int length = array == null ? 0 : array.length;
if (length == 0)
{
return CharOperation.NO_CHAR;
}
int size = length - 1;
int index = length;
while (--index >= 0)
{
if (array[index].length == 0)
{
size--;
} else
{
size += array[index].length;
}
}
if (size <= 0)
{
return CharOperation.NO_CHAR;
}
char[] result = new char[size];
index = length;
while (--index >= 0)
{
length = array[index].length;
if (length > 0)
{
System.arraycopy(array[index], 0, result, size -= length, length);
if (--size >= 0)
{
result[size] = separator;
}
}
}
return result;
}
public static final char[] concatWith(String[] array, char separator)
{
int length = array == null ? 0 : array.length;
if (length == 0)
{
return CharOperation.NO_CHAR;
}
int size = length - 1;
int index = length;
while (--index >= 0)
{
final int len = array[index].length();
if (len == 0)
{
size--;
} else
{
size += len;
}
}
if (size <= 0)
{
return CharOperation.NO_CHAR;
}
char[] result = new char[size];
index = length;
while (--index >= 0)
{
length = array[index].length();
if (length > 0)
{
array[index].getChars(0, length, result, size -= length);
if (--size >= 0)
{
result[size] = separator;
}
}
}
return result;
}
/**
* Answers true if the array contains an occurrence of character, false otherwise. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* character = 'c'
* array = { { ' a' }, { ' b' } }
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* character = 'a'
* array = { { ' a' }, { ' b' } }
* result => true
* </pre>
*
* </li>
* </ol>
*
* @param character
* the character to search
* @param array
* the array in which the search is done
* @return true if the array contains an occurrence of character, false otherwise.
* @throws NullPointerException
* if array is null.
*/
public static final boolean contains(char character, char[][] array)
{
for (int i = array.length; --i >= 0;)
{
char[] subarray = array[i];
for (int j = subarray.length; --j >= 0;)
{
if (subarray[j] == character)
{
return true;
}
}
}
return false;
}
/**
* Answers true if the array contains an occurrence of character, false otherwise. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* character = 'c'
* array = { ' b' }
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* character = 'a'
* array = { ' a' , ' b' }
* result => true
* </pre>
*
* </li>
* </ol>
*
* @param character
* the character to search
* @param array
* the array in which the search is done
* @return true if the array contains an occurrence of character, false otherwise.
* @throws NullPointerException
* if array is null.
*/
public static final boolean contains(char character, char[] array)
{
for (int i = array.length; --i >= 0;)
{
if (array[i] == character)
{
return true;
}
}
return false;
}
/**
* Answers true if the array contains an occurrence of one of the characters, false otherwise. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* characters = { 'c', 'd' }
* array = { 'a', ' b' }
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* characters = { 'c', 'd' }
* array = { 'a', ' b', 'c' }
* result => true
* </pre>
*
* </li>
* </ol>
*
* @param characters
* the characters to search
* @param array
* the array in which the search is done
* @return true if the array contains an occurrence of one of the characters, false otherwise.
* @throws NullPointerException
* if array is null.
*/
public static final boolean contains(char[] characters, char[] array)
{
for (int i = array.length; --i >= 0;)
{
for (int j = characters.length; --j >= 0;)
{
if (array[i] == characters[j])
{
return true;
}
}
}
return false;
}
/**
* Answers a deep copy of the toCopy array.
*
* @param toCopy
* the array to copy
* @return a deep copy of the toCopy array.
*/
public static final char[][] deepCopy(char[][] toCopy)
{
int toCopyLength = toCopy.length;
char[][] result = new char[toCopyLength][];
for (int i = 0; i < toCopyLength; i++)
{
char[] toElement = toCopy[i];
int toElementLength = toElement.length;
char[] resultElement = new char[toElementLength];
System.arraycopy(toElement, 0, resultElement, 0, toElementLength);
result[i] = resultElement;
}
return result;
}
/**
* Return <code>true</code> if array starts with the sequence of characters contained in toBeFound, otherwise
* <code>false</code>.
*
* @param array
* @param toBeFound
* @return
*/
public static final boolean startsWith(char[] array, char[] toBeFound)
{
int i = toBeFound.length;
if (array.length < i)
{
return false;
}
while (--i >= 0)
{
if (toBeFound[i] != array[i])
{
return false;
}
}
return true;
}
/**
* Return true if array ends with the sequence of characters contained in toBeFound, otherwise false. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* array = { 'a', 'b', 'c', 'd' }
* toBeFound = { 'b', 'c' }
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'a', 'b', 'c' }
* toBeFound = { 'b', 'c' }
* result => true
* </pre>
*
* </li>
* </ol>
*
* @param array
* the array to check
* @param toBeFound
* the array to find
* @return true if array ends with the sequence of characters contained in toBeFound, otherwise false.
* @throws NullPointerException
* if array is null or toBeFound is null
*/
public static final boolean endsWith(char[] array, char[] toBeFound)
{
int i = toBeFound.length;
int j = array.length - i;
if (j < 0)
{
return false;
}
while (--i >= 0)
{
if (toBeFound[i] != array[i + j])
{
return false;
}
}
return true;
}
/**
* Answers true if the two arrays are identical character by character, otherwise false. The equality is case
* sensitive. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = null
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { { } }
* second = null
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { { 'a' } }
* second = { { 'a' } }
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { { 'A' } }
* second = { { 'a' } }
* result => false
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array
* @param second
* the second array
* @return true if the two arrays are identical character by character, otherwise false
*/
public static final boolean equals(char[][] first, char[][] second)
{
if (first == second)
{
return true;
}
if (first == null || second == null)
{
return false;
}
if (first.length != second.length)
{
return false;
}
for (int i = first.length; --i >= 0;)
{
if (!equals(first[i], second[i]))
{
return false;
}
}
return true;
}
/**
* Compares two strings null-safe.
*
* @param first
* @param second
* @return
*/
public static final boolean equals(String first, String second)
{
if (first == second)
{
return true;
} else if (first == null || second == null)
{
return false;
} else
{
return first.equals(second);
}
}
public static final boolean equals(String[] first, String[] second)
{
if (first == second)
{
return true;
}
if (first == null || second == null)
{
return false;
}
if (first.length != second.length)
{
return false;
}
for (int i = first.length; --i >= 0;)
{
if (first[i] == null && second[i] != null)
{
return false;
}
if (first[i] != null && second[i] == null)
{
return false;
}
if (first[i] != null && !first[i].equals(second[i]))
{
return false;
}
}
return true;
}
/**
* If isCaseSensite is true, answers true if the two arrays are identical character by character, otherwise false.
* If it is false, answers true if the two arrays are identical character by character without checking the case,
* otherwise false. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = null
* isCaseSensitive = true
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { { } }
* second = null
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { { 'A' } }
* second = { { 'a' } }
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { { 'A' } }
* second = { { 'a' } }
* isCaseSensitive = false
* result => true
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array
* @param second
* the second array
* @param isCaseSensitive
* check whether or not the equality should be case sensitive
* @return true if the two arrays are identical character by character according to the value of isCaseSensitive,
* otherwise false
*/
public static final boolean equals(char[][] first, char[][] second,
boolean isCaseSensitive)
{
if (isCaseSensitive)
{
return equals(first, second);
}
if (first == second)
{
return true;
}
if (first == null || second == null)
{
return false;
}
if (first.length != second.length)
{
return false;
}
for (int i = first.length; --i >= 0;)
{
if (!equals(first[i], second[i], false))
{
return false;
}
}
return true;
}
/**
* Answers true if the two arrays are identical character by character, otherwise false. The equality is case
* sensitive. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = null
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { }
* second = null
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* second = { 'a' }
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* second = { 'A' }
* result => false
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array
* @param second
* the second array
* @return true if the two arrays are identical character by character, otherwise false
*/
public static final boolean equals(char[] first, char[] second)
{
if (first == second)
{
return true;
}
if (first == null || second == null)
{
return false;
}
if (first.length != second.length)
{
return false;
}
for (int i = first.length; --i >= 0;)
{
if (first[i] != second[i])
{
return false;
}
}
return true;
}
/**
* Answers true if the first array is identical character by character to a portion of the second array delimited
* from position secondStart (inclusive) to secondEnd(exclusive), otherwise false. The equality is case sensitive. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = null
* secondStart = 0
* secondEnd = 0
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { }
* second = null
* secondStart = 0
* secondEnd = 0
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* second = { 'a' }
* secondStart = 0
* secondEnd = 1
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'a' }
* second = { 'A' }
* secondStart = 0
* secondEnd = 1
* result => false
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array
* @param second
* the second array
* @param secondStart
* inclusive start position in the second array to compare
* @param secondEnd
* exclusive end position in the second array to compare
* @return true if the first array is identical character by character to fragment of second array ranging from
* secondStart to secondEnd-1, otherwise false
*/
public static final boolean equals(char[] first, char[] second,
int secondStart, int secondEnd)
{
if (first == second)
{
return true;
}
if (first == null || second == null)
{
return false;
}
if (first.length != secondEnd - secondStart)
{
return false;
}
for (int i = first.length; --i >= 0;)
{
if (first[i] != second[i + secondStart])
{
return false;
}
}
return true;
}
/**
* If isCaseSensite is true, answers true if the two arrays are identical character by character, otherwise false.
* If it is false, answers true if the two arrays are identical character by character without checking the case,
* otherwise false. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* first = null
* second = null
* isCaseSensitive = true
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { }
* second = null
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'A' }
* second = { 'a' }
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* first = { 'A' }
* second = { 'a' }
* isCaseSensitive = false
* result => true
* </pre>
*
* </li>
* </ol>
*
* @param first
* the first array
* @param second
* the second array
* @param isCaseSensitive
* check whether or not the equality should be case sensitive
* @return true if the two arrays are identical character by character according to the value of isCaseSensitive,
* otherwise false
*/
public static final boolean equals(char[] first, char[] second,
boolean isCaseSensitive)
{
if (isCaseSensitive)
{
return equals(first, second);
}
if (first == second)
{
return true;
}
if (first == null || second == null)
{
return false;
}
if (first.length != second.length)
{
return false;
}
for (int i = first.length; --i >= 0;)
{
if (Character.toLowerCase(first[i]) != Character.toLowerCase(second[i]))
{
return false;
}
}
return true;
}
/**
* If isCaseSensite is true, the equality is case sensitive, otherwise it is case insensitive. Answers true if the
* name contains the fragment at the starting index startIndex, otherwise false. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* fragment = { 'b', 'c' , 'd' }
* name = { 'a', 'b', 'c' , 'd' }
* startIndex = 1
* isCaseSensitive = true
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* fragment = { 'b', 'c' , 'd' }
* name = { 'a', 'b', 'C' , 'd' }
* startIndex = 1
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* fragment = { 'b', 'c' , 'd' }
* name = { 'a', 'b', 'C' , 'd' }
* startIndex = 0
* isCaseSensitive = false
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* fragment = { 'b', 'c' , 'd' }
* name = { 'a', 'b'}
* startIndex = 0
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* </ol>
*
* @param fragment
* the fragment to check
* @param name
* the array to check
* @param startIndex
* the starting index
* @param isCaseSensitive
* check whether or not the equality should be case sensitive
* @return true if the name contains the fragment at the starting index startIndex according to the value of
* isCaseSensitive, otherwise false.
* @throws NullPointerException
* if fragment or name is null.
*/
public static final boolean fragmentEquals(char[] fragment, char[] name,
int startIndex, boolean isCaseSensitive)
{
int max = fragment.length;
if (name.length < max + startIndex)
{
return false;
}
if (isCaseSensitive)
{
for (int i = max; --i >= 0;)
{
// assumes the prefix is not larger than the name
if (fragment[i] != name[i + startIndex])
{
return false;
}
}
return true;
}
for (int i = max; --i >= 0;)
{
// assumes the prefix is not larger than the name
if (Character.toLowerCase(fragment[i]) != Character.toLowerCase(name[i
+ startIndex]))
{
return false;
}
}
return true;
}
/**
* Answers a hashcode for the array
*
* @param array
* the array for which a hashcode is required
* @return the hashcode
* @throws NullPointerException
* if array is null
*/
public static final int hashCode(char[] array)
{
int length = array.length;
int hash = length == 0 ? 31 : array[0];
if (length < 8)
{
for (int i = length; --i > 0;)
{
hash = hash * 31 + array[i];
}
} else
{
// 8 characters is enough to compute a decent hash code, don't waste
// time examining every character
for (int i = length - 1, last = i > 16 ? i - 16 : 0; i > last; i -= 2)
{
hash = hash * 31 + array[i];
}
}
return hash & 0x7FFFFFFF;
}
/**
* Answers true if c is a whitespace according to the JLS (\u000a, \u000c, \u000d, \u0009),
* otherwise false. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* c = ' '
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* c = ' \u3000'
* result => false
* </pre>
*
* </li>
* </ol>
*
* @param c
* the character to check
* @return true if c is a whitespace according to the JLS, otherwise false.
*/
public static boolean isWhitespace(char c)
{
switch (c)
{
case 10: /* \ u000a: LINE FEED */
case 12: /* \ u000c: FORM FEED */
case 13: /* \ u000d: CARRIAGE RETURN */
case 32: /* \ u0020: SPACE */
case 9: /* \ u0009: HORIZONTAL TABULATION */
return true;
default:
return false;
}
}
/**
* Answers the first index in the array for which the corresponding character is equal to toBeFound. Answers -1 if
* no occurrence of this character is found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd' }
* result => 2
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'e'
* array = { ' a', 'b', 'c', 'd' }
* result => -1
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the character to search
* @param array
* the array to be searched
* @return the first index in the array for which the corresponding character is equal to toBeFound, -1 otherwise
* @throws NullPointerException
* if array is null
*/
public static final int indexOf(char toBeFound, char[] array)
{
return indexOf(toBeFound, array, 0);
}
/**
* Answers the first index in the array for which the toBeFound array is a matching subarray following the case
* rule. Answers -1 if no match is found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = { 'c' }
* array = { ' a', 'b', 'c', 'd' }
* result => 2
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = { 'e' }
* array = { ' a', 'b', 'c', 'd' }
* result => -1
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the subarray to search
* @param array
* the array to be searched
* @param isCaseSensitive
* flag to know if the matching should be case sensitive
* @return the first index in the array for which the toBeFound array is a matching subarray following the case
* rule, -1 otherwise
* @throws NullPointerException
* if array is null or toBeFound is null
*/
public static final int indexOf(char[] toBeFound, char[] array,
boolean isCaseSensitive)
{
return indexOf(toBeFound, array, isCaseSensitive, 0);
}
/**
* Answers the first index in the array for which the toBeFound array is a matching subarray following the case rule
* starting at the index start. Answers -1 if no match is found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = { 'c' }
* array = { ' a', 'b', 'c', 'd' }
* result => 2
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = { 'e' }
* array = { ' a', 'b', 'c', 'd' }
* result => -1
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the subarray to search
* @param array
* the array to be searched
* @param isCaseSensitive
* flag to know if the matching should be case sensitive
* @param start
* the starting index
* @return the first index in the array for which the toBeFound array is a matching subarray following the case rule
* starting at the index start, -1 otherwise
* @throws NullPointerException
* if array is null or toBeFound is null
*/
public static final int indexOf(final char[] toBeFound, final char[] array,
final boolean isCaseSensitive, final int start)
{
return indexOf(toBeFound, array, isCaseSensitive, start, array.length);
}
/**
* Answers the first index in the array for which the toBeFound array is a matching subarray following the case rule
* starting at the index start. Answers -1 if no match is found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = { 'c' }
* array = { ' a', 'b', 'c', 'd' }
* result => 2
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = { 'e' }
* array = { ' a', 'b', 'c', 'd' }
* result => -1
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the subarray to search
* @param array
* the array to be searched
* @param isCaseSensitive
* flag to know if the matching should be case sensitive
* @param start
* the starting index (inclusive)
* @param end
* the end index (exclusive)
* @return the first index in the array for which the toBeFound array is a matching subarray following the case rule
* starting at the index start, -1 otherwise
* @throws NullPointerException
* if array is null or toBeFound is null
*/
public static final int indexOf(final char[] toBeFound, final char[] array,
final boolean isCaseSensitive, final int start, final int end)
{
final int arrayLength = end;
final int toBeFoundLength = toBeFound.length;
if (toBeFoundLength > arrayLength)
{
return -1;
}
if (toBeFoundLength == 0)
{
return 0;
}
if (toBeFoundLength == arrayLength)
{
if (isCaseSensitive)
{
for (int i = start; i < arrayLength; i++)
{
if (array[i] != toBeFound[i])
{
return -1;
}
}
return 0;
} else
{
for (int i = start; i < arrayLength; i++)
{
if (Character.toLowerCase(array[i]) != Character.toLowerCase(toBeFound[i]))
{
return -1;
}
}
return 0;
}
}
if (isCaseSensitive)
{
arrayLoop: for (int i = start, max = arrayLength - toBeFoundLength
+ 1; i < max; i++)
{
if (array[i] == toBeFound[0])
{
for (int j = 1; j < toBeFoundLength; j++)
{
if (array[i + j] != toBeFound[j])
{
continue arrayLoop;
}
}
return i;
}
}
} else
{
arrayLoop: for (int i = start, max = arrayLength - toBeFoundLength
+ 1; i < max; i++)
{
if (Character.toLowerCase(array[i]) == Character.toLowerCase(toBeFound[0]))
{
for (int j = 1; j < toBeFoundLength; j++)
{
if (Character.toLowerCase(array[i + j]) != Character.toLowerCase(toBeFound[j]))
{
continue arrayLoop;
}
}
return i;
}
}
}
return -1;
}
/**
* Answers the first index in the array for which the corresponding character is equal to toBeFound starting the
* search at index start. Answers -1 if no occurrence of this character is found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd' }
* start = 2
* result => 2
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd' }
* start = 3
* result => -1
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'e'
* array = { ' a', 'b', 'c', 'd' }
* start = 1
* result => -1
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the character to search
* @param array
* the array to be searched
* @param start
* the starting index
* @return the first index in the array for which the corresponding character is equal to toBeFound, -1 otherwise
* @throws NullPointerException
* if array is null
* @throws ArrayIndexOutOfBoundsException
* if start is lower than 0
*/
public static final int indexOf(char toBeFound, char[] array, int start)
{
for (int i = start; i < array.length; i++)
{
if (toBeFound == array[i])
{
return i;
}
}
return -1;
}
/**
* Answers the first index in the array for which the corresponding character is equal to toBeFound starting the
* search at index start and before the ending index. Answers -1 if no occurrence of this character is found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd' }
* start = 2
* result => 2
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd' }
* start = 3
* result => -1
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'e'
* array = { ' a', 'b', 'c', 'd' }
* start = 1
* result => -1
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the character to search
* @param array
* the array to be searched
* @param start
* the starting index (inclusive)
* @param end
* the ending index (exclusive)
* @return the first index in the array for which the corresponding character is equal to toBeFound, -1 otherwise
* @throws NullPointerException
* if array is null
* @throws ArrayIndexOutOfBoundsException
* if start is lower than 0 or ending greater than array length
*/
public static final int indexOf(char toBeFound, char[] array, int start,
int end)
{
for (int i = start; i < end; i++)
{
if (toBeFound == array[i])
{
return i;
}
}
return -1;
}
/**
* Answers the last index in the array for which the corresponding character is equal to toBeFound starting from the
* end of the array. Answers -1 if no occurrence of this character is found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd' , 'c', 'e' }
* result => 4
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'e'
* array = { ' a', 'b', 'c', 'd' }
* result => -1
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the character to search
* @param array
* the array to be searched
* @return the last index in the array for which the corresponding character is equal to toBeFound starting from the
* end of the array, -1 otherwise
* @throws NullPointerException
* if array is null
*/
public static final int lastIndexOf(char toBeFound, char[] array)
{
for (int i = array.length; --i >= 0;)
{
if (toBeFound == array[i])
{
return i;
}
}
return -1;
}
/**
* Answers the last index in the array for which the corresponding character is equal to toBeFound stopping at the
* index startIndex. Answers -1 if no occurrence of this character is found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd' }
* startIndex = 2
* result => 2
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd', 'e' }
* startIndex = 3
* result => -1
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'e'
* array = { ' a', 'b', 'c', 'd' }
* startIndex = 0
* result => -1
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the character to search
* @param array
* the array to be searched
* @param startIndex
* the stopping index
* @return the last index in the array for which the corresponding character is equal to toBeFound stopping at the
* index startIndex, -1 otherwise
* @throws NullPointerException
* if array is null
* @throws ArrayIndexOutOfBoundsException
* if startIndex is lower than 0
*/
public static final int lastIndexOf(char toBeFound, char[] array,
int startIndex)
{
for (int i = array.length; --i >= startIndex;)
{
if (toBeFound == array[i])
{
return i;
}
}
return -1;
}
/**
* Answers the last index in the array for which the corresponding character is equal to toBeFound starting from
* endIndex to startIndex. Answers -1 if no occurrence of this character is found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd' }
* startIndex = 2
* endIndex = 2
* result => 2
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { ' a', 'b', 'c', 'd', 'e' }
* startIndex = 3
* endIndex = 4
* result => -1
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'e'
* array = { ' a', 'b', 'c', 'd' }
* startIndex = 0
* endIndex = 3
* result => -1
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the character to search
* @param array
* the array to be searched
* @param startIndex
* the stopping index
* @param endIndex
* the starting index
* @return the last index in the array for which the corresponding character is equal to toBeFound starting from
* endIndex to startIndex, -1 otherwise
* @throws NullPointerException
* if array is null
* @throws ArrayIndexOutOfBoundsException
* if endIndex is greater or equals to array length or starting is lower than 0
*/
public static final int lastIndexOf(char toBeFound, char[] array,
int startIndex, int endIndex)
{
for (int i = endIndex; --i >= startIndex;)
{
if (toBeFound == array[i])
{
return i;
}
}
return -1;
}
/**
* Answers the last portion of a name given a separator. <br>
* <br>
* For example,
*
* <pre>
* lastSegment("java.lang.Object".toCharArray(),'.') --> Object
* </pre>
*
* @param array
* the array
* @param separator
* the given separator
* @return the last portion of a name given a separator
* @throws NullPointerException
* if array is null
*/
final static public char[] lastSegment(char[] array, char separator)
{
int pos = lastIndexOf(separator, array);
if (pos < 0)
{
return array;
}
return subarray(array, pos + 1, array.length);
}
/**
* Answers true if the pattern matches the given name, false otherwise. This char[] pattern matching accepts
* wild-cards '*' and '?'. When not case sensitive, the pattern is assumed to already be lowercased, the name will
* be lowercased character per character as comparing. If name is null, the answer is false. If pattern is null, the
* answer is true if name is not null. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* pattern = { '?', 'b', '*' }
* name = { 'a', 'b', 'c' , 'd' }
* isCaseSensitive = true
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* pattern = { '?', 'b', '?' }
* name = { 'a', 'b', 'c' , 'd' }
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* <li>
*
* <pre>
* pattern = { 'b', '*' }
* name = { 'a', 'b', 'c' , 'd' }
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* </ol>
*
* @param pattern
* the given pattern
* @param name
* the given name
* @param isCaseSensitive
* flag to know whether or not the matching should be case sensitive
* @return true if the pattern matches the given name, false otherwise
*/
public static final boolean match(char[] pattern, char[] name,
boolean isCaseSensitive)
{
if (name == null)
{
return false; // null name cannot match
}
if (pattern == null)
{
return true; // null pattern is equivalent to '*'
}
return match(pattern, 0, pattern.length, name, 0, name.length, isCaseSensitive);
}
/**
* Answers true if a sub-pattern matches the subpart of the given name, false otherwise. char[] pattern matching,
* accepting wild-cards '*' and '?'. Can match only subset of name/pattern. end positions are non-inclusive. The
* subpattern is defined by the patternStart and pattternEnd positions. When not case sensitive, the pattern is
* assumed to already be lowercased, the name will be lowercased character per character as comparing. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* pattern = { '?', 'b', '*' }
* patternStart = 1
* patternEnd = 3
* name = { 'a', 'b', 'c' , 'd' }
* nameStart = 1
* nameEnd = 4
* isCaseSensitive = true
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* pattern = { '?', 'b', '*' }
* patternStart = 1
* patternEnd = 2
* name = { 'a', 'b', 'c' , 'd' }
* nameStart = 1
* nameEnd = 2
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* </ol>
*
* @param pattern
* the given pattern
* @param patternStart
* the given pattern start
* @param patternEnd
* the given pattern end
* @param name
* the given name
* @param nameStart
* the given name start
* @param nameEnd
* the given name end
* @param isCaseSensitive
* flag to know if the matching should be case sensitive
* @return true if a sub-pattern matches the subpart of the given name, false otherwise
*/
public static final boolean match(char[] pattern, int patternStart,
int patternEnd, char[] name, int nameStart, int nameEnd,
boolean isCaseSensitive)
{
if (name == null)
{
return false; // null name cannot match
}
if (pattern == null)
{
return true; // null pattern is equivalent to '*'
}
int iPattern = patternStart;
int iName = nameStart;
if (patternEnd < 0)
{
patternEnd = pattern.length;
}
if (nameEnd < 0)
{
nameEnd = name.length;
}
/* check first segment */
char patternChar = 0;
while (iPattern < patternEnd
&& (patternChar = pattern[iPattern]) != '*')
{
if (iName == nameEnd)
{
return false;
}
if (patternChar != (isCaseSensitive ? name[iName]
: Character.toLowerCase(name[iName])) && patternChar != '?')
{
return false;
}
iName++;
iPattern++;
}
/* check sequence of star+segment */
int segmentStart;
if (patternChar == '*')
{
segmentStart = ++iPattern; // skip star
} else
{
segmentStart = 0; // force iName check
}
int prefixStart = iName;
checkSegment: while (iName < nameEnd)
{
if (iPattern == patternEnd)
{
iPattern = segmentStart; // mismatch - restart current
// segment
iName = ++prefixStart;
continue checkSegment;
}
/* segment is ending */
if ((patternChar = pattern[iPattern]) == '*')
{
segmentStart = ++iPattern; // skip start
if (segmentStart == patternEnd)
{
return true;
}
prefixStart = iName;
continue checkSegment;
}
/* check current name character */
if ((isCaseSensitive ? name[iName]
: Character.toLowerCase(name[iName])) != patternChar
&& patternChar != '?')
{
iPattern = segmentStart; // mismatch - restart current
// segment
iName = ++prefixStart;
continue checkSegment;
}
iName++;
iPattern++;
}
return segmentStart == patternEnd || iName == nameEnd
&& iPattern == patternEnd || iPattern == patternEnd - 1
&& pattern[iPattern] == '*';
}
/**
* Answers true if the pattern matches the filepath using the pathSepatator, false otherwise. Path char[] pattern
* matching, accepting wild-cards '**', '*' and '?' (using Ant directory tasks conventions, also see
* "http://jakarta.apache.org/ant/manual/dirtasks.html#defaultexcludes"). Path pattern matching is enhancing regular
* pattern matching in supporting extra rule where '**' represent any folder combination. Special rule: - foo\ is
* equivalent to foo\** When not case sensitive, the pattern is assumed to already be lowercased, the name will be
* lowercased character per character as comparing.
*
* @param pattern
* the given pattern
* @param filepath
* the given path
* @param isCaseSensitive
* to find out whether or not the matching should be case sensitive
* @param pathSeparator
* the given path separator
* @return true if the pattern matches the filepath using the pathSepatator, false otherwise
*/
public static final boolean pathMatch(char[] pattern, char[] filepath,
boolean isCaseSensitive, char pathSeparator)
{
if (filepath == null)
{
return false; // null name cannot match
}
if (pattern == null)
{
return true; // null pattern is equivalent to '*'
}
// offsets inside pattern
int pSegmentStart = pattern[0] == pathSeparator ? 1 : 0;
int pLength = pattern.length;
int pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart + 1);
if (pSegmentEnd < 0)
{
pSegmentEnd = pLength;
}
// special case: pattern foo\ is equivalent to foo\**
boolean freeTrailingDoubleStar = pattern[pLength - 1] == pathSeparator;
// offsets inside filepath
int fSegmentStart, fLength = filepath.length;
if (filepath[0] != pathSeparator)
{
fSegmentStart = 0;
} else
{
fSegmentStart = 1;
}
if (fSegmentStart != pSegmentStart)
{
return false; // both must start with a separator or none.
}
int fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart + 1);
if (fSegmentEnd < 0)
{
fSegmentEnd = fLength;
}
// first segments
while (pSegmentStart < pLength
&& !(pSegmentEnd == pLength && freeTrailingDoubleStar || pSegmentEnd == pSegmentStart + 2
&& pattern[pSegmentStart] == '*'
&& pattern[pSegmentStart + 1] == '*'))
{
if (fSegmentStart >= fLength)
{
return false;
}
if (!CharOperation.match(pattern, pSegmentStart, pSegmentEnd, filepath, fSegmentStart, fSegmentEnd, isCaseSensitive))
{
return false;
}
// jump to next segment
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
// skip separator
if (pSegmentEnd < 0)
{
pSegmentEnd = pLength;
}
fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentEnd + 1);
// skip separator
if (fSegmentEnd < 0)
{
fSegmentEnd = fLength;
}
}
/* check sequence of doubleStar+segment */
int pSegmentRestart;
if (pSegmentStart >= pLength && freeTrailingDoubleStar
|| pSegmentEnd == pSegmentStart + 2
&& pattern[pSegmentStart] == '*'
&& pattern[pSegmentStart + 1] == '*')
{
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
// skip separator
if (pSegmentEnd < 0)
{
pSegmentEnd = pLength;
}
pSegmentRestart = pSegmentStart;
} else
{
if (pSegmentStart >= pLength)
{
return fSegmentStart >= fLength; // true if filepath is done
}
// too.
pSegmentRestart = 0; // force fSegmentStart check
}
int fSegmentRestart = fSegmentStart;
checkSegment: while (fSegmentStart < fLength)
{
if (pSegmentStart >= pLength)
{
if (freeTrailingDoubleStar)
{
return true;
}
// mismatch - restart current path segment
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
if (pSegmentEnd < 0)
{
pSegmentEnd = pLength;
}
fSegmentRestart = CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
// skip separator
if (fSegmentRestart < 0)
{
fSegmentRestart = fLength;
} else
{
fSegmentRestart++;
}
fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
if (fSegmentEnd < 0)
{
fSegmentEnd = fLength;
}
continue checkSegment;
}
/* path segment is ending */
if (pSegmentEnd == pSegmentStart + 2
&& pattern[pSegmentStart] == '*'
&& pattern[pSegmentStart + 1] == '*')
{
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
// skip separator
if (pSegmentEnd < 0)
{
pSegmentEnd = pLength;
}
pSegmentRestart = pSegmentStart;
fSegmentRestart = fSegmentStart;
if (pSegmentStart >= pLength)
{
return true;
}
continue checkSegment;
}
/* chech current path segment */
if (!CharOperation.match(pattern, pSegmentStart, pSegmentEnd, filepath, fSegmentStart, fSegmentEnd, isCaseSensitive))
{
// mismatch - restart current path segment
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentRestart);
if (pSegmentEnd < 0)
{
pSegmentEnd = pLength;
}
fSegmentRestart = CharOperation.indexOf(pathSeparator, filepath, fSegmentRestart + 1);
// skip separator
if (fSegmentRestart < 0)
{
fSegmentRestart = fLength;
} else
{
fSegmentRestart++;
}
fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentRestart);
if (fSegmentEnd < 0)
{
fSegmentEnd = fLength;
}
continue checkSegment;
}
// jump to next segment
pSegmentEnd = CharOperation.indexOf(pathSeparator, pattern, pSegmentStart = pSegmentEnd + 1);
// skip separator
if (pSegmentEnd < 0)
{
pSegmentEnd = pLength;
}
fSegmentEnd = CharOperation.indexOf(pathSeparator, filepath, fSegmentStart = fSegmentEnd + 1);
// skip separator
if (fSegmentEnd < 0)
{
fSegmentEnd = fLength;
}
}
return pSegmentRestart >= pSegmentEnd || fSegmentStart >= fLength
&& pSegmentStart >= pLength || pSegmentStart == pLength - 2
&& pattern[pSegmentStart] == '*'
&& pattern[pSegmentStart + 1] == '*'
|| pSegmentStart == pLength && freeTrailingDoubleStar;
}
/**
* Answers the number of occurrences of the given character in the given array, 0 if any. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = 'b'
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* result => 3
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* result => 0
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the given character
* @param array
* the given array
* @return the number of occurrences of the given character in the given array, 0 if any
* @throws NullPointerException
* if array is null
*/
public static final int occurencesOf(char toBeFound, char[] array)
{
int count = 0;
for (int i = 0; i < array.length; i++)
{
if (toBeFound == array[i])
{
count++;
}
}
return count;
}
/**
* Answers the number of occurrences of the given character in the given array starting at the given index, 0 if
* any. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* toBeFound = 'b'
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* start = 2
* result => 2
* </pre>
*
* </li>
* <li>
*
* <pre>
* toBeFound = 'c'
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* start = 0
* result => 0
* </pre>
*
* </li>
* </ol>
*
* @param toBeFound
* the given character
* @param array
* the given array
* @param start
* the given index
* @return the number of occurrences of the given character in the given array, 0 if any
* @throws NullPointerException
* if array is null
* @throws ArrayIndexOutOfBoundsException
* if start is lower than 0
*/
public static final int occurencesOf(char toBeFound, char[] array, int start)
{
int count = 0;
for (int i = start; i < array.length; i++)
{
if (toBeFound == array[i])
{
count++;
}
}
return count;
}
/**
* Answers true if the given name starts with the given prefix, false otherwise. The comparison is case sensitive. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* prefix = { 'a' , 'b' }
* name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* prefix = { 'a' , 'c' }
* name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* result => false
* </pre>
*
* </li>
* </ol>
*
* @param prefix
* the given prefix
* @param name
* the given name
* @return true if the given name starts with the given prefix, false otherwise
* @throws NullPointerException
* if the given name is null or if the given prefix is null
*/
public static final boolean prefixEquals(char[] prefix, char[] name)
{
int max = prefix.length;
if (name.length < max)
{
return false;
}
for (int i = max; --i >= 0;)
{
// assumes the prefix is not larger than the name
if (prefix[i] != name[i])
{
return false;
}
}
return true;
}
/**
* Answers true if the given name starts with the given prefix, false otherwise. isCaseSensitive is used to find out
* whether or not the comparison should be case sensitive. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* prefix = { 'a' , 'B' }
* name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* isCaseSensitive = false
* result => true
* </pre>
*
* </li>
* <li>
*
* <pre>
* prefix = { 'a' , 'B' }
* name = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* isCaseSensitive = true
* result => false
* </pre>
*
* </li>
* </ol>
*
* @param prefix
* the given prefix
* @param name
* the given name
* @param isCaseSensitive
* to find out whether or not the comparison should be case sensitive
* @return true if the given name starts with the given prefix, false otherwise
* @throws NullPointerException
* if the given name is null or if the given prefix is null
*/
public static final boolean prefixEquals(char[] prefix, char[] name,
boolean isCaseSensitive)
{
int max = prefix.length;
if (name.length < max)
{
return false;
}
if (isCaseSensitive)
{
for (int i = max; --i >= 0;)
{
// assumes the prefix is not larger than the name
if (prefix[i] != name[i])
{
return false;
}
}
return true;
}
for (int i = max; --i >= 0;)
{
// assumes the prefix is not larger than the name
if (Character.toLowerCase(prefix[i]) != Character.toLowerCase(name[i]))
{
return false;
}
}
return true;
}
/**
* Replace all occurrence of the character to be replaced with the remplacement character in the given array. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* toBeReplaced = 'b'
* replacementChar = 'a'
* result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* toBeReplaced = 'c'
* replacementChar = 'a'
* result => No returned value, but array is now equals to { 'a' , 'b', 'b', 'a', 'b', 'a' }
* </pre>
*
* </li>
* </ol>
*
* @param array
* the given array
* @param toBeReplaced
* the character to be replaced
* @param replacementChar
* the replacement character
* @throws NullPointerException
* if the given array is null
*/
public static final void replace(char[] array, char toBeReplaced,
char replacementChar)
{
if (toBeReplaced != replacementChar)
{
for (int i = 0, max = array.length; i < max; i++)
{
if (array[i] == toBeReplaced)
{
array[i] = replacementChar;
}
}
}
}
/**
* Replace all occurrence of characters to be replaced with the remplacement character in the given array. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* array = { 'a' , 'b', 'b', 'c', 'a', 'b', 'c', 'a' }
* toBeReplaced = { 'b', 'c' }
* replacementChar = 'a'
* result => No returned value, but array is now equals to { 'a' , 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
* </pre>
*
* </li>
* </ol>
*
* @param array
* the given array
* @param toBeReplaced
* characters to be replaced
* @param replacementChar
* the replacement character
* @throws NullPointerException
* if arrays are null.
*/
public static final void replace(char[] array, char[] toBeReplaced,
char replacementChar)
{
for (int i = array.length; --i >= 0;)
{
for (int j = toBeReplaced.length; --j >= 0;)
{
if (array[i] == toBeReplaced[j])
{
array[i] = replacementChar;
}
}
}
}
/**
* Answers a new array of characters with substitutions. No side-effect is operated on the original array, in case
* no substitution happened, then the result is the same as the original one. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* toBeReplaced = { 'b' }
* replacementChar = { 'a', 'a' }
* result => { 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* toBeReplaced = { 'c' }
* replacementChar = { 'a' }
* result => { 'a' , 'b', 'b', 'a', 'b', 'a' }
* </pre>
*
* </li>
* </ol>
*
* @param array
* the given array
* @param toBeReplaced
* characters to be replaced
* @param replacementChars
* the replacement characters
* @return a new array of characters with substitutions or the given array if none
* @throws NullPointerException
* if the given array is null
*/
public static final char[] replace(char[] array, char[] toBeReplaced,
char[] replacementChars)
{
int max = array.length;
int replacedLength = toBeReplaced.length;
int replacementLength = replacementChars.length;
int[] starts = new int[5];
int occurrenceCount = 0;
if (!equals(toBeReplaced, replacementChars))
{
next: for (int i = 0; i < max; i++)
{
int j = 0;
while (j < replacedLength)
{
if (i + j == max)
{
continue next;
}
if (array[i + j] != toBeReplaced[j++])
{
continue next;
}
}
if (occurrenceCount == starts.length)
{
System.arraycopy(starts, 0, starts = new int[occurrenceCount * 2], 0, occurrenceCount);
}
starts[occurrenceCount++] = i;
}
}
if (occurrenceCount == 0)
{
return array;
}
char[] result = new char[max + occurrenceCount
* (replacementLength - replacedLength)];
int inStart = 0, outStart = 0;
for (int i = 0; i < occurrenceCount; i++)
{
int offset = starts[i] - inStart;
System.arraycopy(array, inStart, result, outStart, offset);
inStart += offset;
outStart += offset;
System.arraycopy(replacementChars, 0, result, outStart, replacementLength);
inStart += replacedLength;
outStart += replacementLength;
}
System.arraycopy(array, inStart, result, outStart, max - inStart);
return result;
}
/**
* Replace all occurrence of the character to be replaced with the remplacement character in a copy of the given
* array. Returns the given array if no occurrences of the character to be replaced are found. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* toBeReplaced = 'b'
* replacementChar = 'a'
* result => A new array that is equals to { 'a' , 'a', 'a', 'a', 'a', 'a' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* toBeReplaced = 'c'
* replacementChar = 'a'
* result => The original array that remains unchanged.
* </pre>
*
* </li>
* </ol>
*
* @param array
* the given array
* @param toBeReplaced
* the character to be replaced
* @param replacementChar
* the replacement character
* @throws NullPointerException
* if the given array is null
*/
public static final char[] replaceOnCopy(char[] array, char toBeReplaced,
char replacementChar)
{
char[] result = null;
for (int i = 0, length = array.length; i < length; i++)
{
char c = array[i];
if (c == toBeReplaced)
{
if (result == null)
{
result = new char[length];
System.arraycopy(array, 0, result, 0, i);
}
result[i] = replacementChar;
} else if (result != null)
{
result[i] = c;
}
}
if (result == null)
{
return array;
}
return result;
}
/**
* Return a new array which is the split of the given array using the given divider and triming each subarray to
* remove whitespaces equals to ' '. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* divider = 'b'
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* result => { { 'a' }, { }, { 'a' }, { 'a' } }
* </pre>
*
* </li>
* <li>
*
* <pre>
* divider = 'c'
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
* </pre>
*
* </li>
* <li>
*
* <pre>
* divider = 'b'
* array = { 'a' , ' ', 'b', 'b', 'a', 'b', 'a' }
* result => { { 'a' }, { }, { 'a' }, { 'a' } }
* </pre>
*
* </li>
* <li>
*
* <pre>
* divider = 'c'
* array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
* result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
* </pre>
*
* </li>
* </ol>
*
* @param divider
* the given divider
* @param array
* the given array
* @return a new array which is the split of the given array using the given divider and triming each subarray to
* remove whitespaces equals to ' '
*/
public static final char[][] splitAndTrimOn(char divider, char[] array)
{
int length = array == null ? 0 : array.length;
if (length == 0)
{
return NO_CHAR_CHAR;
}
int wordCount = 1;
for (int i = 0; i < length; i++)
{
if (array[i] == divider)
{
wordCount++;
}
}
char[][] split = new char[wordCount][];
int last = 0, currentWord = 0;
for (int i = 0; i < length; i++)
{
if (array[i] == divider)
{
int start = last, end = i - 1;
while (start < i && array[start] == ' ')
{
start++;
}
while (end > start && array[end] == ' ')
{
end--;
}
split[currentWord] = new char[end - start + 1];
System.arraycopy(array, start, split[currentWord++], 0, end
- start + 1);
last = i + 1;
}
}
int start = last, end = length - 1;
while (start < length && array[start] == ' ')
{
start++;
}
while (end > start && array[end] == ' ')
{
end--;
}
split[currentWord] = new char[end - start + 1];
System.arraycopy(array, start, split[currentWord++], 0, end - start + 1);
return split;
}
/**
* Return a new array which is the split of the given array using the given divider. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* divider = 'b'
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* result => { { 'a' }, { }, { 'a' }, { 'a' } }
* </pre>
*
* </li>
* <li>
*
* <pre>
* divider = 'c'
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* result => { { 'a', 'b', 'b', 'a', 'b', 'a' } }
* </pre>
*
* </li>
* <li>
*
* <pre>
* divider = 'c'
* array = { ' ', ' ', 'a' , 'b', 'b', 'a', 'b', 'a', ' ' }
* result => { { ' ', 'a', 'b', 'b', 'a', 'b', 'a', ' ' } }
* </pre>
*
* </li>
* </ol>
*
* @param divider
* the given divider
* @param array
* the given array
* @return a new array which is the split of the given array using the given divider
*/
public static final char[][] splitOn(char divider, char[] array)
{
int length = array == null ? 0 : array.length;
if (length == 0)
{
return NO_CHAR_CHAR;
}
int wordCount = 1;
for (int i = 0; i < length; i++)
{
if (array[i] == divider)
{
wordCount++;
}
}
char[][] split = new char[wordCount][];
int last = 0, currentWord = 0;
for (int i = 0; i < length; i++)
{
if (array[i] == divider)
{
split[currentWord] = new char[i - last];
System.arraycopy(array, last, split[currentWord++], 0, i - last);
last = i + 1;
}
}
split[currentWord] = new char[length - last];
System.arraycopy(array, last, split[currentWord], 0, length - last);
return split;
}
/**
* Return a new array which is the split of the given array using the given divider.
*
* @param divider
* the given divider
* @param array
* the given array
* @return a new array which is the split of the given array using the given divider or <code>null</code> if
* {@code array} parameter is <code>null</code>.
*/
public static final char[][] splitOn(char[] divider, char[] array)
{
if (array == null)
{
return null;
}
int length = array.length;
if (length == 0)
{
return NO_CHAR_CHAR;
}
int wordCount = 1;
{
int i = 0;
while (i + divider.length <= length)
{
i = indexOf(divider, array, false, i);
if (i == -1)
{
break;
}
++wordCount;
i += divider.length;
}
}
char[][] split = new char[wordCount][];
int last = 0, currentWord = 0;
int i = 0;
while (i + divider.length <= length)
{
i = indexOf(divider, array, false, i);
if (i == -1)
{
break;
}
split[currentWord] = new char[i - last];
System.arraycopy(array, last, split[currentWord++], 0, i - last);
i += divider.length;
last = i;
}
split[currentWord] = new char[length - last];
System.arraycopy(array, last, split[currentWord], 0, length - last);
return split;
}
/**
* Return a new array which is the split of the given array using the given divider. The given end is exclusive and
* the given start is inclusive. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* divider = 'b'
* array = { 'a' , 'b', 'b', 'a', 'b', 'a' }
* start = 2
* end = 5
* result => { { }, { 'a' }, { } }
* </pre>
*
* </li>
* </ol>
*
* @param divider
* the given divider
* @param array
* the given array
* @param start
* the given starting index
* @param end
* the given ending index
* @return a new array which is the split of the given array using the given divider
* @throws ArrayIndexOutOfBoundsException
* if start is lower than 0 or end is greater than the array length
*/
public static final char[][] splitOn(char divider, char[] array, int start,
int end)
{
int length = array == null ? 0 : array.length;
if (length == 0 || start > end)
{
return NO_CHAR_CHAR;
}
int wordCount = 1;
for (int i = start; i < end; i++)
{
if (array[i] == divider)
{
wordCount++;
}
}
char[][] split = new char[wordCount][];
int last = start, currentWord = 0;
for (int i = start; i < end; i++)
{
if (array[i] == divider)
{
split[currentWord] = new char[i - last];
System.arraycopy(array, last, split[currentWord++], 0, i - last);
last = i + 1;
}
}
split[currentWord] = new char[end - last];
System.arraycopy(array, last, split[currentWord], 0, end - last);
return split;
}
/**
* Answers a new array which is a copy of the given array starting at the given start and ending at the given end.
* The given start is inclusive and the given end is exclusive. Answers null if start is greater than end, if start
* is lower than 0 or if end is greater than the length of the given array. If end equals -1, it is converted to the
* array length. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* array = { { 'a' } , { 'b' } }
* start = 0
* end = 1
* result => { { 'a' } }
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { { 'a' } , { 'b' } }
* start = 0
* end = -1
* result => { { 'a' }, { 'b' } }
* </pre>
*
* </li>
* </ol>
*
* @param array
* the given array
* @param start
* the given starting index
* @param end
* the given ending index
* @return a new array which is a copy of the given array starting at the given start and ending at the given end
* @throws NullPointerException
* if the given array is null
*/
public static final char[][] subarray(char[][] array, int start, int end)
{
if (end == -1)
{
end = array.length;
}
if (start > end)
{
return null;
}
if (start < 0)
{
return null;
}
if (end > array.length)
{
return null;
}
char[][] result = new char[end - start][];
System.arraycopy(array, start, result, 0, end - start);
return result;
}
/**
* Answers a new array which is a copy of the given array starting at the given start and ending at the given end.
* The given start is inclusive and the given end is exclusive. Answers null if start is greater than end, if start
* is lower than 0 or if end is greater than the length of the given array. If end equals -1, it is converted to the
* array length. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* array = { 'a' , 'b' }
* start = 0
* end = 1
* result => { 'a' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'a', 'b' }
* start = 0
* end = -1
* result => { 'a' , 'b' }
* </pre>
*
* </li>
* </ol>
*
* @param array
* the given array
* @param start
* the given starting index
* @param end
* the given ending index
* @return a new array which is a copy of the given array starting at the given start and ending at the given end
* @throws NullPointerException
* if the given array is null
*/
public static final char[] subarray(char[] array, int start, int end)
{
if (end == -1)
{
end = array.length;
}
if (start > end)
{
return null;
}
if (start < 0)
{
return null;
}
if (end > array.length)
{
return null;
}
char[] result = new char[end - start];
System.arraycopy(array, start, result, 0, end - start);
return result;
}
/**
* Answers the result of a char[] conversion to lowercase. Answers null if the given chars array is null. <br>
* NOTE: If no conversion was necessary, then answers back the argument one. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* chars = { 'a' , 'b' }
* result => { 'a' , 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'A', 'b' }
* result => { 'a' , 'b' }
* </pre>
*
* </li>
* </ol>
*
* @param chars
* the chars to convert
* @return the result of a char[] conversion to lowercase
*/
final static public char[] toLowerCase(char[] chars)
{
if (chars == null)
{
return null;
}
int length = chars.length;
char[] lowerChars = null;
for (int i = 0; i < length; i++)
{
char c = chars[i];
char lc = Character.toLowerCase(c);
if (c != lc || lowerChars != null)
{
if (lowerChars == null)
{
System.arraycopy(chars, 0, lowerChars = new char[length], 0, i);
}
lowerChars[i] = lc;
}
}
return lowerChars == null ? chars : lowerChars;
}
/**
* Answers a new array removing leading and trailing spaces (' '). Answers the given array if there is no space
* characters to remove. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* chars = { ' ', 'a' , 'b', ' ', ' ' }
* result => { 'a' , 'b' }
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { 'A', 'b' }
* result => { 'A' , 'b' }
* </pre>
*
* </li>
* </ol>
*
* @param chars
* the given array
* @return a new array removing leading and trailing spaces (' ')
*/
final static public char[] trim(char[] chars)
{
if (chars == null)
{
return null;
}
int start = 0, length = chars.length, end = length - 1;
while (start < length && chars[start] == ' ')
{
start++;
}
while (end > start && chars[end] == ' ')
{
end--;
}
if (start != 0 || end != length - 1)
{
return subarray(chars, start, end + 1);
}
return chars;
}
/**
* Answers a string which is the concatenation of the given array using the '.' as a separator. <br>
* <br>
* For example:
* <ol>
* <li>
*
* <pre>
* array = { { 'a' } , { 'b' } }
* result => "a.b"
* </pre>
*
* </li>
* <li>
*
* <pre>
* array = { { ' ', 'a' } , { 'b' } }
* result => " a.b"
* </pre>
*
* </li>
* </ol>
*
* @param array
* the given array
* @return a string which is the concatenation of the given array using the '.' as a separator
*/
final static public String toString(char[][] array)
{
char[] result = concatWith(array, '.');
return new String(result);
}
/**
* Answers an array of strings from the given array of char array.
*
* @param array
* the given array
* @return an array of strings
*/
final static public String[] toStrings(char[][] array)
{
if (array == null)
{
return NO_STRINGS;
}
int length = array.length;
if (length == 0)
{
return NO_STRINGS;
}
String[] result = new String[length];
for (int i = 0; i < length; i++)
{
result[i] = new String(array[i]);
}
return result;
}
/**
* @param name
* @param separator
* @return
*/
public static String lastSegment(String name, char separator)
{
int pos = name.lastIndexOf(separator);
if (pos >= 0)
{
return name.substring(pos + 1);
} else
{
return name;
}
}
}