diff --git a/src/lib/nbt.cpp b/src/lib/nbt.cpp index f60a3ca..76aecbf 100644 --- a/src/lib/nbt.cpp +++ b/src/lib/nbt.cpp @@ -976,6 +976,20 @@ namespace NBT { this->endPointer = new End(); } + ErrorOr Compound::constructWithData(tiny_utf8::string name, std::vector data) { + if (data.size() > 0) { + for (uint64_t i=0; igetTagType() == TagType::END && i != data.size()-1) { + return ErrorOr(true, ErrorCodes::NOT_ALLOWED, nullptr); + } + } + if (data[data.size()-1]->getTagType() == TagType::END) { + return ErrorOr(new Compound(name, std::vector(data.begin(), data.end()-1))); + } + } + return ErrorOr(new Compound(name, data)); + } + Compound::~Compound() { for (uint64_t i=0; itags.size(); i++) { delete this->tags.at(i); @@ -1342,7 +1356,7 @@ namespace NBT { returnValue = ErrorOr>(true, nextCompoundData.errorCode); goto returnError; } - contents.push_back(new Tag::Compound("", nextCompoundData.value)); + contents.push_back(reinterpret_cast(Tag::Compound::constructWithData("", nextCompoundData.value).value)); *processedDataSize += *containedDataSize; } delete containedDataSize; @@ -1454,7 +1468,7 @@ namespace NBT { returnValue = ErrorOr>(true, compoundData.errorCode); goto returnNow; } - tags.push_back(new Tag::Compound(tagName.value, compoundData.value)); + tags.push_back(reinterpret_cast(Tag::Compound::constructWithData(tagName.value, compoundData.value).value)); *processedTagSize += (uint64_t) nameSize + 3; } currentPosition += *processedTagSize; diff --git a/src/lib/nbt.hpp b/src/lib/nbt.hpp index c0940e0..5a4e3a8 100644 --- a/src/lib/nbt.hpp +++ b/src/lib/nbt.hpp @@ -248,10 +248,10 @@ namespace NBT { std::vector tags; // built-in end tag End* endPointer; + Compound(tiny_utf8::string name, std::vector data); public: Compound(); Compound(tiny_utf8::string name); - Compound(tiny_utf8::string name, std::vector data); ~Compound() override; @@ -262,6 +262,7 @@ namespace NBT { ErrorOrVoid appendPointer(Generic* pointer); ErrorOrVoid deleteElement(uint64_t position); uint64_t length(); + static ErrorOr constructWithData(tiny_utf8::string name, std::vector data); }; class Int32Array: public Generic { diff --git a/src/test/nbt_tags.cpp b/src/test/nbt_tags.cpp index 1682c46..79e135c 100644 --- a/src/test/nbt_tags.cpp +++ b/src/test/nbt_tags.cpp @@ -890,7 +890,11 @@ int main(){ NBT::Tag::Compound compound_0 = NBT::Tag::Compound(); compound_0.name = "compound_0"; NBT::Tag::Compound compound_1 = NBT::Tag::Compound("compound_1"); - NBT::Tag::Compound compound_2 = NBT::Tag::Compound("compound_2", compoundDataVector); + //TODO: Check that constructing with a vector containing an end tag that + // isn’t at the end results in a clearly defined failure mode (issue #60) + ErrorOr compound_2_or_error = NBT::Tag::Compound::constructWithData("compound_2", compoundDataVector); + ASSERT(!compound_2_or_error.isError); + NBT::Tag::Compound* compound_2 = compound_2_or_error.value; ASSERT(!compound_1.appendPointer(new NBT::Tag::Int32("0", 69420)).isError); ASSERT(!compound_1.appendPointer(new NBT::Tag::Int8("1", 1)).isError); @@ -906,15 +910,15 @@ int main(){ resultNotAllowed = compound_1.setElementPointerAt(0, new NBT::Tag::End()); ASSERT(resultNotAllowed.isError && resultNotAllowed.errorCode==ErrorCodes::NOT_ALLOWED); ASSERT(compound_0.setElementPointerAt(1, new NBT::Tag::Int8()).isError && compound_0.setElementPointerAt(1, new NBT::Tag::Int8()).errorCode == ErrorCodes::OUT_OF_RANGE); - ASSERT(!compound_2.deleteElement(1).isError); + ASSERT(!compound_2->deleteElement(1).isError); ASSERT(compound_0.deleteElement(0).isError && compound_0.deleteElement(0).errorCode == ErrorCodes::NOT_ALLOWED); ASSERT(compound_0.deleteElement(1).isError && compound_0.deleteElement(1).errorCode == ErrorCodes::OUT_OF_RANGE); ASSERT(compound_0.length() == 1); ASSERT(compound_1.length() == 3); - ASSERT(compound_2.length() == 4); + ASSERT(compound_2->length() == 4); compound_0.serialize(&vector); compound_1.serialize(&vector); - compound_2.serialize(&vector); + compound_2->serialize(&vector); ASSERT(vector.size() == 95); ASSERT( vector.at( 0) == 10 && @@ -1016,7 +1020,7 @@ int main(){ vector.clear(); compound_0.serializeWithoutHeader(&vector); compound_1.serializeWithoutHeader(&vector); - compound_2.serializeWithoutHeader(&vector); + compound_2->serializeWithoutHeader(&vector); ASSERT(vector.size() == 56); ASSERT( vector.at( 0) == 0 &&