From 704b440d5ac4ded3014b1a56ab7774965a29aa96 Mon Sep 17 00:00:00 2001 From: Milan Suman <> Date: Thu, 4 Aug 2022 00:01:12 +0530 Subject: [PATCH] lib/nbt: Add tag classes --- src/lib/nbt.cpp | 55 +++++++++++++++++++++++++++++++++++++--- src/lib/nbt.hpp | 26 +++++++++++++++++++ src/test/nbt_helpers.cpp | 11 ++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) diff --git a/src/lib/nbt.cpp b/src/lib/nbt.cpp index 427c109..7ef557b 100644 --- a/src/lib/nbt.cpp +++ b/src/lib/nbt.cpp @@ -149,9 +149,6 @@ namespace NBT { return ErrorOr>(result); } - // Maybe use a struct that holds decoded (de-Java-fied) string - // data, decoded size, and original size? Original size is needed - // so the parser knows where to continue. ErrorOr readString(uint8_t data[], uint64_t dataSize, uint64_t currentPosition) { if(dataSize > 0xFFFF){ return ErrorOr(true, ErrorCodes::OVERRUN); @@ -381,6 +378,58 @@ namespace NBT { } } + //Tag constructors + + template + Tag::Tag(uint8_t tagType, tiny_utf8::string name, uint16_t nameSize, T content, uint32_t size) + : tagType(tagType), name(name), nameSize(nameSize), content(content) ,size(size) + {} + + End::End() : Tag::Tag(0, "", 0, 0, 0) {} + + Byte::Byte(tiny_utf8::string name, uint16_t nameSize, int8_t content) + : Tag::Tag(1, name, nameSize, content, 1) + {} + + Byte::Byte(uint8_t data[]){ + if(validate(data)){ + this->tagType = 1; + + uint8_t nameSizeSlice[] = {data[1], data[2]}; + + ErrorOr readIntResult = helper::readInt16(nameSizeSlice, 2, 0); + if(!readIntResult.isError){ + this->nameSize = readIntResult.value; + }else{ + throw readIntResult.errorCode; + } + + uint8_t nameSlice[this->nameSize+2]; + for(int i=0; inameSize+2; i++){ + nameSlice[i] = data[i+1]; + } + + ErrorOr readStringResult = helper::readString(nameSlice, this->nameSize, 0); + if(!readStringResult.isError){ + this->name = readStringResult.value; + }else{ + throw readStringResult.errorCode; + } + + //int8 needs only one byte + this->content = data[this->nameSize+4]; + } + } + + //more conditions will be added + bool Byte::validate(uint8_t data[]){ + if(data[0] == 0x01){ + return true; + }else{ + return false; + } + } + bool validateRawNBTData(uint8_t data[], uint64_t dataSize){ //state machine? //TODO: implement diff --git a/src/lib/nbt.hpp b/src/lib/nbt.hpp index 6eca6db..3042b16 100644 --- a/src/lib/nbt.hpp +++ b/src/lib/nbt.hpp @@ -76,5 +76,31 @@ namespace NBT { void writeInt64Array(std::vector* destination, int64_t data[], uint32_t dataSize); } + //Generic parent class to make declaration easier + template + class Tag{ + public: + uint8_t tagType; + tiny_utf8::string name; + uint16_t nameSize; + T content; + int32_t size; + + Tag(){} + Tag(uint8_t tagType, tiny_utf8::string name, uint16_t nameSize, T content, uint32_t size); + }; + + class End: public Tag{ + public: + End(); + }; + + class Byte: public Tag{ + public: + Byte(tiny_utf8::string name, uint16_t nameSize, int8_t content); + Byte(uint8_t data[]); + bool validate(uint8_t data[]); + }; + bool validateRawNBTData(uint8_t data[], int length); } diff --git a/src/test/nbt_helpers.cpp b/src/test/nbt_helpers.cpp index 803bfd5..95a082d 100644 --- a/src/test/nbt_helpers.cpp +++ b/src/test/nbt_helpers.cpp @@ -523,5 +523,16 @@ int main(){ ASSERT(javaStdString1 == *exportedString); std::cout << "Passed writeString NBT helper test." << std::endl; + + //Byte tag constructor test + uint8_t bytetest[] = {0x01, 0x00, 0x02, 0x68, 0x69, 0x32}; + NBT::Byte byte = NBT::Byte(bytetest); + + ASSERT(byte.tagType == 1); + 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; }