Collection of useful utilities for Java games and apps. A lot of interesting utilities that could maybe still find some use if you work with Java...
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mightyutils/src/mightypork/utils/ion/IonInput.java

506 lines
9.5 KiB

package mightypork.utils.ion;
import java.io.Closeable;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import mightypork.utils.exceptions.CorruptDataException;
/**
* Ion input stream
*
* @author Ondřej Hruška (MightyPork)
*/
public class IonInput implements Closeable {
private final DataInput in;
private final InputStream stream;
@SuppressWarnings("resource")
public IonInput(File inFile) throws FileNotFoundException
{
this(new FileInputStream(inFile));
}
public IonInput(InputStream in)
{
this.stream = in;
this.in = new DataInputStream(in);
}
/**
* Read int 0-255. Suitable when the int was written using
* <code>writeIntByte()</code> method.
*
* @return int
* @throws IOException
*/
public int readIntByte() throws IOException
{
return in.readUnsignedByte();
}
/**
* Read an int 0-65535. Suitable when the int was written using
* <code>writeIntShort()</code> method.
*
* @return int
* @throws IOException
*/
public int readIntShort() throws IOException
{
return in.readUnsignedShort();
}
public boolean readBoolean() throws IOException
{
return in.readBoolean();
}
public byte readByte() throws IOException
{
return in.readByte();
}
public short readShort() throws IOException
{
return in.readShort();
}
public char readChar() throws IOException
{
return in.readChar();
}
public int readInt() throws IOException
{
return in.readInt();
}
public long readLong() throws IOException
{
return in.readLong();
}
public float readFloat() throws IOException
{
return in.readFloat();
}
public double readDouble() throws IOException
{
return in.readDouble();
}
public String readString() throws IOException
{
return in.readUTF();
}
public boolean[] readBooleans() throws IOException
{
final int length = readLength();
final boolean[] arr = new boolean[length];
for (int i = 0; i < length; i++) {
arr[i] = in.readBoolean();
}
return arr;
}
public byte[] readBytes() throws IOException
{
final int length = readLength();
final byte[] arr = new byte[length];
for (int i = 0; i < length; i++) {
arr[i] = in.readByte();
}
return arr;
}
public char[] readChars() throws IOException
{
final int length = readLength();
final char[] arr = new char[length];
for (int i = 0; i < length; i++) {
arr[i] = in.readChar();
}
return arr;
}
public short[] readShorts() throws IOException
{
final int length = readLength();
final short[] arr = new short[length];
for (int i = 0; i < length; i++) {
arr[i] = in.readShort();
}
return arr;
}
public int[] readInts() throws IOException
{
final int length = readLength();
final int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = in.readInt();
}
return arr;
}
public long[] readLongs() throws IOException
{
final int length = readLength();
final long[] arr = new long[length];
for (int i = 0; i < length; i++) {
arr[i] = in.readLong();
}
return arr;
}
public float[] readFloats() throws IOException
{
final int length = readLength();
final float[] arr = new float[length];
for (int i = 0; i < length; i++) {
arr[i] = in.readFloat();
}
return arr;
}
public double[] readDoubles() throws IOException
{
final int length = readLength();
final double[] arr = new double[length];
for (int i = 0; i < length; i++) {
arr[i] = in.readDouble();
}
return arr;
}
public String[] readStrings() throws IOException
{
final int length = readLength();
final String[] arr = new String[length];
for (int i = 0; i < length; i++) {
arr[i] = in.readUTF();
}
return arr;
}
public Object[] readObjects() throws IOException
{
final int length = readLength();
final Object[] arr = new Object[length];
for (int i = 0; i < length; i++) {
arr[i] = readObject();
}
return arr;
}
/**
* Read bundle without a mark
*/
public IonDataBundle readBundle() throws IOException
{
final IonDataBundle ib = new IonDataBundle();
ib.load(this);
return ib;
}
/**
* Read bundle without a mark, load into a provided one
*/
public void readBundle(IonDataBundle filled) throws IOException
{
filled.clear();
filled.load(this);
}
private int readMark() throws IOException
{
return readIntByte();
}
private int readLength() throws IOException
{
return readInt();
}
/**
* <p>
* Read object based on mark; if null mark is found, returns default value.
* </p>
* <p>
* If, however, an object of invalid or different type is found, an
* exception will be thrown.
* </p>
*
* @param def default value.
* @return the loaded object
* @throws CorruptDataException
*/
@SuppressWarnings("unchecked")
public <T> T readObject(T def) throws CorruptDataException
{
try {
final Object o = readObject();
return (T) (o == null ? def : o);
} catch (final Exception e) {
throw new CorruptDataException("Could not load object.", e);
}
}
/**
* Read single object, preceded by a mark.
*
* @return the loaded object
* @throws IOException
*/
public Object readObject() throws IOException
{
final int mark = readMark();
try {
if (Ion.isMarkForBinary(mark)) {
IonBinary loaded;
loaded = (IonBinary) Ion.getClassForMark(mark).newInstance();
loaded.load(this);
return loaded;
}
if (Ion.isMarkForBundled(mark)) {
IonBundled loaded;
loaded = (IonBundled) Ion.getClassForMark(mark).newInstance();
final IonDataBundle ib = readBundle();
loaded.load(ib);
return loaded;
}
if (Ion.isMarkForIndirectBundled(mark)) {
final IonizerBundled<?> ionizer = Ion.getIonizerBundledForClass(Ion.getClassForMark(mark));
return ionizer.load(readBundle());
}
if (Ion.isMarkForIndirectBinary(mark)) {
final IonizerBinary<?> ionizer = Ion.getIonizerBinaryForClass(Ion.getClassForMark(mark));
return ionizer.load(this);
}
} catch (final Exception e) {
throw new RuntimeException("Could not load object for mark: " + mark, e);
}
switch (mark) {
case Ion.NULL:
return null;
case Ion.BOOLEAN:
return readBoolean();
case Ion.BYTE:
return readByte();
case Ion.CHAR:
return readChar();
case Ion.SHORT:
return readShort();
case Ion.INT:
return readInt();
case Ion.LONG:
return readLong();
case Ion.FLOAT:
return readFloat();
case Ion.DOUBLE:
return readDouble();
case Ion.STRING:
return readString();
case Ion.BOOLEAN_ARRAY:
return readBooleans();
case Ion.BYTE_ARRAY:
return readBytes();
case Ion.CHAR_ARRAY:
return readChars();
case Ion.SHORT_ARRAY:
return readShorts();
case Ion.INT_ARRAY:
return readInts();
case Ion.LONG_ARRAY:
return readLongs();
case Ion.FLOAT_ARRAY:
return readFloats();
case Ion.DOUBLE_ARRAY:
return readDoubles();
case Ion.STRING_ARRAY:
return readStrings();
case Ion.OBJECT_ARRAY:
return readObjects();
case Ion.MAP:
return readMap();
case Ion.SEQUENCE:
return readSequence();
default:
throw new CorruptDataException("Invalid mark: " + mark);
}
}
/**
* Reads mark and returns true if the mark is ENTRY, false if the mark is
* END. Throws an exception otherwise.
*
* @return mark was ENTRY
* @throws IOException when the mark is neither ENTRY or END.
*/
public boolean hasNextEntry() throws IOException
{
final int mark = readMark();
if (mark == Ion.ENTRY) return true;
if (mark == Ion.END) return false;
throw new CorruptDataException("Unexpected mark in sequence: " + mark);
}
/**
* Read a sequence of elements into an ArrayList
*
* @return the collection
* @throws IOException
*/
public <T> Collection<T> readSequence() throws IOException
{
return readSequence(new ArrayList<T>());
}
/**
* Load entries into a collection. The collection is cleaned first.
*
* @param filled collection to populate
* @return the collection
* @throws IOException
*/
@SuppressWarnings("unchecked")
public <T> Collection<T> readSequence(Collection<T> filled) throws IOException
{
try {
filled.clear();
while (hasNextEntry()) {
filled.add((T) readObject());
}
return filled;
} catch (final ClassCastException e) {
throw new CorruptDataException("Unexpected element type in sequence.", e);
}
}
/**
* Read element pairs into a HashMap
*
* @return the map
* @throws IOException
*/
public <K, V> Map<K, V> readMap() throws IOException
{
return readMap(new HashMap<K, V>());
}
/**
* Load data into a map. The map is cleaned first.
*
* @param filled filled map
* @return the map
* @throws IOException
*/
@SuppressWarnings("unchecked")
public <K, V> Map<K, V> readMap(Map<K, V> filled) throws IOException
{
try {
filled.clear();
while (hasNextEntry()) {
final K key = (K) readObject();
final V value = (V) readObject();
filled.put(key, value);
}
return filled;
} catch (final ClassCastException e) {
throw new CorruptDataException("Unexpected element type in map.", e);
}
}
@Override
public void close() throws IOException
{
stream.close();
}
}