Compare commits

...

3 Commits

Author SHA1 Message Date
BodgeMaster c59a1ac723 Resources: Add two NBT files that can be used for testing. 2022-08-05 09:12:27 +02:00
BodgeMaster aef91fe7cd test/nbt_helpers: Fix wrong test pass message 2022-08-04 07:50:20 +02:00
BodgeMaster 4af9003761 Code style: I just decided to accept that float and double exist and that we can just assume they are 32 and 64 bits repectively.
This isn't going to run on an Arduino or anything like that anyway.
2022-08-04 07:47:24 +02:00
9 changed files with 64 additions and 83 deletions

View File

@ -48,11 +48,6 @@ universally used.
Use explicitly sized data types where possible.
For example, use `int32_t` instead of `int`.
When coming up with names, refer to data types by category and size.
For example, refer to double precision floating point numbers as `float64`
instead of `double`.
## Shell Script
Use the hash bang `#!/usr/bin/env bash`.

Binary file not shown.

Binary file not shown.

View File

@ -23,11 +23,11 @@ A simple tool written in Java that takes an input as UTF-8 and outputs it in Jav
Usage example: `echo -ne "\x00" | java JavaStringGenerator > output_file`
## servers.dat
## NBT_data
My current servers.dat as pulled from my Minecraft installation. Used for testing the NBT library until we have something better.
Data used to test the NBT library.
## servers.dat_nbt_decoded.txt
The same file manually decoded. I did this to get a better understanding how NBT works, might come in handy in the future.
`servers.dat`: My current servers.dat as pulled from my Minecraft installation
`servers.dat_nbt_decoded.txt`: The same file manually decoded (I did this to get a better understanding how NBT works, might come in handy in the future.)
`simple_nbt`: A simple NBT file containing all tags
`nested_compounds_and_lists`: A combination of nested compound and list tags intended to be challenging to parse

View File

