comparison src/main/gov/nasa/jpf/util/ObjVector.java @ 0:61d41facf527

initial v8 import (history reset)
author Peter Mehlitz <Peter.C.Mehlitz@nasa.gov>
date Fri, 23 Jan 2015 10:14:01 -0800
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:61d41facf527
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 import java.io.PrintStream;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Comparator;
24 import java.util.Iterator;
25 import java.util.NoSuchElementException;
26
27 /**
28 * more customizable alternative to java.util.Vector. Other than Vector, it
29 * supports dynamic growth on set() operations. While it supports list
30 * functions such as append, ObjVector resembles mostly an array, i.e.
31 * is meant to be a random-access collection
32 *
33 * this collection does not keep a count of non-null elements, but does maintain the
34 * highest set index as its size through set/add and remove operations. Note that size
35 * only shrinks through remove operations, not by setting null values. This means there
36 * is no guarantee that data[size-1] is not null. The converse however is true - there is no
37 * non-null element at an index >= size.
38 *
39 * @author pcd
40 */
41 public class ObjVector<E> implements ReadOnlyObjList<E>, Cloneable {
42 public static final int defaultInitCap = 40;
43
44 /** <i>size</i> as in a java.util.Vector. */
45 protected int size;
46
47 /** the backing array. */
48 protected Object[] data;
49
50 /** growth strategy. */
51 protected Growth growth;
52
53
54 //--- constructors
55
56 public ObjVector(Growth initGrowth, int initCap) {
57 growth = initGrowth;
58 data = new Object[initCap];
59 size = 0;
60 }
61
62 public ObjVector(Growth initGrowth) {
63 this(initGrowth,defaultInitCap);
64 }
65
66 public ObjVector(int initCap) {
67 this(Growth.defaultGrowth, initCap);
68 }
69
70 public ObjVector() {
71 this(Growth.defaultGrowth,defaultInitCap);
72 }
73
74 public <F extends E> ObjVector(F[] init) {
75 this(init.length);
76 append(init);
77 }
78
79 public <F extends E> ObjVector(ObjVector<F> from) {
80 this.data = new Object[from.data.length];
81 this.size = from.size;
82 this.growth = from.growth;
83 System.arraycopy(from.data, 0, this.data, 0, size);
84 }
85
86 //--- set/add/remove operations
87
88 public void add(E x) {
89 if (size >= data.length) {
90 ensureCapacity(size+1);
91 }
92 data[size] = x;
93 size++;
94 }
95
96 public void addNulls (int length) {
97 int newSize = size + length;
98 if (newSize > data.length) {
99 ensureCapacity(size + length);
100 }
101 for (int i = size; i < newSize; i++) {
102 data[i] = null;
103 }
104 size = newSize;
105 }
106
107 public <F extends E> void append(F[] x) {
108 if (size + x.length > data.length) {
109 ensureCapacity(size + x.length);
110 }
111 System.arraycopy(x, 0, data, size, x.length);
112 size += x.length;
113 }
114
115 public <F extends E> void append(F[] x, int pos, int len) {
116 if (size + len > data.length) {
117 ensureCapacity(size + len);
118 }
119 System.arraycopy(x, pos, data, size, len);
120 size += len;
121 }
122
123 public <F extends E> void append(ObjVector<F> x) {
124 if (size + x.size > data.length) {
125 ensureCapacity(size + x.size);
126 }
127 System.arraycopy(x.data, 0, data, size, x.size);
128 size += x.size;
129 }
130
131 @SuppressWarnings("unchecked")
132 public <F extends E> void append(ObjArray<F> x) {
133 append((F[])(x.data));
134 }
135
136 public <F extends E> void append(ArrayList<F> x){
137 int n = x.size();
138 int newSize = size + n;
139 if (newSize > data.length) {
140 ensureCapacity(newSize);
141 }
142 for (int i = size, j=0; i < newSize; i++,j++) {
143 data[i] = x.get(j);
144 }
145 size = newSize;
146 }
147
148 public <F extends E> void addAll(Iterable<F> x) {
149 if (x instanceof ObjVector) {
150 append((ObjVector<F>) x);
151 return;
152 }
153 // else
154 if (x instanceof ObjArray) {
155 append((ObjArray<F>) x);
156 return;
157 }
158 // else
159 if (x == null) return;
160 // else
161 for (F e : x) {
162 add(e);
163 }
164 }
165
166 public int nextNull (int fromIndex){
167 for (int i=fromIndex; i<size; i++){
168 if (data[i] == null){
169 return i;
170 }
171 }
172
173 ensureCapacity(size+1);
174 return size;
175 }
176
177 @Override
178 @SuppressWarnings("unchecked")
179 public E get(int idx) {
180 if (idx >= size) {
181 return null;
182 } else {
183 return (E) data[idx];
184 }
185 }
186
187 public void set(int idx, E v) {
188 ensureSize(idx+1);
189 data[idx] = v;
190 }
191
192 /**
193 * set range of values
194 * @param fromIndex first index (inclusive)
195 * @param toIndex last index (exclusive)
196 * @param val value to set
197 */
198 public void setRange (int fromIndex, int toIndex, E val) {
199 ensureSize(toIndex);
200 Arrays.fill(data, fromIndex, toIndex, val);
201 }
202
203 public <F> F[] toArray (F[] dst) {
204 System.arraycopy(data,0,dst,0,size);
205 return dst;
206 }
207
208 public ObjArray<E> toObjArray () {
209 ObjArray<E> dst = new ObjArray<E>(size);
210 System.arraycopy(data,0,dst.data,0,size);
211 return dst;
212 }
213
214 public int dumpTo (Object[] dst, int pos) {
215 System.arraycopy(data,0,dst,pos,size);
216 return pos + size;
217 }
218
219 @Override
220 public ObjVector<E> clone() {
221 return new ObjVector<E>(this);
222 }
223
224 public void squeeze() {
225 while (size > 0 && data[size - 1] == null) size--;
226 }
227
228 public void setSize(int sz) {
229 if (sz > size) {
230 ensureCapacity(sz);
231 size = sz;
232 } else {
233 while (size > sz) {
234 size--;
235 data[size] = null;
236 }
237 }
238 }
239
240 public void clear() {
241 // faster than iterating over the whole array
242 data = new Object[data.length];
243 size = 0;
244 }
245
246 @SuppressWarnings("unchecked")
247 public void clearAllSatisfying (Predicate<E> pred) {
248 Object[] d = data;
249 int newSize = 0;
250 for (int i=size-1; i>=0; i--) {
251 E e = (E)d[i];
252 if (e != null) {
253 if (pred.isTrue(e)) {
254 d[i] = null;
255 } else {
256 if (newSize == 0) {
257 newSize = i+1;
258 }
259 }
260 }
261 }
262
263 size = newSize;
264 }
265
266 public int size() {
267 return size;
268 }
269
270 @Override
271 public int length() {
272 return size;
273 }
274
275 public void ensureSize(int sz) {
276 if (size < sz) {
277 ensureCapacity(sz);
278 size = sz;
279 }
280 }
281
282 public void ensureCapacity(int desiredCap) {
283 if (data.length < desiredCap) {
284 Object[] newData = new Object[growth.grow(data.length, desiredCap)];
285 System.arraycopy(data, 0, newData, 0, size);
286 data = newData;
287 }
288 }
289
290 @SuppressWarnings("unchecked")
291 public void sort(Comparator<? super E> comp) {
292 Arrays.sort(data, 0, size, (Comparator<Object>) comp);
293 }
294
295 public static <E> void copy(ObjVector<? extends E> src, int srcPos,
296 ObjVector<E> dst, int dstPos, int len) {
297 src.ensureCapacity(srcPos + len);
298 dst.ensureSize(dstPos+len);
299 System.arraycopy(src.data, srcPos, dst.data, dstPos, len);
300 }
301
302 public static <E> void copy(ObjVector<? extends E> src, int srcPos,
303 E[] dst, int dstPos, int len) {
304 src.ensureCapacity(srcPos + len);
305 //dst.ensureSize(dstPos+len);
306 System.arraycopy(src.data, srcPos, dst, dstPos, len);
307 }
308
309 /**
310 * remove all non-null elements between 'fromIdx' (inclusive) and
311 * 'toIdx' (exclusive)
312 * throw IndexOutOfBoundsException if index values are out of range
313 */
314 public int removeRange(int fromIdx, int toIdx){
315 int n = 0;
316 Object[] data = this.data;
317
318 // it's the callers responsibility to ensure proper index ranges
319 //if (fromIdx < 0) fromIdx = 0;
320 //if (toIdx > size) toIdx = size;
321
322 for (int i=fromIdx; i<toIdx; i++){
323 if (data[i] != null){
324 data[i] = null;
325 n++;
326 }
327 }
328
329 if (toIdx >= size){
330 int i=fromIdx-1;
331 for (; i>=0 && (data[i] == null); i--);
332 size = i+1;
333 }
334
335 return n;
336 }
337
338 public int removeFrom(int fromIdx){
339 return removeRange(fromIdx,size);
340 }
341
342 public E remove (int i) {
343 E e = (E) data[i];
344
345 if (e != null) {
346 data[i] = null;
347 if (i+1 == size) {
348 int j=i-1;
349 for (; j>=0 && (data[j] == null); j--);
350 size = j+1;
351 }
352 }
353
354 return e;
355 }
356
357 //--- store/restore snapshot operations
358
359 static final int DEFAULT_MAX_GAP = 10;
360
361 /**
362 * this is a block operation snapshot that stores chunks of original data with
363 * not more than DEFAULT_MAX_GAP consecutive null elements. Use this if
364 * elements can be stored directly
365 */
366 public static class Snapshot<E> {
367 static class Block {
368 int baseIndex;
369 Object[] data;
370 Block next;
371
372 Block (int baseIndex, Object[] data, Block next){
373 this.baseIndex = baseIndex;
374 this.data = data;
375 this.next = next;
376 }
377 }
378
379 // the ObjVector state we directly store
380 int size;
381 Growth growth;
382
383 // where we keep the data
384 Block head;
385
386 int saveBlock (Object[] d, int start, int end) {
387 int len = end-start+1;
388 Object[] bd = new Object[len];
389 System.arraycopy(d, start, bd, 0, len);
390 head = new Block(start, bd, head);
391
392 return len;
393 }
394
395 Snapshot (ObjVector<E> v, int maxGap){
396 int n = v.size;
397 size = n;
398 growth = v.growth;
399 Object[] d = v.data;
400
401 int end = -1, start = -1;
402
403 for (int i=n-1; (i>=0) && (n>0); i--) {
404 if (d[i] != null) {
405 if (start > 0 && (start - i) > maxGap ) { // store prev block
406 n -= saveBlock( d, start, end);
407 end = i;
408 start = i;
409
410 } else {
411 if (end < 0) {
412 end = i;
413 }
414 start = i;
415 }
416 }
417 }
418
419 if (end >=0 && end >= start) {
420 saveBlock( d, start, end);
421 }
422 }
423
424 public void restore (ObjVector<E> v) {
425 // this is faster than iterating through the array
426 Object[] d = new Object[size];
427 v.data = d;
428
429 for (Block block = head; block != null; block = block.next) {
430 Object[] bd = block.data;
431 System.arraycopy(bd, 0, d, block.baseIndex, bd.length);
432 }
433
434 v.size = size;
435 v.growth = growth;
436 }
437 }
438
439
440 public Snapshot<E> getSnapshot(){
441 return new Snapshot<E>(this, DEFAULT_MAX_GAP);
442 }
443
444 /**
445 * create a snapshot that doesn't store more than maxGap consecutive null values
446 */
447 public Snapshot<E> getSnapshot( int maxGap){
448 return new Snapshot<E>(this, maxGap);
449 }
450
451 public void restore (Snapshot<E> snap) {
452 snap.restore(this);
453 }
454
455
456 /**
457 * snapshot that can mutate element values, but therefore can't use block operations.
458 * This is slower to store/restore, but can be more memory efficient if the elements
459 * are fragmented (lots of small holes in data)
460 */
461
462 public static class MutatingSnapshot<E,T>{
463 T[] values;
464 int[] indices;
465
466 @SuppressWarnings("unchecked")
467 MutatingSnapshot (ObjVector<E> vec, Transformer<E,T> transformer){
468 E[] d = (E[])vec.data;
469 int size = vec.size;
470 int len = 0;
471
472 //--- get number of non-null elements
473 for (int i=0; i<size; i++) {
474 if (d[i] != null) {
475 len++;
476 }
477 }
478
479 //--- allocate data
480 T[] values = (T[])new Object[len];
481 int[] indices = new int[len];
482
483 //--- fill it
484 int j=0;
485 for (int i=0; j < len; i++) {
486 if (d[i] != null) {
487 indices[j] = i;
488 values[j] = transformer.transform(d[i]);
489 j++;
490 }
491 }
492
493 this.values = values;
494 this.indices = indices;
495 }
496
497 @SuppressWarnings("unchecked")
498 protected void restore (ObjVector<E> vec, Transformer<T,E> transformer) {
499 T[] values = this.values;
500 int[] indices = this.indices;
501 int len = indices.length;
502 int size = indices[len-1] +1;
503
504 vec.clear();
505 vec.ensureSize(size);
506 E[] d = (E[])vec.data;
507
508 for (int i=0; i<len; i++){
509 E obj = transformer.transform(values[i]);
510 int index = indices[i];
511 d[index] = obj;
512 }
513
514 vec.size = size;
515 }
516 }
517
518 public <T> MutatingSnapshot<E,T> getSnapshot( Transformer<E,T> transformer){
519 return new MutatingSnapshot<E,T>(this, transformer);
520 }
521
522 public <T> void restore (MutatingSnapshot<E,T> snap, Transformer<T,E> transformer) {
523 snap.restore(this, transformer);
524 }
525
526
527 //--- iterators
528
529 /**
530 * iterator that goes over all elements regardless of value (i.e. also includes null values)
531 */
532 protected class OVIterator implements Iterator<E> {
533 int idx = 0;
534
535 @Override
536 public boolean hasNext () {
537 return idx < size;
538 }
539
540 @Override
541 @SuppressWarnings("unchecked")
542 public E next () {
543 if (idx >= data.length) throw new NoSuchElementException();
544 E e = (E) data[idx];
545 idx++;
546 return e;
547 }
548
549 @Override
550 public void remove () {
551 throw new UnsupportedOperationException();
552 }
553 }
554
555 @Override
556 public Iterator<E> iterator () {
557 return new OVIterator();
558 }
559
560 /**
561 * iterator that only includes element values that are not null
562 */
563 protected class NonNullIterator implements Iterator<E>, Iterable<E> {
564 int idx = 0;
565 //int count = 0;
566
567 @Override
568 public boolean hasNext() {
569 return (idx < size); // size is max set index
570 }
571
572 @Override
573 @SuppressWarnings("unchecked")
574 public E next () {
575 int len = data.length;
576 for (int i=idx; i<len; i++){
577 Object o = data[i];
578 if (o != null){
579 //count++;
580 idx = i+1;
581 return (E)o;
582 }
583 }
584
585 throw new NoSuchElementException();
586 }
587
588 @Override
589 public void remove () {
590 throw new UnsupportedOperationException();
591 }
592
593 @Override
594 public Iterator<E> iterator() {
595 return this;
596 }
597 }
598
599
600
601 public Iterator<E> nonNullIterator() {
602 return new NonNullIterator();
603 }
604
605 public Iterable<E> elements() {
606 return new NonNullIterator();
607 }
608
609 public void process (Processor<E> processor) {
610 for (int i=0; i<data.length; i++) {
611 Object o = data[i];
612 if (o != null) {
613 processor.process( (E)o);
614 }
615 }
616 }
617
618 //--- misc (debugging etc.)
619
620 public void printOn (PrintStream ps) {
621 ps.println("ObjVector = [");
622 for (int i=0; i<size; i++) {
623 ps.print(" ");
624 ps.print(i);
625 ps.print(": ");
626 ps.println(get(i));
627 }
628 ps.println(']');
629 }
630
631 }