From 7cb45827aa2de074973ec0674f9ccb44021b4208 Mon Sep 17 00:00:00 2001 From: Niclas Thobaben Date: Tue, 23 Jan 2018 08:45:20 +0100 Subject: [PATCH] inserted org.hwo.serialize package for binary serialization --- src/org/hwo/serialize/BinaryParser.java | 169 +++++++++++++ src/org/hwo/serialize/Database.java | 118 +++++++++ src/org/hwo/serialize/DatabaseField.java | 286 ++++++++++++++++++++++ src/org/hwo/serialize/DatabaseObject.java | 185 ++++++++++++++ src/org/hwo/serialize/DatabaseStructure | 23 ++ 5 files changed, 781 insertions(+) create mode 100644 src/org/hwo/serialize/BinaryParser.java create mode 100644 src/org/hwo/serialize/Database.java create mode 100644 src/org/hwo/serialize/DatabaseField.java create mode 100644 src/org/hwo/serialize/DatabaseObject.java create mode 100644 src/org/hwo/serialize/DatabaseStructure diff --git a/src/org/hwo/serialize/BinaryParser.java b/src/org/hwo/serialize/BinaryParser.java new file mode 100644 index 0000000..f3b708c --- /dev/null +++ b/src/org/hwo/serialize/BinaryParser.java @@ -0,0 +1,169 @@ +package org.hwo.serialize; + +import java.nio.ByteBuffer; +import java.util.List; + +public class BinaryParser { + + private static final String _hex = "0123456789ABCDEF"; + + static void printBytes(List src) { + + for(Byte b : src) { + System.out.print(Integer.toHexString(b) + " "); + } + + System.out.print("\n"); + } + + static void printBytes(byte[] src) { + + for(byte b : src) { + System.out.print(Integer.toHexString(b) + " "); + } + + System.out.print("\n"); + } + + static void writeBytes(List src, byte value) { + src.add(value); + } + + static void writeBytes(List src, short value) { + byte[] buf = ByteBuffer.allocate(Short.BYTES).putShort(value).array(); + for(byte b : buf) + src.add(b); + } + + static void writeBytes(List src, int value) { + byte[] buf = ByteBuffer.allocate(Integer.BYTES).putInt(value).array(); + for(byte b : buf) + src.add(b); + } + + static void writeBytes(List src, long value) { + byte[] buf = ByteBuffer.allocate(Long.BYTES).putLong(value).array(); + for(byte b : buf) + src.add(b); + } + + static void writeBytes(List src, String value) { + char[] arr = value.toCharArray(); + for(char c : arr) + src.add((byte)c); + } + + static byte readByte(List src, int ptr) { + if(ptr >= src.size() || ptr < 0) + return 0; + return src.get(ptr); + } + + static byte readByte(byte[] src, int ptr) { + if(ptr >= src.length || ptr < 0) + return 0; + return src[ptr]; + } + + static short readShort(List src, int ptr) { + if(ptr >= src.size() || ptr < 0) + return 0; + + byte[] temp = new byte[Short.BYTES]; + for(int i = 0; i < Short.BYTES; i++) + temp[i] = src.get(i + ptr); + + ByteBuffer bb = ByteBuffer.wrap(temp); + + return bb.getShort(); + } + + static short readShort(byte[] src, int ptr) { + if(ptr >= src.length || ptr < 0) + return 0; + + byte[] temp = new byte[Short.BYTES]; + for(int i = 0; i < Short.BYTES; i++) + temp[i] = src[i + ptr]; + + ByteBuffer bb = ByteBuffer.wrap(temp); + + return bb.getShort(); + } + + static int readInt(List src, int ptr) { + if(ptr >= src.size() || ptr < 0) + return 0; + + byte[] temp = new byte[Integer.BYTES]; + for(int i = 0; i < Integer.BYTES; i++) + temp[i] = src.get(i + ptr); + + ByteBuffer bb = ByteBuffer.wrap(temp); + + return bb.getInt(); + } + + static int readInt(byte[] src, int ptr) { + if(ptr >= src.length || ptr < 0) + return 0; + + byte[] temp = new byte[Integer.BYTES]; + for(int i = 0; i < Integer.BYTES; i++) + temp[i] = src[i + ptr]; + + ByteBuffer bb = ByteBuffer.wrap(temp); + + return bb.getInt(); + } + + static long readLong(List src, int ptr) { + if(ptr >= src.size() || ptr < 0) + return 0; + + byte[] temp = new byte[Long.BYTES]; + for(int i = 0; i < Long.BYTES; i++) + temp[i] = src.get(i + ptr); + + ByteBuffer bb = ByteBuffer.wrap(temp); + + return bb.getLong(); + } + + static long readLong(byte[] src, int ptr) { + if(ptr >= src.length || ptr < 0) + return 0; + + byte[] temp = new byte[Long.BYTES]; + for(int i = 0; i < Long.BYTES; i++) + temp[i] = src[i + ptr]; + + ByteBuffer bb = ByteBuffer.wrap(temp); + + return bb.getLong(); + } + + static String readString(List src, int strLen, int ptr) { + if(ptr >= src.size() || ptr < 0) + return ""; + + char[] temp = new char[strLen]; + for(int i = 0; i < strLen; i++) + temp[i] = (char)src.get(i + ptr).byteValue(); + + return new String(temp); + } + + static String readString(byte[] src, int strLen, int ptr) { + if(ptr >= src.length || ptr < 0) + return ""; + + char[] temp = new char[strLen]; + for(int i = 0; i < strLen; i++) + temp[i] = (char)src[i + ptr]; + + return new String(temp); + } + + +} diff --git a/src/org/hwo/serialize/Database.java b/src/org/hwo/serialize/Database.java new file mode 100644 index 0000000..d61198f --- /dev/null +++ b/src/org/hwo/serialize/Database.java @@ -0,0 +1,118 @@ +package org.hwo.serialize; + +import java.util.ArrayList; +import java.util.List; + +public class Database { + + //HEADER + //[4]String DatabaseID + //[4] Short ObjectCount + //[2] Short InfoSize + //[InfoSize] Info + //[4] String "DATA" + + private static final String DATABASE_ID = "HF3B"; + + private List objects; + private long sizeInBytes; + + public Database() { + this.objects = new ArrayList(); + + } + + public void addObject(DatabaseObject obj) { + if(this.objects.contains(obj)) + return; + this.objects.add(obj); + } + + public void addObject(String name) { + DatabaseObject temp = new DatabaseObject(name); + if(temp != null) + this.objects.add(temp); + } + + public DatabaseObject getObject(String name) { + for(DatabaseObject o : objects) + if(o.getName().equals(name)) + return o; + return null; + } + + public void removeObject(DatabaseObject obj) { + if(this.objects.contains(obj)) + return; + int index = this.objects.indexOf(obj); + this.objects.remove(index); + } + + public void removeObject(String obj) { + DatabaseObject temp = getObject(obj); + removeObject(temp); + } + + public String toString() { + String result = new String(); + + result += "==========Database==========" + "\n"; + for(DatabaseObject o : this.objects) + result += o.toString(5); + result += "\n"; + return result; + } + + public void print() { + System.out.print(this.toString()); + } + + public byte[] serialize() { + List bytes = new ArrayList(); + + BinaryParser.writeBytes(bytes, DATABASE_ID); + BinaryParser.writeBytes(bytes, (short)this.objects.size()); + BinaryParser.writeBytes(bytes, "DATA"); + + for(DatabaseObject obj : this.objects) { + byte[] temp = obj.serialize(); + for(byte b : temp) + bytes.add(b); + } + + byte[] result = new byte[bytes.size()]; + for(int i = 0; i < bytes.size(); i++) + result[i] = bytes.get(i); + + this.sizeInBytes = result.length; + + bytes = null; + return result; + } + + public static Database deserialize(byte[] src) { + //HEADER + //[4]String DatabaseID + //[4] Short ObjectCount + //[4] String "DATA" + int ptr = 0; + String tDbId = BinaryParser.readString(src, 4, ptr); + ptr += 4; + if(!tDbId.equals(DATABASE_ID)) + return null; + short tObjCount = BinaryParser.readShort(src, ptr); + ptr += 2; + String tDataId = BinaryParser.readString(src, 4, ptr); + ptr += 4; + + Database result = new Database(); + for(int i = 0; i < tObjCount; i++) { + DatabaseObject obj = DatabaseObject.deserialize(src, ptr); + ptr += obj.getSizeInBytes(); + result.addObject(obj); + } + + return result; + + } +} diff --git a/src/org/hwo/serialize/DatabaseField.java b/src/org/hwo/serialize/DatabaseField.java new file mode 100644 index 0000000..0050dcc --- /dev/null +++ b/src/org/hwo/serialize/DatabaseField.java @@ -0,0 +1,286 @@ +package org.hwo.serialize; + +import java.util.ArrayList; +import java.util.List; + +public class DatabaseField { + //FORMAT: + //[4] String FieldID (DFLD) + //[1] Byte FieldType + //[2] Short NameLength + //[NameLength] String Name + // if type==string [2] Short ValueLength + //[TypeLength] Value + + //second nibble == type, first nibble == type if array + public static final byte BYTE = 0x00; + public static final byte SHORT = 0x01; + public static final byte INT = 0x02; + public static final byte LONG = 0x03; + public static final byte STRING = 0x04; + public static final byte OBJECT = 0x05; + public static final byte ARRAY = 0x06; + + private static final String FIELD_ID = "DFLD"; + + public enum Type { + BYTE, + SHORT, + INT, + LONG, + STRING, + OBJECT, + ARRAY + } + + private class _valueType{ + private T value; + + public _valueType(T value) { + this.value = value; + } + + @SuppressWarnings("unused") + public void setValue(T value) { + this.value = value; + } + + public T getValue() { + return value; + } + } + + private byte type; + private String name; + @SuppressWarnings("rawtypes") + private _valueType value; + private int sizeInBytes; + + public DatabaseField(byte type, String name) { + this.type = type; + this.name = name; + } + + public DatabaseField(byte type, String name, Object value) { + this.type = type; + this.name = name; + + switch(this.type) { + case 0x00: + setValue((byte)value); + break; + case 0x01: + setValue((short)value); + break; + case 0x02: + setValue((int)value); + break; + case 0x03: + setValue((long)value); + break; + case 0x04: + setValue((String)value); + break; + case OBJECT: + setValue((DatabaseObject)value); + break; + case ARRAY: + + default: + } + } + + public Type getType() { + return _byteToType(this.type); + } + + private static Type _byteToType(byte t) { + switch(t) { + case 0x00: + return Type.BYTE; + case 0x01: + return Type.SHORT; + case 0x02: + return Type.INT; + case 0x03: + return Type.LONG; + case 0x04: + return Type.STRING; + case 0x05: + return Type.OBJECT; + case 0x06: + return Type.ARRAY; + default: + return null; + } + } + + public String getName() { + return this.name; + } + + private void _setValue(T value) { + this.value = new _valueType(value); + } + + public void setValue(byte value) { _setValue(value); } + public void setValue(short value) { _setValue(value); } + public void setValue(int value) { _setValue(value); } + public void setValue(long value) { _setValue(value); } + public void setValue(String value) { _setValue(value); } + public void setValue(DatabaseObject value) { _setValue(value); } + + @SuppressWarnings("unchecked") + public T getValue(){ + return (T)this.value.getValue(); + } + + public int getSizeInBytes() { + return this.sizeInBytes; + } + + public String toString(int indendation) { + String indend = new String(); + String result = new String(); + for(int i = 0; i < indendation; i++) + indend += " "; + + result += indend + "Field " + this.name + "\n"; + result += indend + "Type: " + _byteToType(this.type) + "\n"; + if(_byteToType(this.type) == Type.OBJECT) + result += indend + "Value " + ((DatabaseObject)getValue()).toString(indendation + 5); + else + result += indend + "Value: " + getValue() + "\n"; + result += "\n"; + + return result; + } + + public String toString() { + return toString(0); + } + + public void print(int indendation) { + System.out.print(this.toString(indendation)); + } + + public void print() { + print(0); + } + + public byte[] serialize() { + List bytes = new ArrayList(); + + BinaryParser.writeBytes(bytes, FIELD_ID); + BinaryParser.writeBytes(bytes, this.type); + BinaryParser.writeBytes(bytes, (short)this.name.length()); + BinaryParser.writeBytes(bytes, this.name); + + switch(getType()) { + case BYTE: + BinaryParser.writeBytes(bytes, (int)Byte.BYTES); + BinaryParser.writeBytes(bytes, (byte)getValue()); + break; + case SHORT: + BinaryParser.writeBytes(bytes, (int)Short.BYTES); + BinaryParser.writeBytes(bytes, (short)getValue()); + break; + case INT: + BinaryParser.writeBytes(bytes, (int)Integer.BYTES); + BinaryParser.writeBytes(bytes, (int)getValue()); + break; + case LONG: + BinaryParser.writeBytes(bytes, (int)Long.BYTES); + BinaryParser.writeBytes(bytes, (long)getValue()); + break; + case STRING: + BinaryParser.writeBytes(bytes, (int)((String)getValue()).length()); + BinaryParser.writeBytes(bytes, (String)getValue()); + break; + case OBJECT: + BinaryParser.writeBytes(bytes, (int)(((DatabaseObject)getValue()).getSizeInBytes())); + byte[] temp = ((DatabaseObject)getValue()).serialize(); + for(byte b : temp) + bytes.add(b); + case ARRAY: + //BinaryParser.writeBytes(bytes, getValue()); + default: + } + + byte[] result = new byte[bytes.size()]; + for(int i = 0; i < bytes.size(); i++) + result[i] = bytes.get(i); + + this.sizeInBytes = result.length; + + bytes = null; + return result; + } + + public static DatabaseField deserialize(byte[] src, int ptr) { + String tid; + byte ttype; + short tnameLen; + String tname; + int tvalueLen = 0; + Object tvalue = null; + + DatabaseField result = null; + + tid = BinaryParser.readString(src, 4, ptr); + ptr += 4; + if(!tid.equals(FIELD_ID)) { + //throw new Exception(); + System.out.println("Field to deserialize is not of type Field!"); + return null; + } + + ttype = BinaryParser.readByte(src, ptr); + ptr += 1; + + tnameLen = BinaryParser.readShort(src, ptr); + ptr += 2; + + tname = BinaryParser.readString(src, tnameLen, ptr); + ptr += tnameLen; + + tvalueLen = BinaryParser.readInt(src, ptr); + ptr += 4; + + //Length = 9 + NameLength + TypeLength + switch(_byteToType(ttype)) { + case BYTE: + tvalue = BinaryParser.readByte(src, ptr); + result = new DatabaseField(ttype, tname, (byte)tvalue); + break; + case SHORT: + tvalue = BinaryParser.readShort(src, ptr); + result = new DatabaseField(ttype, tname, (short)tvalue); + break; + case INT: + tvalue = BinaryParser.readInt(src, ptr); + result = new DatabaseField(ttype, tname, (int)tvalue); + break; + case LONG: + tvalue = BinaryParser.readLong(src, ptr); + result = new DatabaseField(ttype, tname, (long)tvalue); + break; + case STRING: + tvalue = BinaryParser.readString(src, tvalueLen, ptr); + result = new DatabaseField(ttype, tname, (String)tvalue); + break; + case OBJECT: + tvalue = DatabaseObject.deserialize(src, ptr); + result = new DatabaseField(ttype, tname, (DatabaseObject)tvalue); + break; + case ARRAY: + return null; + } + + result.sizeInBytes = 11 + tnameLen + tvalueLen; + return result; + } + + + +} diff --git a/src/org/hwo/serialize/DatabaseObject.java b/src/org/hwo/serialize/DatabaseObject.java new file mode 100644 index 0000000..da090c6 --- /dev/null +++ b/src/org/hwo/serialize/DatabaseObject.java @@ -0,0 +1,185 @@ +package org.hwo.serialize; + +import java.util.ArrayList; +import java.util.List; + +public class DatabaseObject { + + //OBJECT + //[4] String ObjectID ("OBJT") + //[2] Short NameLen + //[NameLen] String Name + //[2] Short NumFields + + private static final String OBJECT_ID = "OBJT"; + + private List fields; + private String name; + private int sizeInBytes; + + public DatabaseObject(String name) { + this.name = name; + this.fields = new ArrayList(); + } + + public void addField(DatabaseField field) { + if(fields.contains(field)) + return; + fields.add(field); + } + + public void addField(String name, byte value) { + DatabaseField temp = new DatabaseField(DatabaseField.BYTE, name, value); + if(temp != null) + addField(temp); + } + + public void addField(String name, short value) { + DatabaseField temp = new DatabaseField(DatabaseField.SHORT, name, value); + if(temp != null) + addField(temp); + } + + public void addField(String name, int value) { + DatabaseField temp = new DatabaseField(DatabaseField.INT, name, value); + if(temp != null) + addField(temp); + } + + public void addField(String name, long value) { + DatabaseField temp = new DatabaseField(DatabaseField.LONG, name, value); + if(temp != null) + addField(temp); + } + + public void addField(String name, String value) { + DatabaseField temp = new DatabaseField(DatabaseField.STRING, name, value); + if(temp != null) + addField(temp); + } + + public void addField(String name, DatabaseObject value) { + DatabaseField temp = new DatabaseField(DatabaseField.OBJECT, name, value); + if(temp != null) + addField(temp); + } + + public void removeField(DatabaseField field) { + if(fields.contains(field)) + return; + int index = fields.indexOf(field); + fields.remove(index); + } + + public DatabaseField getField(String name) { + for(DatabaseField f : fields) + if(f.getName().equals(name)) + return f; + return null; + } + + public T getValue(String name){ + DatabaseField f = getField(name); + if(f != null) + return f.getValue(); + return null; + } + + public String getName() { + return this.name; + } + + public int getSizeInBytes() { + return this.sizeInBytes; + } + + public String toString(int indendation) { + String indend = new String(); + String result = new String(); + + for(int i = 0; i < indendation; i++) + indend += " "; + + result += indend + "Object: " + this.name + "\n"; + result += indend + "Fields: " + "\n"; + + for(DatabaseField f : this.fields) { + result += f.toString(indendation + 5); + } + + + return result; + } + + public String toString() { + return toString(0); + } + + public void print(int indendation) { + System.out.print(this.toString(indendation)); + } + + public void print() { + print(0); + } + + public byte[] serialize() { + List bytes = new ArrayList(); + + BinaryParser.writeBytes(bytes, OBJECT_ID); //Object ID + BinaryParser.writeBytes(bytes, (short)this.name.length()); //Name Length + BinaryParser.writeBytes(bytes, this.name); // Name + BinaryParser.writeBytes(bytes, (short)this.fields.size()); //Field Count + + for(DatabaseField f : this.fields) { + byte[] temp = f.serialize(); + for(byte b : temp) + bytes.add(b); + } + + byte[] result = new byte[bytes.size()]; + for(int i = 0; i < bytes.size(); i++) + result[i] = bytes.get(i); + + this.sizeInBytes = result.length; + + bytes = null; + return result; + } + + //@SuppressWarnings("unused") + public static DatabaseObject deserialize(byte[] src, int ptr) { + String tObjId = BinaryParser.readString(src, 4, ptr); + ptr += 4; + + if(!tObjId.equals(OBJECT_ID)) + return null; + + short tNameLen = BinaryParser.readShort(src, ptr); + ptr += 2; + String tName = BinaryParser.readString(src, tNameLen, ptr); + ptr += tNameLen; + short tFieldCount = BinaryParser.readShort(src, ptr); + ptr += 2; + + DatabaseObject result = new DatabaseObject(tName); + DatabaseField field = null; + int fieldSize = 0; + + if(result == null) + return null; + + for(short i = 0; i < tFieldCount; i++) { + field = DatabaseField.deserialize(src, ptr); + if(field != null) { + ptr += field.getSizeInBytes(); + fieldSize += field.getSizeInBytes(); + result.addField(field); + } + } + + result.sizeInBytes = 8 + tNameLen + fieldSize; + return result; + } + +} diff --git a/src/org/hwo/serialize/DatabaseStructure b/src/org/hwo/serialize/DatabaseStructure new file mode 100644 index 0000000..fa16d60 --- /dev/null +++ b/src/org/hwo/serialize/DatabaseStructure @@ -0,0 +1,23 @@ + +HEADER +[4] String DatabaseID +[4] Short ObjectCount +[4] String "DATA" + + + OBJECT + [4] String ObjectID ("OBJT") + [2] Short NameLen + [NameLen] String Name + [2] Short NumFields + Length = 8 + NameLen + Fields.Length + + FIELD + [4] String FieldID + [1] Byte FieldType + [2] Short NameLength + [NameLength] String Name + [4] Int ValueLength + [TypeLength] Value + Length = 9 + NameLength + TypeLength + \ No newline at end of file