//
// Copyright (C) 2006 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA). All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3. The NOSA has been approved by the Open Source
// Initiative. See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.util;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
@SuppressWarnings("unchecked")
public class Misc {
public static int hashCode(Object o) {
return o == null ? 0 : o.hashCode();
}
public static boolean equal(Object a, Object b) {
if (a == b) {
return true;
} else if (a == null || b == null) {
// only one could be null
return false;
} else {
return a.equals(b);
}
}
public static <E> Iterator<E> emptyIterator() {
return (Iterator<E>) emptyIterator;
}
public static <E> Iterable<E> emptyIterable() {
return (Iterable<E>) emptyIterable;
}
public static <E> Iterable<E> iterableFromIterator(Iterator<E> iter) {
return new Iteratorable<E>(iter);
}
public static final Object[] emptyObjectArray = new Object[] {};
public static final Iterator<?> emptyIterator = new Iterator<Object>() {
public boolean hasNext () { return false; }
public Object next () { throw new NoSuchElementException(); }
public void remove () { throw new NoSuchElementException(); }
};
public static final Iterable<?> emptyIterable = new Iterable<Object>() {
public Iterator<Object> iterator () {
return (Iterator<Object>) emptyIterator;
}
};
public static <E> void addAll(Collection<E> target, Iterable<? extends E> src) {
for (E e : src) target.add(e);
}
public static <T> int indexOf (T[] array, Object elem){
for (int i=0; i<array.length; i++){
if (array[i].equals(elem)){
return i;
}
}
return -1;
}
public static <T> boolean contains (T[] array, Object elem){
for (int i=0; i<array.length; i++){
if (array[i].equals(elem)){
return true;
}
}
return false;
}
public static <T> T[] stripNullElements(T[] oldArray){
int count = 0;
for (int i=0; i<oldArray.length; i++){
if (oldArray[i] != null){
count++;
}
}
if (count == oldArray.length){ // nothing to strip
return oldArray;
} else {
Class<?> ct = oldArray.getClass().getComponentType();
T[] newArray = (T[]) Array.newInstance(ct, count);
int j=0;
for (int i=0; i<oldArray.length; i++){
T e = oldArray[i];
if (e != null){
newArray[j++] = e;
if (j == count){
break;
}
}
}
return newArray;
}
}
public static <T> T[] getAddedElements (T[] oldArray, T[] newArray) {
if (newArray == null || newArray.length == 0) {
return oldArray;
}
if (oldArray == null || oldArray.length == 0) {
return newArray;
}
T[] na = newArray.clone();
int n = na.length;
for (int i=0; i<na.length; i++) {
Object eNew = na[i];
if (eNew != null) {
for (int j=0; j<oldArray.length; j++) {
if (eNew.equals(oldArray[j])) {
na[i] = null;
n--;
break;
}
}
} else {
n--;
}
}
Class<?> ct = newArray.getClass().getComponentType();
T[] addedElements = (T[]) Array.newInstance(ct, n);
for (int i=0, j=0; i<na.length; i++) {
if (na[i] != null) {
addedElements[j++] = na[i];
}
}
return addedElements;
}
public static <T> T[] getRemovedElements (T[] oldArray, T[] newArray) {
if (newArray == null || newArray.length == 0 || oldArray == null || oldArray.length == 0) {
return null;
}
T[] oa = oldArray.clone();
int n = oa.length;
for (int i=0; i<oa.length; i++) {
Object eOld = oa[i];
if (eOld != null) {
for (int j=0; j<newArray.length; j++) {
if (eOld.equals(newArray[j])) {
oa[i] = null;
n--;
break;
}
}
} else {
n--;
}
}
Class<?> ct = oldArray.getClass().getComponentType();
T[] addedElements = (T[]) Array.newInstance(ct, n);
for (int i=0, j=0; i<oa.length; i++) {
if (oa[i] != null) {
addedElements[j++] = oa[i];
}
}
return addedElements;
}
public static <K,V> ArrayList<String> getSortedKeyStrings (HashMap<K,V> map){
ArrayList<String> list = new ArrayList<String>();
nextKey:
for (K key : map.keySet()){
String ks = key.toString();
for (int i=0; i<list.size(); i++){
String k = list.get(i);
if (ks.compareTo(k) > 0){
list.add(i, ks);
continue nextKey;
}
}
list.add(ks);
}
return list;
}
public static <K,V> ArrayList<Map.Entry<K,V>> createSortedEntryList (HashMap<K,V> map,
Comparator<Map.Entry<K,V>> comparer) {
ArrayList<Map.Entry<K,V>> list = new ArrayList<Map.Entry<K,V>>();
nextEntry:
for (Map.Entry<K,V> e : map.entrySet()){
for (int i=0; i<list.size(); i++){
if (comparer.compare(e,list.get(i)) > 0) {
list.add(i, e);
continue nextEntry;
}
}
list.add(e);
}
return list;
}
public static <K,V,E> ArrayList<E> createSortedList (HashMap<K,V> map,
TwoTypeComparator<Map.Entry<K,V>,E> comparer,
ElementCreator<Map.Entry<K,V>,E> creator) {
ArrayList<E> list = new ArrayList<E>();
nextEntry:
for (Map.Entry<K,V> e : map.entrySet()){
for (int i=0; i<list.size(); i++){
if (comparer.compare(e,list.get(i)) > 0) {
list.add(i, creator.create(e));
continue nextEntry;
}
}
list.add(creator.create(e));
}
return list;
}
public static int compare (Integer i1, Integer i2) {
return Integer.signum(i1.intValue() - i2.intValue());
}
public static <E,T> HashMap<E,Integer> createOccurrenceMap (Collection<T> collection,
ElementCreator<T,E> creator) {
HashMap<E,Integer> map = new HashMap<E,Integer>();
for (T o : collection) {
E e = creator.create(o);
Integer nE = map.get(e);
if (nE == null){
map.put(e,1);
} else {
map.put(e,nE.intValue()+1);
}
}
return map;
}
public static <T> T createObject (Class<T> cls, Class<?>[] argTypes, Object[] args){
if (argTypes.length != args.length){
return null;
}
while (argTypes.length >= 0){
try {
Constructor<T> ctor = cls.getConstructor(argTypes);
return ctor.newInstance(args);
} catch (NoSuchMethodException nsmx){
Class<?>[] at = new Class<?>[argTypes.length-1];
System.arraycopy(argTypes, 1, at,0, at.length);
argTypes = at;
Object[] a = new Object[at.length];
System.arraycopy(args,1, a,0, a.length);
args = a;
} catch (Throwable t){
return null;
}
}
return null;
}
public static String toString( Iterable<?> collection,
String prefix, String separator, String postfix) {
StringBuilder sb = new StringBuilder();
if (prefix != null) {
sb.append(prefix);
}
int i=0;
for (Object e : collection) {
if (i++ > 0) {
sb.append(separator);
}
sb.append(e);
}
if (postfix != null) {
sb.append(postfix);
}
return sb.toString();
}
public static String toString( Object[] array,
String prefix, String separator, String postfix) {
StringBuilder sb = new StringBuilder();
if (prefix != null) {
sb.append(prefix);
}
for (int i=0; i<array.length; i++) {
if (i > 0) {
sb.append(separator);
}
sb.append(array[i]);
}
if (postfix != null) {
sb.append(postfix);
}
return sb.toString();
}
public static String toString( int[] array, int start, int end, String prefix, String separator, String postfix){
StringBuilder sb = new StringBuilder();
if (prefix != null) {
sb.append(prefix);
}
for (int i=start; i<array.length && i < end; i++) {
if (i > 0) {
sb.append(separator);
}
sb.append(array[i]);
}
if (postfix != null) {
sb.append(postfix);
}
return sb.toString();
}
@SafeVarargs
public static <T> T[] newArray (T... elements) {
return elements;
}
@SafeVarargs
public static <T> T[] appendArray (T[] base, T... elements) {
if (base == null || base.length == 0){
return elements;
} else if (elements == null || elements.length == 0){
return base;
} else {
Class<?> componentType = base.getClass().getComponentType();
T[] a = (T[]) Array.newInstance(componentType, base.length + elements.length);
System.arraycopy(base, 0, a, 0, base.length);
System.arraycopy(elements, 0, a, base.length, elements.length);
return a;
}
}
public static <T> T[] prependArray (T[] base, T... elements) {
if (base == null || base.length == 0){
return elements;
} else if (elements == null || elements.length == 0){
return base;
} else {
Class<?> componentType = base.getClass().getComponentType();
T[] a = (T[]) Array.newInstance(componentType, base.length + elements.length);
System.arraycopy(base,0, a,elements.length, base.length);
System.arraycopy(elements,0, a,0, elements.length);
return a;
}
}
public static String[] prependArray (String[] base, String... elements){
if (base == null || base.length == 0){
return elements;
} else if (elements == null || elements.length == 0){
return base;
} else {
String[] a = new String[base.length + elements.length];
System.arraycopy(base,0, a,elements.length, base.length);
System.arraycopy(elements,0, a,0, elements.length);
return a;
}
}
public static <T> T[] arrayWithoutFirst( T[] base, int nElements){
if (base == null){
return null;
} else if (nElements >= base.length){
Class<?> componentType = base.getClass().getComponentType();
T[] a = (T[]) Array.newInstance(componentType, 0);
return a;
} else {
int n = base.length - nElements;
Class<?> componentType = base.getClass().getComponentType();
T[] a = (T[]) Array.newInstance(componentType, n);
System.arraycopy(base, nElements, a, 0, n);
return a;
}
}
public static <T> T[] appendElement (T[] base, T newElement){
int len = base.length;
Class<?> componentType = base.getClass().getComponentType();
T[] a = (T[]) Array.newInstance(componentType, len + 1);
System.arraycopy(base, 0, a, 0, len);
a[len] = newElement;
return a;
}
public static <T> T[] removeElement (T[] base, T element) {
int len = base.length;
for (int i=0; i<len; i++){
if (base[i] == element){
Class<?> componentType = base.getClass().getComponentType();
T[] a = (T[]) Array.newInstance(componentType, len -1);
System.arraycopy(base, 0, a, 0, i);
System.arraycopy(base, i+1, a, i, len-i-1);
return a;
}
}
return base;
}
public static <T> boolean hasElementOfType (T[] base, Class<?> elemType){
int len = base.length;
for (int i=0; i<len; i++){
if (elemType.isInstance(base[i])){
return true;
}
}
return false;
}
public static <T,E> E getNextElementOfType (T[] base, Class<E> elemType, T prev){
boolean prevSeen = (prev == null);
int len = base.length;
for (int i=0; i<len; i++){
if (elemType.isInstance(base[i])){
if (prevSeen){
return (E)base[i];
} else {
prevSeen = (base[i] == prev);
}
}
}
return null;
}
public static String[] arrayWithoutFirst(String[] base, int nElements){
String[] a = new String[base.length-1];
if (a.length > 0){
System.arraycopy(base,1,a,0,a.length);
}
return a;
}
public static boolean compare (Object[] a1, Object[] a2){
if (a1 == null && a2 == null){
return true;
}
if (a1 == null){
if (a2 != null){
for (int i=0; i<a2.length; i++){
if (a2[i] != null){
return false;
}
}
}
} else if (a2 == null){
for (int i=0; i<a1.length; i++){
if (a1[i] != null){
return false;
}
}
} else {
if (a1.length != a2.length){
return false;
}
for (int i = 0; i < a1.length; i++) {
Object o1 = a1[i];
Object o2 = a2[i];
if (o1 != null) {
if (!o1.equals(o2)) {
return false;
}
} else if (o2 != null) {
return false;
}
}
}
return true;
}
/**
* compare first len objects of two reference arrays, which can contain null
* elements. If any of the reference arrays is null, this is treated as
* if all elements would be null
*/
public static boolean compare (int len, Object[] a1, Object[] a2){
if (a1 == null && a2 == null){
return true;
}
if (a1 == null){
if (a2 != null){
if (a2.length < len){
return false;
}
for (int i=0; i<len; i++){
if (a2[i] != null){
return false;
}
}
}
} else if (a2 == null){
if (a1.length < len){
return false;
}
for (int i=0; i<len; i++){
if (a1[i] != null){
return false;
}
}
} else {
if (a1.length < len || a2.length < len){
return false;
}
for (int i = 0; i < len; i++) {
Object o1 = a1[i];
Object o2 = a2[i];
if (o1 != null) {
if (!o1.equals(o2)) {
return false;
}
} else if (o2 != null) {
return false;
}
}
}
return true;
}
public static String stripToLastDot (String s){
int i = s.lastIndexOf('.');
if (i>=0){
return s.substring(i+1);
} else {
return s;
}
}
public static int setBit (int val, int idx){
return (val | (1<<idx));
}
public static int clearBit (int val, int idx){
return (val & ~(1<<idx));
}
public static String upToFirst( String s, char c){
int i = s.indexOf(c);
if (i >= 0){
return s.substring(0, i);
} else {
return s;
}
}
public static String fromFirst( String s, char c){
int i = s.indexOf(c);
if (i >= 0){
return s.substring(i);
} else {
return s;
}
}
/*=================== PRIVATE STUFF ===================*/
private static final class Iteratorable<E> implements Iterable<E> {
Iterator<E> iter;
public Iteratorable(Iterator<E> iter) {
this.iter = iter;
}
public Iterator<E> iterator () {
Iterator<E> ret = iter;
iter = null;
return ret;
}
}
}