Got a functional version of BDF 3

This commit is contained in:
josua 2020-07-27 11:11:01 +10:00
parent 31e6b9b637
commit f73eb0454f
9 changed files with 180 additions and 149 deletions

View File

@ -1,10 +1,12 @@
package bdf.file;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import bdf.data.BdfDatabase;
import bdf.types.BdfObject;
@ -65,7 +67,7 @@ public class BdfFileManager extends BdfReader
OutputStream out = new FileOutputStream(path);
if(compressed) {
out = new DeflaterOutputStream(out);
out = new GZIPOutputStream(out);
}
// Write the database to the file

View File

@ -41,25 +41,13 @@ public class BdfArray implements IBdfType, Iterable<BdfObject>
}
}
public BdfObject createObject() {
return new BdfObject(lookupTable);
}
public BdfNamedList createNamedList() {
return new BdfNamedList(lookupTable);
}
public BdfArray createArray() {
return new BdfArray(lookupTable);
}
@Override
public int serializeSeeker()
public int serializeSeeker(int[] locations)
{
int size = 0;
for(BdfObject o : elements) {
size += o.serializeSeeker();
size += o.serializeSeeker(locations);
size += 4;
}
@ -67,13 +55,13 @@ public class BdfArray implements IBdfType, Iterable<BdfObject>
}
@Override
public int serialize(IBdfDatabase database)
public int serialize(IBdfDatabase database, int[] locations)
{
int pos = 0;
for(BdfObject o : elements)
{
int size = o.serialize(database.getPointer(pos + 4));
int size = o.serialize(database.getPointer(pos + 4), locations);
database.setBytes(pos, DataHelpers.serializeInt(size));
pos += size;
@ -191,4 +179,11 @@ public class BdfArray implements IBdfType, Iterable<BdfObject>
};
}
@Override
public void getLocationUses(int[] locations) {
for(BdfObject element : elements) {
element.getLocationUses(locations);
}
}
}

View File

