Rogue: Savage Rats, a retro-themed dungeon crawler
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.
 
 
rogue-savage-rats/src/mightypork/utils/files/ion/Ion.java

298 lines
6.5 KiB

package mightypork.utils.files.ion;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import mightypork.utils.math.Calc;
/**
* Universal data storage system
*
* @author MightyPork
*/
public class Ion {
/** Ionizables<Mark, Class> */
private static Map<Byte, Class<?>> customIonizables = new HashMap<Byte, Class<?>>();
// register default ionizables
static {
try {
registerIonizable(IonMarks.MAP, IonMap.class);
registerIonizable(IonMarks.LIST, IonList.class);
} catch (IonException e) {
e.printStackTrace();
}
}
/**
* Register new Ionizable for direct reconstructing.
*
* @param mark byte mark to be used, see {@link IonMarks} for reference.
* @param objClass class of the registered Ionizable
* @throws IonException
*/
public static void registerIonizable(byte mark, Class<?> objClass) throws IonException
{
if (customIonizables.containsKey(mark)) {
throw new IonException("IonMark " + mark + " is already used.");
}
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
*/
public static Object fromFile(File file) throws IonException
{
InputStream in = null;
try {
in = new FileInputStream(file);
Object obj = fromStream(in);
return obj;
} catch (IOException e) {
throw new IonException("Error loading ION file.", e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* Load Ion object from stream.
*
* @param in input stream
* @return the loaded object
* @throws IonException
*/
public static Object fromStream(InputStream in) throws IonException
{
return readObject(in);
}
/**
* Store Ion object to file.
*
* @param path file path
* @param obj object to store
* @throws IonException
*/
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
{
OutputStream out = null;
try {
String f = path.toString();
File dir = new File(f.substring(0, f.lastIndexOf(File.separator)));
dir.mkdirs();
out = new FileOutputStream(path);
toStream(out, obj);
out.flush();
out.close();
} catch (Exception e) {
throw new IonException("Error writing to ION file.", e);
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 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
*
* @param in input stream
* @return the loaded object
* @throws IonException
*/
public static Object readObject(InputStream in) throws IonException
{
try {
int bi = in.read();
if (bi == -1) throw new IonException("Unexpected end of stream.");
byte b = (byte) bi;
if (customIonizables.containsKey(b)) {
Ionizable ion;
try {
ion = ((Ionizable) customIonizables.get(b).newInstance());
} catch (InstantiationException e) {
throw new IonException("Cound not instantiate " + customIonizables.get(b).getSimpleName(), e);
} catch (IllegalAccessException e) {
throw new IonException("Cound not instantiate " + customIonizables.get(b).getSimpleName(), e);
}
ion.ionRead(in);
return ion;
}
switch (b) {
case IonMarks.BOOLEAN:
return StreamUtils.readBoolean(in);
case IonMarks.BYTE:
return StreamUtils.readByte(in);
case IonMarks.CHAR:
return StreamUtils.readChar(in);
case IonMarks.SHORT:
return StreamUtils.readShort(in);
case IonMarks.INT:
return StreamUtils.readInt(in);
case IonMarks.LONG:
return StreamUtils.readLong(in);
case IonMarks.FLOAT:
return StreamUtils.readFloat(in);
case IonMarks.DOUBLE:
return StreamUtils.readDouble(in);
case IonMarks.STRING:
String s = StreamUtils.readString(in);
return s;
default:
throw new IonException("Invalid Ion mark " + Integer.toHexString(bi));
}
} catch (IOException e) {
throw new IonException("Error loading ION file: ", e);
}
}
/**
* Write single ionizable or primitive object to output stream
*
* @param out output stream
* @param obj stored object
* @throws IonException
*/
public static void writeObject(OutputStream out, Object obj) throws IonException
{
try {
if (obj instanceof Ionizable) {
out.write(((Ionizable) obj).ionMark());
((Ionizable) obj).ionWrite(out);
return;
}
if (obj instanceof Boolean) {
out.write(IonMarks.BOOLEAN);
StreamUtils.writeBoolean(out, (Boolean) obj);
return;
}
if (obj instanceof Byte) {
out.write(IonMarks.BYTE);
StreamUtils.writeByte(out, (Byte) obj);
return;
}
if (obj instanceof Character) {
out.write(IonMarks.CHAR);
StreamUtils.writeChar(out, (Character) obj);
return;
}
if (obj instanceof Short) {
out.write(IonMarks.SHORT);
StreamUtils.writeShort(out, (Short) obj);
return;
}
if (obj instanceof Integer) {
out.write(IonMarks.INT);
StreamUtils.writeInt(out, (Integer) obj);
return;
}
if (obj instanceof Long) {
out.write(IonMarks.LONG);
StreamUtils.writeLong(out, (Long) obj);
return;
}
if (obj instanceof Float) {
out.write(IonMarks.FLOAT);
StreamUtils.writeFloat(out, (Float) obj);
return;
}
if (obj instanceof Double) {
out.write(IonMarks.DOUBLE);
StreamUtils.writeDouble(out, (Double) obj);
return;
}
if (obj instanceof String) {
out.write(IonMarks.STRING);
StreamUtils.writeString(out, (String) obj);
return;
}
throw new IonException(Calc.cname(obj) + " can't be stored in Ion storage.");
} catch (IOException e) {
throw new IonException("Could not store " + obj, e);
}
}
}