Compare commits

..

No commits in common. "c59a1ac7236a9d8cfde3cda4775ae7bfcbb42c3b" and "704b440d5ac4ded3014b1a56ab7774965a29aa96" have entirely different histories.

9 changed files with 83 additions and 64 deletions

View File

@ -48,6 +48,11 @@ universally used.
Use explicitly sized data types where possible. Use explicitly sized data types where possible.
For example, use `int32_t` instead of `int`. 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 ## Shell Script
Use the hash bang `#!/usr/bin/env bash`. Use the hash bang `#!/usr/bin/env bash`.

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` Usage example: `echo -ne "\x00" | java JavaStringGenerator > output_file`
## NBT_data ## servers.dat
Data used to test the NBT library. My current servers.dat as pulled from my Minecraft installation. Used for testing the NBT library until we have something better.
`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.) ## servers.dat_nbt_decoded.txt
`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 The same file manually decoded. I did this to get a better understanding how NBT works, might come in handy in the future.

View File

@ -71,8 +71,10 @@ namespace NBT {
)); ));
} }
//FIXME: endian-dependent implementations //FIXME: we just assume that float is a single-precision IEEE754
ErrorOr<float> readFloat(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { // floating point number, also we are using endian-dependent
// implementations
ErrorOr<float> readFloat32(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
float* value = new float; float* value = new float;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value); uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
if (dataSize<=currentPosition) return ErrorOr<float>(true, ErrorCodes::OUT_OF_RANGE); if (dataSize<=currentPosition) return ErrorOr<float>(true, ErrorCodes::OUT_OF_RANGE);
@ -89,7 +91,7 @@ namespace NBT {
*(valueAsBytes+2) = data[currentPosition+1]; *(valueAsBytes+2) = data[currentPosition+1];
*(valueAsBytes+3) = data[currentPosition]; *(valueAsBytes+3) = data[currentPosition];
#else #else
#error "NBT::helper::readFloat: An implementation for your endianness is unavailable." #error "NBT::helper::readFloat32: An implementation for your endianness is unavailable."
#endif #endif
#endif #endif
float dereferencedValue = *value; float dereferencedValue = *value;
@ -97,8 +99,10 @@ namespace NBT {
return ErrorOr<float>(dereferencedValue); return ErrorOr<float>(dereferencedValue);
} }
//FIXME: endian-dependent implementations //FIXME: we just assume that double is a double-precision IEEE754
ErrorOr<double> readDouble(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { // floating point number, also we are using endian-dependent
// implementations
ErrorOr<double> readFloat64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) {
double* value = new double; double* value = new double;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value); uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
if (dataSize<=currentPosition) return ErrorOr<double>(true, ErrorCodes::OUT_OF_RANGE); if (dataSize<=currentPosition) return ErrorOr<double>(true, ErrorCodes::OUT_OF_RANGE);
@ -123,7 +127,7 @@ namespace NBT {
*(valueAsBytes+6) = data[currentPosition+1]; *(valueAsBytes+6) = data[currentPosition+1];
*(valueAsBytes+7) = data[currentPosition]; *(valueAsBytes+7) = data[currentPosition];
#else #else
#error "NBT::helper::readDouble: An implementation for your endianness is unavailable." #error "NBT::helper::readFloat64: An implementation for your endianness is unavailable."
#endif #endif
#endif #endif
double dereferencedValue = *value; double dereferencedValue = *value;
@ -266,8 +270,9 @@ namespace NBT {
delete value; delete value;
} }
//FIXME: endian-specific implementations //FIXME: we just assume that float is a single-precision IEEE754
void writeFloat(std::vector<uint8_t>* destination, float data) { // floating point number, also endian specific implementation
void writeFloat32(std::vector<uint8_t>* destination, float data) {
float* value = new float; float* value = new float;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value); uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
*value = data; *value = data;
@ -289,8 +294,9 @@ namespace NBT {
delete value; delete value;
} }
//FIXME: endian-specific implementations //FIXME: we just assume that double is a single-precision IEEE754
void writeDouble(std::vector<uint8_t>* destination, double data) { // floating point number, also endian specific implementation
void writeFloat64(std::vector<uint8_t>* destination, double data) {
double* value = new double; double* value = new double;
uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value); uint8_t* valueAsBytes = reinterpret_cast<uint8_t*>(value);
*value = data; *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 // 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 // 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 // int64: Tag( 4, String:name, uint16:name_size, int64:content, 8) => 64 bit signed integer, size not stored
// float: Tag( 5, String:name, uint16:name_size, float:content, 4) => 32 bit IEEE754 floating point number, size not stored // float32: Tag( 5, String:name, uint16:name_size, float32: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 // float64: Tag( 6, String:name, uint16:name_size, float64: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 // 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 // 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 // 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,8 +46,12 @@ namespace NBT {
ErrorOr<int16_t> readInt16(uint8_t data[], uint64_t dataSize, uint64_t currentPosition); 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<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); ErrorOr<int64_t> readInt64(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
ErrorOr<float> readFloat(uint8_t data[], uint64_t dataSize, uint64_t currentPosition); //FIXME: we just assume that float is a single-precision IEEE754
ErrorOr<double> readDouble(uint8_t data[], uint64_t dataSize, uint64_t currentPosition); // 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<std::vector<int8_t>> readInt8Array(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<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); ErrorOr<std::vector<int32_t>> readInt32Array(uint8_t data[], uint64_t dataSize, uint64_t currentPosition);
@ -57,8 +61,12 @@ namespace NBT {
void writeInt16(std::vector<uint8_t>* destination, int16_t data); void writeInt16(std::vector<uint8_t>* destination, int16_t data);
void writeInt32(std::vector<uint8_t>* destination, int32_t data); void writeInt32(std::vector<uint8_t>* destination, int32_t data);
void writeInt64(std::vector<uint8_t>* destination, int64_t data); void writeInt64(std::vector<uint8_t>* destination, int64_t data);
void writeFloat(std::vector<uint8_t>* destination, float data); //FIXME: we just assume that float is a single-precision IEEE754
void writeDouble(std::vector<uint8_t>* destination, double data); // 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 writeInt8Array(std::vector<uint8_t>* destination, std::vector<int8_t> 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 writeInt8Array(std::vector<uint8_t>* destination, int8_t data[], uint32_t dataSize);
void writeString(std::vector<uint8_t>* destination, tiny_utf8::string data); void writeString(std::vector<uint8_t>* destination, tiny_utf8::string data);

View File

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