/*
* The MIT License
*
* Copyright (c) 2012, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package jenkins.model.lazy;
import java.util.AbstractList;
import java.util.Arrays;
/**
* {@code ArrayList<Integer>} that uses {@code int} for storage.
*
* Plus a number of binary-search related methods that assume the array is sorted in the ascending order.
*
* @author Kohsuke Kawaguchi
*/
class SortedIntList extends AbstractList<Integer> {
private int[] data;
private int size;
public SortedIntList(int capacity) {
this.data = new int[capacity];
this.size = 0;
}
/**
* Internal copy constructor.
*/
public SortedIntList(SortedIntList that) {
this.data = new int[that.size+8];
System.arraycopy(that.data, 0, this.data, 0,
that.size);
this.size = that.size;
}
/**
* Binary search to find the position of the given string.
*
* @return
* -(insertionPoint+1) if the exact string isn't found.
* That is, -1 means the probe would be inserted at the very beginning.
*/
public int find(int probe) {
return binarySearch(data, 0, size, probe);
}
@Override
public boolean contains(Object o) {
return o instanceof Integer && contains(((Integer)o).intValue());
}
public boolean contains(int i) {
return find(i)>=0;
}
@Override
public Integer get(int index) {
if (size<=index) throw new IndexOutOfBoundsException();
return data[index];
}
@Override
public int size() {
return size;
}
public int max() {
return size > 0 ? data[size - 1] : 0;
}
@Override
public boolean add(Integer i) {
return add(i.intValue());
}
public boolean add(int i) {
ensureCapacity(size+1);
data[size++] = i;
return true;
}
private void ensureCapacity(int i) {
if (data.length<i) {
int[] r = new int[Math.max(data.length*2,i)];
System.arraycopy(data,0,r,0,size);
data = r;
}
}
/**
* Finds the index of the entry lower than v.
*/
public int lower(int v) {
return Boundary.LOWER.apply(find(v));
}
/**
* Finds the index of the entry greater than v.
*/
public int higher(int v) {
return Boundary.HIGHER.apply(find(v));
}
/**
* Finds the index of the entry lower or equal to v.
*/
public int floor(int v) {
return Boundary.FLOOR.apply(find(v));
}
/**
* Finds the index of the entry greater or equal to v.
*/
public int ceil(int v) {
return Boundary.CEIL.apply(find(v));
}
public boolean isInRange(int idx) {
return 0<=idx && idx<size;
}
public void sort() {
Arrays.sort(data,0,size);
}
public void copyInto(int[] dest) {
System.arraycopy(data,0,dest,0,size);
}
public void removeValue(int n) {
int idx = find(n);
if (idx<0) return;
System.arraycopy(data,idx+1,data,idx,size-(idx+1));
size--;
}
/**
* Switch to {@code java.util.Arrays.binarySearch} when we depend on Java6.
*/
private static int binarySearch(int[] a, int start, int end, int key) {
int lo = start, hi = end-1; // search range is [lo,hi]
// invariant lo<=hi
while (lo <= hi) {
int pivot = (lo + hi)/2;
int v = a[pivot];
if (v < key) // needs to search upper half
lo = pivot+1;
else if (v > key) // needs to search lower half
hi = pivot-1;
else // eureka!
return pivot;
}
return -(lo + 1); // insertion point
}
}