@ -11,14 +11,18 @@ import bdf.util.DataHelpers;
class BdfLookupTable implements IBdfType
{
private ArrayList<byte[]> keys;
private BdfReader reader;
BdfLookupTable() {
keys = new ArrayList<byte[]>();
BdfLookupTable(BdfReader reader)
{
this.keys = new ArrayList<byte[]>();
this.reader = reader;
}
BdfLookupTable(IBdfDatabase database)
BdfLookupTable(BdfReader reader, IBdfDatabase database)
{
keys = new ArrayList<byte[]>();
this.keys = new ArrayList<byte[]>();
this.reader = reader;
for(int i=0;i<database.size();)
{
@ -49,12 +53,17 @@ class BdfLookupTable implements IBdfType
}
@Override
public int serialize(IBdfDatabase database)
public int serialize(IBdfDatabase database, int[] locations)
{
int upto = 0;
for(int i=0;i<keys.size();i++)
{
// Skip this key if the location is unset (the key has been culled)
if(locations[i] == -1) {
continue;
}
byte[] key = keys.get(i);
database.setBytes(upto + 4, key);
@ -68,11 +77,17 @@ class BdfLookupTable implements IBdfType
}
@Override
public int serializeSeeker()
public int serializeSeeker(int[] locations)
{
int size = 0;
for(int i=0;i<keys.size();i++) {
for(int i=0;i<keys.size();i++)
{
// Skip this key if the location is unset (the key has been culled)
if(locations[i] == -1) {
continue;
}
size += keys.get(i).length;
size += 4;
}
@ -80,7 +95,30 @@ class BdfLookupTable implements IBdfType
return size;
}
public int[] serializeGetLocations()
{
int[] locations = new int[keys.size()];
int next = 0;
reader.bdf.getLocationUses(locations);
for(int i=0;i<locations.length;i++) {
if(locations[i] > 0) {
locations[i] = next;
next += 1;
} else {
locations[i] = -1;
}
}
return locations;
}
@Override
public void serializeHumanReadable(OutputStream stream, BdfIndent indent, int it) {
}
@Override
public void getLocationUses(int[] locations) {
}
}

View File

@ -56,17 +56,17 @@ public class BdfNamedList implements IBdfType
}
@Override
public int serialize(IBdfDatabase database)
public int serialize(IBdfDatabase database, int[] locations)
{
int pos = 0;
for(Element o : elements)
{
database.setBytes(pos, DataHelpers.serializeInt(o.key));
database.setBytes(pos, DataHelpers.serializeInt(locations[o.key]));
pos += 4;
int size = o.object.serialize(database.getPointer(pos + 4));
int size = o.object.serialize(database.getPointer(pos + 4), locations);
database.setBytes(pos, DataHelpers.serializeInt(size));
@ -78,14 +78,14 @@ public class BdfNamedList implements IBdfType
}
@Override
public int serializeSeeker()
public int serializeSeeker(int[] locations)
{
int size = 0;
for(Element o : elements)
{
size += 8;
size += o.object.serializeSeeker();
size += o.object.serializeSeeker(locations);
}
return size;
@ -181,30 +181,6 @@ public class BdfNamedList implements IBdfType
return null;
}
public BdfNamedList remove(BdfObject bdf)
{
for(int i=0;i<elements.size();i++) {
if(elements.get(i).object == bdf) {
elements.remove(i);
i -= 1;
}
}
return this;
}
public BdfObject createObject() {
return new BdfObject(lookupTable);
}
public BdfNamedList createNamedList() {
return new BdfNamedList(lookupTable);
}
public BdfArray createArray() {
return new BdfArray(lookupTable);
}
public BdfNamedList set(String key, BdfObject object)
{
// Convert the key to bytes
@ -276,4 +252,13 @@ public class BdfNamedList implements IBdfType
public int size() {
return elements.size();
}
@Override
public void getLocationUses(int[] locations)
{
for(Element e : elements) {
locations[e.key] += 1;
e.object.getLocationUses(locations);
}
}
}

View File

@ -18,15 +18,13 @@ public class BdfObject implements IBdfType
BdfObject(BdfLookupTable lookupTable) {
this.lookupTable = lookupTable;
this.database = new BdfDatabase(0);
}
BdfObject(BdfLookupTable lookupTable, IBdfDatabase data)
{
this.lookupTable = lookupTable;
// Is the database length greater than 1
if(data.size() > 1)
{
// Get the type and database values
type = data.getByte(0);
database = data.getPointer(1, data.size() - 1);
@ -41,15 +39,16 @@ public class BdfObject implements IBdfType
}
}
else
@Override
public void getLocationUses(int[] locations)
{
// Create a new database
database = new BdfDatabase(0);
if(type == BdfTypes.NAMED_LIST || type == BdfTypes.ARRAY) {
((IBdfType)object).getLocationUses(locations);
}
}
@Override
public int serialize(IBdfDatabase database)
public int serialize(IBdfDatabase database, int[] locations)
{
int size;
@ -59,11 +58,11 @@ public class BdfObject implements IBdfType
switch(type)
{
case BdfTypes.ARRAY:
size = ((BdfArray)object).serialize(db) + 1;
size = ((BdfArray)object).serialize(db, locations) + 1;
break;
case BdfTypes.NAMED_LIST:
size = ((BdfNamedList)object).serialize(db) + 1;
size = ((BdfNamedList)object).serialize(db, locations) + 1;
break;
case BdfTypes.STRING:
@ -84,13 +83,13 @@ public class BdfObject implements IBdfType
}
@Override
public int serializeSeeker()
public int serializeSeeker(int[] locations)
{
// Objects
switch(type)
{
case BdfTypes.ARRAY: return ((BdfArray)object).serializeSeeker() + 1;
case BdfTypes.NAMED_LIST: return ((BdfNamedList)object).serializeSeeker() + 1;
case BdfTypes.ARRAY: return ((BdfArray)object).serializeSeeker(locations) + 1;
case BdfTypes.NAMED_LIST: return ((BdfNamedList)object).serializeSeeker(locations) + 1;
case BdfTypes.STRING: return ((String)object).getBytes().length + 1;
}
@ -158,7 +157,7 @@ public class BdfObject implements IBdfType
int[] array = this.getIntegerArray();
for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Integer.toString(array[i]) + "I").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes());
if(i != array.length - 1) stream.write(", ".getBytes());
}
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break;
@ -169,7 +168,7 @@ public class BdfObject implements IBdfType
boolean[] array = this.getBooleanArray();
for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + (array[i] ? "true" : "false")).getBytes());
if(i == array.length - 1) stream.write(", ".getBytes());
if(i != array.length - 1) stream.write(", ".getBytes());
}
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break;
@ -180,7 +179,7 @@ public class BdfObject implements IBdfType
short[] array = this.getShortArray();
for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Short.toString(array[i]) + "S").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes());
if(i != array.length - 1) stream.write(", ".getBytes());
}
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break;
@ -191,7 +190,7 @@ public class BdfObject implements IBdfType
long[] array = this.getLongArray();
for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Long.toString(array[i]) + "L").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes());
if(i != array.length - 1) stream.write(", ".getBytes());
}
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break;
@ -202,7 +201,7 @@ public class BdfObject implements IBdfType
byte[] array = this.getByteArray();
for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Byte.toString(array[i]) + "B").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes());
if(i != array.length - 1) stream.write(", ".getBytes());
}
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break;
@ -213,7 +212,7 @@ public class BdfObject implements IBdfType
double[] array = this.getDoubleArray();
for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Double.toString(array[i]) + "D").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes());
if(i != array.length - 1) stream.write(", ".getBytes());
}
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break;
@ -224,7 +223,7 @@ public class BdfObject implements IBdfType
float[] array = this.getFloatArray();
for(int i=0;i<array.length;i++) {
stream.write((indent.breaker + calcIndent(indent, it) + Float.toString(array[i]) + "F").getBytes());
if(i == array.length - 1) stream.write(", ".getBytes());
if(i != array.length - 1) stream.write(", ".getBytes());
}
stream.write((indent.breaker + calcIndent(indent, it - 1) + ")").getBytes());
break;
@ -448,7 +447,7 @@ public class BdfObject implements IBdfType
public BdfArray getArray()
{
if(this.type != BdfTypes.ARRAY)
setArray(createArray());
setArray(newArray());
return (BdfArray)object;
}
@ -456,7 +455,7 @@ public class BdfObject implements IBdfType
public BdfNamedList getNamedList()
{
if(this.type != BdfTypes.NAMED_LIST)
setNamedList(createNamedList());
setNamedList(newNamedList());
return (BdfNamedList)object;
}
@ -533,15 +532,15 @@ public class BdfObject implements IBdfType
return this;
}
public BdfObject createObject() {
public BdfObject newObject() {
return new BdfObject(lookupTable);
}
public BdfNamedList createNamedList() {
public BdfNamedList newNamedList() {
return new BdfNamedList(lookupTable);
}
public BdfArray createArray() {
public BdfArray newArray() {
return new BdfArray(lookupTable);
}

View File

@ -13,69 +13,69 @@ public class BdfReader
protected BdfLookupTable lookupTable;
protected BdfObject bdf;
public BdfReader() {
lookupTable = new BdfLookupTable();
private void initNew() {
lookupTable = new BdfLookupTable(this);
bdf = new BdfObject(lookupTable);
}
public BdfReader() {
initNew();
}
public BdfReader(byte[] database) {
this(new BdfDatabase(database));
}
public BdfReader(IBdfDatabase database)
{
// Check the version of the BDF file
if(!"BDF3".contentEquals(new String(database.getBytes(0, 4)))) {
lookupTable = new BdfLookupTable();
bdf = new BdfObject(lookupTable);
if(database.size() < 4) {
initNew();
return;
}
// Get the lookup table
int lookupTable_size = DataHelpers.getByteBuffer(database.getPointer(4, 4)).getInt();
lookupTable = new BdfLookupTable(database.getPointer(8, lookupTable_size));
int lookupTable_size = DataHelpers.getByteBuffer(database.getPointer(0, 4)).getInt();
lookupTable = new BdfLookupTable(this, database.getPointer(4, lookupTable_size));
// Get the rest of the data
int upto = lookupTable_size + 8;
int upto = lookupTable_size + 4;
int bdf_size = DataHelpers.getByteBuffer(database.getPointer(upto, 4)).getInt();
bdf = new BdfObject(lookupTable, database.getPointer(upto + 4, bdf_size));
}
public BdfDatabase serialize()
{
int bdf_size = bdf.serializeSeeker();
int lookupTable_size = lookupTable.serializeSeeker();
int database_size = bdf_size + lookupTable_size + 12;
int[] locations = lookupTable.serializeGetLocations();
int bdf_size = bdf.serializeSeeker(locations);
int lookupTable_size = lookupTable.serializeSeeker(locations);
int database_size = bdf_size + lookupTable_size + 8;
BdfDatabase database = new BdfDatabase(database_size);
database.setBytes(0, "BDF3".getBytes());
database.setBytes(4, DataHelpers.serializeInt(lookupTable_size));
database.setBytes(8 + lookupTable_size, DataHelpers.serializeInt(bdf_size));
database.setBytes(0, DataHelpers.serializeInt(lookupTable_size));
database.setBytes(4 + lookupTable_size, DataHelpers.serializeInt(bdf_size));
lookupTable.serialize(database.getPointer(8, lookupTable_size));
bdf.serialize(database.getPointer(12 + lookupTable_size, database_size));
lookupTable.serialize(database.getPointer(4, lookupTable_size), locations);
bdf.serialize(database.getPointer(8 + lookupTable_size, database_size), locations);
return database;
}
public BdfObject getBDF() {
public BdfObject getObject() {
return bdf;
}
public String serializeHumanReadable(BdfIndent indent) {
return serializeHumanReadable(indent, 0);
public BdfObject resetObject() {
bdf = new BdfObject(lookupTable);
return bdf;
}
public String serializeHumanReadable() {
return serializeHumanReadable(new BdfIndent("", ""), 0);
}
public String serializeHumanReadable(BdfIndent indent, int it)
public String serializeHumanReadable(BdfIndent indent)
{
ByteArrayOutputStream stream = new ByteArrayOutputStream();
try {
bdf.serializeHumanReadable(stream, indent, it);
bdf.serializeHumanReadable(stream, indent, 0);
return stream.toString();
}
@ -84,23 +84,19 @@ public class BdfReader
}
}
public void serializeHumanReadable(OutputStream stream, BdfIndent indent) throws IOException {
public String serializeHumanReadable() {
return serializeHumanReadable(new BdfIndent("", ""));
}
public void serializeHumanReadable(OutputStream stream, BdfIndent indent) throws IOException
{
bdf.serializeHumanReadable(stream, indent, 0);
stream.write('\n');
stream.flush();
}
public void serializeHumanReadable(OutputStream stream) throws IOException {
bdf.serializeHumanReadable(stream, new BdfIndent("", ""), 0);
}
public BdfObject createObject() {
return new BdfObject(lookupTable);
}
public BdfNamedList createNamedList() {
return new BdfNamedList(lookupTable);
}
public BdfArray createArray() {
return new BdfArray(lookupTable);
serializeHumanReadable(stream, new BdfIndent("", ""));
}
}

View File

@ -7,8 +7,9 @@ import bdf.data.IBdfDatabase;
interface IBdfType
{
int serialize(IBdfDatabase database);
int serializeSeeker();
void getLocationUses(int[] locations);
int serialize(IBdfDatabase database, int[] locations);
int serializeSeeker(int[] locations);
void serializeHumanReadable(OutputStream stream, BdfIndent indent, int it) throws IOException;
}

View File

@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;
public class FileHelpers
@ -50,7 +51,7 @@ public class FileHelpers
public static byte[] readAllCompressed(String path) throws IOException
{
// Create the file input stream
InflaterInputStream in = new InflaterInputStream(new FileInputStream(path));
GZIPInputStream in = new GZIPInputStream(new FileInputStream(path));
// Load all of its data
byte[] data = readAll(in);

View File

@ -8,21 +8,10 @@ import bdf.types.BdfNamedList;
import bdf.types.BdfObject;
import bdf.types.BdfReader;
public class Tests {
public static void main(String[] args) throws InterruptedException, IOException
public class Tests
{
static void displayHex(IBdfDatabase db)
{
BdfReader reader = new BdfReader();
BdfObject bdf = reader.getBDF();
BdfNamedList nl = bdf.getNamedList();
nl.set("hello", nl.createObject().setInteger(69));
nl.set("world", nl.createObject().setString("👋"));
nl.set("👋", nl.createObject().setArray(nl.createArray()));
reader.serializeHumanReadable(System.out);
System.out.println();
IBdfDatabase db = reader.serialize();
char[] hex_chars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
for(int i=0;i<db.size();i++)
@ -36,10 +25,35 @@ public class Tests {
}
System.out.println();
}
public static void main(String[] args) throws InterruptedException, IOException
{
BdfReader reader = new BdfReader();
BdfObject bdf = reader.getObject();
BdfNamedList nl = bdf.newNamedList();
bdf.setNamedList(nl);
nl.set("Hello, ", bdf.newObject().setInteger(69));
nl.set("world!", bdf.newObject().setInteger(420));
nl.remove("Hello, ");
reader.serializeHumanReadable(System.out);
IBdfDatabase db = reader.serialize();
displayHex(db);
reader = new BdfReader(db);
reader.serializeHumanReadable(System.out);
reader.getObject().setArray(bdf.newArray());
db = reader.serialize();
displayHex(db);
reader.serializeHumanReadable(System.out);
System.out.println();
}
}