pull/1/head
valoeghese 2020-02-24 16:32:51 +13:00
parent 3ac06e30b1
commit a76bd342e5
5 changed files with 374 additions and 0 deletions

View File

@ -0,0 +1,64 @@
package tk.valoeghese.sod;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import tk.valoeghese.sod.exception.SODParseException;
public class BinaryData implements Iterable<Map.Entry<String, DataSection>> {
public BinaryData() {
this.sections = new HashMap<>();
}
private final Map<String, DataSection> sections;
public DataSection get(String name) {
return this.sections.get(name);
}
public DataSection getOrCreate(String name) {
return this.sections.computeIfAbsent(name, k -> new DataSection());
}
public void put(String name, DataSection section) {
this.sections.put(name, section);
}
public boolean write(File file) {
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream(file))) {
Parser.write(this, dos);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
@Override
public Iterator<Map.Entry<String, DataSection>> iterator() {
return this.sections.entrySet().iterator();
}
public static BinaryData read(File file) throws SODParseException {
try (DataInputStream dis = new DataInputStream(new FileInputStream(file))) {
long magic = dis.readLong();
if (magic != 0xA77D1E) {
throw new SODParseException("Not a valid SOD file!");
}
return Parser.parse(dis);
} catch (IOException e) {
e.printStackTrace();
//throw new SODParseException("Error in parsing file " + file.toString());
return new BinaryData();
}
}
}

View File

@ -0,0 +1,106 @@
package tk.valoeghese.sod;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* Represents a section of SOD data.
* @author Valoeghese
*/
public class DataSection implements Iterable<Object> {
public DataSection() {
this.data = new ArrayList<>();
}
private final List<Object> data;
public void writeByte(byte data) {
this.data.add(data);
}
public void writeShort(short data) {
this.data.add(data);
}
public void writeInt(int data) {
this.data.add(data);
}
public void writeLong(long data) {
this.data.add(data);
}
public void writeFloat(float data) {
this.data.add(data);
}
public void writeDouble(double data) {
this.data.add(data);
}
public void writeString(String data) {
this.data.add(data);
}
public void writeBoolean(boolean data) {
this.data.add(data ? (byte) 1 : (byte) 0);
}
public <T extends Enum<?>> void writeEnum(T enumValue) {
this.data.add(enumValue.ordinal());
}
public <T extends Enum<?>> void writeEnumAsString(T enumValue) {
this.data.add(enumValue.toString());
}
public int size() {
return this.data.size();
}
public byte readByte(int index) {
return (byte) this.data.get(index);
}
public short readShort(int index) {
return (short) this.data.get(index);
}
public int readInt(int index) {
return (int) this.data.get(index);
}
public long readLong(int index) {
return (long) this.data.get(index);
}
public float readFloat(int index) {
return (float) this.data.get(index);
}
public double readDouble(int index) {
return (double) this.data.get(index);
}
public String readString(int index) {
return (String) this.data.get(index);
}
public boolean readBoolean(int index) {
return ((byte) this.data.get(index)) != 0;
}
public <T extends Enum<T>> T readEnumString(int index, Class<T> type) {
return Enum.valueOf(type, (String) this.data.get(index));
}
public <T extends Enum<?>> T readEnum(int index, T[] values) {
return values[(int) this.data.get(index)];
}
@Override
public Iterator<Object> iterator() {
return this.data.iterator();
}
}

View File

