Reworked ION
This commit is contained in:
@@ -1,81 +0,0 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* Ionizable Arraylist
|
||||
*
|
||||
* @author MightyPork
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class AbstractIonList<T> extends ArrayList<T> implements Ionizable {
|
||||
|
||||
@Override
|
||||
public void ionRead(InputStream in) throws IonException
|
||||
{
|
||||
try {
|
||||
while (true) {
|
||||
final byte b = BinaryUtils.readByte(in);
|
||||
|
||||
if (b == IonMarks.ENTRY) {
|
||||
final T value = (T) Ion.readObject(in);
|
||||
add(value);
|
||||
} else if (b == IonMarks.END) {
|
||||
break;
|
||||
} else {
|
||||
throw new IonException("Unexpected mark in IonList: " + Integer.toHexString(b));
|
||||
}
|
||||
}
|
||||
ionReadCustomData(in);
|
||||
} catch (final IOException e) {
|
||||
throw new IonException("Error reading ion list", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void ionWrite(OutputStream out) throws IonException
|
||||
{
|
||||
try {
|
||||
for (final T entry : this) {
|
||||
if (entry instanceof IonizableOptional && !((IonizableOptional) entry).ionShouldSave()) continue;
|
||||
BinaryUtils.writeByte(out, IonMarks.ENTRY);
|
||||
Ion.writeObject(out, entry);
|
||||
}
|
||||
BinaryUtils.writeByte(out, IonMarks.END);
|
||||
ionWriteCustomData(out);
|
||||
} catch (final IOException e) {
|
||||
throw new IonException("Error reading ion map", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read custom data of this AbstractIonList implementation
|
||||
*
|
||||
* @param in input stream
|
||||
*/
|
||||
public void ionReadCustomData(InputStream in)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write custom data of this AbstractIonList implementation
|
||||
*
|
||||
* @param out output stream
|
||||
*/
|
||||
public void ionWriteCustomData(OutputStream out)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public abstract byte ionMark();
|
||||
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
|
||||
/**
|
||||
* Ionizable HashMap
|
||||
*
|
||||
* @author MightyPork
|
||||
* @param <V>
|
||||
*/
|
||||
public abstract class AbstractIonMap<V> extends LinkedHashMap<String, V> implements Ionizable {
|
||||
|
||||
@Override
|
||||
public V get(Object key)
|
||||
{
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public V put(String key, V value)
|
||||
{
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void ionRead(InputStream in) throws IonException
|
||||
{
|
||||
try {
|
||||
while (true) {
|
||||
final byte b = BinaryUtils.readByte(in);
|
||||
if (b == IonMarks.ENTRY) {
|
||||
final String key = BinaryUtils.readString(in);
|
||||
|
||||
final V value = (V) Ion.readObject(in);
|
||||
put(key, value);
|
||||
|
||||
} else if (b == IonMarks.END) {
|
||||
break;
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected mark in IonMap: " + Integer.toHexString(b));
|
||||
}
|
||||
}
|
||||
ionReadCustomData(in);
|
||||
} catch (final IOException e) {
|
||||
throw new IonException("Error reading ion map", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void ionWrite(OutputStream out) throws IonException
|
||||
{
|
||||
try {
|
||||
for (final java.util.Map.Entry<String, V> entry : entrySet()) {
|
||||
BinaryUtils.writeByte(out, IonMarks.ENTRY);
|
||||
BinaryUtils.writeString(out, entry.getKey());
|
||||
Ion.writeObject(out, entry.getValue());
|
||||
}
|
||||
BinaryUtils.writeByte(out, IonMarks.END);
|
||||
ionWriteCustomData(out);
|
||||
} catch (final IOException e) {
|
||||
throw new IonException("Error reading ion map", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read custom data of this AbstractIonMap implementation
|
||||
*
|
||||
* @param in input stream
|
||||
*/
|
||||
public void ionReadCustomData(InputStream in)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write custom data of this AbstractIonMap implementation
|
||||
*
|
||||
* @param out output stream
|
||||
*/
|
||||
public void ionWriteCustomData(OutputStream out)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte ionMark()
|
||||
{
|
||||
return IonMarks.MAP;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
|
||||
/**
|
||||
* Utilities to store and load objects to streams.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class BinaryUtils {
|
||||
|
||||
private static ByteBuffer bi = ByteBuffer.allocate(Integer.SIZE / 8);
|
||||
private static ByteBuffer bd = ByteBuffer.allocate(Double.SIZE / 8);
|
||||
private static ByteBuffer bf = ByteBuffer.allocate(Float.SIZE / 8);
|
||||
private static ByteBuffer bc = ByteBuffer.allocate(Character.SIZE / 8);
|
||||
private static ByteBuffer bl = ByteBuffer.allocate(Long.SIZE / 8);
|
||||
private static ByteBuffer bs = ByteBuffer.allocate(Short.SIZE / 8);
|
||||
|
||||
private static byte[] ai = new byte[Integer.SIZE / 8];
|
||||
private static byte[] ad = new byte[Double.SIZE / 8];
|
||||
private static byte[] af = new byte[Float.SIZE / 8];
|
||||
private static byte[] ac = new byte[Character.SIZE / 8];
|
||||
private static byte[] al = new byte[Long.SIZE / 8];
|
||||
private static byte[] as = new byte[Short.SIZE / 8];
|
||||
|
||||
|
||||
// CONVERSIONS
|
||||
|
||||
public static byte[] getBytesBool(boolean bool)
|
||||
{
|
||||
return new byte[] { (byte) (bool ? 1 : 0) };
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getBytesByte(byte num)
|
||||
{
|
||||
return new byte[] { num };
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getBytesChar(char num)
|
||||
{
|
||||
bc.clear();
|
||||
bc.putChar(num);
|
||||
return bc.array();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getBytesShort(short num)
|
||||
{
|
||||
bs.clear();
|
||||
bs.putShort(num);
|
||||
return bs.array();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getBytesInt(int num)
|
||||
{
|
||||
bi.clear();
|
||||
bi.putInt(num);
|
||||
return bi.array();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getBytesLong(long num)
|
||||
{
|
||||
bl.clear();
|
||||
bl.putLong(num);
|
||||
return bl.array();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getBytesFloat(float num)
|
||||
{
|
||||
bf.clear();
|
||||
bf.putFloat(num);
|
||||
return bf.array();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getBytesDouble(double num)
|
||||
{
|
||||
bd.clear();
|
||||
bd.putDouble(num);
|
||||
return bd.array();
|
||||
}
|
||||
|
||||
|
||||
public static byte[] getBytesString(String str)
|
||||
{
|
||||
final char[] chars = str.toCharArray();
|
||||
|
||||
final ByteBuffer bstr = ByteBuffer.allocate((Character.SIZE / 8) * chars.length + (Character.SIZE / 8));
|
||||
for (final char c : chars) {
|
||||
bstr.putChar(c);
|
||||
}
|
||||
|
||||
bstr.putChar((char) 0);
|
||||
|
||||
return bstr.array();
|
||||
}
|
||||
|
||||
|
||||
public static void writeBoolean(OutputStream out, boolean num) throws IOException
|
||||
{
|
||||
out.write(getBytesBool(num));
|
||||
}
|
||||
|
||||
|
||||
public static void writeByte(OutputStream out, byte num) throws IOException
|
||||
{
|
||||
out.write(getBytesByte(num));
|
||||
}
|
||||
|
||||
|
||||
public static void writeChar(OutputStream out, char num) throws IOException
|
||||
{
|
||||
out.write(getBytesChar(num));
|
||||
}
|
||||
|
||||
|
||||
public static void writeShort(OutputStream out, short num) throws IOException
|
||||
{
|
||||
out.write(getBytesShort(num));
|
||||
}
|
||||
|
||||
|
||||
public static void writeInt(OutputStream out, int num) throws IOException
|
||||
{
|
||||
out.write(getBytesInt(num));
|
||||
}
|
||||
|
||||
|
||||
public static void writeLong(OutputStream out, long num) throws IOException
|
||||
{
|
||||
out.write(getBytesLong(num));
|
||||
}
|
||||
|
||||
|
||||
public static void writeFloat(OutputStream out, float num) throws IOException
|
||||
{
|
||||
out.write(getBytesFloat(num));
|
||||
}
|
||||
|
||||
|
||||
public static void writeDouble(OutputStream out, double num) throws IOException
|
||||
{
|
||||
out.write(getBytesDouble(num));
|
||||
}
|
||||
|
||||
|
||||
public static void writeString(OutputStream out, String str) throws IOException
|
||||
{
|
||||
out.write(getBytesString(str));
|
||||
}
|
||||
|
||||
|
||||
// READING
|
||||
|
||||
public static boolean readBoolean(InputStream in) throws IOException
|
||||
{
|
||||
return in.read() > 0;
|
||||
}
|
||||
|
||||
|
||||
public static byte readByte(InputStream in) throws IOException
|
||||
{
|
||||
return (byte) in.read();
|
||||
}
|
||||
|
||||
|
||||
public static char readChar(InputStream in) throws IOException
|
||||
{
|
||||
if (-1 == in.read(ac, 0, ac.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(ac);
|
||||
return buf.getChar();
|
||||
}
|
||||
|
||||
|
||||
public static short readShort(InputStream in) throws IOException
|
||||
{
|
||||
if (-1 == in.read(as, 0, as.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(as);
|
||||
return buf.getShort();
|
||||
}
|
||||
|
||||
|
||||
public static long readLong(InputStream in) throws IOException
|
||||
{
|
||||
if (-1 == in.read(al, 0, al.length)) throw new IOException("End of stream.");
|
||||
|
||||
final ByteBuffer buf = ByteBuffer.wrap(al);
|
||||
return buf.getLong();
|
||||
}
|
||||
|
||||
|
||||
public static int readInt(InputStream in) throws IOException
|
||||
{
|
||||
if (-1 == in.read(ai, 0, ai.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(ai);
|
||||
return buf.getInt();
|
||||
}
|
||||
|
||||
|
||||
public static float readFloat(InputStream in) throws IOException
|
||||
{
|
||||
if (-1 == in.read(af, 0, af.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(af);
|
||||
return buf.getFloat();
|
||||
}
|
||||
|
||||
|
||||
public static double readDouble(InputStream in) throws IOException
|
||||
{
|
||||
if (-1 == in.read(ad, 0, ad.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(ad);
|
||||
return buf.getDouble();
|
||||
}
|
||||
|
||||
|
||||
public static String readString(InputStream in) throws IOException
|
||||
{
|
||||
String s = "";
|
||||
char c;
|
||||
while ((c = readChar(in)) > 0) {
|
||||
s += c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,11 @@ package mightypork.util.files.ion;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import mightypork.util.math.Calc;
|
||||
import mightypork.util.logging.Log;
|
||||
|
||||
|
||||
/**
|
||||
@@ -15,57 +16,128 @@ import mightypork.util.math.Calc;
|
||||
*/
|
||||
public class Ion {
|
||||
|
||||
/*
|
||||
* 0-29 ... primitive and Java built-in types
|
||||
* 30-59 ... technical marks
|
||||
* 60-99 ... built-in ION types
|
||||
*/
|
||||
|
||||
// primitives
|
||||
/** Null mark (for internal use) */
|
||||
private static final short NULL = 0;
|
||||
/** Boolean mark (for internal use) */
|
||||
private static final short BOOLEAN = 1;
|
||||
/** Byte mark (for internal use) */
|
||||
private static final short BYTE = 2;
|
||||
/** Character mark (for internal use) */
|
||||
private static final short CHAR = 3;
|
||||
/** Short mark (for internal use) */
|
||||
private static final short SHORT = 4;
|
||||
/** Integer mark (for internal use) */
|
||||
private static final short INT = 5;
|
||||
/** Long mark (for internal use) */
|
||||
private static final short LONG = 6;
|
||||
/** Float mark (for internal use) */
|
||||
private static final short FLOAT = 7;
|
||||
/** Double mark (for internal use) */
|
||||
private static final short DOUBLE = 8;
|
||||
/** String mark (for internal use) */
|
||||
private static final short STRING = 9;
|
||||
|
||||
// technical
|
||||
|
||||
/**
|
||||
* Entry mark - general purpose, marks an entry in sequence of objects. Used
|
||||
* to indicate that the sequence continues wityh another element.
|
||||
*/
|
||||
public static final short ENTRY = 30;
|
||||
|
||||
/**
|
||||
* Start mark - general purpose, marks start of a sequence of stored
|
||||
* objects.
|
||||
*/
|
||||
public static final short START = 31;
|
||||
|
||||
/**
|
||||
* End mark - general purpose, marks end of sequence of stored objects.
|
||||
*/
|
||||
public static final short END = 32;
|
||||
|
||||
/**
|
||||
* Length mark, indicating length of something (such as array) - general
|
||||
* purpose
|
||||
*/
|
||||
public static final short LENGTH = 33;
|
||||
|
||||
// built in
|
||||
/** Map mark (built-in data structure) */
|
||||
static final short DATA_BUNDLE = 60;
|
||||
|
||||
/** List mark (built-in data structure) */
|
||||
static final short DATA_LIST = 61;
|
||||
|
||||
/** Ionizables<Mark, Class> */
|
||||
private static Map<Byte, Class<?>> customIonizables = new HashMap<>();
|
||||
private static Map<Short, Class<?>> customIonizables = new HashMap<>();
|
||||
|
||||
// buffers and helper arrays for storing to streams.
|
||||
private static ByteBuffer bi = ByteBuffer.allocate(Integer.SIZE / 8);
|
||||
private static ByteBuffer bd = ByteBuffer.allocate(Double.SIZE / 8);
|
||||
private static ByteBuffer bf = ByteBuffer.allocate(Float.SIZE / 8);
|
||||
private static ByteBuffer bc = ByteBuffer.allocate(Character.SIZE / 8);
|
||||
private static ByteBuffer bl = ByteBuffer.allocate(Long.SIZE / 8);
|
||||
private static ByteBuffer bs = ByteBuffer.allocate(Short.SIZE / 8);
|
||||
private static byte[] ai = new byte[Integer.SIZE / 8];
|
||||
private static byte[] ad = new byte[Double.SIZE / 8];
|
||||
private static byte[] af = new byte[Float.SIZE / 8];
|
||||
private static byte[] ac = new byte[Character.SIZE / 8];
|
||||
private static byte[] al = new byte[Long.SIZE / 8];
|
||||
private static byte[] as = new byte[Short.SIZE / 8];
|
||||
|
||||
/**
|
||||
* Indicates whether range checking should be performed when registering
|
||||
* marks.
|
||||
*/
|
||||
private static boolean safety;
|
||||
|
||||
// register default ionizables
|
||||
static {
|
||||
try {
|
||||
registerIonizable(IonMarks.MAP, IonMap.class);
|
||||
registerIonizable(IonMarks.LIST, IonList.class);
|
||||
} catch (final IonException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// register default ionizables
|
||||
safety = false;
|
||||
registerIonizable(Ion.DATA_BUNDLE, IonDataBundle.class);
|
||||
registerIonizable(Ion.DATA_LIST, IonDataList.class);
|
||||
safety = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register new Ionizable for direct reconstructing.
|
||||
*
|
||||
* @param mark byte mark to be used, see {@link IonMarks} for reference.
|
||||
* @param mark mark to be used. Numbers 0..99 are reserved.
|
||||
* @param objClass class of the registered Ionizable
|
||||
* @throws IonException
|
||||
*/
|
||||
public static void registerIonizable(byte mark, Class<?> objClass) throws IonException
|
||||
public static void registerIonizable(short mark, Class<?> objClass)
|
||||
{
|
||||
if (customIonizables.containsKey(mark)) {
|
||||
throw new IonException("IonMark " + mark + " is already used.");
|
||||
// negative marks are allowed.
|
||||
|
||||
if (safety && mark >= 0 && mark < 100) {
|
||||
throw new RuntimeException("Marks 0..99 are reserved.");
|
||||
}
|
||||
|
||||
if (customIonizables.containsKey(mark)) {
|
||||
throw new RuntimeException("Mark " + mark + " is already in use.");
|
||||
}
|
||||
|
||||
customIonizables.put(mark, objClass);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load Ion object from file.
|
||||
*
|
||||
* @param file file path
|
||||
* @return the loaded object
|
||||
* @throws IonException
|
||||
*/
|
||||
public static Object fromFile(String file) throws IonException
|
||||
{
|
||||
return fromFile(new File(file));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load Ion object from file.
|
||||
*
|
||||
* @param file file
|
||||
* @return the loaded object
|
||||
* @throws IonException on failure
|
||||
* @throws IOException on failure
|
||||
*/
|
||||
public static Object fromFile(File file) throws IonException
|
||||
public static Object fromFile(File file) throws IOException
|
||||
{
|
||||
try(InputStream in = new FileInputStream(file)) {
|
||||
|
||||
@@ -73,7 +145,7 @@ public class Ion {
|
||||
return obj;
|
||||
|
||||
} catch (final IOException e) {
|
||||
throw new IonException("Error loading ION file.", e);
|
||||
throw new IOException("Error loading ION file.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +155,9 @@ public class Ion {
|
||||
*
|
||||
* @param in input stream
|
||||
* @return the loaded object
|
||||
* @throws IonException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Object fromStream(InputStream in) throws IonException
|
||||
public static Object fromStream(InputStream in) throws IOException
|
||||
{
|
||||
return readObject(in);
|
||||
}
|
||||
@@ -96,22 +168,9 @@ public class Ion {
|
||||
*
|
||||
* @param path file path
|
||||
* @param obj object to store
|
||||
* @throws IonException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void toFile(String path, Object obj) throws IonException
|
||||
{
|
||||
toFile(new File(path), obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store Ion object to file.
|
||||
*
|
||||
* @param path file path
|
||||
* @param obj object to store
|
||||
* @throws IonException
|
||||
*/
|
||||
public static void toFile(File path, Object obj) throws IonException
|
||||
public static void toFile(File path, Object obj) throws IOException
|
||||
{
|
||||
try(OutputStream out = new FileOutputStream(path)) {
|
||||
final String f = path.toString();
|
||||
@@ -119,159 +178,399 @@ public class Ion {
|
||||
|
||||
if (!dir.mkdirs()) throw new IOException("Could not create file.");
|
||||
|
||||
toStream(out, obj);
|
||||
writeObject(out, obj);
|
||||
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (final Exception e) {
|
||||
throw new IonException("Error writing to ION file.", e);
|
||||
throw new IOException("Error writing to ION file.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store Ion object to output stream.
|
||||
*
|
||||
* @param out output stream *
|
||||
* @param obj object to store
|
||||
* @throws IonException
|
||||
*/
|
||||
public static void toStream(OutputStream out, Object obj) throws IonException
|
||||
{
|
||||
writeObject(out, obj);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read single ionizable or primitive object from input stream
|
||||
* Read single object from input stream
|
||||
*
|
||||
* @param in input stream
|
||||
* @return the loaded object
|
||||
* @throws IonException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Object readObject(InputStream in) throws IonException
|
||||
public static Object readObject(InputStream in) throws IOException
|
||||
{
|
||||
try {
|
||||
final int bi = in.read();
|
||||
if (bi == -1) throw new IonException("Unexpected end of stream.");
|
||||
final byte b = (byte) bi;
|
||||
if (customIonizables.containsKey(b)) {
|
||||
Ionizable ion;
|
||||
final short mark = readMark(in);
|
||||
if (customIonizables.containsKey(mark)) {
|
||||
Ionizable ionObj;
|
||||
|
||||
try {
|
||||
ion = ((Ionizable) customIonizables.get(b).newInstance());
|
||||
} catch (final InstantiationException e) {
|
||||
throw new IonException("Cound not instantiate " + customIonizables.get(b).getSimpleName(), e);
|
||||
} catch (final IllegalAccessException e) {
|
||||
throw new IonException("Cound not instantiate " + customIonizables.get(b).getSimpleName(), e);
|
||||
ionObj = ((Ionizable) customIonizables.get(mark).newInstance());
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
throw new IOException("Cound not instantiate: " + Log.str(customIonizables.get(mark)), e);
|
||||
}
|
||||
ion.ionRead(in);
|
||||
return ion;
|
||||
|
||||
ionObj.loadFrom(in);
|
||||
return ionObj;
|
||||
}
|
||||
|
||||
switch (b) {
|
||||
case IonMarks.BOOLEAN:
|
||||
return BinaryUtils.readBoolean(in);
|
||||
case IonMarks.BYTE:
|
||||
return BinaryUtils.readByte(in);
|
||||
case IonMarks.CHAR:
|
||||
return BinaryUtils.readChar(in);
|
||||
case IonMarks.SHORT:
|
||||
return BinaryUtils.readShort(in);
|
||||
case IonMarks.INT:
|
||||
return BinaryUtils.readInt(in);
|
||||
case IonMarks.LONG:
|
||||
return BinaryUtils.readLong(in);
|
||||
case IonMarks.FLOAT:
|
||||
return BinaryUtils.readFloat(in);
|
||||
case IonMarks.DOUBLE:
|
||||
return BinaryUtils.readDouble(in);
|
||||
case IonMarks.STRING:
|
||||
final String s = BinaryUtils.readString(in);
|
||||
switch (mark) {
|
||||
case Ion.NULL:
|
||||
return null;
|
||||
|
||||
case Ion.BOOLEAN:
|
||||
return readBoolean(in);
|
||||
|
||||
case Ion.BYTE:
|
||||
return readByte(in);
|
||||
|
||||
case Ion.CHAR:
|
||||
return readChar(in);
|
||||
|
||||
case Ion.SHORT:
|
||||
return readShort(in);
|
||||
|
||||
case Ion.INT:
|
||||
return readInt(in);
|
||||
|
||||
case Ion.LONG:
|
||||
return readLong(in);
|
||||
|
||||
case Ion.FLOAT:
|
||||
return readFloat(in);
|
||||
|
||||
case Ion.DOUBLE:
|
||||
return readDouble(in);
|
||||
|
||||
case Ion.STRING:
|
||||
final String s = readString(in);
|
||||
return s;
|
||||
default:
|
||||
throw new IonException("Invalid Ion mark " + Integer.toHexString(bi));
|
||||
throw new IOException("Invalid Ion mark: " + mark);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new IonException("Error loading ION file: ", e);
|
||||
throw new IOException("Error loading ION file: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void expect(InputStream in, short mark) throws IOException
|
||||
{
|
||||
if (readMark(in) != mark) throw new IOException("Unexpected mark in ION stream.");
|
||||
}
|
||||
|
||||
|
||||
public static short readMark(InputStream in) throws IOException
|
||||
{
|
||||
return readShort(in);
|
||||
}
|
||||
|
||||
|
||||
public static void writeMark(OutputStream out, short mark) throws IOException
|
||||
{
|
||||
writeShort(out, mark);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write single ionizable or primitive object to output stream
|
||||
*
|
||||
* @param out output stream
|
||||
* @param obj stored object
|
||||
* @throws IonException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void writeObject(OutputStream out, Object obj) throws IonException
|
||||
public static void writeObject(OutputStream out, Object obj) throws IOException
|
||||
{
|
||||
try {
|
||||
if (obj instanceof Ionizable) {
|
||||
out.write(((Ionizable) obj).ionMark());
|
||||
((Ionizable) obj).ionWrite(out);
|
||||
writeMark(out, ((Ionizable) obj).getIonMark());
|
||||
((Ionizable) obj).saveTo(out);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj instanceof Boolean) {
|
||||
out.write(IonMarks.BOOLEAN);
|
||||
BinaryUtils.writeBoolean(out, (Boolean) obj);
|
||||
writeMark(out, Ion.BOOLEAN);
|
||||
writeBoolean(out, (Boolean) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj instanceof Byte) {
|
||||
out.write(IonMarks.BYTE);
|
||||
BinaryUtils.writeByte(out, (Byte) obj);
|
||||
writeMark(out, Ion.BYTE);
|
||||
writeByte(out, (Byte) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj instanceof Character) {
|
||||
out.write(IonMarks.CHAR);
|
||||
BinaryUtils.writeChar(out, (Character) obj);
|
||||
writeMark(out, Ion.CHAR);
|
||||
writeChar(out, (Character) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj instanceof Short) {
|
||||
out.write(IonMarks.SHORT);
|
||||
BinaryUtils.writeShort(out, (Short) obj);
|
||||
writeMark(out, Ion.SHORT);
|
||||
writeShort(out, (Short) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj instanceof Integer) {
|
||||
out.write(IonMarks.INT);
|
||||
BinaryUtils.writeInt(out, (Integer) obj);
|
||||
writeMark(out, Ion.INT);
|
||||
writeInt(out, (Integer) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj instanceof Long) {
|
||||
out.write(IonMarks.LONG);
|
||||
BinaryUtils.writeLong(out, (Long) obj);
|
||||
writeMark(out, Ion.LONG);
|
||||
writeLong(out, (Long) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj instanceof Float) {
|
||||
out.write(IonMarks.FLOAT);
|
||||
BinaryUtils.writeFloat(out, (Float) obj);
|
||||
writeMark(out, Ion.FLOAT);
|
||||
writeFloat(out, (Float) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj instanceof Double) {
|
||||
out.write(IonMarks.DOUBLE);
|
||||
BinaryUtils.writeDouble(out, (Double) obj);
|
||||
writeMark(out, Ion.DOUBLE);
|
||||
writeDouble(out, (Double) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj instanceof String) {
|
||||
out.write(IonMarks.STRING);
|
||||
BinaryUtils.writeString(out, (String) obj);
|
||||
writeMark(out, Ion.STRING);
|
||||
writeString(out, (String) obj);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new IonException(Calc.cname(obj) + " can't be stored in Ion storage.");
|
||||
throw new IOException("Object " + Log.str(obj) + " could not be be ionized.");
|
||||
|
||||
} catch (final IOException e) {
|
||||
throw new IonException("Could not store " + obj, e);
|
||||
throw new IOException("Could not store: " + obj, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static byte[] getBytesBool(boolean bool)
|
||||
{
|
||||
return new byte[] { (byte) (bool ? 1 : 0) };
|
||||
}
|
||||
|
||||
|
||||
private static byte[] getBytesByte(byte num)
|
||||
{
|
||||
return new byte[] { num };
|
||||
}
|
||||
|
||||
|
||||
private static byte[] getBytesChar(char num)
|
||||
{
|
||||
synchronized (bc) {
|
||||
bc.clear();
|
||||
bc.putChar(num);
|
||||
return bc.array();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static byte[] getBytesShort(short num)
|
||||
{
|
||||
synchronized (bs) {
|
||||
bs.clear();
|
||||
bs.putShort(num);
|
||||
return bs.array();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static byte[] getBytesInt(int num)
|
||||
{
|
||||
synchronized (bi) {
|
||||
bi.clear();
|
||||
bi.putInt(num);
|
||||
return bi.array();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static byte[] getBytesLong(long num)
|
||||
{
|
||||
synchronized (bl) {
|
||||
bl.clear();
|
||||
bl.putLong(num);
|
||||
return bl.array();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static byte[] getBytesFloat(float num)
|
||||
{
|
||||
synchronized (bf) {
|
||||
bf.clear();
|
||||
bf.putFloat(num);
|
||||
return bf.array();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static byte[] getBytesDouble(double num)
|
||||
{
|
||||
synchronized (bd) {
|
||||
bd.clear();
|
||||
bd.putDouble(num);
|
||||
return bd.array();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static byte[] getBytesString(String str)
|
||||
{
|
||||
final char[] chars = str.toCharArray();
|
||||
|
||||
final ByteBuffer bstr = ByteBuffer.allocate((Character.SIZE / 8) * chars.length + (Character.SIZE / 8));
|
||||
for (final char c : chars) {
|
||||
bstr.putChar(c);
|
||||
}
|
||||
|
||||
bstr.putChar((char) 0);
|
||||
|
||||
return bstr.array();
|
||||
}
|
||||
|
||||
|
||||
public static void writeBoolean(OutputStream out, boolean bool) throws IOException
|
||||
{
|
||||
out.write(getBytesBool(bool));
|
||||
}
|
||||
|
||||
|
||||
public static void writeByte(OutputStream out, byte b) throws IOException
|
||||
{
|
||||
out.write(getBytesByte(b));
|
||||
}
|
||||
|
||||
|
||||
public static void writeChar(OutputStream out, char c) throws IOException
|
||||
{
|
||||
out.write(getBytesChar(c));
|
||||
}
|
||||
|
||||
|
||||
public static void writeShort(OutputStream out, short s) throws IOException
|
||||
{
|
||||
out.write(getBytesShort(s));
|
||||
}
|
||||
|
||||
|
||||
public static void writeInt(OutputStream out, int i) throws IOException
|
||||
{
|
||||
out.write(getBytesInt(i));
|
||||
}
|
||||
|
||||
|
||||
public static void writeLong(OutputStream out, long l) throws IOException
|
||||
{
|
||||
out.write(getBytesLong(l));
|
||||
}
|
||||
|
||||
|
||||
public static void writeFloat(OutputStream out, float f) throws IOException
|
||||
{
|
||||
out.write(getBytesFloat(f));
|
||||
}
|
||||
|
||||
|
||||
public static void writeDouble(OutputStream out, double d) throws IOException
|
||||
{
|
||||
out.write(getBytesDouble(d));
|
||||
}
|
||||
|
||||
|
||||
public static void writeString(OutputStream out, String str) throws IOException
|
||||
{
|
||||
out.write(getBytesString(str));
|
||||
}
|
||||
|
||||
|
||||
public static boolean readBoolean(InputStream in) throws IOException
|
||||
{
|
||||
return readByte(in) > 0;
|
||||
}
|
||||
|
||||
|
||||
public static byte readByte(InputStream in) throws IOException
|
||||
{
|
||||
int b = in.read();
|
||||
if (-1 == b) throw new IOException("End of stream.");
|
||||
return (byte) b;
|
||||
}
|
||||
|
||||
|
||||
public static char readChar(InputStream in) throws IOException
|
||||
{
|
||||
synchronized (ac) {
|
||||
if (-1 == in.read(ac, 0, ac.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(ac);
|
||||
return buf.getChar();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static short readShort(InputStream in) throws IOException
|
||||
{
|
||||
synchronized (as) {
|
||||
if (-1 == in.read(as, 0, as.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(as);
|
||||
return buf.getShort();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static long readLong(InputStream in) throws IOException
|
||||
{
|
||||
synchronized (al) {
|
||||
if (-1 == in.read(al, 0, al.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(al);
|
||||
return buf.getLong();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static int readInt(InputStream in) throws IOException
|
||||
{
|
||||
synchronized (ai) {
|
||||
if (-1 == in.read(ai, 0, ai.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(ai);
|
||||
return buf.getInt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static float readFloat(InputStream in) throws IOException
|
||||
{
|
||||
synchronized (af) {
|
||||
if (-1 == in.read(af, 0, af.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(af);
|
||||
return buf.getFloat();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static double readDouble(InputStream in) throws IOException
|
||||
{
|
||||
synchronized (ad) {
|
||||
if (-1 == in.read(ad, 0, ad.length)) throw new IOException("End of stream.");
|
||||
final ByteBuffer buf = ByteBuffer.wrap(ad);
|
||||
return buf.getDouble();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String readString(InputStream in) throws IOException
|
||||
{
|
||||
String s = "";
|
||||
char c;
|
||||
while ((c = readChar(in)) > 0) {
|
||||
s += c;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Ionizable HashMap
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class IonDataBundle extends IonMap<String, Object> {
|
||||
|
||||
public boolean getBoolean(String key)
|
||||
{
|
||||
return (Boolean) get(key);
|
||||
}
|
||||
|
||||
|
||||
public boolean getBool(String key)
|
||||
{
|
||||
return (Boolean) get(key);
|
||||
}
|
||||
|
||||
|
||||
public byte getByte(String key)
|
||||
{
|
||||
return (Byte) get(key);
|
||||
}
|
||||
|
||||
|
||||
public char getChar(String key)
|
||||
{
|
||||
return (Character) get(key);
|
||||
}
|
||||
|
||||
|
||||
public short getShort(String key)
|
||||
{
|
||||
return (Short) get(key);
|
||||
}
|
||||
|
||||
|
||||
public int getInt(String key)
|
||||
{
|
||||
return (Integer) get(key);
|
||||
}
|
||||
|
||||
|
||||
public long getLong(String key)
|
||||
{
|
||||
return (Long) get(key);
|
||||
}
|
||||
|
||||
|
||||
public float getFloat(String key)
|
||||
{
|
||||
return (Float) get(key);
|
||||
}
|
||||
|
||||
|
||||
public double getDouble(String key)
|
||||
{
|
||||
return (Double) get(key);
|
||||
}
|
||||
|
||||
|
||||
public String getString(String key)
|
||||
{
|
||||
return (String) get(key);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object get(Object arg0)
|
||||
{
|
||||
return super.get(arg0);
|
||||
}
|
||||
|
||||
|
||||
public void putBoolean(String key, boolean num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putBool(String key, boolean num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putByte(String key, int num)
|
||||
{
|
||||
put(key, (byte) num);
|
||||
}
|
||||
|
||||
|
||||
public void putChar(String key, char num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putCharacter(String key, char num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putShort(String key, int num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putInt(String key, int num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putInteger(String key, int num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putLong(String key, long num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putFloat(String key, double num)
|
||||
{
|
||||
put(key, (float) num);
|
||||
}
|
||||
|
||||
|
||||
public void putDouble(String key, double num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putString(String key, String num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
return Ion.DATA_BUNDLE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Ionizable Arraylist
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class IonDataList extends IonList<Object> {
|
||||
|
||||
public Ionizable getIonizable(int index) throws IOException
|
||||
{
|
||||
return (Ionizable) getOfType(index, Ionizable.class);
|
||||
}
|
||||
|
||||
|
||||
public boolean getBoolean(int index) throws IOException
|
||||
{
|
||||
return (Boolean) getOfType(index, Boolean.class);
|
||||
}
|
||||
|
||||
|
||||
public byte getByte(int index) throws IOException
|
||||
{
|
||||
return (Byte) getOfType(index, Byte.class);
|
||||
}
|
||||
|
||||
|
||||
public char getChar(int index) throws IOException
|
||||
{
|
||||
return (Character) getOfType(index, Character.class);
|
||||
}
|
||||
|
||||
|
||||
public short getShort(int index) throws IOException
|
||||
{
|
||||
return (Short) getOfType(index, Short.class);
|
||||
}
|
||||
|
||||
|
||||
public int getInt(int index) throws IOException
|
||||
{
|
||||
return (Integer) getOfType(index, Integer.class);
|
||||
}
|
||||
|
||||
|
||||
public long getLong(int index) throws IOException
|
||||
{
|
||||
return (Long) getOfType(index, Long.class);
|
||||
}
|
||||
|
||||
|
||||
public float getFloat(int index) throws IOException
|
||||
{
|
||||
return (Float) getOfType(index, Float.class);
|
||||
}
|
||||
|
||||
|
||||
public double getDouble(int index) throws IOException
|
||||
{
|
||||
return (Double) getOfType(index, Double.class);
|
||||
}
|
||||
|
||||
|
||||
public String getString(int index) throws IOException
|
||||
{
|
||||
return (String) getOfType(index, String.class);
|
||||
}
|
||||
|
||||
|
||||
public void addIonizable(Ionizable o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public void addBoolean(boolean o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public void addByte(byte o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public void addChar(char o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public void addShort(short o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public void addInt(int o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public void addLong(long o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public void addFloat(float o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public void addDouble(double o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public void addString(String o) throws IOException
|
||||
{
|
||||
assertNotNull(o);
|
||||
add(o);
|
||||
}
|
||||
|
||||
|
||||
public Object getOfType(int index, Class<?> type) throws IOException
|
||||
{
|
||||
try {
|
||||
final Object o = super.get(index);
|
||||
if (o == null || !o.getClass().isAssignableFrom(type)) {
|
||||
throw new IOException("Incorrect object type");
|
||||
}
|
||||
return o;
|
||||
} catch (final IndexOutOfBoundsException e) {
|
||||
throw new IOException("Out of bounds");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void assertNotNull(Object o) throws IOException
|
||||
{
|
||||
if (o == null) throw new IOException("Cannot store null");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
return Ion.DATA_LIST;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
public class IonException extends Exception {
|
||||
|
||||
public IonException() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public IonException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
|
||||
public IonException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public IonException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,157 +1,80 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* Ionizable Arraylist
|
||||
*
|
||||
* @author MightyPork
|
||||
* @param <T>
|
||||
*/
|
||||
public class IonList extends AbstractIonList<Object> {
|
||||
public abstract class IonList<T> extends ArrayList<T> implements Ionizable {
|
||||
|
||||
public Ionizable getIonizable(int index) throws IonException
|
||||
{
|
||||
return (Ionizable) getCheckType(index, Ionizable.class);
|
||||
}
|
||||
|
||||
|
||||
public boolean getBoolean(int index) throws IonException
|
||||
{
|
||||
return (Boolean) getCheckType(index, Boolean.class);
|
||||
}
|
||||
|
||||
|
||||
public byte getByte(int index) throws IonException
|
||||
{
|
||||
return (Byte) getCheckType(index, Byte.class);
|
||||
}
|
||||
|
||||
|
||||
public char getChar(int index) throws IonException
|
||||
{
|
||||
return (Character) getCheckType(index, Character.class);
|
||||
}
|
||||
|
||||
|
||||
public short getShort(int index) throws IonException
|
||||
{
|
||||
return (Short) getCheckType(index, Short.class);
|
||||
}
|
||||
|
||||
|
||||
public int getInt(int index) throws IonException
|
||||
{
|
||||
return (Integer) getCheckType(index, Integer.class);
|
||||
}
|
||||
|
||||
|
||||
public long getLong(int index) throws IonException
|
||||
{
|
||||
return (Long) getCheckType(index, Long.class);
|
||||
}
|
||||
|
||||
|
||||
public float getFloat(int index) throws IonException
|
||||
{
|
||||
return (Float) getCheckType(index, Float.class);
|
||||
}
|
||||
|
||||
|
||||
public double getDouble(int index) throws IonException
|
||||
{
|
||||
return (Double) getCheckType(index, Double.class);
|
||||
}
|
||||
|
||||
|
||||
public String getString(int index) throws IonException
|
||||
{
|
||||
return (String) getCheckType(index, String.class);
|
||||
}
|
||||
|
||||
|
||||
public void addIonizable(Ionizable o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public void addBoolean(boolean o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public void addByte(byte o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public void addChar(char o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public void addShort(short o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public void addInt(int o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public void addLong(long o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public void addFloat(float o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public void addDouble(double o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public void addString(String o) throws IonException
|
||||
{
|
||||
assertNotNull(o);
|
||||
}
|
||||
|
||||
|
||||
public Object getCheckType(int index, Class<?> type) throws IonException
|
||||
@Override
|
||||
public void loadFrom(InputStream in) throws IOException
|
||||
{
|
||||
try {
|
||||
final Object o = super.get(index);
|
||||
if (o == null || !o.getClass().isAssignableFrom(type)) {
|
||||
throw new IonException("Incorrect object type");
|
||||
while (true) {
|
||||
final short mark = Ion.readMark(in);
|
||||
|
||||
if (mark == Ion.ENTRY) {
|
||||
final T value = (T) Ion.readObject(in);
|
||||
add(value);
|
||||
} else if (mark == Ion.END) {
|
||||
break;
|
||||
} else {
|
||||
throw new IOException("Unexpected mark in IonList: " + mark);
|
||||
}
|
||||
}
|
||||
return o;
|
||||
} catch (final IndexOutOfBoundsException e) {
|
||||
throw new IonException("Out of bounds");
|
||||
readCustomData(in);
|
||||
} catch (final IOException e) {
|
||||
throw new IOException("Error reading ion list", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void assertNotNull(Object o) throws IonException
|
||||
@Override
|
||||
public void saveTo(OutputStream out) throws IOException
|
||||
{
|
||||
try {
|
||||
for (final T entry : this) {
|
||||
Ion.writeMark(out, Ion.ENTRY);
|
||||
Ion.writeObject(out, entry);
|
||||
}
|
||||
Ion.writeMark(out, Ion.END);
|
||||
writeCustomData(out);
|
||||
} catch (final IOException e) {
|
||||
throw new IOException("Error reading ion map", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read custom data of this AbstractIonList implementation
|
||||
*
|
||||
* @param in input stream
|
||||
*/
|
||||
public void readCustomData(InputStream in)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write custom data of this AbstractIonList implementation
|
||||
*
|
||||
* @param out output stream
|
||||
*/
|
||||
public void writeCustomData(OutputStream out)
|
||||
{
|
||||
if (o == null) throw new IonException("Cannot store null");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte ionMark()
|
||||
{
|
||||
return IonMarks.LIST;
|
||||
}
|
||||
public abstract short getIonMark();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,156 +1,104 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import mightypork.util.annotations.DefaultImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Ionizable HashMap
|
||||
*
|
||||
* @author MightyPork
|
||||
* @param <K> key
|
||||
* @param <V> value
|
||||
*/
|
||||
public class IonMap extends AbstractIonMap<Object> {
|
||||
public abstract class IonMap<K, V> extends LinkedHashMap<K, V> implements Ionizable {
|
||||
|
||||
public boolean getBoolean(String key)
|
||||
@Override
|
||||
public V get(Object key)
|
||||
{
|
||||
return (Boolean) get(key);
|
||||
}
|
||||
|
||||
|
||||
public boolean getBool(String key)
|
||||
{
|
||||
return (Boolean) get(key);
|
||||
}
|
||||
|
||||
|
||||
public byte getByte(String key)
|
||||
{
|
||||
return (Byte) get(key);
|
||||
}
|
||||
|
||||
|
||||
public char getChar(String key)
|
||||
{
|
||||
return (Character) get(key);
|
||||
}
|
||||
|
||||
|
||||
public short getShort(String key)
|
||||
{
|
||||
return (Short) get(key);
|
||||
}
|
||||
|
||||
|
||||
public int getInt(String key)
|
||||
{
|
||||
return (Integer) get(key);
|
||||
}
|
||||
|
||||
|
||||
public long getLong(String key)
|
||||
{
|
||||
return (Long) get(key);
|
||||
}
|
||||
|
||||
|
||||
public float getFloat(String key)
|
||||
{
|
||||
return (Float) get(key);
|
||||
}
|
||||
|
||||
|
||||
public double getDouble(String key)
|
||||
{
|
||||
return (Double) get(key);
|
||||
}
|
||||
|
||||
|
||||
public String getString(String key)
|
||||
{
|
||||
return (String) get(key);
|
||||
return super.get(key);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Object get(Object arg0)
|
||||
public V put(K key, V value)
|
||||
{
|
||||
return super.get(arg0);
|
||||
}
|
||||
|
||||
|
||||
public void putBoolean(String key, boolean num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putBool(String key, boolean num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putByte(String key, int num)
|
||||
{
|
||||
put(key, (byte) num);
|
||||
}
|
||||
|
||||
|
||||
public void putChar(String key, char num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putCharacter(String key, char num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putShort(String key, int num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putInt(String key, int num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putInteger(String key, int num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putLong(String key, long num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putFloat(String key, double num)
|
||||
{
|
||||
put(key, (float) num);
|
||||
}
|
||||
|
||||
|
||||
public void putDouble(String key, double num)
|
||||
{
|
||||
put(key, num);
|
||||
}
|
||||
|
||||
|
||||
public void putString(String key, String num)
|
||||
{
|
||||
put(key, num);
|
||||
return super.put(key, value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte ionMark()
|
||||
public void loadFrom(InputStream in) throws IOException
|
||||
{
|
||||
return IonMarks.MAP;
|
||||
try {
|
||||
while (true) {
|
||||
final short mark = Ion.readMark(in);
|
||||
if (mark == Ion.ENTRY) {
|
||||
final K key = (K) Ion.readObject(in);
|
||||
final V value = (V) Ion.readObject(in);
|
||||
put(key, value);
|
||||
|
||||
} else if (mark == Ion.END) {
|
||||
break;
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected mark in IonMap: " + mark);
|
||||
}
|
||||
}
|
||||
readCustomData(in);
|
||||
} catch (final IOException | ClassCastException e) {
|
||||
throw new IOException("Error reading ion map", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void saveTo(OutputStream out) throws IOException
|
||||
{
|
||||
try {
|
||||
for (final java.util.Map.Entry<K, V> entry : entrySet()) {
|
||||
Ion.writeMark(out, Ion.ENTRY);
|
||||
Ion.writeObject(out, entry.getKey());
|
||||
Ion.writeObject(out, entry.getValue());
|
||||
}
|
||||
Ion.writeMark(out, Ion.END);
|
||||
writeCustomData(out);
|
||||
} catch (final IOException e) {
|
||||
throw new IOException("Error writing ion map", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read custom data of this AbstractIonMap implementation
|
||||
*
|
||||
* @param in input stream
|
||||
*/
|
||||
@DefaultImpl
|
||||
public void readCustomData(InputStream in)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write custom data of this AbstractIonMap implementation
|
||||
*
|
||||
* @param out output stream
|
||||
*/
|
||||
@DefaultImpl
|
||||
public void writeCustomData(OutputStream out)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
return Ion.DATA_BUNDLE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
/**
|
||||
* Byte marks used to structure data in Ion files.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class IonMarks {
|
||||
|
||||
/** Null value */
|
||||
public static final byte NULL = 0;
|
||||
|
||||
/** Boolean value */
|
||||
public static final byte BOOLEAN = 1;
|
||||
|
||||
/** Byte value */
|
||||
public static final byte BYTE = 2;
|
||||
|
||||
/** Character value */
|
||||
public static final byte CHAR = 3;
|
||||
|
||||
/** Short value */
|
||||
public static final byte SHORT = 4;
|
||||
|
||||
/** Integer value */
|
||||
public static final byte INT = 5;
|
||||
|
||||
/** Long value */
|
||||
public static final byte LONG = 6;
|
||||
|
||||
/** Float value */
|
||||
public static final byte FLOAT = 7;
|
||||
|
||||
/** Double value */
|
||||
public static final byte DOUBLE = 8;
|
||||
|
||||
/** String value */
|
||||
public static final byte STRING = 9;
|
||||
|
||||
/** List value (begin) - contains entries, ends with END */
|
||||
public static final byte LIST = 10;
|
||||
|
||||
/** Map value (begin) - contains entries, ends with END */
|
||||
public static final byte MAP = 11;
|
||||
|
||||
/**
|
||||
* List / Map entry<br>
|
||||
* In list directly followed by entry value. In map followed by (string) key
|
||||
* and the entry value.
|
||||
*/
|
||||
public static final byte ENTRY = 12;
|
||||
|
||||
/** End of List / Map */
|
||||
public static final byte END = 13;
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
@@ -19,19 +20,19 @@ public interface Ionizable {
|
||||
* reading right after it.
|
||||
*
|
||||
* @param in input stream
|
||||
* @throws IonException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void ionRead(InputStream in) throws IonException;
|
||||
void loadFrom(InputStream in) throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Store data to output stream. mark has already been written, begin right
|
||||
* Store data to output stream. Mark has already been written, begin right
|
||||
* after it.
|
||||
*
|
||||
* @param out Output stream
|
||||
* @throws IonException
|
||||
* @throws IOException
|
||||
*/
|
||||
public void ionWrite(OutputStream out) throws IonException;
|
||||
void saveTo(OutputStream out) throws IOException;
|
||||
|
||||
|
||||
/**
|
||||
@@ -39,5 +40,5 @@ public interface Ionizable {
|
||||
*
|
||||
* @return Ion mark byte.
|
||||
*/
|
||||
public byte ionMark();
|
||||
public short getIonMark();
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
package mightypork.util.files.ion;
|
||||
|
||||
|
||||
/**
|
||||
* Optional ionizable
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public interface IonizableOptional extends Ionizable {
|
||||
|
||||
/**
|
||||
* Get if this ionizable should be saved to a list
|
||||
*
|
||||
* @return should save
|
||||
*/
|
||||
public boolean ionShouldSave();
|
||||
}
|
||||
Reference in New Issue
Block a user