/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package net.sourceforge.phpdt.internal.core.util;
import java.io.BufferedInputStream;
//import java.io.DataInput;
//import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
//import java.io.OutputStream;
import java.io.PrintStream;
//import java.io.UTFDataFormatException;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
//import java.util.StringTokenizer;
import net.sourceforge.phpdt.core.IJavaElement;
import net.sourceforge.phpdt.core.IJavaModelStatusConstants;
import net.sourceforge.phpdt.core.IPackageFragment;
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;
//incastrix
//import net.sourceforge.phpdt.internal.corext.Assert;
//import org.eclipse.core.runtime.Assert;
//import net.sourceforge.phpdt.internal.core.PackageFragmentRoot;
import net.sourceforge.phpdt.internal.core.util.PHPFileUtil;
import org.eclipse.core.resources.IFile;
//import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
//import org.eclipse.jface.text.BadLocationException;
//import org.eclipse.text.edits.MalformedTreeException;
//import org.eclipse.text.edits.TextEdit;
/**
* Provides convenient utility methods to other types in this package.
*/
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 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; // } /** * 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
// }
}