@ -0,0 +1,142 @@
package tk.valoeghese.sod;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import tk.valoeghese.sod.exception.SODParseException;
final class Parser {
static BinaryData parse(DataInputStream input) throws IOException, SODParseException {
BinaryData data = new BinaryData();
DataType dataType;
dataType = DataType.of(input.readByte());
if (dataType != DataType.SECTION) {
throw new SODParseException("Data must be segregated into sections!");
}
DataSection currentSection = new DataSection();
data.put(input.readUTF(), currentSection);
while (input.available() > 0) {
dataType = DataType.of(input.readByte());
switch (dataType) {
case BYTE:
currentSection.writeByte(input.readByte());
break;
case DOUBLE:
currentSection.writeDouble(input.readDouble());
break;
case FLOAT:
currentSection.writeFloat(input.readFloat());
break;
case INT:
currentSection.writeInt(input.readInt());
break;
case LONG:
currentSection.writeLong(input.readLong());
break;
case SECTION:
currentSection = new DataSection();
data.put(input.readUTF(), currentSection);
break;
case SHORT:
currentSection.writeShort(input.readShort());
break;
case STRING:
currentSection.writeString(input.readUTF());
break;
default:
throw new RuntimeException("This error should never be thrown! If this error occurs, the parser is not properly dealing with a most-likely-invalid data type.");
}
}
return data;
}
static void write(BinaryData data, DataOutputStream dos) throws IOException {
dos.writeLong(0xA77D1E);
Iterator<Map.Entry<String, DataSection>> sectionStream = data.iterator();
while (sectionStream.hasNext()) {
Map.Entry<String, DataSection> section = sectionStream.next();
dos.writeByte(DataType.SECTION.id);
dos.writeUTF(section.getKey());
Iterator<Object> dataStream = section.getValue().iterator();
while (dataStream.hasNext()) {
Object o = dataStream.next();
if (o instanceof Byte) {
dos.writeByte(DataType.BYTE.id);
dos.writeByte((byte) o);
} else if (o instanceof Short) {
dos.writeByte(DataType.SHORT.id);
dos.writeShort((short) o);
} else if (o instanceof Integer) {
dos.writeByte(DataType.INT.id);
dos.writeInt((int) o);
} else if (o instanceof Long) {
dos.writeByte(DataType.LONG.id);
dos.writeLong((long) o);
} else if (o instanceof Float) {
dos.writeByte(DataType.FLOAT.id);
dos.writeFloat((float) o);
} else if (o instanceof Double) {
dos.writeByte(DataType.DOUBLE.id);
dos.writeDouble((double) o);
} else if (o instanceof String) {
dos.writeByte(DataType.STRING.id);
dos.writeUTF((String) o);
}
}
}
}
}
enum DataType {
SECTION(0),
BYTE(1),
SHORT(2),
INT(3),
LONG(4),
FLOAT(5),
DOUBLE(6),
STRING(7);
private DataType(int id) {
this.id = (byte) id;
}
public final byte id;
public static DataType of(byte id) throws SODParseException {
switch (id) {
case 0:
return SECTION;
case 1:
return BYTE;
case 2:
return SHORT;
case 3:
return INT;
case 4:
return LONG;
case 5:
return FLOAT;
case 6:
return DOUBLE;
case 7:
return STRING;
default:
throw new SODParseException("Unknown data type " + String.valueOf(id));
}
}
}

View File

@ -0,0 +1,53 @@
package tk.valoeghese.sod;
import java.io.File;
import java.io.IOException;
public class TestMain {
public static void main(String[] args) throws IOException {
//writeTest()
readTest();
}
static void readTest() throws IOException {
File f = new File("../test.sod");
if (!f.createNewFile()) {
BinaryData bd = BinaryData.read(f);
DataSection ds1 = bd.get("DS1");
for (Object i : ds1) {
System.out.println(i);
}
DataSection ds2 = bd.get("yeet");
for (Object i : ds2) {
System.out.println(i);
}
}
}
static void writeTest() throws IOException {
File f = new File("../test.sod");
f.createNewFile();
BinaryData bd = new BinaryData();
DataSection ds1 = bd.getOrCreate("DS1");
ds1.writeBoolean(false);
ds1.writeDouble(0.666D);
ds1.writeLong(69696969);
ds1.writeString("yaY33T");
DataSection ds2 = bd.getOrCreate("yeet");
ds2.writeByte((byte) 4);
ds2.writeFloat(1.3F);
ds2.writeString("e");
ds2.writeString("ff");
bd.write(f);
}
}

View File

@ -0,0 +1,9 @@
package tk.valoeghese.sod.exception;
public class SODParseException extends RuntimeException {
private static final long serialVersionUID = -3337517517501006140L;
public SODParseException(String message) {
super(message);
}
}