complete merge

Soda
Shwoomple 2022-09-28 08:22:09 +05:30
commit c1d7801436
6 changed files with 519 additions and 62 deletions

View File

@ -36,7 +36,6 @@ COMPILE_COMMANDS=(
"$CXX_WITH_FLAGS src/test/nbt_read_write_helpers.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_read_write_helpers" "$CXX_WITH_FLAGS src/test/nbt_read_write_helpers.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_read_write_helpers"
"$CXX_WITH_FLAGS src/test/cli_argument_parser.cpp -Lbin/lib -l:cli.so -o bin/test/cli_argument_parser" "$CXX_WITH_FLAGS src/test/cli_argument_parser.cpp -Lbin/lib -l:cli.so -o bin/test/cli_argument_parser"
"$CXX_WITH_FLAGS src/test/javacompat.cpp -I./include -Lbin/lib -l:javacompat.so -o bin/test/javacompat" "$CXX_WITH_FLAGS src/test/javacompat.cpp -I./include -Lbin/lib -l:javacompat.so -o bin/test/javacompat"
"$CXX_WITH_FLAGS src/test/nbt_write_string_failure_mode.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_write_string_failure_mode"
"$CXX_WITH_FLAGS src/test/nbt_tags.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_tags" "$CXX_WITH_FLAGS src/test/nbt_tags.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_tags"
"$CXX_WITH_FLAGS src/test/nbt_size_helpers.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_size_helpers" "$CXX_WITH_FLAGS src/test/nbt_size_helpers.cpp -I./include -Lbin/lib -l:nbt.so -l:javacompat.so -o bin/test/nbt_size_helpers"
"$CXX_WITH_FLAGS src/test/file.cpp -I./include -Lbin/lib -l:file.so -o bin/test/file" "$CXX_WITH_FLAGS src/test/file.cpp -I./include -Lbin/lib -l:file.so -o bin/test/file"

View File

@ -17,7 +17,6 @@
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <tinyutf8/tinyutf8.h> #include <tinyutf8/tinyutf8.h>
#include <iostream>
#include "nbt.hpp" #include "nbt.hpp"
#include "error.hpp" #include "error.hpp"
@ -360,13 +359,13 @@ namespace NBT {
} }
} }
void writeString(std::vector<uint8_t>* destination, tiny_utf8::string data) { ErrorOrVoid writeString(std::vector<uint8_t>* destination, tiny_utf8::string data) {
ErrorOr<std::vector<uint8_t>> exportedString = JavaCompat::exportJavaString(data); ErrorOr<std::vector<uint8_t>> exportedString = JavaCompat::exportJavaString(data);
if(exportedString.isError){ if(exportedString.isError){
std::cerr << "NBT::Helpers::writeString encountered an error: " << (int) exportedString.errorCode << std::endl; return ErrorOrVoid(true, ErrorCodes::OVERRUN);
std::abort();
} }
*destination = exportedString.value; *destination = exportedString.value;
return ErrorOrVoid();
} }
void writeInt32Array(std::vector<uint8_t>* destination, std::vector<int32_t> data) { void writeInt32Array(std::vector<uint8_t>* destination, std::vector<int32_t> data) {
@ -543,15 +542,307 @@ namespace NBT {
} }
} }
// generic class that all tag types are derived from namespace Tag {
template <typename T>
Tag<T>::Tag() {
Generic::Generic() {
this->type = TagType::INVALID;
} }
template <typename T> Generic::~Generic() {}
ErrorOr<std::vector<uint8_t>> Tag<T>::toRawData() {
return ErrorOr<std::vector<uint8_t>>(true, ErrorCodes::INVALID_TYPE); ErrorOrVoid Generic::toRawData([[maybe_unused]] std::vector<uint8_t>* rawData) {
return ErrorOrVoid(true, ErrorCodes::INVALID_TYPE);
}
uint8_t Generic::getTagType(){
return this->type;
}
End::End() {
this->type = TagType::END;
}
ErrorOrVoid End::toRawData(std::vector<uint8_t>* rawData) {
rawData->push_back(this->type);
return ErrorOrVoid();
}
Int8::Int8() {
this->type = TagType::INT8;
}
Int8::Int8(tiny_utf8::string name, int8_t value) {
this->type = TagType::INT8;
this->name = name;
this->value = value;
}
ErrorOrVoid Int8::toRawData(std::vector<uint8_t>* rawData) {
rawData->push_back(this->type);
if (Helper::writeString(rawData, this->name).isError) {
return ErrorOrVoid(true, ErrorCodes::OVERRUN);
}
Helper::writeInt8(rawData, this->value);
return ErrorOrVoid();
}
int8_t Int8::getValue() {
this->mutex.lock();
int8_t value = this->value;
this->mutex.unlock();
return value;
}
void Int8::setValue(int8_t value) {
this->mutex.lock();
this->value = value;
this->mutex.unlock();
}
Int16::Int16() {
this->type = TagType::INT16;
}
Int16::Int16(tiny_utf8::string name, int16_t value) {
this->type = TagType::INT16;
this->name = name;
this->value = value;
}
ErrorOrVoid Int16::toRawData(std::vector<uint8_t>* rawData) {
rawData->push_back(this->type);
if (Helper::writeString(rawData, this->name).isError) {
return ErrorOrVoid(true, ErrorCodes::OVERRUN);
}
Helper::writeInt16(rawData, this->value);
return ErrorOrVoid();
}
int16_t Int16::getValue() {
this->mutex.lock();
int16_t value = this->value;
this->mutex.unlock();
return value;
}
void Int16::setValue(int16_t value) {
this->mutex.lock();
this->value = value;
this->mutex.unlock();
}
Int32::Int32() {
this->type = TagType::INT32;
}
Int32::Int32(tiny_utf8::string name, int32_t value) {
this->type = TagType::INT32;
this->name = name;
this->value = value;
}
ErrorOrVoid Int32::toRawData(std::vector<uint8_t>* rawData) {
rawData->push_back(this->type);
if (Helper::writeString(rawData, this->name).isError) {
return ErrorOrVoid(true, ErrorCodes::OVERRUN);
}
Helper::writeInt32(rawData, this->value);
return ErrorOrVoid();
}
int32_t Int32::getValue() {
this->mutex.lock();
int32_t value = this->value;
this->mutex.unlock();
return value;
}
void Int32::setValue(int32_t value) {
this->mutex.lock();
this->value = value;
this->mutex.unlock();
}
Int64::Int64() {
this->type = TagType::INT64;
}
Int64::Int64(tiny_utf8::string name, int64_t value) {
this->type = TagType::INT64;
this->name = name;
this->value = value;
}
ErrorOrVoid Int64::toRawData(std::vector<uint8_t>* rawData) {
rawData->push_back(this->type);
if (Helper::writeString(rawData, this->name).isError) {
return ErrorOrVoid(true, ErrorCodes::OVERRUN);
}
Helper::writeInt64(rawData, this->value);
return ErrorOrVoid();
}
int64_t Int64::getValue() {
this->mutex.lock();
int64_t value = this->value;
this->mutex.unlock();
return value;
}
void Int64::setValue(int64_t value) {
this->mutex.lock();
this->value = value;
this->mutex.unlock();
}
Float::Float() {
this->type = TagType::FLOAT;
}
Float::Float(tiny_utf8::string name, float value) {
this->type = TagType::FLOAT;
this->name = name;
this->value = value;
}
ErrorOrVoid Float::toRawData(std::vector<uint8_t>* rawData) {
rawData->push_back(this->type);
if (Helper::writeString(rawData, this->name).isError) {
return ErrorOrVoid(true, ErrorCodes::OVERRUN);
}
Helper::writeFloat(rawData, this->value);
return ErrorOrVoid();
}
float Float::getValue() {
this->mutex.lock();
float value = this->value;
this->mutex.unlock();
return value;
}
void Float::setValue(float value) {
this->mutex.lock();
this->value = value;
this->mutex.unlock();
}
Double::Double() {
this->type = TagType::DOUBLE;
}
Double::Double(tiny_utf8::string name, double value) {
this->type = TagType::DOUBLE;
this->name = name;
this->value = value;
}
ErrorOrVoid Double::toRawData(std::vector<uint8_t>* rawData) {
rawData->push_back(this->type);
if (Helper::writeString(rawData, this->name).isError) {
return ErrorOrVoid(true, ErrorCodes::OVERRUN);
}
Helper::writeDouble(rawData, this->value);
return ErrorOrVoid();
}
double Double::getValue() {
this->mutex.lock();
double value = this->value;
this->mutex.unlock();
return value;
}
void Double::setValue(double value) {
this->mutex.lock();
this->value = value;
this->mutex.unlock();
}
Int8Array::Int8Array() {
this->type = TagType::INT8_ARRAY;
}
Int8Array::Int8Array(tiny_utf8::string name, std::vector<int8_t> data) {
this->type = TagType::INT8_ARRAY;
this->name = name;
this->data = data;
}
Int8Array::Int8Array(tiny_utf8::string name, uint64_t length, int8_t data[]){
this->type = TagType::INT8_ARRAY;
this->name = name;
this->data = std::vector<int8_t>(data, data+length);
}
ErrorOrVoid Int8Array::toRawData(std::vector<uint8_t>* rawData) {
rawData->push_back(this->type);
if (Helper::writeString(rawData, this->name).isError) {
return ErrorOrVoid(true, ErrorCodes::OVERRUN);
}
Helper::writeInt8Array(rawData, this->data);
return ErrorOrVoid();
}
std::vector<int8_t> Int8Array::getData() {
return this->data;
}
ErrorOr<int8_t> Int8Array::getValue(uint64_t position) {
if (this->data.size() <= position) {
return ErrorOr<int8_t>(this->data.at(position));
}
return ErrorOr<int8_t>(true, ErrorCodes::OUT_OF_RANGE);
}
void Int8Array::setData(std::vector<int8_t> newData) {
this->data = newData;
}
ErrorOrVoid Int8Array::setValue(uint64_t position, int8_t value) {
if (this->data.size() <= position) {
return ErrorOrVoid(true, ErrorCodes::OUT_OF_RANGE);
}
this->data[position] = value;
return ErrorOrVoid();
}
uint64_t Int8Array::length() {
return this->data.size();
}
void Int8Array::addElement(int8_t element) {
this->data.push_back(element);
}
ErrorOrVoid Int8Array::removeElement(uint64_t position) {
//TODO: implement
//this->data.erase(position);
}
} }
bool validateRawListContents(uint8_t data[], uint64_t dataSize, uint64_t initialPosition, uint64_t* processedDataSize) { bool validateRawListContents(uint8_t data[], uint64_t dataSize, uint64_t initialPosition, uint64_t* processedDataSize) {

View File

@ -38,6 +38,8 @@
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include <tinyutf8/tinyutf8.h> #include <tinyutf8/tinyutf8.h>
#include <mutex>
#include "error.hpp" #include "error.hpp"
namespace NBT { namespace NBT {
@ -61,7 +63,7 @@ namespace NBT {
void writeDouble(std::vector<uint8_t>* destination, double 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, 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); ErrorOrVoid writeString(std::vector<uint8_t>* destination, tiny_utf8::string data);
void writeInt32Array(std::vector<uint8_t>* destination, std::vector<int32_t> data); void writeInt32Array(std::vector<uint8_t>* destination, std::vector<int32_t> data);
void writeInt32Array(std::vector<uint8_t>* destination, int32_t data[], uint32_t dataSize); void writeInt32Array(std::vector<uint8_t>* destination, int32_t data[], uint32_t dataSize);
void writeInt64Array(std::vector<uint8_t>* destination, std::vector<int64_t> data); void writeInt64Array(std::vector<uint8_t>* destination, std::vector<int64_t> data);
@ -87,20 +89,211 @@ namespace NBT {
const uint8_t INT64_ARRAY= 12; const uint8_t INT64_ARRAY= 12;
// This is a workaround that's not part of the spec. // This is a workaround that's not part of the spec.
const uint8_t INVALID = 255; const uint8_t INVALID = 255;
// This class is used as a placeholder for implementing the end tag.
class End {};
} }
// generic class that all tag types are derived from namespace Tag {
template <typename T>
struct Tag {
const uint8_t type = TagType::INVALID;
T* containedData;
Tag(); class Generic {
ErrorOr<std::vector<uint8_t>> toRawData(); protected:
std::mutex mutex;
uint8_t type;
public:
tiny_utf8::string name;
Generic();
virtual ~Generic();
virtual ErrorOrVoid toRawData(std::vector<uint8_t>* rawData);
uint8_t getTagType();
}; };
class End: public Generic {
public:
End();
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
};
class Int8: public Generic {
private:
int8_t value;
public:
Int8();
Int8(tiny_utf8::string name, int8_t value);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
int8_t getValue();
void setValue(int8_t value);
};
class Int16: public Generic {
private:
int16_t value;
public:
Int16();
Int16(tiny_utf8::string name, int16_t value);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
int16_t getValue();
void setValue(int16_t value);
};
class Int32: public Generic {
private:
int32_t value;
public:
Int32();
Int32(tiny_utf8::string name, int32_t value);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
int32_t getValue();
void setValue(int32_t value);
};
class Int64: public Generic {
private:
int64_t value;
public:
Int64();
Int64(tiny_utf8::string name, int64_t value);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
int64_t getValue();
void setValue(int64_t value);
};
class Float: public Generic {
private:
float value;
public:
Float();
Float(tiny_utf8::string name, float value);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
float getValue();
void setValue(float value);
};
class Double: public Generic {
private:
double value;
public:
Double();
Double(tiny_utf8::string name, double value);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
double getValue();
void setValue(double value);
};
class Int8Array: public Generic {
private:
std::vector<int8_t> data;
public:
Int8Array();
Int8Array(tiny_utf8::string name, std::vector<int8_t> data);
Int8Array(tiny_utf8::string name, uint64_t length, int8_t data[]);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
std::vector<int8_t> getData();
ErrorOr<int8_t> getValue(uint64_t position);
void setData(std::vector<int8_t> newData);
ErrorOrVoid setValue(uint64_t position, int8_t value);
uint64_t length();
void addElement(int8_t element);
ErrorOrVoid removeElement(uint64_t position);
};
class String: public Generic {
private:
tiny_utf8::string value;
public:
String();
String(tiny_utf8::string name, tiny_utf8::string value);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
tiny_utf8::string getValue();
void setValue(tiny_utf8::string value);
};
class List: public Generic {
private:
std::vector<Generic*> tags;
uint8_t type;
public:
List();
List(tiny_utf8::string name, uint8_t type);
List(tiny_utf8::string name, std::vector<Generic*> data);
~List() override;
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
ErrorOr<Generic*> getElementPointer(uint64_t position);
ErrorOrVoid setElementPointerAt(uint64_t position, Generic*);
ErrorOrVoid appendPointer(Generic*);
ErrorOrVoid deleteElement(uint64_t position);
uint64_t length();
};
class Compound: public Generic {
private:
std::vector<Generic*> tags;
public:
Compound();
Compound(tiny_utf8::string name);
Compound(tiny_utf8::string name, std::vector<Generic*> data);
~Compound() override;
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
ErrorOr<Generic*> getElementPointer(uint64_t position);
ErrorOrVoid setElementPointerAt(uint64_t position, Generic*);
ErrorOrVoid appendPointer(Generic*);
ErrorOrVoid deleteElement(uint64_t position);
uint64_t length();
};
class Int32Array: public Generic {
private:
std::vector<int32_t> data;
public:
Int32Array();
Int32Array(tiny_utf8::string name, std::vector<int32_t> data);
Int32Array(tiny_utf8::string name, uint64_t length, int32_t data[]);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
std::vector<int32_t> getData();
ErrorOr<int32_t> getValue(uint64_t position);
void setData(std::vector<int32_t> newData);
ErrorOrVoid setValue(uint64_t position, int32_t value);
uint64_t length();
void addElement(int32_t element);
ErrorOrVoid removeElement(uint64_t position);
};
class Int64Array: public Generic {
private:
std::vector<int64_t> data;
public:
Int64Array();
Int64Array(tiny_utf8::string name, std::vector<int64_t> data);
Int64Array(tiny_utf8::string name, uint64_t length, int64_t data[]);
ErrorOrVoid toRawData(std::vector<uint8_t>* rawData) override;
std::vector<int64_t> getData();
ErrorOr<int64_t> getValue(uint64_t position);
void setData(std::vector<int64_t> newData);
ErrorOrVoid setValue(uint64_t position, int64_t value);
uint64_t length();
void addElement(int64_t element);
ErrorOrVoid removeElement(uint64_t position);
};
}
bool validateRawNBTData(uint8_t data[], uint64_t dataSize, uint64_t initialPosition=0, uint64_t* processedDataSize=nullptr); bool validateRawNBTData(uint8_t data[], uint64_t dataSize, uint64_t initialPosition=0, uint64_t* processedDataSize=nullptr);
} }

View File

@ -573,6 +573,11 @@ int main(){
NBT::Helper::writeString(exportedString, normalString); NBT::Helper::writeString(exportedString, normalString);
ASSERT(javaStdString1 == *exportedString); ASSERT(javaStdString1 == *exportedString);
//check that we get an error when trying to write a string that is too long
std::string overrunString = std::string(0x10000, '.');
ASSERT(NBT::Helper::writeString(exportedString, tiny_utf8::string(overrunString)).isError);
ASSERT(NBT::Helper::writeString(exportedString, tiny_utf8::string(overrunString)).errorCode == ErrorCodes::OVERRUN);
std::cout << "Passed writeString NBT helper test." << std::endl; std::cout << "Passed writeString NBT helper test." << std::endl;
return 0; return 0;

View File

@ -30,15 +30,15 @@ int main(){
std::cout << "################################################################################" << std::endl; std::cout << "################################################################################" << std::endl;
//Byte tag constructor test //Byte tag constructor test
uint8_t bytetest[] = {0x01, 0x00, 0x02, 0x68, 0x69, 0x32}; //uint8_t bytetest[] = {0x01, 0x00, 0x02, 0x68, 0x69, 0x32};
NBT::Byte byte = NBT::Byte(bytetest); //NBT::Byte byte = NBT::Byte(bytetest);
ASSERT(byte.tagType == 1); //ASSERT(byte.tagType == 1);
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;
} }

View File

@ -1,31 +0,0 @@
// Copyright 2022, FOSS-VG Developers and Contributers
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, version 3.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// version 3 along with this program.
// If not, see https://www.gnu.org/licenses/agpl-3.0.en.html
#include <string>
#include <vector>
#include <iostream>
#include "../lib/nbt.hpp"
#include "../lib/error.hpp"
#include "../lib/javacompat.hpp"
int main() {
std::cout << "================================================================================" << std::endl;
std::cout << "NBT write string helper failure mode test" << std::endl;
std::cout << "================================================================================" << std::endl;
std::cout << "This is supposed to abort." << std::endl;
std::vector<uint8_t>* exportedString = new std::vector<uint8_t>();
std::string overrunString = std::string(0xFFFFF, '.');
NBT::Helper::writeString(exportedString, tiny_utf8::string(overrunString));
}