Initial import
[jpf-core.git] / src / main / gov / nasa / jpf / util / Misc.java
1 /*
2  * Copyright (C) 2014, United States Government, as represented by the
3  * Administrator of the National Aeronautics and Space Administration.
4  * All rights reserved.
5  *
6  * The Java Pathfinder core (jpf-core) platform is licensed under the
7  * Apache License, Version 2.0 (the "License"); you may not use this file except
8  * in compliance with the License. You may obtain a copy of the License at
9  * 
10  *        http://www.apache.org/licenses/LICENSE-2.0. 
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and 
16  * limitations under the License.
17  */
18 package gov.nasa.jpf.util;
19
20
21 import java.lang.reflect.Array;
22 import java.lang.reflect.Constructor;
23 import java.util.ArrayList;
24 import java.util.Collection;
25 import java.util.Comparator;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.NoSuchElementException;
30
31 public class Misc {
32   public static int hashCode(Object o) {
33     return o == null ? 0 : o.hashCode();
34   }
35
36   public static boolean equals(Object a, Object b) {
37     if (a == b) {
38       return true;
39     } else if (a == null || b == null) {
40       // only one could be null
41       return false;
42     } else {
43       return a.equals(b);
44     }
45   }
46
47   @SuppressWarnings("unchecked")
48   public static <E> Iterator<E> emptyIterator() {
49     return (Iterator<E>) emptyIterator;
50   }
51
52   @SuppressWarnings("unchecked")
53   public static <E> Iterable<E> emptyIterable() {
54     return (Iterable<E>) emptyIterable;
55   }
56
57   public static <E> Iterable<E> iterableFromIterator(Iterator<E> iter) {
58     return new Iteratorable<E>(iter);
59   }
60
61   public static final Object[] emptyObjectArray = new Object[] {};
62
63   public static final Iterator<?> emptyIterator = new Iterator<Object>() {
64     @Override
65         public boolean hasNext () { return false; }
66     @Override
67         public Object next () { throw new NoSuchElementException(); }
68     @Override
69         public void remove () { throw new NoSuchElementException(); }
70   };
71
72   public static final Iterable<?> emptyIterable = new Iterable<Object>() {
73     @Override
74         @SuppressWarnings("unchecked")
75     public Iterator<Object> iterator () {
76       return (Iterator<Object>) emptyIterator;
77     }
78   };
79
80   @SuppressWarnings("unchecked")
81   public static <B, E extends B> Iterable<B> asBaseIterable (Collection<E> col){
82     Collection<B> base = (Collection)col;
83     return base;
84   }
85
86   @SuppressWarnings("unchecked")
87   public static <B, E extends B> Iterator<B> getBaseIterator (Collection<E> col){
88     Collection<B> base = (Collection)col;
89     return base.iterator();
90   }
91   
92   public static <E> void addAll(Collection<E> target, Iterable<? extends E> src) {
93     for (E e : src) target.add(e);
94   }
95
96   public static <T> int indexOf (T[] array, Object elem){
97     for (int i=0; i<array.length; i++){
98       if (array[i].equals(elem)){
99         return i;
100       }
101     }
102     
103     return -1;
104   } 
105
106   public static <T> boolean contains (T[] array, Object elem){
107     for (int i=0; i<array.length; i++){
108       if (array[i].equals(elem)){
109         return true;
110       }
111     }
112     
113     return false;
114   } 
115   
116   @SuppressWarnings("unchecked")
117   public static <T> T[] stripNullElements(T[] oldArray){
118     int count = 0;
119     for (int i=0; i<oldArray.length; i++){
120       if (oldArray[i] != null){
121         count++;
122       }
123     }
124     
125     if (count == oldArray.length){ // nothing to strip
126       return oldArray;
127       
128     } else {
129       Class<?> ct = oldArray.getClass().getComponentType();
130       T[] newArray = (T[]) Array.newInstance(ct, count);
131
132       int j=0;
133       for (int i=0; i<oldArray.length; i++){
134         T e = oldArray[i];
135         if (e != null){
136           newArray[j++] = e;
137           if (j == count){
138             break;
139           }
140         }
141       }
142       
143       return newArray;
144     }
145   }
146   
147   @SuppressWarnings("unchecked")
148   public static <T> T[] getAddedElements (T[] oldArray, T[] newArray) {
149     
150     if (newArray == null || newArray.length == 0) {
151       return oldArray; 
152     }
153     if (oldArray == null || oldArray.length == 0) {
154       return newArray;
155     }
156     
157     T[] na = newArray.clone();
158     int n = na.length;
159     
160     for (int i=0; i<na.length; i++) {
161       Object eNew = na[i];
162       if (eNew != null) {
163         for (int j=0; j<oldArray.length; j++) {
164           if (eNew.equals(oldArray[j])) {
165             na[i] = null;
166             n--;
167             break;
168           }
169         }
170       } else {
171         n--;
172       }
173     }
174     
175     Class<?> ct = newArray.getClass().getComponentType();
176     T[] addedElements = (T[]) Array.newInstance(ct, n);
177     
178     for (int i=0, j=0; i<na.length; i++) {
179       if (na[i] != null) {
180         addedElements[j++] = na[i];
181       }
182     }
183     
184     return addedElements;
185   }
186   
187   public static <T> T[] getRemovedElements (T[] oldArray, T[] newArray) {
188
189     if (newArray == null || newArray.length == 0 || oldArray == null || oldArray.length == 0) {
190       return null;
191     }
192     
193     T[] oa = oldArray.clone();
194     int n = oa.length;
195     
196     for (int i=0; i<oa.length; i++) {
197       Object eOld = oa[i];
198       if (eOld != null) {
199         for (int j=0; j<newArray.length; j++) {
200           if (eOld.equals(newArray[j])) {
201             oa[i] = null;
202             n--;
203             break;
204           }
205         }
206       } else {
207         n--;
208       }
209     }
210     
211     Class<?> ct = oldArray.getClass().getComponentType();
212     T[] addedElements = (T[]) Array.newInstance(ct, n);
213     
214     for (int i=0, j=0; i<oa.length; i++) {
215       if (oa[i] != null) {
216         addedElements[j++] = oa[i];
217       }
218     }
219     
220     return addedElements;
221   }
222   
223   
224   public static <K,V> ArrayList<String> getSortedKeyStrings (HashMap<K,V> map){
225     ArrayList<String> list = new ArrayList<String>();
226
227     nextKey:
228     for (K key : map.keySet()){
229       String ks = key.toString();
230
231       for (int i=0; i<list.size(); i++){
232         String k = list.get(i);
233         if (ks.compareTo(k) > 0){
234           list.add(i, ks);
235           continue nextKey;
236         }
237       }
238
239       list.add(ks);
240     }
241
242     return list;
243   }
244
245   public static <K,V> ArrayList<Map.Entry<K,V>> createSortedEntryList (HashMap<K,V> map,
246                                                                        Comparator<Map.Entry<K,V>> comparer) {
247     ArrayList<Map.Entry<K,V>> list = new ArrayList<Map.Entry<K,V>>();
248
249     nextEntry:
250       for (Map.Entry<K,V> e : map.entrySet()){
251
252         for (int i=0; i<list.size(); i++){
253           if (comparer.compare(e,list.get(i)) > 0) {
254             list.add(i, e);
255             continue nextEntry;
256           }
257         }
258         list.add(e);
259       }
260
261
262     return list;
263   }
264
265   public static <K,V,E> ArrayList<E> createSortedList (HashMap<K,V> map,
266                                                     TwoTypeComparator<Map.Entry<K,V>,E> comparer,
267                                                     ElementCreator<Map.Entry<K,V>,E> creator) {
268     ArrayList<E> list = new ArrayList<E>();
269
270     nextEntry:
271       for (Map.Entry<K,V> e : map.entrySet()){
272
273         for (int i=0; i<list.size(); i++){
274           if (comparer.compare(e,list.get(i)) > 0) {
275             list.add(i, creator.create(e));
276             continue nextEntry;
277           }
278         }
279         list.add(creator.create(e));
280       }
281
282
283     return list;
284   }
285
286   public static int compare (Integer i1, Integer i2) {
287     return Integer.signum(i1.intValue() - i2.intValue());
288   }
289
290   public static <E,T> HashMap<E,Integer> createOccurrenceMap (Collection<T> collection,
291                                                             ElementCreator<T,E> creator) {
292     HashMap<E,Integer> map = new HashMap<E,Integer>();
293
294     for (T o : collection) {
295       E e = creator.create(o);
296       Integer nE = map.get(e);
297       if (nE == null){
298         map.put(e,1);
299       } else {
300         map.put(e,nE.intValue()+1);
301       }
302     }
303
304     return map;
305   }
306
307   public static <T> T createObject (Class<T> cls, Class<?>[] argTypes, Object[] args){
308     if (argTypes.length != args.length){
309       return null;
310     }
311
312     while (argTypes.length >= 0){
313       try {
314         Constructor<T> ctor = cls.getConstructor(argTypes);
315         return ctor.newInstance(args);
316
317       } catch (NoSuchMethodException nsmx){
318         Class<?>[] at = new Class<?>[argTypes.length-1];
319         System.arraycopy(argTypes, 1, at,0, at.length);
320         argTypes = at;
321
322         Object[] a = new Object[at.length];
323         System.arraycopy(args,1, a,0, a.length);
324         args = a;
325
326       } catch (Throwable t){
327         return null;
328       }
329     }
330
331     return null;
332   }
333
334   public static String toString (Object[] collection) {
335     StringBuilder sb = new StringBuilder();
336     
337     for (Object e : collection) {
338       sb.append(e);
339     }
340
341     return sb.toString();
342   }
343   
344   public static String toString (String[] collection) {
345     StringBuilder sb = new StringBuilder();
346     
347     for (Object e : collection) {
348       sb.append(e);
349     }
350
351     return sb.toString();
352   }
353   
354   public static String toString (Iterable<?> collection) {
355     StringBuilder sb = new StringBuilder();
356     
357     for (Object e : collection) {
358       sb.append(e);
359     }
360
361     return sb.toString();
362   }
363   
364   public static String toString( Iterable<?> collection,
365                                  String prefix, String separator, String postfix) {
366     StringBuilder sb = new StringBuilder();
367
368     if (prefix != null) {
369       sb.append(prefix);
370     }
371
372     int i=0;
373     for (Object e : collection) {
374       if (i++ > 0) {
375         sb.append(separator);
376       }
377       sb.append(e);
378     }
379
380     if (postfix != null) {
381       sb.append(postfix);
382     }
383
384     return sb.toString();
385   }
386
387   public static String toString( Object[] array,
388                                  String prefix, String separator, String postfix) {
389     StringBuilder sb = new StringBuilder();
390
391     if (prefix != null) {
392       sb.append(prefix);
393     }
394
395     for (int i=0; i<array.length; i++) {
396       if (i > 0) {
397         sb.append(separator);
398       }
399       sb.append(array[i]);
400     }
401
402     if (postfix != null) {
403       sb.append(postfix);
404     }
405
406     return sb.toString();
407   }
408
409   public static String toString( int[] array, int start, int end, String prefix, String separator, String postfix){
410     StringBuilder sb = new StringBuilder();
411
412     if (prefix != null) {
413       sb.append(prefix);
414     }
415
416     for (int i=start; i<array.length && i < end; i++) {
417       if (i > 0) {
418         sb.append(separator);
419       }
420       sb.append(array[i]);
421     }
422
423     if (postfix != null) {
424       sb.append(postfix);
425     }
426
427     return sb.toString();    
428   }
429
430   public static <T> T[] newArray (T... elements) {
431     return elements;
432   }
433
434   public static <T> T[] appendArray (T[] base, T... elements) {
435     if (base == null || base.length == 0){
436       return elements;
437     } else if (elements == null || elements.length == 0){
438       return base;
439     } else {
440       Class<?> componentType = base.getClass().getComponentType();
441       T[] a = (T[]) Array.newInstance(componentType, base.length + elements.length);
442       System.arraycopy(base, 0, a, 0, base.length);
443       System.arraycopy(elements, 0, a, base.length, elements.length);
444       return a;
445     }
446   }
447
448   public static <T> T[] prependArray (T[] base, T... elements) {
449     if (base == null || base.length == 0){
450       return elements;
451     } else if (elements == null || elements.length == 0){
452       return base;
453     } else {
454       Class<?> componentType = base.getClass().getComponentType();
455       T[] a = (T[]) Array.newInstance(componentType, base.length + elements.length);
456       System.arraycopy(base,0, a,elements.length, base.length);
457       System.arraycopy(elements,0, a,0, elements.length);
458       return a;
459     }
460   }
461
462   public static String[] prependArray (String[] base, String... elements){
463     if (base == null || base.length == 0){
464       return elements;
465     } else if (elements == null || elements.length == 0){
466       return base;
467     } else {
468       String[] a = new String[base.length + elements.length];
469       System.arraycopy(base,0, a,elements.length, base.length);
470       System.arraycopy(elements,0, a,0, elements.length);
471       return a;
472     }
473   }
474
475
476   public static <T> T[] arrayWithoutFirst( T[] base, int nElements){
477     if (base == null){
478       return null;
479     } else if (nElements >= base.length){
480       Class<?> componentType = base.getClass().getComponentType();
481       T[] a = (T[]) Array.newInstance(componentType, 0);
482       return a;
483     } else {
484       int n = base.length - nElements;
485       Class<?> componentType = base.getClass().getComponentType();
486       T[] a = (T[]) Array.newInstance(componentType, n);
487       System.arraycopy(base, nElements, a, 0, n);
488       return a;
489     }
490   }
491
492   public static <T> T[] appendElement (T[] base, T newElement){
493     int len = base.length;
494
495     Class<?> componentType = base.getClass().getComponentType();
496     T[] a = (T[]) Array.newInstance(componentType, len + 1);
497     System.arraycopy(base, 0, a, 0, len);
498     a[len] = newElement;
499
500     return a;
501   }
502
503   public static <T> T[] appendUniqueElement (T[] base, T newElement){
504     int len = base.length;
505
506     for (int i=0; i<len; i++){
507       if (base[i] == newElement){
508         return base;
509       }
510     }
511
512     return appendElement(base, newElement);
513   }
514
515   
516   public static <T> T[] removeElement (T[] base, T element) {
517     int len = base.length;
518
519     for (int i=0; i<len; i++){
520       if (base[i] == element){
521         Class<?> componentType = base.getClass().getComponentType();
522         T[] a = (T[]) Array.newInstance(componentType, len -1);
523         System.arraycopy(base, 0, a, 0, i);
524         System.arraycopy(base, i+1, a, i, len-i-1);
525         return a;
526       }
527     }
528
529     return base;
530   }
531
532   public static <T> boolean hasElementOfType (T[] base, Class<?> elemType){
533     int len = base.length;
534     for (int i=0; i<len; i++){
535       if (elemType.isInstance(base[i])){
536         return true;
537       }
538     }
539
540     return false;
541   }
542
543   public static <T,E> E getNextElementOfType (T[] base, Class<E> elemType, T prev){
544     boolean prevSeen = (prev == null);
545     int len = base.length;
546     for (int i=0; i<len; i++){
547       if (elemType.isInstance(base[i])){
548         if (prevSeen){
549           return (E)base[i];
550         } else {
551           prevSeen = (base[i] == prev);
552         }
553       }
554     }
555     
556     return null;
557   }
558
559   public static String[] arrayWithoutFirst(String[] base, int nElements){
560     String[] a = new String[base.length-1];
561     if (a.length > 0){
562       System.arraycopy(base,1,a,0,a.length);
563     }
564     return a;
565   }
566
567   public static boolean equals (Object[] a1, Object[] a2){
568     if (a1 == a2){
569       return true;
570     }
571
572     if (a1 == null){
573       if (a2 != null){
574         for (int i=0; i<a2.length; i++){
575           if (a2[i] != null){
576             return false;
577           }
578         }
579       }
580     } else if (a2 == null){
581       for (int i=0; i<a1.length; i++){
582         if (a1[i] != null){
583           return false;
584         }
585       }
586     } else {
587       if (a1.length != a2.length){
588         return false;
589       }
590
591       for (int i = 0; i < a1.length; i++) {
592         Object o1 = a1[i];
593         Object o2 = a2[i];
594
595         if (o1 != null) {
596           if (!o1.equals(o2)) {
597             return false;
598           }
599         } else if (o2 != null) {
600           return false;
601         }
602       }
603     }
604
605     return true;
606
607   }
608
609   /**
610    * equals first len objects of two reference arrays, which can contain null
611    * elements. If any of the reference arrays is null, this is treated as
612    * if all elements would be null
613    */
614   public static boolean compare (int len, Object[] a1, Object[] a2){
615     if (a1 == null && a2 == null){
616       return true;
617     }
618     
619     if (a1 == null){
620       if (a2 != null){
621         if (a2.length < len){
622           return false;
623         }
624         for (int i=0; i<len; i++){
625           if (a2[i] != null){
626             return false;
627           }
628         }
629       }
630     } else if (a2 == null){
631       if (a1.length < len){
632         return false;
633       }
634       for (int i=0; i<len; i++){
635         if (a1[i] != null){
636           return false;
637         }
638       }      
639     } else {
640       if (a1.length < len || a2.length < len){
641         return false;
642       }
643
644       for (int i = 0; i < len; i++) {
645         Object o1 = a1[i];
646         Object o2 = a2[i];
647
648         if (o1 != null) {
649           if (!o1.equals(o2)) {
650             return false;
651           }
652         } else if (o2 != null) {
653           return false;
654         }
655       }
656     }
657     
658     return true;
659   }
660
661   public static String stripToLastDot (String s){
662     int i = s.lastIndexOf('.');
663     if (i>=0){
664       return s.substring(i+1);
665     } else {
666       return s;
667     }
668   }
669
670   public static int setBit (int val, int idx){
671     return (val | (1<<idx));
672   }
673   
674   public static int clearBit (int val, int idx){
675     return (val & ~(1<<idx));
676   }
677
678   public static String upToFirst( String s, char c){
679     int i = s.indexOf(c);
680     if (i >= 0){
681       return s.substring(0, i);
682     } else {
683       return s;
684     }
685   }
686   
687   public static String fromFirst( String s, char c){
688     int i = s.indexOf(c);
689     if (i >= 0){
690       return s.substring(i);
691     } else {
692       return s;
693     }
694   }
695   
696   
697   /*=================== PRIVATE STUFF ===================*/
698
699   private static final class Iteratorable<E> implements Iterable<E> {
700     Iterator<E> iter;
701
702     public Iteratorable(Iterator<E> iter) {
703       this.iter = iter;
704     }
705
706     @Override
707         public Iterator<E> iterator () {
708       Iterator<E> ret = iter;
709       iter = null;
710       return ret;
711     }
712   }
713 }