@ -71,10 +71,8 @@ namespace NBT {
));
}
//FIXME: we just assume that float is a single-precision IEEE754
// floating point number, also we are using endian-dependent
// implementations
ErrorOr<float> readFloat32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
//FIXME: endian-dependent implementations
ErrorOr<float> readFloat(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
float* value = new float;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
if (dataSize<=currentPosition) return ErrorOr<float>(true, ErrorCodes::OUT_OF_RANGE);
@ -91,7 +89,7 @@ namespace NBT {
*(valueAsBytes+2) = data[currentPosition+1];
*(valueAsBytes+3) = data[currentPosition];
#else
#error "NBT::helper::readFloat32: An implementation for your endianness is unavailable."
#error "NBT::helper::readFloat: An implementation for your endianness is unavailable."
#endif
#endif
float dereferencedValue = *value;
@ -99,10 +97,8 @@ namespace NBT {
return ErrorOr<float>(dereferencedValue);
}
//FIXME: we just assume that double is a double-precision IEEE754
// floating point number, also we are using endian-dependent
// implementations
ErrorOr<double> readFloat64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
//FIXME: endian-dependent implementations
ErrorOr<double> readDouble(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
double* value = new double;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
if (dataSize<=currentPosition) return ErrorOr<double>(true, ErrorCodes::OUT_OF_RANGE);
@ -127,7 +123,7 @@ namespace NBT {
*(valueAsBytes+6) = data[currentPosition+1];
*(valueAsBytes+7) = data[currentPosition];
#else
#error "NBT::helper::readFloat64: An implementation for your endianness is unavailable."
#error "NBT::helper::readDouble: An implementation for your endianness is unavailable."
#endif
#endif
double dereferencedValue = *value;
@ -270,9 +266,8 @@ namespace NBT {
delete value;
}
//FIXME: we just assume that float is a single-precision IEEE754
// floating point number, also endian specific implementation
void writeFloat32(std::vector<uint8_t>* destination, float data) {
//FIXME: endian-specific implementations
void writeFloat(std::vector<uint8_t>* destination, float data) {
float* value = new float;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
*value = data;
@ -294,9 +289,8 @@ namespace NBT {
delete value;
}
//FIXME: we just assume that double is a single-precision IEEE754
// floating point number, also endian specific implementation
void writeFloat64(std::vector<uint8_t>* destination, double data) {
//FIXME: endian-specific implementations
void writeDouble(std::vector<uint8_t>* destination, double data) {
double* value = new double;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
*value = data;

View File

@ -25,8 +25,8 @@
// int16: Tag( 2, String:name, uint16:name_size, int16:content, 2) => 16 bit signed integer, size not stored
// int32: Tag( 3, String:name, uint16:name_size, int32:content, 4) => 32 bit signed integer, size not stored
// int64: Tag( 4, String:name, uint16:name_size, int64:content, 8) => 64 bit signed integer, size not stored
// float32: Tag( 5, String:name, uint16:name_size, float32:content,4) => 32 bit IEEE754 floating point number, size not stored
// float64: Tag( 6, String:name, uint16:name_size, float64:content,8) => 64 bit IEEE754 floating point number, size not stored
// float: Tag( 5, String:name, uint16:name_size, float:content, 4) => 32 bit IEEE754 floating point number, size not stored
// double: Tag( 6, String:name, uint16:name_size, double:content, 8) => 64 bit IEEE754 floating point number, size not stored
// int8[]: Tag( 7, String:name, uint16:name_size, int8[]:content, int32:size) => content stored prefixed with size
// String: Tag( 8, String:name, uint16:name_size, String:content, uint16:size) => Java style modified UTF-8 string, content stored prefixed with size
// Tag[] (list): Tag<Tag:type>( 9, String:name, uint16:name_size, Tag[]:content, int32:size) => list of tags of the same type with tag type and name information omitted prefixed by (in order) content type and size
@ -46,12 +46,8 @@ namespace NBT {
ErrorOr<int16_t> readInt16(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<int32_t> readInt32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<int64_t> readInt64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
//FIXME: we just assume that float is a single-precision IEEE754
// floating point number
ErrorOr<float> readFloat32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
//FIXME: we just assume that double is a double-precision IEEE754
// floating point number
ErrorOr<double> readFloat64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<float> readFloat(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<double> readDouble(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<std::vector<int8_t>> readInt8Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<tiny_utf8::string> readString(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<std::vector<int32_t>> readInt32Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
@ -61,12 +57,8 @@ namespace NBT {
void writeInt16(std::vector<uint8_t>* destination, int16_t data);
void writeInt32(std::vector<uint8_t>* destination, int32_t data);
void writeInt64(std::vector<uint8_t>* destination, int64_t data);
//FIXME: we just assume that float is a single-precision IEEE754
// floating point number
void writeFloat32(std::vector<uint8_t>* destination, float data);
//FIXME: we just assume that double is a single-precision IEEE754
// floating point number
void writeFloat64(std::vector<uint8_t>* destination, double data);
void writeFloat(std::vector<uint8_t>* destination, float data);
void writeDouble(std::vector<uint8_t>* destination, double data);
void writeInt8Array(std::vector<uint8_t>* destination, std::vector<int8_t> data);
void writeInt8Array(std::vector<uint8_t>* destination, int8_t data[], uint32_t dataSize);
void writeString(std::vector<uint8_t>* destination, tiny_utf8::string data);

View File

@ -376,73 +376,73 @@ int main(){
);
delete int64ArrayTestOutput;
std::cout << "Passed writeInt32Array NBT helper test" << std::endl;
std::cout << "Passed writeInt64Array NBT helper test" << std::endl;
// float32 ["float" in the current implementation :( ] #############
uint8_t dataForFloat32Test[] = {0xC7, 0x77, 0x77, 0x77};
// float ###########################################################
uint8_t dataForFloatTest[] = {0xC7, 0x77, 0x77, 0x77};
dataSize = 4;
currentPosition = 0;
// read successfully
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).value == -63351.46484375f);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).isError == false);
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).value == -63351.46484375f);
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == false);
// read overrun
currentPosition = 1;
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read out of bounds
currentPosition = 4;
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat32(dataForFloat32Test, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat(dataForFloatTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readFloat32 NBT helper test" << std::endl;
std::cout << "Passed readFloat NBT helper test" << std::endl;
std::vector<uint8_t>* writeFloat32TestResult = new std::vector<uint8_t>();
NBT::helper::writeFloat32(writeFloat32TestResult, (float) -63351.46484375f);
std::vector<uint8_t> dereferencedWriteFloat32TestResult = *writeFloat32TestResult;
delete writeFloat32TestResult;
std::vector<uint8_t>* writeFloatTestResult = new std::vector<uint8_t>();
NBT::helper::writeFloat(writeFloatTestResult, (float) -63351.46484375f);
std::vector<uint8_t> dereferencedWriteFloatTestResult = *writeFloatTestResult;
delete writeFloatTestResult;
ASSERT(
dereferencedWriteFloat32TestResult[0] == (uint8_t) 0xC7 &&
dereferencedWriteFloat32TestResult[1] == (uint8_t) 0x77 &&
dereferencedWriteFloat32TestResult[2] == (uint8_t) 0x77 &&
dereferencedWriteFloat32TestResult[3] == (uint8_t) 0x77
dereferencedWriteFloatTestResult[0] == (uint8_t) 0xC7 &&
dereferencedWriteFloatTestResult[1] == (uint8_t) 0x77 &&
dereferencedWriteFloatTestResult[2] == (uint8_t) 0x77 &&
dereferencedWriteFloatTestResult[3] == (uint8_t) 0x77
);
std::cout << "Passed writeFloat32 NBT helper test" << std::endl;
std::cout << "Passed writeFloat NBT helper test" << std::endl;
// float64 ["double" in the current implementation :( ] ############
uint8_t dataForFloat64Test[] = {0xC0, 0x34, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00};
// double ##########################################################
uint8_t dataForDoubleTest[] = {0xC0, 0x34, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00};
dataSize = 8;
currentPosition = 0;
// read successfully
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).value == -20.015625476837158203125);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).isError == false);
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).value == -20.015625476837158203125);
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == false);
// read overrun
currentPosition = 1;
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).errorCode == ErrorCodes::OVERRUN);
// read out of bounds
currentPosition = 8;
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readFloat64(dataForFloat64Test, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).isError == true);
ASSERT(NBT::helper::readDouble(dataForDoubleTest, dataSize, currentPosition).errorCode == ErrorCodes::OUT_OF_RANGE);
std::cout << "Passed readFloat64 NBT helper test" << std::endl;
std::cout << "Passed readDouble NBT helper test" << std::endl;
std::vector<uint8_t>* writeFloat64TestResult = new std::vector<uint8_t>();
NBT::helper::writeFloat64(writeFloat64TestResult, (double) -20.015625476837158203125);
std::vector<uint8_t> dereferencedWriteFloat64TestResult = *writeFloat64TestResult;
delete writeFloat64TestResult;
std::vector<uint8_t>* writeDoubleTestResult = new std::vector<uint8_t>();
NBT::helper::writeDouble(writeDoubleTestResult, (double) -20.015625476837158203125);
std::vector<uint8_t> dereferencedWriteDoubleTestResult = *writeDoubleTestResult;
delete writeDoubleTestResult;
ASSERT(
dereferencedWriteFloat64TestResult[0] == (uint8_t) 0xC0 &&
dereferencedWriteFloat64TestResult[1] == (uint8_t) 0x34 &&
dereferencedWriteFloat64TestResult[2] == (uint8_t) 0x04 &&
dereferencedWriteFloat64TestResult[3] == (uint8_t) 0x00 &&
dereferencedWriteFloat64TestResult[4] == (uint8_t) 0x08 &&
dereferencedWriteFloat64TestResult[5] == (uint8_t) 0x00 &&
dereferencedWriteFloat64TestResult[6] == (uint8_t) 0x00 &&
dereferencedWriteFloat64TestResult[7] == (uint8_t) 0x00
dereferencedWriteDoubleTestResult[0] == (uint8_t) 0xC0 &&
dereferencedWriteDoubleTestResult[1] == (uint8_t) 0x34 &&
dereferencedWriteDoubleTestResult[2] == (uint8_t) 0x04 &&
dereferencedWriteDoubleTestResult[3] == (uint8_t) 0x00 &&
dereferencedWriteDoubleTestResult[4] == (uint8_t) 0x08 &&
dereferencedWriteDoubleTestResult[5] == (uint8_t) 0x00 &&
dereferencedWriteDoubleTestResult[6] == (uint8_t) 0x00 &&
dereferencedWriteDoubleTestResult[7] == (uint8_t) 0x00
);
std::cout << "Passed writeInt64 NBT helper test" << std::endl;
std::cout << "Passed writeDouble NBT helper test" << std::endl;
//readString test
char* nextChar = new char;
@ -532,7 +532,7 @@ int main(){
ASSERT(byte.nameSize == 2);
ASSERT(byte.content = 0x32);
ASSERT(byte.name == tiny_utf8::string("hi"));
std::cout << "Passed Byte Tag constructor test." << std::endl;
return 0;
}