- Overview
- Languages
- Data types
- Creating an object
- Arrays
- Named lists
- Human readable representation
- Special notes
Binary Data Format (BDF) is a statically typed data representation format. It was made to be free, fast, compact, and seamlessly convertable between its human readable and binary representations.
- C++
- Java
- Undefined
- Boolean
- Integer
- Long
- Short
- Byte
- Double
- Float
- Boolean Array
- Integer Array
- Long Array
- Short Array
- Byte Array
- Double Array
- Float Array
- String
- Array
- Named List
You will need to generate a BdfObject to serialize anything, this can be done by first generating a BdfReader, or generating a new object via an existing BdfObject.
// Create a reader object
BdfReader reader;
// Get the BdfObject instance
BdfObject* bdf = reader->getObject();
// Generate another BdfObject instance
BdfObject* bdf_new = bdf->newObject();
delete bdf_new;
// Get an integer
int v = bdf->getInteger();
// Set an integer
bdf->setInteger(5);
// Set an integer with an automatic type
bdf->setAutoInt(53);
// Set a primitive array of ints
int intArray[] = {3, 4, 5, 6};
bdf->setIntegerArray(intArray, 4);
// Get a byte array
char* byteArray;
int byteArraySize;
bdf->getByteArray(&byteArray, &byteArraySize);
delete[] byteArray;
// Get the type of variable of the object
int type = bdf->getType();
// Compare the type with a type from BdfTypes
if(type == BdfTypes::INTEGER)
{
}
// Serialize the BDF object
char* data;
int data_size;
bdf->serialize(&data, &data_size);
delete[] data;
// Load another reader object from the serialized bytes
BdfReader reader2(data, data_size);
/*
A reader object can be serialized to the human readable
representation as a string or sent over a stream
*/
reader2->serializeHumanReadable(std::cout, BdfIndent("\t", "\n"));
std::string data_hr = reader2->serializeHumanReadable(BdfIndent("\t", "\n"));
// A reader object can be loaded from a human readable object
BdfReaderHuman reader3(data_hr);
Arrays can be used to store chunks of information, they hold instances of BdfObject. Arrays can also be iterated over just like any other array.
BdfReader reader;
BdfObject* bdf = reader->getObject();
// Can be created from a bdf object
BdfArray* array = bdf->newArray();
// Get the length of an array
int size = array->size();
// Remove any index from an array
array->remove(3);
// Set an object to an index of an array
array->set(4, bdf->newObject()->setString("A String"));
// Add an object to an array
array->add(bdf->newObject()->setByte(53));
// Set the array to the bdf object
bdf->setArray(array);
Named lists can be used to store data under ids/strings to be used like variables in a program. A named list can be created similar to an array.
BdfReader reader;
BdfObject* bdf = reader->getObject();
// New named list
BdfNamedList* list = bdf->newNamedList();
// Set an element to the named list
list->set("key1", bdf->newObject()->setInteger(5));
// Use ids instead of strings for optimisation
// if set/get is being called multiple times
// on the same key.
int key2 = bdf->getKeyLocation("key2");
list->set(key2, bdf->newObject()->setFloat(42.0F));
// Get an elements value
int v = list->get("key1")->getInteger();
// Check if an element exists
bool has_key = list->contains("key1");
// Get the lists keys
std::vector<int> keys = list.getKeys();
// Iterate over the lists keys
for(int key : keys)
{
// Get the keys name
std::string key_name = bdf->getKeyName(key);
}
A big part of binary data format is the human readable representation. It has a JSON-like syntax. This can be used with config files and to modify/view binaries. A big advantage to using the human readable representation in configuration files is its support for comments.
/*
A Named List is represented
by an opening tag and a closing
tag { }
*/
{
/*
A key value pair can be stored
within a Named List with a string
property
*/
"hello": "world",
/*
Integers can be stored here too.
They have a character at the end
to say what type they are.
The tag at the end can be:
- I: Integer - a value between -2^31 and 2^31 - 1
- S: Short - a value between -32768 and 32767
- L: Long - a value between -2^63 and 2^63 - 1
- B: Byte - a value between -128 and 127
- D: Double - has 15 decimal digits of precision
- F: Float - has 7 decimal digits of precision
*/
"number": 42I,
"byte": -23B,
"decimal": 73.5D,
/*
This is a boolean. It can
be true or false.
*/
"boolTest": false,
/*
Primitive arrays are represented
by a type, an opening tag, and a
closing tag. They are like an array
but they contain only 1 data type.
The tag at the start can be:
- int
- short
- long
- byte
- double
- float
- bool
*/
"intArray": int (
64I, 42I, 63I,
22I, 96I, -12I,
),
/*
The double and float types support
Infinity, -Infinity, and NaN.
They also support both really
high and really low value numbers.
*/
"doubleArray": double (
42.5D, -20D, 400D,
NaND, -InfinityD, InfinityD,
5.3e-200F, 4e+500F, 2.2e200F,
)
/*
Arrays are enclosed by an opening
tag and a closing tag [ ]
Like the Named List, it can hold
any data type.
*/
"people": [
{"name": "foo", "age": 60B},
{"name": "bar", "age": 21B},
],
// This is a single-line comment
/* This is a multi-line comment */
}
Don't mix bdf types between different readers, this will cause problems.
BdfReader reader1;
BdfReader reader2;
BdfObject* bdf1 = reader1->getObject();
BdfObject* bdf2 = reader2->getObject();
// Don't do this
bdf1->setNamedList(bdf2->newNamedList());
// Or this
bdf1->setArray(bdf2->newArray());
// Or this
BdfNamedList* nl = bdf1->newArray();
nl.set("illegal", bdf2->newObject()->setString("action"));
Once a reader has been freed, or any object connected to it, every object connected to that object will also bee freed.
BdfReader reader;
BdfObject* bdf = reader->getObject();
BdfNamedList* nl = bdf->getNamedList();
BdfNamedList* nl2 = nl->get("namedList")->getNamedList();
// This will free nl, nl2, and the parent of nl2.
// This will also cause problems for bdf
// and it will result in undefined behaviour
// so don't do this.
delete nl;
// Do this instead to avoid undefined
// behaviour and nl will be freed.
bdf->setNamedList(bdf->newNamedList());