diff --git a/README.md b/README.md index 786a7cc..aca3372 100644 --- a/README.md +++ b/README.md @@ -7,16 +7,16 @@ - Creating an object - Arrays - Named lists -- Example BDF program +- Saving classes ### Overview -Binary Data Format (or BDF) is designed to store data in a tag-like binary structure, +Binary Data Format (or BDF) is designed to store data in a tree-like binary structure, like Notch's NBT format, but also open source and free like JSON. The format is fast and allows multiple data types, it uses 32-bit integers, so BDF files can be fast and work well on 32-bit systems, but have a maximum size of 2 GB. BDF allows human readable serialization to see what is going on for debugging -purposes, but it currently can't parse the result to an object. +purposes, but it currently can't parse the human readable serialized string to an object. ### Data types @@ -166,70 +166,92 @@ for(String key : list) ``` +### Saving classes -### Example BDF program +Classes can be saved with `BdfClassManager` and by +implementing the `IBdfClassManager` interface, +adding 2 functions `BdfClassLoad` and `BdfClassSave`. +`BdfClassLoad` is for checking and loading data from +bdf into the classes variables, while `BdfClassSave` +is for packing pre-existing variables into bdf format. +A BdfClassManager can be used to pass the `IBdfClassManager` +interface into. + +A class with `IBdfClassManager` to save the data +could look like this: ```java -// Create a new BdfObject instance +class HelloWorld implements IBdfClassManager +{ + int iterator = 0; + + @Override + public void BdfClassLoad(BdfObject bdf) + { + // Load scripts here + + // Create a new named list if the object isn't a named list + bdf.setNamedListIfInvalid(); + + // Set the iterator if the iterator hasn't been set yet + bdf.getNamedList().setIfUndefined("iterator", BdfObject.withInteger(0)); + + // Set the iterator stored in bdf + int iterator = bdf.getNamedList().get("iterator").getInteger(); + } + + @Override + public void BdfClassSave(BdfObject bdf) + { + // Save scripts here + + // Create a named list + bdf.setNamedList(); + + // Set the iterator to the named list + bdf.getNamedList().set("iterator", BdfObject.withInteger(iterator)); + } + + public void hello() + { + // Increase the iterator by 1 + iterator++; + + // Say "Hello, World! Script executed times!" + System.out.println("Hello, World! Script executed "+iterator+" times!"); + } + +} + +``` + +A script to manage this could look something like this: + +```java + +/* + Get a new BdfObject instance, it could be existing, + or from another file, BdfArray, or BdfNamedList instance. +*/ BdfObject bdf = new BdfObject(); -// Create a named list -BdfNamedList bdf_nl = new BdfNamedList(); +// Create the HelloWorld class +HelloWorld hello = new HelloWorld(); -// Add some variables to the named list -bdf_nl.set("boolean", BdfObject.with(true)); -bdf_nl.set("an_int", BdfObject.with((int)53)); -bdf_nl.set("double", new BdfObject().setDouble(632.5)); +// Get a new BdfClassManager instance to deal with BDF data +BdfClassManager manager = new BdfClassManager(hello); -// Output some checks on BdfNamedList -System.out.println(bdf_nl.contains("an_int")); // true -System.out.println(bdf_nl.contains("this_dosn't_exist")); // false +// Give the manager an existing BdfObject instance +manager.setBdf(bdf); -// Create an array -BdfArray bdf_array = new BdfArray(); +// Load the classes bdf data +manager.load(); -// Add some values to the array -bdf_array.add(BdfObject.with("Hello, World!")); -bdf_array.add(BdfObject.with(1234567890L)); -bdf_array.set(1, BdfObject.with((short)432)); +// Call the hello world function +hello.hello(); -// Output the size of the array -System.out.println(bdf_array.size()); // 2 +// Save the classes bdf data +manager.save(); -// Output the type of the 2nd item in the array, value types are in BdfTypes -System.out.println(bdf_array.get(1).getType()); // 3 (BdfTypes.SHORT) - -// Save the array to the named list -bdf_nl.set("array", BdfObject.with(bdf_array)); - -// Set the named list to the bdf object -bdf.setNamedList(bdf_nl); - -// Serialize the data -byte[] bdf_data = bdf.serialize().getBytes(); - - - -// Load the serialized data -BdfObject bdf2 = new BdfObject(new BdfDatabase(bdf_data)); - -// Show the human readable serialized data -System.out.println(bdf2.serializeHumanReadable()); // {"boolean": true, "an_int": 53I, "double": 632.5D, "array": ["Hello, World!", 432S]} - -// Show the value of the boolean in the named list -System.out.println(bdf2.getNamedList().get("boolean").getBoolean()); // true - -// Show the value of item 0 in the array -System.out.println(bdf2.getNamedList().get("array").getArray().get(0).getString()); // Hello, World! - -// Check if the double exists -System.out.println(bdf2.getNamedList().contains("double")); // true - -// Remove the double from the named list -bdf2.getNamedList().remove("double"); - -// Check if the double exists -System.out.println(bdf2.getNamedList().contains("double")); // false - ``` \ No newline at end of file diff --git a/db.bdf b/db.bdf new file mode 100755 index 0000000..6ba2bbf Binary files /dev/null and b/db.bdf differ diff --git a/db/file.db b/db/file.db deleted file mode 100755 index 9d461fb..0000000 Binary files a/db/file.db and /dev/null differ diff --git a/src/bdf/Tests.java b/src/bdf/Tests.java deleted file mode 100644 index 519c57e..0000000 --- a/src/bdf/Tests.java +++ /dev/null @@ -1,75 +0,0 @@ -package bdf; - -import bdf.data.BdfDatabase; -import bdf.types.BdfArray; -import bdf.types.BdfNamedList; -import bdf.types.BdfObject; - -public class Tests { - - public static void main(String[] args) - { - // Create a new BdfObject instance - BdfObject bdf = new BdfObject(); - - // Create a named list - BdfNamedList bdf_nl = new BdfNamedList(); - - // Add some variables to the named list - bdf_nl.set("boolean", BdfObject.with(true)); - bdf_nl.set("an_int", BdfObject.with((int)53)); - bdf_nl.set("double", new BdfObject().setDouble(632.5)); - - // Output some checks on BdfNamedList - System.out.println(bdf_nl.contains("an_int")); // true - System.out.println(bdf_nl.contains("this_dosn't_exist")); // false - - // Create an array - BdfArray bdf_array = new BdfArray(); - - // Add some values to the array - bdf_array.add(BdfObject.with("Hello, World!")); - bdf_array.add(BdfObject.with(1234567890L)); - bdf_array.set(1, BdfObject.with((short)432)); - - // Output the size of the array - System.out.println(bdf_array.size()); // 2 - - // Output the type of the 2nd item in the array, value types are in BdfTypes - System.out.println(bdf_array.get(1).getType()); // 3 (BdfTypes.SHORT) - - // Save the array to the named list - bdf_nl.set("array", BdfObject.with(bdf_array)); - - // Set the named list to the bdf object - bdf.setNamedList(bdf_nl); - - // Serialize the data - byte[] bdf_data = bdf.serialize().getBytes(); - - - - // Load the serialized data - BdfObject bdf2 = new BdfObject(new BdfDatabase(bdf_data)); - - // Show the human readable serialized data - System.out.println(bdf2.serializeHumanReadable()); // {"boolean": true, "an_int": 53I, "double": 632.5D, "array": ["Hello, World!", 432S]} - - // Show the value of the boolean in the named list - System.out.println(bdf2.getNamedList().get("boolean").getBoolean()); // true - - // Show the value of item 0 in the array - System.out.println(bdf2.getNamedList().get("array").getArray().get(0).getString()); // Hello, World! - - // Check if the double exists - System.out.println(bdf2.getNamedList().contains("double")); // true - - // Remove the double from the named list - bdf2.getNamedList().remove("double"); - - // Check if the double exists - System.out.println(bdf2.getNamedList().contains("double")); // false - - } - -} diff --git a/src/bdf/classes/BdfClassManager.java b/src/bdf/classes/BdfClassManager.java new file mode 100755 index 0000000..28cff0e --- /dev/null +++ b/src/bdf/classes/BdfClassManager.java @@ -0,0 +1,39 @@ +package bdf.classes; + +import bdf.types.BdfObject; + +public class BdfClassManager +{ + protected IBdfClassManager method; + protected BdfObject object = new BdfObject(); + + public BdfClassManager(IBdfClassManager method) + { + // Save some variables for later + this.method = method; + } + + public void setBdf(BdfObject bdf) { + this.object = bdf; + } + + public BdfObject getBdf() { + return this.object; + } + + public void save(BdfObject bdf) { + method.BdfClassSave(bdf); + } + + public void load(BdfObject bdf) { + method.BdfClassLoad(bdf); + } + + public void save() { + this.save(this.object); + } + + public void load() { + this.load(this.object); + } +} diff --git a/src/bdf/classes/IBdfClassManager.java b/src/bdf/classes/IBdfClassManager.java new file mode 100755 index 0000000..68a0f5d --- /dev/null +++ b/src/bdf/classes/IBdfClassManager.java @@ -0,0 +1,9 @@ +package bdf.classes; + +import bdf.types.BdfObject; + +public interface IBdfClassManager +{ + public void BdfClassLoad(BdfObject bdf); + public void BdfClassSave(BdfObject bdf); +} diff --git a/src/bdf/file/BdfFileManager.java b/src/bdf/file/BdfFileManager.java index 61b9e4a..33ac3f5 100644 --- a/src/bdf/file/BdfFileManager.java +++ b/src/bdf/file/BdfFileManager.java @@ -41,7 +41,7 @@ public class BdfFileManager extends BdfObject File file = new File(path); // Create the parent directories - file.getParentFile().mkdirs(); + file.getAbsoluteFile().getParentFile().mkdirs(); // Get the database file for output FileOutputStream out = new FileOutputStream(path); diff --git a/src/bdf/types/BdfNamedList.java b/src/bdf/types/BdfNamedList.java index 46296ee..56924ae 100644 --- a/src/bdf/types/BdfNamedList.java +++ b/src/bdf/types/BdfNamedList.java @@ -121,7 +121,7 @@ public class BdfNamedList implements IBdfType throw new UndefinedKeyException(key); } - public void remove(String key) + public BdfNamedList remove(String key) { // Convert the key to bytes byte[] key_bytes = key.getBytes(); @@ -139,7 +139,7 @@ public class BdfNamedList implements IBdfType elements.remove(i); // Exit out of the function, prevent NullPointException - return; + return this; } } @@ -147,7 +147,7 @@ public class BdfNamedList implements IBdfType throw new UndefinedKeyException(key); } - public void set(String key, BdfObject object) + public BdfNamedList set(String key, BdfObject object) { // Convert the key to bytes byte[] key_bytes = key.getBytes(); @@ -162,7 +162,7 @@ public class BdfNamedList implements IBdfType e.object = object; // Exit out of the function, don't add another object - return; + return this; } } @@ -173,6 +173,23 @@ public class BdfNamedList implements IBdfType // Add the new element object to the elements list elements.add(e); + + // Send this class back + return this; + } + + public BdfNamedList setIfUndefined(String key, BdfObject object) + { + if(this.contains(key)) return this; + else return this.set(key, object); + } + + public BdfNamedList allocIfUndefined(String key) { + return this.setIfUndefined(key, new BdfObject()); + } + + public BdfNamedList alloc(String key) { + return this.set(key, new BdfObject()); } public boolean contains(String key) diff --git a/src/bdf/types/BdfObject.java b/src/bdf/types/BdfObject.java index 661583d..217273a 100644 --- a/src/bdf/types/BdfObject.java +++ b/src/bdf/types/BdfObject.java @@ -113,6 +113,54 @@ public class BdfObject implements IBdfType return (new BdfObject()).setNamedList(v); } + public static BdfObject withInteger(int v) { + return (new BdfObject()).setInteger(v); + } + + public static BdfObject withByte(byte v) { + return (new BdfObject()).setByte(v); + } + + public static BdfObject withBoolean(boolean v) { + return (new BdfObject()).setBoolean(v); + } + + public static BdfObject withFloat(float v) { + return (new BdfObject()).setFloat(v); + } + + public static BdfObject withDouble(double v) { + return (new BdfObject()).setDouble(v); + } + + public static BdfObject withLong(long v) { + return (new BdfObject()).setLong(v); + } + + public static BdfObject withShort(short v) { + return (new BdfObject()).setShort(v); + } + + public static BdfObject withString(String v) { + return (new BdfObject()).setString(v); + } + + public static BdfObject withArray(BdfArray v) { + return (new BdfObject()).setArray(v); + } + + public static BdfObject withBdfNamedList(BdfNamedList v) { + return (new BdfObject()).setNamedList(v); + } + + public static BdfObject withArray() { + return (new BdfObject()).setArray(new BdfArray()); + } + + public static BdfObject withBdfNamedList() { + return (new BdfObject()).setNamedList(new BdfNamedList()); + } + public byte getType() { return this.type; } @@ -228,4 +276,163 @@ public class BdfObject implements IBdfType this.object = value; return this; } + + public BdfObject setArray() { + return this.setArray(new BdfArray()); + } + + public BdfObject setNamedList() { + return this.setNamedList(new BdfNamedList()); + } + + public BdfObject set(int v) { + return this.setInteger(v); + } + + public BdfObject set(byte v) { + return this.setByte(v); + } + + public BdfObject set(boolean v) { + return this.setBoolean(v); + } + + public BdfObject set(float v) { + return this.setFloat(v); + } + + public BdfObject set(double v) { + return this.setDouble(v); + } + + public BdfObject set(long v) { + return this.setLong(v); + } + + public BdfObject set(short v) { + return this.setShort(v); + } + + public BdfObject set(String v) { + return this.setString(v); + } + + public BdfObject set(BdfArray v) { + return this.setArray(v); + } + + public BdfObject set(BdfNamedList v) { + return this.setNamedList(v); + } + + public BdfObject setIfInvalid(int v) { + if(this.getType() == BdfTypes.INTEGER) return this; + return this.setInteger(v); + } + + public BdfObject setIfInvalid(byte v) { + if(this.getType() == BdfTypes.BYTE) return this; + return this.setByte(v); + } + + public BdfObject setIfInvalid(boolean v) { + if(this.getType() == BdfTypes.BOOLEAN) return this; + return this.setBoolean(v); + } + + public BdfObject setIfInvalid(float v) { + if(this.getType() == BdfTypes.FLOAT) return this; + return this.setFloat(v); + } + + public BdfObject setIfInvalid(double v) { + if(this.getType() == BdfTypes.DOUBLE) return this; + return this.setDouble(v); + } + + public BdfObject setIfInvalid(long v) { + if(this.getType() == BdfTypes.LONG) return this; + return this.setLong(v); + } + + public BdfObject setIfInvalid(short v) { + if(this.getType() == BdfTypes.SHORT) return this; + return this.setShort(v); + } + + public BdfObject setIfInvalid(String v) { + if(this.getType() == BdfTypes.STRING) return this; + return this.setString(v); + } + + public BdfObject setIfInvalid(BdfArray v) { + if(this.getType() == BdfTypes.ARRAY) return this; + return this.setArray(v); + } + + public BdfObject setIfInvalid(BdfNamedList v) { + if(this.getType() == BdfTypes.NAMED_LIST) return this; + return this.setNamedList(v); + } + + public BdfObject setIntegerIfInvalid(int v) { + if(this.getType() == BdfTypes.INTEGER) return this; + return this.setInteger(v); + } + + public BdfObject setByteIfInvalid(byte v) { + if(this.getType() == BdfTypes.BYTE) return this; + return this.setByte(v); + } + + public BdfObject setBooleanIfInvalid(boolean v) { + if(this.getType() == BdfTypes.BOOLEAN) return this; + return this.setBoolean(v); + } + + public BdfObject setFloatIfInvalid(float v) { + if(this.getType() == BdfTypes.FLOAT) return this; + return this.setFloat(v); + } + + public BdfObject setDoubleIfInvalid(double v) { + if(this.getType() == BdfTypes.DOUBLE) return this; + return this.setDouble(v); + } + + public BdfObject setLongIfInvalid(long v) { + if(this.getType() == BdfTypes.LONG) return this; + return this.setLong(v); + } + + public BdfObject setShortIfInvalid(short v) { + if(this.getType() == BdfTypes.SHORT) return this; + return this.setShort(v); + } + + public BdfObject setStringIfInvalid(String v) { + if(this.getType() == BdfTypes.STRING) return this; + return this.setString(v); + } + + public BdfObject setArrayIfInvalid(BdfArray v) { + if(this.getType() == BdfTypes.ARRAY) return this; + return this.setArray(v); + } + + public BdfObject setNamedListIfInvalid(BdfNamedList v) { + if(this.getType() == BdfTypes.NAMED_LIST) return this; + return this.setNamedList(v); + } + + public BdfObject setArrayIfInvalid() { + if(this.getType() == BdfTypes.ARRAY) return this; + return this.setArray(new BdfArray()); + } + + public BdfObject setNamedListIfInvalid() { + if(this.getType() == BdfTypes.NAMED_LIST) return this; + return this.setNamedList(new BdfNamedList()); + } + } diff --git a/src/tests/TestClass.java b/src/tests/TestClass.java new file mode 100755 index 0000000..c12b74a --- /dev/null +++ b/src/tests/TestClass.java @@ -0,0 +1,31 @@ +package tests; + +import bdf.classes.IBdfClassManager; +import bdf.types.BdfObject; + +public class TestClass implements IBdfClassManager +{ + int i = 0; + + @Override + public void BdfClassLoad(BdfObject bdf) + { + bdf.setNamedListIfInvalid(); + bdf.getNamedList().setIfUndefined("i", BdfObject.withInteger(0)); + this.i = bdf.getNamedList().get("i").getInteger(); + } + + @Override + public void BdfClassSave(BdfObject bdf) + { + bdf.setNamedList(); + bdf.getNamedList().set("i", BdfObject.withInteger(i)); + } + + public void tick() + { + System.out.println(i); + i++; + } + +} diff --git a/src/tests/Tests.java b/src/tests/Tests.java new file mode 100755 index 0000000..ca7aa62 --- /dev/null +++ b/src/tests/Tests.java @@ -0,0 +1,38 @@ +package tests; + +import bdf.classes.BdfClassManager; +import bdf.file.BdfFileManager; + +public class Tests { + + public static void main(String[] args) + { + BdfFileManager bdf = new BdfFileManager("db.bdf"); + + bdf.setNamedListIfInvalid(); + bdf.getNamedList().allocIfUndefined("class1"); + bdf.getNamedList().allocIfUndefined("class2"); + + TestClass t1 = new TestClass(); + BdfClassManager m1 = new BdfClassManager(t1); + m1.setBdf(bdf.getNamedList().get("class1")); + + TestClass t2 = new TestClass(); + BdfClassManager m2 = new BdfClassManager(t2); + m2.setBdf(bdf.getNamedList().get("class2")); + + m1.load(); + m2.load(); + + t1.tick(); + t2.tick(); + + m1.save(); + m2.save(); + + bdf.saveDatabase(); + + System.out.println(bdf.serializeHumanReadable()); + } + +}