package railo.runtime.type;
import java.io.Serializable;
import java.util.ArrayList;
import railo.commons.lang.SizeOf;
import railo.runtime.exp.ExpressionException;
/**
* CFML array object
*/
public final class ArrayInt implements Sizeable,Serializable {
private static final int NULL = 0;
private int[] arr;
private final int cap=32;
private int size=0;
private int offset=0;
private int offCount=0;
/**
* constructor with default dimesnion (1)
*/
public ArrayInt() {
arr=new int[offset+cap];
}
/**
* constructor with to data to fill
* @param objects Objects array data to fill
*/
public ArrayInt(int[] objects) {
arr=objects;
size=arr.length;
offset=0;
}
public int get(int key, int defaultValue) {
if(key>size || key<1) {
return defaultValue;
}
int o=arr[(offset+key)-1];
if(o==NULL) return defaultValue;
return o;
}
public int get(int key) throws ExpressionException {
if(key<1 || key>size) {
throw invalidPosition(key);
}
int o=arr[(offset+key)-1];
if(o==NULL) {
throw invalidPosition(key);
}
return o;
}
/**
* Exception method if key doesn't exist at given position
* @param pos
* @return exception
*/
private ExpressionException invalidPosition(int pos) {
return new ExpressionException("Element at position ["+pos+"] doesn't exist in array");
}
public int set(int key, int value) {
if(offset+key>arr.length)enlargeCapacity(key);
if(key>size)size=key;
return arr[(offset+key)-1]=value;
}
/**
* !!! all methods that use this method must be sync
* enlarge the inner array to given size
* @param key min size of the array
*/
private synchronized void enlargeCapacity(int key) {
int diff=offCount-offset;
int newSize=arr.length;
if(newSize<1) newSize=1;
while(newSize<key+offset+diff) {
newSize*=2;
}
if(newSize>arr.length) {
int[] na=new int[newSize];
for(int i=offset;i<offset+size;i++) {
na[i+diff]=arr[i];
}
arr=na;
offset+=diff;
}
}
/* *
* !!! all methods that use this method must be sync
* enlarge the offset if 0
* /
private void enlargeOffset() {
if(offset==0) {
offCount=offCount==0?1:offCount*2;
offset=offCount;
int[] narr=new int[arr.length+offset];
for(int i=0;i<size;i++) {
narr[offset+i]=arr[i];
}
arr=narr;
}
}*/
public int size() {
return size;
}
public int[] keys() {
ArrayList lst=new ArrayList();
int count=0;
for(int i=offset;i<offset+size;i++) {
int o=arr[i];
count++;
if(o!=NULL) lst.add(Integer.valueOf(count));
}
int[] ints=new int[lst.size()];
for(int i=0;i<ints.length;i++){
ints[i]=((Integer)lst.get(i)).intValue();
}
return ints;
}
public int remove(int key) throws ExpressionException {
if(key>size || key<1) throw invalidPosition(key);
int obj=get(key,NULL);
for(int i=(offset+key)-1;i<(offset+size)-1;i++) {
arr[i]=arr[i+1];
}
size--;
return obj;
}
public int removeEL(int key) {
if(key>size || key<1) return NULL;
int obj=get(key,NULL);
for(int i=(offset+key)-1;i<(offset+size)-1;i++) {
arr[i]=arr[i+1];
}
size--;
return obj;
}
public void clear() {
if(size()>0) {
arr=new int[cap];
size=0;
offCount=1;
offset=0;
}
}
public int add(int o) {
if(offset+size+1>arr.length)enlargeCapacity(size+1);
arr[offset+size]=o;
size++;
return o;
}
public int[] toArray() {
int[] rtn=new int[size];
int count=0;
for(int i=offset;i<offset+size;i++) {
rtn[count++]=arr[i];
}
return rtn;
}
public boolean contains(int key) {
return get(key,NULL)!=NULL;
}
@Override
public long sizeOf() {
return SizeOf.size(arr)
+SizeOf.size(cap)
+SizeOf.size(size)
+SizeOf.size(offset)
+SizeOf.size(offCount)
+SizeOf.REF_SIZE;
}
}