X-Git-Url: http://secure.phpeclipse.com
diff --git a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java
index 39b4d39..96a21b0 100644
--- a/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java
+++ b/net.sourceforge.phpeclipse/src/net/sourceforge/phpdt/internal/core/util/Util.java
@@ -30,10 +30,10 @@ import net.sourceforge.phpdt.core.JavaCore;
import net.sourceforge.phpdt.core.JavaModelException;
import net.sourceforge.phpdt.core.Signature;
import net.sourceforge.phpdt.core.compiler.CharOperation;
+import net.sourceforge.phpdt.internal.compiler.ast.TypeReference;
import net.sourceforge.phpdt.internal.core.Assert;
import net.sourceforge.phpdt.internal.core.PackageFragmentRoot;
import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
-import net.sourceforge.phpeclipse.internal.compiler.ast.TypeReference;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
@@ -51,1742 +51,1887 @@ import org.eclipse.text.edits.TextEdit;
*/
public class Util {
- public interface Comparable {
- /**
- * Returns 0 if this and c are equal, >0 if this is greater than c, or <0 if this is less than c.
- */
- int compareTo(Comparable c);
- }
-
- public interface Comparer {
- /**
- * Returns 0 if a and b are equal, >0 if a is greater than b, or <0 if a is less than b.
- */
- int compare(Object a, Object b);
- }
-
- private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
-
- /* Bundle containing messages */
- protected static ResourceBundle bundle;
-
- private final static String bundleName = "net.sourceforge.phpdt.internal.core.util.messages"; //$NON-NLS-1$
-
- private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
-
- private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$
-
- public static final String[] fgEmptyStringArray = new String[0];
-
- private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
-
- static {
- relocalize();
- }
-
- private Util() {
- // cannot be instantiated
- }
-
- /**
- * Lookup the message with the given ID in this catalog
- */
- public static String bind(String id) {
- return bind(id, (String[]) null);
- }
-
- /**
- * Lookup the message with the given ID in this catalog and bind its substitution locations with the given string.
- */
- public static String bind(String id, String binding) {
- return bind(id, new String[] { binding });
- }
-
- /**
- * Lookup the message with the given ID in this catalog and bind its substitution locations with the given strings.
- */
- public static String bind(String id, String binding1, String binding2) {
- return bind(id, new String[] { binding1, binding2 });
- }
-
- /**
- * Lookup the message with the given ID in this catalog and bind its substitution locations with the given string values.
- */
- public static String bind(String id, String[] bindings) {
- if (id == null)
- return "No message available"; //$NON-NLS-1$
- String message = null;
- try {
- message = bundle.getString(id);
- } catch (MissingResourceException e) {
- // If we got an exception looking for the message, fail gracefully by just returning
- // the id we were looking for. In most cases this is semi-informative so is not too bad.
- return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
- }
- // for compatibility with MessageFormat which eliminates double quotes in original message
- char[] messageWithNoDoubleQuotes = CharOperation.replace(message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
-
- if (bindings == null)
- return new String(messageWithNoDoubleQuotes);
-
- int length = messageWithNoDoubleQuotes.length;
- int start = 0;
- int end = length;
- StringBuffer output = null;
- while (true) {
- if ((end = CharOperation.indexOf('{', messageWithNoDoubleQuotes, start)) > -1) {
- if (output == null)
- output = new StringBuffer(length + bindings.length * 20);
- output.append(messageWithNoDoubleQuotes, start, end - start);
- if ((start = CharOperation.indexOf('}', messageWithNoDoubleQuotes, end + 1)) > -1) {
- int index = -1;
- String argId = new String(messageWithNoDoubleQuotes, end + 1, start - end - 1);
- try {
- index = Integer.parseInt(argId);
- output.append(bindings[index]);
- } catch (NumberFormatException nfe) { // could be nested message ID {compiler.name}
- boolean done = false;
- if (!id.equals(argId)) {
- String argMessage = null;
- try {
- argMessage = bundle.getString(argId);
- output.append(argMessage);
- done = true;
- } catch (MissingResourceException e) {
- // unable to bind argument, ignore (will leave argument in)
- }
- }
- if (!done)
- output.append(messageWithNoDoubleQuotes, end + 1, start - end);
- } catch (ArrayIndexOutOfBoundsException e) {
- output.append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
- }
- start++;
- } else {
- output.append(messageWithNoDoubleQuotes, end, length);
- break;
- }
- } else {
- if (output == null)
- return new String(messageWithNoDoubleQuotes);
- output.append(messageWithNoDoubleQuotes, start, length - start);
- break;
- }
- }
- return output.toString();
- }
-
- /**
- * Checks the type signature in String sig, starting at start and ending before end (end is not included). Returns the index of
- * the character immediately after the signature if valid, or -1 if not valid.
- */
- private static int checkTypeSignature(String sig, int start, int end, boolean allowVoid) {
- if (start >= end)
- return -1;
- int i = start;
- char c = sig.charAt(i++);
- int nestingDepth = 0;
- while (c == '[') {
- ++nestingDepth;
- if (i >= end)
- return -1;
- c = sig.charAt(i++);
- }
- switch (c) {
- case 'B':
- case 'C':
- case 'D':
- case 'F':
- case 'I':
- case 'J':
- case 'S':
- case 'Z':
- break;
- case 'V':
- if (!allowVoid)
- return -1;
- // array of void is not allowed
- if (nestingDepth != 0)
- return -1;
- break;
- case 'L':
- int semicolon = sig.indexOf(';', i);
- // Must have at least one character between L and ;
- if (semicolon <= i || semicolon >= end)
- return -1;
- i = semicolon + 1;
- break;
- default:
- return -1;
- }
- return i;
- }
-
- /**
- * Combines two hash codes to make a new one.
- */
- public static int combineHashCodes(int hashCode1, int hashCode2) {
- return hashCode1 * 17 + hashCode2;
- }
-
- /**
- * Compares two byte arrays. Returns <0 if a byte in a is less than the corresponding byte in b, or if a is shorter, or if a is
- * null. Returns >0 if a byte in a is greater than the corresponding byte in b, or if a is longer, or if b is null. Returns 0 if
- * they are equal or both null.
- */
- public static int compare(byte[] a, byte[] b) {
- if (a == b)
- return 0;
- if (a == null)
- return -1;
- if (b == null)
- return 1;
- int len = Math.min(a.length, b.length);
- for (int i = 0; i < len; ++i) {
- int diff = a[i] - b[i];
- if (diff != 0)
- return diff;
- }
- if (a.length > len)
- return 1;
- if (b.length > len)
- return -1;
- return 0;
- }
-
- /**
- * Compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings.
- *
- * @return the value 0
if the str1 is equal to str2; a value less than 0
if str1 is
- * lexicographically less than str2; and a value greater than 0
if str1 is lexicographically greater than
- * str2.
- */
- public static int compare(char[] str1, char[] str2) {
- int len1 = str1.length;
- int len2 = str2.length;
- int n = Math.min(len1, len2);
- int i = 0;
- while (n-- != 0) {
- char c1 = str1[i];
- char c2 = str2[i++];
- if (c1 != c2) {
- return c1 - c2;
- }
- }
- return len1 - len2;
- }
-
- /**
- * Concatenate two strings with a char in between.
- *
- * @see #concat(String, String)
- */
- public static String concat(String s1, char c, String s2) {
- if (s1 == null)
- s1 = "null"; //$NON-NLS-1$
- if (s2 == null)
- s2 = "null"; //$NON-NLS-1$
- int l1 = s1.length();
- int l2 = s2.length();
- char[] buf = new char[l1 + 1 + l2];
- s1.getChars(0, l1, buf, 0);
- buf[l1] = c;
- s2.getChars(0, l2, buf, l1 + 1);
- return new String(buf);
- }
-
- /**
- * Concatenate two strings. Much faster than using +, which: - creates a StringBuffer, - which is synchronized, - of default size,
- * so the resulting char array is often larger than needed. This implementation creates an extra char array, since the String
- * constructor copies its argument, but there's no way around this.
- */
- public static String concat(String s1, String s2) {
- if (s1 == null)
- s1 = "null"; //$NON-NLS-1$
- if (s2 == null)
- s2 = "null"; //$NON-NLS-1$
- int l1 = s1.length();
- int l2 = s2.length();
- char[] buf = new char[l1 + l2];
- s1.getChars(0, l1, buf, 0);
- s2.getChars(0, l2, buf, l1);
- return new String(buf);
- }
-
- /**
- * Concatenate three strings.
- *
- * @see #concat(String, String)
- */
- public static String concat(String s1, String s2, String s3) {
- if (s1 == null)
- s1 = "null"; //$NON-NLS-1$
- if (s2 == null)
- s2 = "null"; //$NON-NLS-1$
- if (s3 == null)
- s3 = "null"; //$NON-NLS-1$
- int l1 = s1.length();
- int l2 = s2.length();
- int l3 = s3.length();
- char[] buf = new char[l1 + l2 + l3];
- s1.getChars(0, l1, buf, 0);
- s2.getChars(0, l2, buf, l1);
- s3.getChars(0, l3, buf, l1 + l2);
- return new String(buf);
- }
-
- /**
- * Converts a type signature from the IBinaryType representation to the DC representation.
- */
- public static String convertTypeSignature(char[] sig) {
- return new String(sig).replace('/', '.');
- }
-
- /**
- * Apply the given edit on the given string and return the updated string. Return the given string if anything wrong happen while
- * applying the edit.
- *
- * @param original
- * the given string
- * @param edit
- * the given edit
- *
- * @return the updated string
- */
- public final static String editedString(String original, TextEdit edit) {
- if (edit == null) {
- return original;
- }
- SimpleDocument document = new SimpleDocument(original);
- try {
- edit.apply(document, TextEdit.NONE);
- return document.get();
- } catch (MalformedTreeException e) {
- e.printStackTrace();
- } catch (BadLocationException e) {
- e.printStackTrace();
- }
- return original;
- }
-
- /**
- * Returns true iff str.toLowerCase().endsWith(end.toLowerCase()) implementation is not creating extra strings.
- */
- public final static boolean endsWithIgnoreCase(String str, String end) {
-
- int strLength = str == null ? 0 : str.length();
- int endLength = end == null ? 0 : end.length();
-
- // return false if the string is smaller than the end.
- if (endLength > strLength)
- return false;
-
- // return false if any character of the end are
- // not the same in lower case.
- for (int i = 1; i <= endLength; i++) {
- if (Character.toLowerCase(end.charAt(endLength - i)) != Character.toLowerCase(str.charAt(strLength - i)))
- return false;
- }
-
- return true;
- }
-
- /**
- * Compares two arrays using equals() on the elements. Either or both arrays may be null. Returns true if both are null. Returns
- * false if only one is null. If both are arrays, returns true iff they have the same length and all elements are equal.
- */
- public static boolean equalArraysOrNull(int[] a, int[] b) {
- if (a == b)
- return true;
- if (a == null || b == null)
- return false;
- int len = a.length;
- if (len != b.length)
- return false;
- for (int i = 0; i < len; ++i) {
- if (a[i] != b[i])
- return false;
- }
- return true;
- }
-
- /**
- * Compares two arrays using equals() on the elements. Either or both arrays may be null. Returns true if both are null. Returns
- * false if only one is null. If both are arrays, returns true iff they have the same length and all elements compare true with
- * equals.
- */
- public static boolean equalArraysOrNull(Object[] a, Object[] b) {
- if (a == b)
- return true;
- if (a == null || b == null)
- return false;
-
- int len = a.length;
- if (len != b.length)
- return false;
- for (int i = 0; i < len; ++i) {
- if (a[i] == null) {
- if (b[i] != null)
- return false;
- } else {
- if (!a[i].equals(b[i]))
- return false;
- }
- }
- return true;
- }
-
- /**
- * Compares two arrays using equals() on the elements. The arrays are first sorted. Either or both arrays may be null. Returns
- * true if both are null. Returns false if only one is null. If both are arrays, returns true iff they have the same length and
- * iff, after sorting both arrays, all elements compare true with equals. The original arrays are left untouched.
- */
- public static boolean equalArraysOrNullSortFirst(Comparable[] a, Comparable[] b) {
- if (a == b)
- return true;
- if (a == null || b == null)
- return false;
- int len = a.length;
- if (len != b.length)
- return false;
- if (len >= 2) { // only need to sort if more than two items
- a = sortCopy(a);
- b = sortCopy(b);
- }
- for (int i = 0; i < len; ++i) {
- if (!a[i].equals(b[i]))
- return false;
- }
- return true;
- }
-
- /**
- * Compares two String arrays using equals() on the elements. The arrays are first sorted. Either or both arrays may be null.
- * Returns true if both are null. Returns false if only one is null. If both are arrays, returns true iff they have the same
- * length and iff, after sorting both arrays, all elements compare true with equals. The original arrays are left untouched.
- */
- public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) {
- if (a == b)
- return true;
- if (a == null || b == null)
- return false;
- int len = a.length;
- if (len != b.length)
- return false;
- if (len >= 2) { // only need to sort if more than two items
- a = sortCopy(a);
- b = sortCopy(b);
- }
- for (int i = 0; i < len; ++i) {
- if (!a[i].equals(b[i]))
- return false;
- }
- return true;
- }
-
- /**
- * Compares two objects using equals(). Either or both array may be null. Returns true if both are null. Returns false if only one
- * is null. Otherwise, return the result of comparing with equals().
- */
- public static boolean equalOrNull(Object a, Object b) {
- if (a == b) {
- return true;
- }
- if (a == null || b == null) {
- return false;
- }
- return a.equals(b);
- }
-
- /**
- * Given a qualified name, extract the last component. If the input is not qualified, the same string is answered.
- */
- public static String extractLastName(String qualifiedName) {
- int i = qualifiedName.lastIndexOf('.');
- if (i == -1)
- return qualifiedName;
- return qualifiedName.substring(i + 1);
- }
-
- /**
- * Extracts the parameter types from a method signature.
- */
- public static String[] extractParameterTypes(char[] sig) {
- int count = getParameterCount(sig);
- String[] result = new String[count];
- if (count == 0)
- return result;
- int i = CharOperation.indexOf('(', sig) + 1;
- count = 0;
- int len = sig.length;
- int start = i;
- for (;;) {
- if (i == len)
- break;
- char c = sig[i];
- if (c == ')')
- break;
- if (c == '[') {
- ++i;
- } else if (c == 'L') {
- i = CharOperation.indexOf(';', sig, i + 1) + 1;
- Assert.isTrue(i != 0);
- result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
- start = i;
- } else {
- ++i;
- result[count++] = convertTypeSignature(CharOperation.subarray(sig, start, i));
- start = i;
- }
- }
- return result;
- }
-
- /**
- * Extracts the return type from a method signature.
- */
- public static String extractReturnType(String sig) {
- int i = sig.lastIndexOf(')');
- Assert.isTrue(i != -1);
- return sig.substring(i + 1);
- }
-
- private static IFile findFirstClassFile(IFolder folder) {
- try {
- IResource[] members = folder.members();
- for (int i = 0, max = members.length; i < max; i++) {
- IResource member = members[i];
- if (member.getType() == IResource.FOLDER) {
- return findFirstClassFile((IFolder) member);
- } else if (net.sourceforge.phpdt.internal.compiler.util.Util.isClassFileName(member.getName())) {
- return (IFile) member;
- }
- }
- } catch (CoreException e) {
- // ignore
- }
- return null;
- }
-
- /**
- * Finds the first line separator used by the given text.
- *
- * @return "\n" or "\r" or "\r\n", or null
if none found
- */
- public static String findLineSeparator(char[] text) {
- // find the first line separator
- int length = text.length;
- if (length > 0) {
- char nextChar = text[0];
- for (int i = 0; i < length; i++) {
- char currentChar = nextChar;
- nextChar = i < length - 1 ? text[i + 1] : ' ';
- switch (currentChar) {
- case '\n':
- return "\n"; //$NON-NLS-1$
- case '\r':
- return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
- }
- }
- }
- // not found
- return null;
- }
-
- // public static IClassFileAttribute getAttribute(IClassFileReader classFileReader, char[] attributeName) {
- // IClassFileAttribute[] attributes = classFileReader.getAttributes();
- // for (int i = 0, max = attributes.length; i < max; i++) {
- // if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
- // return attributes[i];
- // }
- // }
- // return null;
- // }
- //
- // public static IClassFileAttribute getAttribute(ICodeAttribute codeAttribute, char[] attributeName) {
- // IClassFileAttribute[] attributes = codeAttribute.getAttributes();
- // for (int i = 0, max = attributes.length; i < max; i++) {
- // if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
- // return attributes[i];
- // }
- // }
- // return null;
- // }
-
- // public static IClassFileAttribute getAttribute(IFieldInfo fieldInfo, char[] attributeName) {
- // IClassFileAttribute[] attributes = fieldInfo.getAttributes();
- // for (int i = 0, max = attributes.length; i < max; i++) {
- // if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
- // return attributes[i];
- // }
- // }
- // return null;
- // }
- //
- // public static IClassFileAttribute getAttribute(IMethodInfo methodInfo, char[] attributeName) {
- // IClassFileAttribute[] attributes = methodInfo.getAttributes();
- // for (int i = 0, max = attributes.length; i < max; i++) {
- // if (CharOperation.equals(attributes[i].getAttributeName(), attributeName)) {
- // return attributes[i];
- // }
- // }
- // return null;
- // }
- /**
- * Get the jdk level of this root. The value can be:
- *
0 if the root is a source package fragment root or if a Java model exception occured
".class"
suffix
- * IStatus.OK
if the given name is valid as a .class file name, otherwise a
- * status object indicating what is wrong with the name
- */
- // public static boolean isValidClassFileName(String name) {
- // return JavaConventions.validateClassFileName(name).getSeverity() != IStatus.ERROR;
- // }
- /**
- * Validate the given compilation unit name. A compilation unit name must obey the following rules:
- * ".java"
suffix
- * IStatus.OK
if the given name is valid as a compilation unit name, otherwise a
- * status object indicating what is wrong with the name
- */
- public static boolean isValidCompilationUnitName(String name) {
- return PHPFileUtil.isPHPFileName(name);
- // return JavaConventions.validateCompilationUnitName(name).getSeverity() != IStatus.ERROR;
- }
-
- /**
- * Returns true if the given folder name is valid for a package, false if it is not.
- */
- public static boolean isValidFolderNameForPackage(String folderName) {
- // return JavaConventions.validateIdentifier(folderName).getSeverity() != IStatus.ERROR;
- return true;
- }
- /**
- * Returns true if the given method signature is valid, false if it is not.
- */
- public static boolean isValidMethodSignature(String sig) {
- int len = sig.length();
- if (len == 0)
- return false;
- int i = 0;
- char c = sig.charAt(i++);
- if (c != '(')
- return false;
- if (i >= len)
- return false;
- while (sig.charAt(i) != ')') {
- // Void is not allowed as a parameter type.
- i = checkTypeSignature(sig, i, len, false);
- if (i == -1)
- return false;
- if (i >= len)
- return false;
- }
- ++i;
- i = checkTypeSignature(sig, i, len, true);
- return i == len;
- }
-
- /**
- * Returns true if the given type signature is valid, false if it is not.
- */
- public static boolean isValidTypeSignature(String sig, boolean allowVoid) {
- int len = sig.length();
- return checkTypeSignature(sig, 0, len, allowVoid) == len;
- }
-
- /*
- * Add a log entry
- */
- public static void log(Throwable e, String message) {
- Throwable nestedException;
- if (e instanceof JavaModelException && (nestedException = ((JavaModelException) e).getException()) != null) {
- e = nestedException;
- }
- IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, IStatus.ERROR, message, e);
- JavaCore.getPlugin().getLog().log(status);
- }
-
- /**
- * Normalizes the cariage returns in the given text. They are all changed to use the given buffer's line separator.
- */
- public static char[] normalizeCRs(char[] text, char[] buffer) {
- CharArrayBuffer result = new CharArrayBuffer();
- int lineStart = 0;
- int length = text.length;
- if (length == 0)
- return text;
- String lineSeparator = getLineSeparator(text, buffer);
- char nextChar = text[0];
- for (int i = 0; i < length; i++) {
- char currentChar = nextChar;
- nextChar = i < length - 1 ? text[i + 1] : ' ';
- switch (currentChar) {
- case '\n':
- int lineLength = i - lineStart;
- char[] line = new char[lineLength];
- System.arraycopy(text, lineStart, line, 0, lineLength);
- result.append(line);
- result.append(lineSeparator);
- lineStart = i + 1;
- break;
- case '\r':
- lineLength = i - lineStart;
- if (lineLength >= 0) {
- line = new char[lineLength];
- System.arraycopy(text, lineStart, line, 0, lineLength);
- result.append(line);
- result.append(lineSeparator);
- if (nextChar == '\n') {
- nextChar = ' ';
- lineStart = i + 2;
- } else {
- // when line separator are mixed in the same file
- // \r might not be followed by a \n. If not, we should increment
- // lineStart by one and not by two.
- lineStart = i + 1;
- }
- } else {
- // when line separator are mixed in the same file
- // we need to prevent NegativeArraySizeException
- lineStart = i + 1;
- }
- break;
- }
- }
- char[] lastLine;
- if (lineStart > 0) {
- int lastLineLength = length - lineStart;
- if (lastLineLength > 0) {
- lastLine = new char[lastLineLength];
- System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
- result.append(lastLine);
- }
- return result.getContents();
- }
- return text;
- }
-
- /**
- * Normalizes the cariage returns in the given text. They are all changed to use given buffer's line sepatator.
- */
- public static String normalizeCRs(String text, String buffer) {
- return new String(normalizeCRs(text.toCharArray(), buffer.toCharArray()));
- }
-
- /**
- * Converts the given relative path into a package name. Returns null if the path is not a valid package name.
- */
- public static String packageName(IPath pkgPath) {
- StringBuffer pkgName = new StringBuffer(IPackageFragment.DEFAULT_PACKAGE_NAME);
- for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
- String segment = pkgPath.segment(j);
- // if (!isValidFolderNameForPackage(segment)) {
- // return null;
- // }
- pkgName.append(segment);
- if (j < pkgPath.segmentCount() - 1) {
- pkgName.append("."); //$NON-NLS-1$
- }
- }
- return pkgName.toString();
- }
-
- /**
- * Returns the length of the common prefix between s1 and s2.
- */
- public static int prefixLength(char[] s1, char[] s2) {
- int len = 0;
- int max = Math.min(s1.length, s2.length);
- for (int i = 0; i < max && s1[i] == s2[i]; ++i)
- ++len;
- return len;
- }
-
- /**
- * Returns the length of the common prefix between s1 and s2.
- */
- public static int prefixLength(String s1, String s2) {
- int len = 0;
- int max = Math.min(s1.length(), s2.length());
- for (int i = 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
- ++len;
- return len;
- }
-
- private static void quickSort(char[][] list, int left, int right) {
- int original_left = left;
- int original_right = right;
- char[] mid = list[(left + right) / 2];
- do {
- while (compare(list[left], mid) < 0) {
- left++;
- }
- while (compare(mid, list[right]) < 0) {
- right--;
- }
- if (left <= right) {
- char[] tmp = list[left];
- list[left] = list[right];
- list[right] = tmp;
- left++;
- right--;
- }
- } while (left <= right);
- if (original_left < right) {
- quickSort(list, original_left, right);
- }
- if (left < original_right) {
- quickSort(list, left, original_right);
- }
- }
-
- /**
- * Sort the comparable objects in the given collection.
- */
- private static void quickSort(Comparable[] sortedCollection, int left, int right) {
- int original_left = left;
- int original_right = right;
- Comparable mid = sortedCollection[(left + right) / 2];
- do {
- while (sortedCollection[left].compareTo(mid) < 0) {
- left++;
- }
- while (mid.compareTo(sortedCollection[right]) < 0) {
- right--;
- }
- if (left <= right) {
- Comparable tmp = sortedCollection[left];
- sortedCollection[left] = sortedCollection[right];
- sortedCollection[right] = tmp;
- left++;
- right--;
- }
- } while (left <= right);
- if (original_left < right) {
- quickSort(sortedCollection, original_left, right);
- }
- if (left < original_right) {
- quickSort(sortedCollection, left, original_right);
- }
- }
-
- private static void quickSort(int[] list, int left, int right) {
- int original_left = left;
- int original_right = right;
- int mid = list[(left + right) / 2];
- do {
- while (list[left] < mid) {
- left++;
- }
- while (mid < list[right]) {
- right--;
- }
- if (left <= right) {
- int tmp = list[left];
- list[left] = list[right];
- list[right] = tmp;
- left++;
- right--;
- }
- } while (left <= right);
- if (original_left < right) {
- quickSort(list, original_left, right);
- }
- if (left < original_right) {
- quickSort(list, left, original_right);
- }
- }
-
- /**
- * Sort the objects in the given collection using the given comparer.
- */
- private static void quickSort(Object[] sortedCollection, int left, int right, Comparer comparer) {
- int original_left = left;
- int original_right = right;
- Object mid = sortedCollection[(left + right) / 2];
- do {
- while (comparer.compare(sortedCollection[left], mid) < 0) {
- left++;
- }
- while (comparer.compare(mid, sortedCollection[right]) < 0) {
- right--;
- }
- if (left <= right) {
- Object tmp = sortedCollection[left];
- sortedCollection[left] = sortedCollection[right];
- sortedCollection[right] = tmp;
- left++;
- right--;
- }
- } while (left <= right);
- if (original_left < right) {
- quickSort(sortedCollection, original_left, right, comparer);
- }
- if (left < original_right) {
- quickSort(sortedCollection, left, original_right, comparer);
- }
- }
-
- /**
- * Sort the objects in the given collection using the given sort order.
- */
- private static void quickSort(Object[] sortedCollection, int left, int right, int[] sortOrder) {
- int original_left = left;
- int original_right = right;
- int mid = sortOrder[(left + right) / 2];
- do {
- while (sortOrder[left] < mid) {
- left++;
- }
- while (mid < sortOrder[right]) {
- right--;
- }
- if (left <= right) {
- Object tmp = sortedCollection[left];
- sortedCollection[left] = sortedCollection[right];
- sortedCollection[right] = tmp;
- int tmp2 = sortOrder[left];
- sortOrder[left] = sortOrder[right];
- sortOrder[right] = tmp2;
- left++;
- right--;
- }
- } while (left <= right);
- if (original_left < right) {
- quickSort(sortedCollection, original_left, right, sortOrder);
- }
- if (left < original_right) {
- quickSort(sortedCollection, left, original_right, sortOrder);
- }
- }
-
- /**
- * Sort the strings in the given collection.
- */
- private static void quickSort(String[] sortedCollection, int left, int right) {
- int original_left = left;
- int original_right = right;
- String mid = sortedCollection[(left + right) / 2];
- do {
- while (sortedCollection[left].compareTo(mid) < 0) {
- left++;
- }
- while (mid.compareTo(sortedCollection[right]) < 0) {
- right--;
- }
- if (left <= right) {
- String tmp = sortedCollection[left];
- sortedCollection[left] = sortedCollection[right];
- sortedCollection[right] = tmp;
- left++;
- right--;
- }
- } while (left <= right);
- if (original_left < right) {
- quickSort(sortedCollection, original_left, right);
- }
- if (left < original_right) {
- quickSort(sortedCollection, left, original_right);
- }
- }
-
- /**
- * Sort the strings in the given collection in reverse alphabetical order.
- */
- private static void quickSortReverse(String[] sortedCollection, int left, int right) {
- int original_left = left;
- int original_right = right;
- String mid = sortedCollection[(left + right) / 2];
- do {
- while (sortedCollection[left].compareTo(mid) > 0) {
- left++;
- }
- while (mid.compareTo(sortedCollection[right]) > 0) {
- right--;
- }
- if (left <= right) {
- String tmp = sortedCollection[left];
- sortedCollection[left] = sortedCollection[right];
- sortedCollection[right] = tmp;
- left++;
- right--;
- }
- } while (left <= right);
- if (original_left < right) {
- quickSortReverse(sortedCollection, original_left, right);
- }
- if (left < original_right) {
- quickSortReverse(sortedCollection, left, original_right);
- }
- }
-
- /**
- * Reads in a string from the specified data input stream. The string has been encoded using a modified UTF-8 format.
- *
- * The first two bytes are read as if by readUnsignedShort
. This value gives the number of following bytes that
- * are in the encoded string, not the length of the resulting string. The following bytes are then interpreted as bytes encoding
- * characters in the UTF-8 format and are converted into characters.
- *
- * This method blocks until all the bytes are read, the end of the stream is detected, or an exception is thrown.
- *
- * @param in
- * a data input stream.
- * @return a Unicode string.
- * @exception EOFException
- * if the input stream reaches the end before all the bytes.
- * @exception IOException
- * if an I/O error occurs.
- * @exception UTFDataFormatException
- * if the bytes do not represent a valid UTF-8 encoding of a Unicode string.
- * @see java.io.DataInputStream#readUnsignedShort()
- */
- public final static char[] readUTF(DataInput in) throws IOException {
- int utflen = in.readUnsignedShort();
- char str[] = new char[utflen];
- int count = 0;
- int strlen = 0;
- while (count < utflen) {
- int c = in.readUnsignedByte();
- int char2, char3;
- switch (c >> 4) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- case 5:
- case 6:
- case 7:
- // 0xxxxxxx
- count++;
- str[strlen++] = (char) c;
- break;
- case 12:
- case 13:
- // 110x xxxx 10xx xxxx
- count += 2;
- if (count > utflen)
- throw new UTFDataFormatException();
- char2 = in.readUnsignedByte();
- if ((char2 & 0xC0) != 0x80)
- throw new UTFDataFormatException();
- str[strlen++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F));
- break;
- case 14:
- // 1110 xxxx 10xx xxxx 10xx xxxx
- count += 3;
- if (count > utflen)
- throw new UTFDataFormatException();
- char2 = in.readUnsignedByte();
- char3 = in.readUnsignedByte();
- if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
- throw new UTFDataFormatException();
- str[strlen++] = (char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
- break;
- default:
- // 10xx xxxx, 1111 xxxx
- throw new UTFDataFormatException();
- }
- }
- if (strlen < utflen) {
- System.arraycopy(str, 0, str = new char[strlen], 0, strlen);
- }
- return str;
- }
-
- /**
- * Creates a NLS catalog for the given locale.
- */
- public static void relocalize() {
- try {
- bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault());
- } catch (MissingResourceException e) {
- System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$
- throw e;
- }
- }
-
- public static void sort(char[][] list) {
- if (list.length > 1)
- quickSort(list, 0, list.length - 1);
- }
-
- /**
- * Sorts an array of Comparable objects in place.
- */
- public static void sort(Comparable[] objects) {
- if (objects.length > 1)
- quickSort(objects, 0, objects.length - 1);
- }
-
- public static void sort(int[] list) {
- if (list.length > 1)
- quickSort(list, 0, list.length - 1);
- }
-
- /**
- * Sorts an array of objects in place. The given comparer compares pairs of items.
- */
- public static void sort(Object[] objects, Comparer comparer) {
- if (objects.length > 1)
- quickSort(objects, 0, objects.length - 1, comparer);
- }
-
- /**
- * Sorts an array of objects in place, using the sort order given for each item.
- */
- public static void sort(Object[] objects, int[] sortOrder) {
- if (objects.length > 1)
- quickSort(objects, 0, objects.length - 1, sortOrder);
- }
-
- /**
- * Sorts an array of strings in place using quicksort.
- */
- public static void sort(String[] strings) {
- if (strings.length > 1)
- quickSort(strings, 0, strings.length - 1);
- }
-
- /**
- * Sorts an array of Comparable objects, returning a new array with the sorted items. The original array is left untouched.
- */
- public static Comparable[] sortCopy(Comparable[] objects) {
- int len = objects.length;
- Comparable[] copy = new Comparable[len];
- System.arraycopy(objects, 0, copy, 0, len);
- sort(copy);
- return copy;
- }
-
- /**
- * Sorts an array of Strings, returning a new array with the sorted items. The original array is left untouched.
- */
- public static Object[] sortCopy(Object[] objects, Comparer comparer) {
- int len = objects.length;
- Object[] copy = new Object[len];
- System.arraycopy(objects, 0, copy, 0, len);
- sort(copy, comparer);
- return copy;
- }
-
- /**
- * Sorts an array of Strings, returning a new array with the sorted items. The original array is left untouched.
- */
- public static String[] sortCopy(String[] objects) {
- int len = objects.length;
- String[] copy = new String[len];
- System.arraycopy(objects, 0, copy, 0, len);
- sort(copy);
- return copy;
- }
-
- /**
- * Sorts an array of strings in place using quicksort in reverse alphabetical order.
- */
- public static void sortReverseOrder(String[] strings) {
- if (strings.length > 1)
- quickSortReverse(strings, 0, strings.length - 1);
- }
-
- /**
- * Converts a String[] to char[][].
- */
- public static char[][] toCharArrays(String[] a) {
- int len = a.length;
- char[][] result = new char[len][];
- for (int i = 0; i < len; ++i) {
- result[i] = toChars(a[i]);
- }
- return result;
- }
-
- /**
- * Converts a String to char[].
- */
- public static char[] toChars(String s) {
- int len = s.length();
- char[] chars = new char[len];
- s.getChars(0, len, chars, 0);
- return chars;
- }
-
- /**
- * Converts a String to char[][], where segments are separate by '.'.
- */
- public static char[][] toCompoundChars(String s) {
- int len = s.length();
- if (len == 0) {
- return CharOperation.NO_CHAR_CHAR;
- }
- int segCount = 1;
- for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) {
- ++segCount;
- }
- char[][] segs = new char[segCount][];
- int start = 0;
- for (int i = 0; i < segCount; ++i) {
- int dot = s.indexOf('.', start);
- int end = (dot == -1 ? s.length() : dot);
- segs[i] = new char[end - start];
- s.getChars(start, end, segs[i], 0);
- start = end + 1;
- }
- return segs;
- }
-
- /**
- * Converts a char[] to String.
- */
- public static String toString(char[] c) {
- return new String(c);
- }
-
- /**
- * Converts a char[][] to String, where segments are separated by '.'.
- */
- public static String toString(char[][] c) {
- StringBuffer sb = new StringBuffer();
- for (int i = 0, max = c.length; i < max; ++i) {
- if (i != 0)
- sb.append('.');
- sb.append(c[i]);
- }
- return sb.toString();
- }
-
- /**
- * Converts a char[][] and a char[] to String, where segments are separated by '.'.
- */
- public static String toString(char[][] c, char[] d) {
- if (c == null)
- return new String(d);
- StringBuffer sb = new StringBuffer();
- for (int i = 0, max = c.length; i < max; ++i) {
- sb.append(c[i]);
- sb.append('.');
- }
- sb.append(d);
- return sb.toString();
- }
-
- /*
- * Returns the unresolved type parameter signatures of the given method e.g. {"QString;", "[int", "[[Qjava.util.Vector;"}
- */
- // public static String[] typeParameterSignatures(AbstractMethodDeclaration method) {
- // Argument[] args = method.arguments;
- // if (args != null) {
- // int length = args.length;
- // String[] signatures = new String[length];
- // for (int i = 0; i < args.length; i++) {
- // Argument arg = args[i];
- // signatures[i] = typeSignature(arg.type);
- // }
- // return signatures;
- // }
- // return new String[0];
- // }
- /*
- * Returns the unresolved type signature of the given type reference, e.g. "QString;", "[int", "[[Qjava.util.Vector;"
- */
- // public static String typeSignature(TypeReference type) {
- // char[][] compoundName = type.getTypeName();
- // char[] typeName =CharOperation.concatWith(compoundName, '.');
- // String signature = Signature.createTypeSignature(typeName, false/*don't resolve*/);
- // int dimensions = type.dimensions();
- // if (dimensions > 0) {
- // signature = Signature.createArraySignature(signature, dimensions);
- // }
- // return signature;
- // }
- /*
- * Returns the unresolved type signature of the given type reference,
- * e.g. "QString;", "[int", "[[Qjava.util.Vector;"
+ public interface Comparable {
+ /**
+ * Returns 0 if this and c are equal, >0 if this is greater than c, or
+ * <0 if this is less than c.
+ */
+ int compareTo(Comparable c);
+ }
+
+ public interface Comparer {
+ /**
+ * Returns 0 if a and b are equal, >0 if a is greater than b, or <0 if a
+ * is less than b.
+ */
+ int compare(Object a, Object b);
+ }
+
+ private static final String ARGUMENTS_DELIMITER = "#"; //$NON-NLS-1$
+
+ /* Bundle containing messages */
+ protected static ResourceBundle bundle;
+
+ private final static String bundleName = "net.sourceforge.phpdt.internal.core.util.messages"; //$NON-NLS-1$
+
+ private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
+
+ private static final String EMPTY_ARGUMENT = " "; //$NON-NLS-1$
+
+ public static final String[] fgEmptyStringArray = new String[0];
+
+ private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
+
+ static {
+ relocalize();
+ }
+
+ private Util() {
+ // cannot be instantiated
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog
+ */
+ public static String bind(String id) {
+ return bind(id, (String[]) null);
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given string.
+ */
+ public static String bind(String id, String binding) {
+ return bind(id, new String[] { binding });
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given strings.
+ */
+ public static String bind(String id, String binding1, String binding2) {
+ return bind(id, new String[] { binding1, binding2 });
+ }
+
+ /**
+ * Lookup the message with the given ID in this catalog and bind its
+ * substitution locations with the given string values.
+ */
+ public static String bind(String id, String[] bindings) {
+ if (id == null)
+ return "No message available"; //$NON-NLS-1$
+ String message = null;
+ try {
+ message = bundle.getString(id);
+ } catch (MissingResourceException e) {
+ // If we got an exception looking for the message, fail gracefully
+ // by just returning
+ // the id we were looking for. In most cases this is
+ // semi-informative so is not too bad.
+ return "Missing message: " + id + " in: " + bundleName; //$NON-NLS-2$ //$NON-NLS-1$
+ }
+ // for compatibility with MessageFormat which eliminates double quotes
+ // in original message
+ char[] messageWithNoDoubleQuotes = CharOperation.replace(message
+ .toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
+
+ if (bindings == null)
+ return new String(messageWithNoDoubleQuotes);
+
+ int length = messageWithNoDoubleQuotes.length;
+ int start = 0;
+ int end = length;
+ StringBuffer output = null;
+ while (true) {
+ if ((end = CharOperation.indexOf('{', messageWithNoDoubleQuotes,
+ start)) > -1) {
+ if (output == null)
+ output = new StringBuffer(length + bindings.length * 20);
+ output.append(messageWithNoDoubleQuotes, start, end - start);
+ if ((start = CharOperation.indexOf('}',
+ messageWithNoDoubleQuotes, end + 1)) > -1) {
+ int index = -1;
+ String argId = new String(messageWithNoDoubleQuotes,
+ end + 1, start - end - 1);
+ try {
+ index = Integer.parseInt(argId);
+ output.append(bindings[index]);
+ } catch (NumberFormatException nfe) { // could be nested
+ // message ID
+ // {compiler.name}
+ boolean done = false;
+ if (!id.equals(argId)) {
+ String argMessage = null;
+ try {
+ argMessage = bundle.getString(argId);
+ output.append(argMessage);
+ done = true;
+ } catch (MissingResourceException e) {
+ // unable to bind argument, ignore (will leave
+ // argument in)
+ }
+ }
+ if (!done)
+ output.append(messageWithNoDoubleQuotes, end + 1,
+ start - end);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ output
+ .append("{missing " + Integer.toString(index) + "}"); //$NON-NLS-2$ //$NON-NLS-1$
+ }
+ start++;
+ } else {
+ output.append(messageWithNoDoubleQuotes, end, length);
+ break;
+ }
+ } else {
+ if (output == null)
+ return new String(messageWithNoDoubleQuotes);
+ output.append(messageWithNoDoubleQuotes, start, length - start);
+ break;
+ }
+ }
+ return output.toString();
+ }
+
+ /**
+ * Checks the type signature in String sig, starting at start and ending
+ * before end (end is not included). Returns the index of the character
+ * immediately after the signature if valid, or -1 if not valid.
+ */
+ private static int checkTypeSignature(String sig, int start, int end,
+ boolean allowVoid) {
+ if (start >= end)
+ return -1;
+ int i = start;
+ char c = sig.charAt(i++);
+ int nestingDepth = 0;
+ while (c == '[') {
+ ++nestingDepth;
+ if (i >= end)
+ return -1;
+ c = sig.charAt(i++);
+ }
+ switch (c) {
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'F':
+ case 'I':
+ case 'J':
+ case 'S':
+ case 'Z':
+ break;
+ case 'V':
+ if (!allowVoid)
+ return -1;
+ // array of void is not allowed
+ if (nestingDepth != 0)
+ return -1;
+ break;
+ case 'L':
+ int semicolon = sig.indexOf(';', i);
+ // Must have at least one character between L and ;
+ if (semicolon <= i || semicolon >= end)
+ return -1;
+ i = semicolon + 1;
+ break;
+ default:
+ return -1;
+ }
+ return i;
+ }
+
+ /**
+ * Combines two hash codes to make a new one.
+ */
+ public static int combineHashCodes(int hashCode1, int hashCode2) {
+ return hashCode1 * 17 + hashCode2;
+ }
+
+ /**
+ * Compares two byte arrays. Returns <0 if a byte in a is less than the
+ * corresponding byte in b, or if a is shorter, or if a is null. Returns >0
+ * if a byte in a is greater than the corresponding byte in b, or if a is
+ * longer, or if b is null. Returns 0 if they are equal or both null.
+ */
+ public static int compare(byte[] a, byte[] b) {
+ if (a == b)
+ return 0;
+ if (a == null)
+ return -1;
+ if (b == null)
+ return 1;
+ int len = Math.min(a.length, b.length);
+ for (int i = 0; i < len; ++i) {
+ int diff = a[i] - b[i];
+ if (diff != 0)
+ return diff;
+ }
+ if (a.length > len)
+ return 1;
+ if (b.length > len)
+ return -1;
+ return 0;
+ }
+
+ /**
+ * Compares two strings lexicographically. The comparison is based on the
+ * Unicode value of each character in the strings.
+ *
+ * @return the value 0
if the str1 is equal to str2; a value
+ * less than 0
if str1 is lexicographically less than
+ * str2; and a value greater than 0
if str1 is
+ * lexicographically greater than str2.
+ */
+ public static int compare(char[] str1, char[] str2) {
+ int len1 = str1.length;
+ int len2 = str2.length;
+ int n = Math.min(len1, len2);
+ int i = 0;
+ while (n-- != 0) {
+ char c1 = str1[i];
+ char c2 = str2[i++];
+ if (c1 != c2) {
+ return c1 - c2;
+ }
+ }
+ return len1 - len2;
+ }
+
+ /**
+ * Concatenate two strings with a char in between.
+ *
+ * @see #concat(String, String)
+ */
+ public static String concat(String s1, char c, String s2) {
+ if (s1 == null)
+ s1 = "null"; //$NON-NLS-1$
+ if (s2 == null)
+ s2 = "null"; //$NON-NLS-1$
+ int l1 = s1.length();
+ int l2 = s2.length();
+ char[] buf = new char[l1 + 1 + l2];
+ s1.getChars(0, l1, buf, 0);
+ buf[l1] = c;
+ s2.getChars(0, l2, buf, l1 + 1);
+ return new String(buf);
+ }
+
+ /**
+ * Concatenate two strings. Much faster than using +, which: - creates a
+ * StringBuffer, - which is synchronized, - of default size, so the
+ * resulting char array is often larger than needed. This implementation
+ * creates an extra char array, since the String constructor copies its
+ * argument, but there's no way around this.
+ */
+ public static String concat(String s1, String s2) {
+ if (s1 == null)
+ s1 = "null"; //$NON-NLS-1$
+ if (s2 == null)
+ s2 = "null"; //$NON-NLS-1$
+ int l1 = s1.length();
+ int l2 = s2.length();
+ char[] buf = new char[l1 + l2];
+ s1.getChars(0, l1, buf, 0);
+ s2.getChars(0, l2, buf, l1);
+ return new String(buf);
+ }
+
+ /**
+ * Concatenate three strings.
+ *
+ * @see #concat(String, String)
+ */
+ public static String concat(String s1, String s2, String s3) {
+ if (s1 == null)
+ s1 = "null"; //$NON-NLS-1$
+ if (s2 == null)
+ s2 = "null"; //$NON-NLS-1$
+ if (s3 == null)
+ s3 = "null"; //$NON-NLS-1$
+ int l1 = s1.length();
+ int l2 = s2.length();
+ int l3 = s3.length();
+ char[] buf = new char[l1 + l2 + l3];
+ s1.getChars(0, l1, buf, 0);
+ s2.getChars(0, l2, buf, l1);
+ s3.getChars(0, l3, buf, l1 + l2);
+ return new String(buf);
+ }
+
+ /**
+ * Converts a type signature from the IBinaryType representation to the DC
+ * representation.
+ */
+ public static String convertTypeSignature(char[] sig) {
+ return new String(sig).replace('/', '.');
+ }
+
+ /**
+ * Apply the given edit on the given string and return the updated string.
+ * Return the given string if anything wrong happen while applying the edit.
+ *
+ * @param original
+ * the given string
+ * @param edit
+ * the given edit
+ *
+ * @return the updated string
+ */
+ public final static String editedString(String original, TextEdit edit) {
+ if (edit == null) {
+ return original;
+ }
+ SimpleDocument document = new SimpleDocument(original);
+ try {
+ edit.apply(document, TextEdit.NONE);
+ return document.get();
+ } catch (MalformedTreeException e) {
+ e.printStackTrace();
+ } catch (BadLocationException e) {
+ e.printStackTrace();
+ }
+ return original;
+ }
+
+ /**
+ * Returns true iff str.toLowerCase().endsWith(end.toLowerCase())
+ * implementation is not creating extra strings.
+ */
+ public final static boolean endsWithIgnoreCase(String str, String end) {
+
+ int strLength = str == null ? 0 : str.length();
+ int endLength = end == null ? 0 : end.length();
+
+ // return false if the string is smaller than the end.
+ if (endLength > strLength)
+ return false;
+
+ // return false if any character of the end are
+ // not the same in lower case.
+ for (int i = 1; i <= endLength; i++) {
+ if (Character.toLowerCase(end.charAt(endLength - i)) != Character
+ .toLowerCase(str.charAt(strLength - i)))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Compares two arrays using equals() on the elements. Either or both arrays
+ * may be null. Returns true if both are null. Returns false if only one is
+ * null. If both are arrays, returns true iff they have the same length and
+ * all elements are equal.
+ */
+ public static boolean equalArraysOrNull(int[] a, int[] b) {
+ if (a == b)
+ return true;
+ if (a == null || b == null)
+ return false;
+ int len = a.length;
+ if (len != b.length)
+ return false;
+ for (int i = 0; i < len; ++i) {
+ if (a[i] != b[i])
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares two arrays using equals() on the elements. Either or both arrays
+ * may be null. Returns true if both are null. Returns false if only one is
+ * null. If both are arrays, returns true iff they have the same length and
+ * all elements compare true with equals.
+ */
+ public static boolean equalArraysOrNull(Object[] a, Object[] b) {
+ if (a == b)
+ return true;
+ if (a == null || b == null)
+ return false;
+
+ int len = a.length;
+ if (len != b.length)
+ return false;
+ for (int i = 0; i < len; ++i) {
+ if (a[i] == null) {
+ if (b[i] != null)
+ return false;
+ } else {
+ if (!a[i].equals(b[i]))
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Compares two arrays using equals() on the elements. The arrays are first
+ * sorted. Either or both arrays may be null. Returns true if both are null.
+ * Returns false if only one is null. If both are arrays, returns true iff
+ * they have the same length and iff, after sorting both arrays, all
+ * elements compare true with equals. The original arrays are left
+ * untouched.
+ */
+ public static boolean equalArraysOrNullSortFirst(Comparable[] a,
+ Comparable[] b) {
+ if (a == b)
+ return true;
+ if (a == null || b == null)
+ return false;
+ int len = a.length;
+ if (len != b.length)
+ return false;
+ if (len >= 2) { // only need to sort if more than two items
+ a = sortCopy(a);
+ b = sortCopy(b);
+ }
+ for (int i = 0; i < len; ++i) {
+ if (!a[i].equals(b[i]))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares two String arrays using equals() on the elements. The arrays are
+ * first sorted. Either or both arrays may be null. Returns true if both are
+ * null. Returns false if only one is null. If both are arrays, returns true
+ * iff they have the same length and iff, after sorting both arrays, all
+ * elements compare true with equals. The original arrays are left
+ * untouched.
+ */
+ public static boolean equalArraysOrNullSortFirst(String[] a, String[] b) {
+ if (a == b)
+ return true;
+ if (a == null || b == null)
+ return false;
+ int len = a.length;
+ if (len != b.length)
+ return false;
+ if (len >= 2) { // only need to sort if more than two items
+ a = sortCopy(a);
+ b = sortCopy(b);
+ }
+ for (int i = 0; i < len; ++i) {
+ if (!a[i].equals(b[i]))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares two objects using equals(). Either or both array may be null.
+ * Returns true if both are null. Returns false if only one is null.
+ * Otherwise, return the result of comparing with equals().
+ */
+ public static boolean equalOrNull(Object a, Object b) {
+ if (a == b) {
+ return true;
+ }
+ if (a == null || b == null) {
+ return false;
+ }
+ return a.equals(b);
+ }
+
+ /**
+ * Given a qualified name, extract the last component. If the input is not
+ * qualified, the same string is answered.
+ */
+ public static String extractLastName(String qualifiedName) {
+ int i = qualifiedName.lastIndexOf('.');
+ if (i == -1)
+ return qualifiedName;
+ return qualifiedName.substring(i + 1);
+ }
+
+ /**
+ * Extracts the parameter types from a method signature.
+ */
+ public static String[] extractParameterTypes(char[] sig) {
+ int count = getParameterCount(sig);
+ String[] result = new String[count];
+ if (count == 0)
+ return result;
+ int i = CharOperation.indexOf('(', sig) + 1;
+ count = 0;
+ int len = sig.length;
+ int start = i;
+ for (;;) {
+ if (i == len)
+ break;
+ char c = sig[i];
+ if (c == ')')
+ break;
+ if (c == '[') {
+ ++i;
+ } else if (c == 'L') {
+ i = CharOperation.indexOf(';', sig, i + 1) + 1;
+ Assert.isTrue(i != 0);
+ result[count++] = convertTypeSignature(CharOperation.subarray(
+ sig, start, i));
+ start = i;
+ } else {
+ ++i;
+ result[count++] = convertTypeSignature(CharOperation.subarray(
+ sig, start, i));
+ start = i;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Extracts the return type from a method signature.
+ */
+ public static String extractReturnType(String sig) {
+ int i = sig.lastIndexOf(')');
+ Assert.isTrue(i != -1);
+ return sig.substring(i + 1);
+ }
+
+ private static IFile findFirstClassFile(IFolder folder) {
+ try {
+ IResource[] members = folder.members();
+ for (int i = 0, max = members.length; i < max; i++) {
+ IResource member = members[i];
+ if (member.getType() == IResource.FOLDER) {
+ return findFirstClassFile((IFolder) member);
+ // } else if
+ // (net.sourceforge.phpdt.internal.compiler.util.Util.isClassFileName(member.getName()))
+ // {
+ // return (IFile) member;
+ }
+ }
+ } catch (CoreException e) {
+ // ignore
+ }
+ return null;
+ }
+
+ /**
+ * Finds the first line separator used by the given text.
+ *
+ * @return "\n" or "\r" or "\r\n",
+ * or null
if none found
+ */
+ public static String findLineSeparator(char[] text) {
+ // find the first line separator
+ int length = text.length;
+ if (length > 0) {
+ char nextChar = text[0];
+ for (int i = 0; i < length; i++) {
+ char currentChar = nextChar;
+ nextChar = i < length - 1 ? text[i + 1] : ' ';
+ switch (currentChar) {
+ case '\n':
+ return "\n"; //$NON-NLS-1$
+ case '\r':
+ return nextChar == '\n' ? "\r\n" : "\r"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+ // not found
+ return null;
+ }
+
+ // public static IClassFileAttribute getAttribute(IClassFileReader
+ // classFileReader, char[] attributeName) {
+ // IClassFileAttribute[] attributes = classFileReader.getAttributes();
+ // for (int i = 0, max = attributes.length; i < max; i++) {
+ // if (CharOperation.equals(attributes[i].getAttributeName(),
+ // attributeName)) {
+ // return attributes[i];
+ // }
+ // }
+ // return null;
+ // }
+ //
+ // public static IClassFileAttribute getAttribute(ICodeAttribute
+ // codeAttribute, char[] attributeName) {
+ // IClassFileAttribute[] attributes = codeAttribute.getAttributes();
+ // for (int i = 0, max = attributes.length; i < max; i++) {
+ // if (CharOperation.equals(attributes[i].getAttributeName(),
+ // attributeName)) {
+ // return attributes[i];
+ // }
+ // }
+ // return null;
+ // }
+
+ // public static IClassFileAttribute getAttribute(IFieldInfo fieldInfo,
+ // char[] attributeName) {
+ // IClassFileAttribute[] attributes = fieldInfo.getAttributes();
+ // for (int i = 0, max = attributes.length; i < max; i++) {
+ // if (CharOperation.equals(attributes[i].getAttributeName(),
+ // attributeName)) {
+ // return attributes[i];
+ // }
+ // }
+ // return null;
+ // }
+ //
+ // public static IClassFileAttribute getAttribute(IMethodInfo methodInfo,
+ // char[] attributeName) {
+ // IClassFileAttribute[] attributes = methodInfo.getAttributes();
+ // for (int i = 0, max = attributes.length; i < max; i++) {
+ // if (CharOperation.equals(attributes[i].getAttributeName(),
+ // attributeName)) {
+ // return attributes[i];
+ // }
+ // }
+ // return null;
+ // }
+ /**
+ * Get the jdk level of this root. The value can be:
+ *
0 if the root is a source package fragment root or if a Java model exception occured
".class"
suffix
+ * IStatus.OK
if the given
+ * name is valid as a .class file name, otherwise a status object
+ * indicating what is wrong with the name
+ */
+ // public static boolean isValidClassFileName(String name) {
+ // return JavaConventions.validateClassFileName(name).getSeverity() !=
+ // IStatus.ERROR;
+ // }
+ /**
+ * Validate the given compilation unit name. A compilation unit name must
+ * obey the following rules:
+ * ".java"
suffix
+ * IStatus.OK
if the given
+ * name is valid as a compilation unit name, otherwise a status
+ * object indicating what is wrong with the name
+ */
+ public static boolean isValidCompilationUnitName(String name) {
+ return PHPFileUtil.isPHPFileName(name);
+ // return
+ // JavaConventions.validateCompilationUnitName(name).getSeverity() !=
+ // IStatus.ERROR;
+ }
+
+ /**
+ * Returns true if the given folder name is valid for a package, false if it
+ * is not.
+ */
+ public static boolean isValidFolderNameForPackage(String folderName) {
+ // return JavaConventions.validateIdentifier(folderName).getSeverity()
+ // != IStatus.ERROR;
+ return true;
+ }
+
+ /**
+ * Returns true if the given method signature is valid, false if it is not.
+ */
+ public static boolean isValidMethodSignature(String sig) {
+ int len = sig.length();
+ if (len == 0)
+ return false;
+ int i = 0;
+ char c = sig.charAt(i++);
+ if (c != '(')
+ return false;
+ if (i >= len)
+ return false;
+ while (sig.charAt(i) != ')') {
+ // Void is not allowed as a parameter type.
+ i = checkTypeSignature(sig, i, len, false);
+ if (i == -1)
+ return false;
+ if (i >= len)
+ return false;
+ }
+ ++i;
+ i = checkTypeSignature(sig, i, len, true);
+ return i == len;
+ }
+
+ /**
+ * Returns true if the given type signature is valid, false if it is not.
+ */
+ public static boolean isValidTypeSignature(String sig, boolean allowVoid) {
+ int len = sig.length();
+ return checkTypeSignature(sig, 0, len, allowVoid) == len;
+ }
+
+ /*
+ * Add a log entry
+ */
+ public static void log(Throwable e, String message) {
+ Throwable nestedException;
+ if (e instanceof JavaModelException
+ && (nestedException = ((JavaModelException) e).getException()) != null) {
+ e = nestedException;
+ }
+ IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID,
+ IStatus.ERROR, message, e);
+ JavaCore.getPlugin().getLog().log(status);
+ }
+
+ /**
+ * Normalizes the cariage returns in the given text. They are all changed to
+ * use the given buffer's line separator.
+ */
+ public static char[] normalizeCRs(char[] text, char[] buffer) {
+ CharArrayBuffer result = new CharArrayBuffer();
+ int lineStart = 0;
+ int length = text.length;
+ if (length == 0)
+ return text;
+ String lineSeparator = getLineSeparator(text, buffer);
+ char nextChar = text[0];
+ for (int i = 0; i < length; i++) {
+ char currentChar = nextChar;
+ nextChar = i < length - 1 ? text[i + 1] : ' ';
+ switch (currentChar) {
+ case '\n':
+ int lineLength = i - lineStart;
+ char[] line = new char[lineLength];
+ System.arraycopy(text, lineStart, line, 0, lineLength);
+ result.append(line);
+ result.append(lineSeparator);
+ lineStart = i + 1;
+ break;
+ case '\r':
+ lineLength = i - lineStart;
+ if (lineLength >= 0) {
+ line = new char[lineLength];
+ System.arraycopy(text, lineStart, line, 0, lineLength);
+ result.append(line);
+ result.append(lineSeparator);
+ if (nextChar == '\n') {
+ nextChar = ' ';
+ lineStart = i + 2;
+ } else {
+ // when line separator are mixed in the same file
+ // \r might not be followed by a \n. If not, we should
+ // increment
+ // lineStart by one and not by two.
+ lineStart = i + 1;
+ }
+ } else {
+ // when line separator are mixed in the same file
+ // we need to prevent NegativeArraySizeException
+ lineStart = i + 1;
+ }
+ break;
+ }
+ }
+ char[] lastLine;
+ if (lineStart > 0) {
+ int lastLineLength = length - lineStart;
+ if (lastLineLength > 0) {
+ lastLine = new char[lastLineLength];
+ System.arraycopy(text, lineStart, lastLine, 0, lastLineLength);
+ result.append(lastLine);
+ }
+ return result.getContents();
+ }
+ return text;
+ }
+
+ /**
+ * Normalizes the cariage returns in the given text. They are all changed to
+ * use given buffer's line sepatator.
+ */
+ public static String normalizeCRs(String text, String buffer) {
+ return new String(
+ normalizeCRs(text.toCharArray(), buffer.toCharArray()));
+ }
+
+ /**
+ * Converts the given relative path into a package name. Returns null if the
+ * path is not a valid package name.
+ */
+ public static String packageName(IPath pkgPath) {
+ StringBuffer pkgName = new StringBuffer(
+ IPackageFragment.DEFAULT_PACKAGE_NAME);
+ for (int j = 0, max = pkgPath.segmentCount(); j < max; j++) {
+ String segment = pkgPath.segment(j);
+ // if (!isValidFolderNameForPackage(segment)) {
+ // return null;
+ // }
+ pkgName.append(segment);
+ if (j < pkgPath.segmentCount() - 1) {
+ pkgName.append("."); //$NON-NLS-1$
+ }
+ }
+ return pkgName.toString();
+ }
+
+ /**
+ * Returns the length of the common prefix between s1 and s2.
+ */
+ public static int prefixLength(char[] s1, char[] s2) {
+ int len = 0;
+ int max = Math.min(s1.length, s2.length);
+ for (int i = 0; i < max && s1[i] == s2[i]; ++i)
+ ++len;
+ return len;
+ }
+
+ /**
+ * Returns the length of the common prefix between s1 and s2.
+ */
+ public static int prefixLength(String s1, String s2) {
+ int len = 0;
+ int max = Math.min(s1.length(), s2.length());
+ for (int i = 0; i < max && s1.charAt(i) == s2.charAt(i); ++i)
+ ++len;
+ return len;
+ }
+
+ private static void quickSort(char[][] list, int left, int right) {
+ int original_left = left;
+ int original_right = right;
+ char[] mid = list[(left + right) / 2];
+ do {
+ while (compare(list[left], mid) < 0) {
+ left++;
+ }
+ while (compare(mid, list[right]) < 0) {
+ right--;
+ }
+ if (left <= right) {
+ char[] tmp = list[left];
+ list[left] = list[right];
+ list[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(list, original_left, right);
+ }
+ if (left < original_right) {
+ quickSort(list, left, original_right);
+ }
+ }
+
+ /**
+ * Sort the comparable objects in the given collection.
+ */
+ private static void quickSort(Comparable[] sortedCollection, int left,
+ int right) {
+ int original_left = left;
+ int original_right = right;
+ Comparable mid = sortedCollection[(left + right) / 2];
+ do {
+ while (sortedCollection[left].compareTo(mid) < 0) {
+ left++;
+ }
+ while (mid.compareTo(sortedCollection[right]) < 0) {
+ right--;
+ }
+ if (left <= right) {
+ Comparable tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(sortedCollection, original_left, right);
+ }
+ if (left < original_right) {
+ quickSort(sortedCollection, left, original_right);
+ }
+ }
+
+ private static void quickSort(int[] list, int left, int right) {
+ int original_left = left;
+ int original_right = right;
+ int mid = list[(left + right) / 2];
+ do {
+ while (list[left] < mid) {
+ left++;
+ }
+ while (mid < list[right]) {
+ right--;
+ }
+ if (left <= right) {
+ int tmp = list[left];
+ list[left] = list[right];
+ list[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(list, original_left, right);
+ }
+ if (left < original_right) {
+ quickSort(list, left, original_right);
+ }
+ }
+
+ /**
+ * Sort the objects in the given collection using the given comparer.
+ */
+ private static void quickSort(Object[] sortedCollection, int left,
+ int right, Comparer comparer) {
+ int original_left = left;
+ int original_right = right;
+ Object mid = sortedCollection[(left + right) / 2];
+ do {
+ while (comparer.compare(sortedCollection[left], mid) < 0) {
+ left++;
+ }
+ while (comparer.compare(mid, sortedCollection[right]) < 0) {
+ right--;
+ }
+ if (left <= right) {
+ Object tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(sortedCollection, original_left, right, comparer);
+ }
+ if (left < original_right) {
+ quickSort(sortedCollection, left, original_right, comparer);
+ }
+ }
+
+ /**
+ * Sort the objects in the given collection using the given sort order.
+ */
+ private static void quickSort(Object[] sortedCollection, int left,
+ int right, int[] sortOrder) {
+ int original_left = left;
+ int original_right = right;
+ int mid = sortOrder[(left + right) / 2];
+ do {
+ while (sortOrder[left] < mid) {
+ left++;
+ }
+ while (mid < sortOrder[right]) {
+ right--;
+ }
+ if (left <= right) {
+ Object tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ int tmp2 = sortOrder[left];
+ sortOrder[left] = sortOrder[right];
+ sortOrder[right] = tmp2;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(sortedCollection, original_left, right, sortOrder);
+ }
+ if (left < original_right) {
+ quickSort(sortedCollection, left, original_right, sortOrder);
+ }
+ }
+
+ /**
+ * Sort the strings in the given collection.
+ */
+ private static void quickSort(String[] sortedCollection, int left, int right) {
+ int original_left = left;
+ int original_right = right;
+ String mid = sortedCollection[(left + right) / 2];
+ do {
+ while (sortedCollection[left].compareTo(mid) < 0) {
+ left++;
+ }
+ while (mid.compareTo(sortedCollection[right]) < 0) {
+ right--;
+ }
+ if (left <= right) {
+ String tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSort(sortedCollection, original_left, right);
+ }
+ if (left < original_right) {
+ quickSort(sortedCollection, left, original_right);
+ }
+ }
+
+ /**
+ * Sort the strings in the given collection in reverse alphabetical order.
+ */
+ private static void quickSortReverse(String[] sortedCollection, int left,
+ int right) {
+ int original_left = left;
+ int original_right = right;
+ String mid = sortedCollection[(left + right) / 2];
+ do {
+ while (sortedCollection[left].compareTo(mid) > 0) {
+ left++;
+ }
+ while (mid.compareTo(sortedCollection[right]) > 0) {
+ right--;
+ }
+ if (left <= right) {
+ String tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+ if (original_left < right) {
+ quickSortReverse(sortedCollection, original_left, right);
+ }
+ if (left < original_right) {
+ quickSortReverse(sortedCollection, left, original_right);
+ }
+ }
+
+ /**
+ * Reads in a string from the specified data input stream. The string has
+ * been encoded using a modified UTF-8 format.
+ *
+ * The first two bytes are read as if by readUnsignedShort
.
+ * This value gives the number of following bytes that are in the encoded
+ * string, not the length of the resulting string. The following bytes are
+ * then interpreted as bytes encoding characters in the UTF-8 format and are
+ * converted into characters.
+ *
+ * This method blocks until all the bytes are read, the end of the stream is + * detected, or an exception is thrown. + * + * @param in + * a data input stream. + * @return a Unicode string. + * @exception EOFException + * if the input stream reaches the end before all the bytes. + * @exception IOException + * if an I/O error occurs. + * @exception UTFDataFormatException + * if the bytes do not represent a valid UTF-8 encoding of a + * Unicode string. + * @see java.io.DataInputStream#readUnsignedShort() + */ + public final static char[] readUTF(DataInput in) throws IOException { + int utflen = in.readUnsignedShort(); + char str[] = new char[utflen]; + int count = 0; + int strlen = 0; + while (count < utflen) { + int c = in.readUnsignedByte(); + int char2, char3; + switch (c >> 4) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + // 0xxxxxxx + count++; + str[strlen++] = (char) c; + break; + case 12: + case 13: + // 110x xxxx 10xx xxxx + count += 2; + if (count > utflen) + throw new UTFDataFormatException(); + char2 = in.readUnsignedByte(); + if ((char2 & 0xC0) != 0x80) + throw new UTFDataFormatException(); + str[strlen++] = (char) (((c & 0x1F) << 6) | (char2 & 0x3F)); + break; + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + count += 3; + if (count > utflen) + throw new UTFDataFormatException(); + char2 = in.readUnsignedByte(); + char3 = in.readUnsignedByte(); + if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) + throw new UTFDataFormatException(); + str[strlen++] = (char) (((c & 0x0F) << 12) + | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); + break; + default: + // 10xx xxxx, 1111 xxxx + throw new UTFDataFormatException(); + } + } + if (strlen < utflen) { + System.arraycopy(str, 0, str = new char[strlen], 0, strlen); + } + return str; + } + + /** + * Creates a NLS catalog for the given locale. + */ + public static void relocalize() { + try { + bundle = ResourceBundle.getBundle(bundleName, Locale.getDefault()); + } catch (MissingResourceException e) { + System.out + .println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + Locale.getDefault()); //$NON-NLS-1$//$NON-NLS-2$ + throw e; + } + } + + public static void sort(char[][] list) { + if (list.length > 1) + quickSort(list, 0, list.length - 1); + } + + /** + * Sorts an array of Comparable objects in place. + */ + public static void sort(Comparable[] objects) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1); + } + + public static void sort(int[] list) { + if (list.length > 1) + quickSort(list, 0, list.length - 1); + } + + /** + * Sorts an array of objects in place. The given comparer compares pairs of + * items. + */ + public static void sort(Object[] objects, Comparer comparer) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1, comparer); + } + + /** + * Sorts an array of objects in place, using the sort order given for each + * item. + */ + public static void sort(Object[] objects, int[] sortOrder) { + if (objects.length > 1) + quickSort(objects, 0, objects.length - 1, sortOrder); + } + + /** + * Sorts an array of strings in place using quicksort. + */ + public static void sort(String[] strings) { + if (strings.length > 1) + quickSort(strings, 0, strings.length - 1); + } + + /** + * Sorts an array of Comparable objects, returning a new array with the + * sorted items. The original array is left untouched. + */ + public static Comparable[] sortCopy(Comparable[] objects) { + int len = objects.length; + Comparable[] copy = new Comparable[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy); + return copy; + } + + /** + * Sorts an array of Strings, returning a new array with the sorted items. + * The original array is left untouched. + */ + public static Object[] sortCopy(Object[] objects, Comparer comparer) { + int len = objects.length; + Object[] copy = new Object[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy, comparer); + return copy; + } + + /** + * Sorts an array of Strings, returning a new array with the sorted items. + * The original array is left untouched. + */ + public static String[] sortCopy(String[] objects) { + int len = objects.length; + String[] copy = new String[len]; + System.arraycopy(objects, 0, copy, 0, len); + sort(copy); + return copy; + } + + /** + * Sorts an array of strings in place using quicksort in reverse + * alphabetical order. + */ + public static void sortReverseOrder(String[] strings) { + if (strings.length > 1) + quickSortReverse(strings, 0, strings.length - 1); + } + + /** + * Converts a String[] to char[][]. + */ + public static char[][] toCharArrays(String[] a) { + int len = a.length; + char[][] result = new char[len][]; + for (int i = 0; i < len; ++i) { + result[i] = toChars(a[i]); + } + return result; + } + + /** + * Converts a String to char[]. + */ + public static char[] toChars(String s) { + int len = s.length(); + char[] chars = new char[len]; + s.getChars(0, len, chars, 0); + return chars; + } + + /** + * Converts a String to char[][], where segments are separate by '.'. + */ + public static char[][] toCompoundChars(String s) { + int len = s.length(); + if (len == 0) { + return CharOperation.NO_CHAR_CHAR; + } + int segCount = 1; + for (int off = s.indexOf('.'); off != -1; off = s.indexOf('.', off + 1)) { + ++segCount; + } + char[][] segs = new char[segCount][]; + int start = 0; + for (int i = 0; i < segCount; ++i) { + int dot = s.indexOf('.', start); + int end = (dot == -1 ? s.length() : dot); + segs[i] = new char[end - start]; + s.getChars(start, end, segs[i], 0); + start = end + 1; + } + return segs; + } + + /** + * Converts a char[] to String. + */ + public static String toString(char[] c) { + return new String(c); + } + + /** + * Converts a char[][] to String, where segments are separated by '.'. + */ + public static String toString(char[][] c) { + StringBuffer sb = new StringBuffer(); + for (int i = 0, max = c.length; i < max; ++i) { + if (i != 0) + sb.append('.'); + sb.append(c[i]); + } + return sb.toString(); + } + + /** + * Converts a char[][] and a char[] to String, where segments are separated + * by '.'. + */ + public static String toString(char[][] c, char[] d) { + if (c == null) + return new String(d); + StringBuffer sb = new StringBuffer(); + for (int i = 0, max = c.length; i < max; ++i) { + sb.append(c[i]); + sb.append('.'); + } + sb.append(d); + return sb.toString(); + } + + /* + * Returns the unresolved type parameter signatures of the given method e.g. + * {"QString;", "[int", "[[Qjava.util.Vector;"} + */ + // public static String[] typeParameterSignatures(AbstractMethodDeclaration + // method) { + // Argument[] args = method.arguments; + // if (args != null) { + // int length = args.length; + // String[] signatures = new String[length]; + // for (int i = 0; i < args.length; i++) { + // Argument arg = args[i]; + // signatures[i] = typeSignature(arg.type); + // } + // return signatures; + // } + // return new String[0]; + // } + /* + * Returns the unresolved type signature of the given type reference, e.g. + * "QString;", "[int", "[[Qjava.util.Vector;" + */ + // public static String typeSignature(TypeReference type) { + // char[][] compoundName = type.getTypeName(); + // char[] typeName =CharOperation.concatWith(compoundName, '.'); + // String signature = Signature.createTypeSignature(typeName, false/*don't + // resolve*/); + // int dimensions = type.dimensions(); + // if (dimensions > 0) { + // signature = Signature.createArraySignature(signature, dimensions); + // } + // return signature; + // } + /* + * Returns the unresolved type signature of the given type reference, e.g. + * "QString;", "[int", "[[Qjava.util.Vector;" */ public static String typeSignature(TypeReference type) { char[][] compoundName = type.getTypeName(); - char[] typeName =CharOperation.concatWith(compoundName, '.'); - String signature = Signature.createTypeSignature(typeName, false/*don't resolve*/); + char[] typeName = CharOperation.concatWith(compoundName, '.'); + String signature = Signature + .createTypeSignature(typeName, false/* don't resolve */); int dimensions = type.dimensions(); if (dimensions > 0) { - signature = Signature.createArraySignature(signature, dimensions); + signature = Signature.createArraySignature(signature, dimensions); } return signature; } - /** - * Asserts that the given method signature is valid. - */ - public static void validateMethodSignature(String sig) { - Assert.isTrue(isValidMethodSignature(sig)); - } - - /** - * Asserts that the given type signature is valid. - */ - public static void validateTypeSignature(String sig, boolean allowVoid) { - Assert.isTrue(isValidTypeSignature(sig, allowVoid)); - } - - public static void verbose(String log) { - verbose(log, System.out); - } - - public static synchronized void verbose(String log, PrintStream printStream) { - int start = 0; - do { - int end = log.indexOf('\n', start); - printStream.print(Thread.currentThread()); - printStream.print(" "); //$NON-NLS-1$ - printStream.print(log.substring(start, end == -1 ? log.length() : end + 1)); - start = end + 1; - } while (start != 0); - printStream.println(); - } - - /** - * Writes a string to the given output stream using UTF-8 encoding in a machine-independent manner. - *
- * First, two bytes are written to the output stream as if by the writeShort
method giving the number of bytes to
- * follow. This value is the number of bytes actually written out, not the length of the string. Following the length, each
- * character of the string is output, in sequence, using the UTF-8 encoding for the character.
- *
- * @param str
- * a string to be written.
- * @return the number of bytes written to the stream.
- * @exception IOException
- * if an I/O error occurs.
- * @since JDK1.0
- */
- public static int writeUTF(OutputStream out, char[] str) throws IOException {
- int strlen = str.length;
- int utflen = 0;
- for (int i = 0; i < strlen; i++) {
- int c = str[i];
- if ((c >= 0x0001) && (c <= 0x007F)) {
- utflen++;
- } else if (c > 0x07FF) {
- utflen += 3;
- } else {
- utflen += 2;
- }
- }
- if (utflen > 65535)
- throw new UTFDataFormatException();
- out.write((utflen >>> 8) & 0xFF);
- out.write((utflen >>> 0) & 0xFF);
- if (strlen == utflen) {
- for (int i = 0; i < strlen; i++)
- out.write(str[i]);
- } else {
- for (int i = 0; i < strlen; i++) {
- int c = str[i];
- if ((c >= 0x0001) && (c <= 0x007F)) {
- out.write(c);
- } else if (c > 0x07FF) {
- out.write(0xE0 | ((c >> 12) & 0x0F));
- out.write(0x80 | ((c >> 6) & 0x3F));
- out.write(0x80 | ((c >> 0) & 0x3F));
- } else {
- out.write(0xC0 | ((c >> 6) & 0x1F));
- out.write(0x80 | ((c >> 0) & 0x3F));
- }
- }
- }
- return utflen + 2; // the number of bytes written to the stream
- }
+
+ /**
+ * Asserts that the given method signature is valid.
+ */
+ public static void validateMethodSignature(String sig) {
+ Assert.isTrue(isValidMethodSignature(sig));
+ }
+
+ /**
+ * Asserts that the given type signature is valid.
+ */
+ public static void validateTypeSignature(String sig, boolean allowVoid) {
+ Assert.isTrue(isValidTypeSignature(sig, allowVoid));
+ }
+
+ public static void verbose(String log) {
+ verbose(log, System.out);
+ }
+
+ public static synchronized void verbose(String log, PrintStream printStream) {
+ int start = 0;
+ do {
+ int end = log.indexOf('\n', start);
+ printStream.print(Thread.currentThread());
+ printStream.print(" "); //$NON-NLS-1$
+ printStream.print(log.substring(start, end == -1 ? log.length()
+ : end + 1));
+ start = end + 1;
+ } while (start != 0);
+ printStream.println();
+ }
+
+ /**
+ * Writes a string to the given output stream using UTF-8 encoding in a
+ * machine-independent manner.
+ *
+ * First, two bytes are written to the output stream as if by the
+ * writeShort
method giving the number of bytes to follow.
+ * This value is the number of bytes actually written out, not the length of
+ * the string. Following the length, each character of the string is output,
+ * in sequence, using the UTF-8 encoding for the character.
+ *
+ * @param str
+ * a string to be written.
+ * @return the number of bytes written to the stream.
+ * @exception IOException
+ * if an I/O error occurs.
+ * @since JDK1.0
+ */
+ public static int writeUTF(OutputStream out, char[] str) throws IOException {
+ int strlen = str.length;
+ int utflen = 0;
+ for (int i = 0; i < strlen; i++) {
+ int c = str[i];
+ if ((c >= 0x0001) && (c <= 0x007F)) {
+ utflen++;
+ } else if (c > 0x07FF) {
+ utflen += 3;
+ } else {
+ utflen += 2;
+ }
+ }
+ if (utflen > 65535)
+ throw new UTFDataFormatException();
+ out.write((utflen >>> 8) & 0xFF);
+ out.write((utflen >>> 0) & 0xFF);
+ if (strlen == utflen) {
+ for (int i = 0; i < strlen; i++)
+ out.write(str[i]);
+ } else {
+ for (int i = 0; i < strlen; i++) {
+ int c = str[i];
+ if ((c >= 0x0001) && (c <= 0x007F)) {
+ out.write(c);
+ } else if (c > 0x07FF) {
+ out.write(0xE0 | ((c >> 12) & 0x0F));
+ out.write(0x80 | ((c >> 6) & 0x3F));
+ out.write(0x80 | ((c >> 0) & 0x3F));
+ } else {
+ out.write(0xC0 | ((c >> 6) & 0x1F));
+ out.write(0x80 | ((c >> 0) & 0x3F));
+ }
+ }
+ }
+ return utflen + 2; // the number of bytes written to the stream
+ }
}
\ No newline at end of file