User:Chase-san/VDA
Jump to navigation
Jump to search
A variable dimension array I wrote up trying to figure out a way I could have a variable number of segment buffers without having to know how many I had in advance. It turned out pretty well!
This and all my other code in which I display on the robowiki falls under the ZLIB License.
package chase.s2.misc.VDA;
import java.io.Serializable;
import java.util.Arrays;
/**
* Variable Dimension Array, an array class with flexible dimensionality.
*
* Just remember (int ... x) means it accepts (0,0,0) and new int[]{0,0,0}.
*
* @author Chase
*
* @param <T>
* Type of data contained
*/
public class VDA<T> implements Serializable, Cloneable {
private static final long serialVersionUID = 3816532930303382063L;
private T[] data = null;
private int[] dims = null;
private boolean constructed = false;
/**
* Initializes the VDA with 0 dimensions.
*/
public VDA() {
dims = new int[0];
}
/**
* Initializes the VDA with the given number of dimensions
*
* @param dimensions
*/
public VDA(int... dimensions) {
if(dimensions == null)
throw new NullPointerException();
dims = (int[])dimensions.clone();
}
/**
* @param size
* Must be at least 2
*/
public void add(int size) {
if(size < 2)
throw new IllegalArgumentException("Dimension size must be at least 2.");
dims = Arrays.copyOf(dims, dims.length + 1);
dims[dims.length - 1] = size;
constructed = false;
}
/**
* @param index
* Must be between 0 and number of dimensions
*/
public void remove(int index) {
if(index < 0 || index >= dims.length)
throw new IndexOutOfBoundsException();
int[] tmp = dims;
dims = Arrays.copyOf(dims, dims.length - 1);
if(index < dims.length) {
System.arraycopy(tmp, index + 1, dims, index, dims.length - index);
}
constructed = false;
}
/**
* Get the value at the given dimension
*/
public T get(int... pos) {
if(pos == null)
throw new NullPointerException();
if(dims.length == 0 || pos.length != dims.length)
throw new IllegalArgumentException("Incorrect or Bad Dimensionality.");
if(!constructed)
construct();
return data[getIndex(pos)];
}
/**
* Set the value at the given dimension
*/
public void set(T value, int... pos) {
if(pos == null)
throw new NullPointerException();
if(dims.length == 0 || pos.length != dims.length)
throw new IllegalArgumentException("Incorrect or Bad Dimensionality.");
if(!constructed)
construct();
data[getIndex(pos)] = value;
}
/**
* Returns the size of this VDA
* @return
*/
public int[] getSize() {
return dims.clone();
}
/**
* Returns the bottom array at the given position
*/
public Object[] getSubArray(int... pos) {
if(pos.length != dims.length - 1)
throw new UnsupportedOperationException("Dimensionality must be one less than the total supported.");
if(!constructed)
construct();
int start = getIndex(pos);
int length = dims[dims.length - 1];
T[] output = createArray(length);
System.arraycopy(data, start, output, 0, length);
return output;
}
/**
* Sets the bottom array at the given position
*/
public void setSubArray(T[] array, int... pos) {
if(pos.length != dims.length - 1)
throw new UnsupportedOperationException("Dimensionality must be one less than the total supported.");
if(!constructed)
construct();
int start = getIndex(pos);
int length = Math.min(dims[dims.length - 1], array.length);
System.arraycopy(array, 0, data, start, length);
}
/**
* @return the array that backs this VDA
*/
public Object[] getBackingArray() {
if(!constructed)
construct();
return data;
}
/**
* Returns an array containing all of the elements in this VDA
*/
public Object[] toArray() {
if(!constructed)
construct();
return data.clone();
}
/**
* Returns an array containing all of the elements in this VDA
*/
@SuppressWarnings("unchecked")
public T[] toArray(T[] a) {
if(!constructed)
construct();
return (T[])Arrays.copyOf(data, data.length, a.getClass());
}
/**
* Sets this VDA to be equal to the given VDA. Data and dimensions are
* copied.
*/
public void set(VDA<T> vda) {
data = (T[])vda.data.clone();
dims = (int[])vda.dims.clone();
constructed = vda.constructed;
}
/**
* Returns a shallow copy of this VDA (dimensions but not data)
*/
public Object clone() {
return new VDA<T>(dims);
}
/**
* Creates the final data array
*/
private void construct() {
Integer size = 1;
for(Integer i : dims)
size *= i;
data = createArray(size);
constructed = true;
}
@SuppressWarnings("unchecked")
private T[] createArray(int size) {
// Warning: Dangerous
return (T[])new Object[size];
}
/**
* Gets the main arrays index from pos
*/
public int getIndex(int[] pos) {
Integer index = 0;
for(int i = 0; i < pos.length; ++i) {
if(pos[i] < 0 || pos[i] >= dims[i])
throw new IndexOutOfBoundsException("Index " + pos[i] + " is out of bounds for dimension " + i + ".");
index += sizeUnder(i) * pos[i];
}
System.out.println("Index " + index);
return index;
}
/**
* Gets the number of elements under the given level
*/
private int sizeUnder(int level) {
Integer size = 1;
for(int i = level + 1; i < dims.length; ++i) {
size *= dims[i];
}
return size;
}
}