NBT finished, need to add decoder / tests
- evil hacks are not fun (blt::nbt::_internal_ forward declares list and compound for use inside list / compound) - list could be made faster by bulk allocating when type is known however i believe the compiler is smart enough to do this for me - testing that should be a todo!v1
parent
7a7ee74924
commit
c4c23e9cc6
|
@ -97,6 +97,7 @@ namespace blt::nbt {
|
||||||
[[nodiscard]] inline const std::string& getName() const {
|
[[nodiscard]] inline const std::string& getName() const {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
virtual ~tag_t() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -116,6 +117,7 @@ namespace blt::nbt {
|
||||||
}
|
}
|
||||||
[[nodiscard]] inline const T& get() const {return t;}
|
[[nodiscard]] inline const T& get() const {return t;}
|
||||||
inline T& get() {return t;}
|
inline T& get() {return t;}
|
||||||
|
~tag() override = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class tag_end : public tag<char> {
|
class tag_end : public tag<char> {
|
||||||
|
@ -229,11 +231,45 @@ namespace blt::nbt {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// EVIL HACK
|
|
||||||
static tag_t* newCompound();
|
|
||||||
|
|
||||||
#define BLT_NBT_POPULATE_VEC(type, vec, length) for (int i = 0; i < length; i++) vec.push_back(type);
|
#define BLT_NBT_POPULATE_VEC(type, vec, length) for (int i = 0; i < length; i++) vec.push_back(type);
|
||||||
|
|
||||||
|
namespace _internal_ {
|
||||||
|
// EVIL HACK
|
||||||
|
static tag_t* newCompound();
|
||||||
|
static tag_t* newList();
|
||||||
|
static tag_t* toType(char id){
|
||||||
|
switch ((nbt_tag) id) {
|
||||||
|
case nbt_tag::END:
|
||||||
|
return nullptr;
|
||||||
|
break;
|
||||||
|
case nbt_tag::BYTE:
|
||||||
|
return new blt::nbt::tag_byte;
|
||||||
|
case nbt_tag::SHORT:
|
||||||
|
return new blt::nbt::tag_short;
|
||||||
|
case nbt_tag::INT:
|
||||||
|
return new blt::nbt::tag_int;
|
||||||
|
case nbt_tag::LONG:
|
||||||
|
return new blt::nbt::tag_long;
|
||||||
|
case nbt_tag::FLOAT:
|
||||||
|
return new blt::nbt::tag_float;
|
||||||
|
case nbt_tag::DOUBLE:
|
||||||
|
return new blt::nbt::tag_double;
|
||||||
|
case nbt_tag::BYTE_ARRAY:
|
||||||
|
return new blt::nbt::tag_byte_array;
|
||||||
|
case nbt_tag::STRING:
|
||||||
|
return new blt::nbt::tag_string;
|
||||||
|
case nbt_tag::LIST:
|
||||||
|
return _internal_::newList();
|
||||||
|
case nbt_tag::COMPOUND:
|
||||||
|
return _internal_::newCompound();
|
||||||
|
case nbt_tag::INT_ARRAY:
|
||||||
|
return new blt::nbt::tag_int_array;
|
||||||
|
case nbt_tag::LONG_ARRAY:
|
||||||
|
return new blt::nbt::tag_long_array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class tag_list : public tag<std::vector<tag_t*>> {
|
class tag_list : public tag<std::vector<tag_t*>> {
|
||||||
public:
|
public:
|
||||||
tag_list(): tag(nbt_tag::LIST) {}
|
tag_list(): tag(nbt_tag::LIST) {}
|
||||||
|
@ -255,54 +291,47 @@ namespace blt::nbt {
|
||||||
readData(in, length);
|
readData(in, length);
|
||||||
if (length == 0 || id == 0)
|
if (length == 0 || id == 0)
|
||||||
return;
|
return;
|
||||||
switch ((nbt_tag) id) {
|
t.reserve(length);
|
||||||
case nbt_tag::END:
|
for (int i = 0; i < length; i++) {
|
||||||
break;
|
t[i] = _internal_::toType(id);
|
||||||
case nbt_tag::BYTE:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_byte, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::SHORT:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_short, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::INT:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_int, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::LONG:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_long, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::FLOAT:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_float, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::DOUBLE:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_double, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::BYTE_ARRAY:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_byte_array, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::STRING:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_string, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::LIST:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_list, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::COMPOUND:
|
|
||||||
BLT_NBT_POPULATE_VEC(newCompound(), t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::INT_ARRAY:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_int_array, t, length);
|
|
||||||
break;
|
|
||||||
case nbt_tag::LONG_ARRAY:
|
|
||||||
BLT_NBT_POPULATE_VEC(new blt::nbt::tag_long_array, t, length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < length; i++)
|
|
||||||
t[i]->readPayload(in);
|
t[i]->readPayload(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~tag_list() override {
|
||||||
|
for (auto* p : t)
|
||||||
|
delete p;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class tag_compound : public tag<std::vector<tag_t*>> {
|
||||||
|
public:
|
||||||
|
tag_compound(): tag(nbt_tag::COMPOUND) {}
|
||||||
|
tag_compound(const std::string& name, const std::vector<tag_t*>& v): tag(nbt_tag::COMPOUND, name, v) {}
|
||||||
|
void writePayload(blt::fs::block_writer& out) final {
|
||||||
|
for (auto*& v : t){
|
||||||
|
out.put((char) v->getType());
|
||||||
|
v->writeName(out);
|
||||||
|
v->writePayload(out);
|
||||||
|
}
|
||||||
|
out.put('\0');
|
||||||
|
}
|
||||||
|
void readPayload(blt::fs::block_reader& in) final {
|
||||||
|
char type;
|
||||||
|
while ((type = in.get()) != (char)nbt_tag::END){
|
||||||
|
auto* v = _internal_::toType(type);
|
||||||
|
v->readName(in);
|
||||||
|
v->readPayload(in);
|
||||||
|
t.push_back(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static tag_t* newCompound(){
|
static tag_t* _internal_::newCompound(){
|
||||||
|
return new blt::nbt::tag_compound;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tag_t* _internal_::newList() {
|
||||||
|
return new blt::nbt::tag_list;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NBTDecoder {
|
class NBTDecoder {
|
||||||
|
|
|
@ -34,6 +34,11 @@ namespace blt::fs {
|
||||||
* @return status code. non-zero return codes indicates a failure has occurred.
|
* @return status code. non-zero return codes indicates a failure has occurred.
|
||||||
*/
|
*/
|
||||||
virtual int read(char* buffer, size_t bytes) = 0;
|
virtual int read(char* buffer, size_t bytes) = 0;
|
||||||
|
virtual char get(){
|
||||||
|
char c[1];
|
||||||
|
read(c, 1);
|
||||||
|
return c[0];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,6 +57,11 @@ namespace blt::fs {
|
||||||
* @return non-zero code if failure
|
* @return non-zero code if failure
|
||||||
*/
|
*/
|
||||||
virtual int write(char* buffer, size_t bytes) = 0;
|
virtual int write(char* buffer, size_t bytes) = 0;
|
||||||
|
virtual int put(char c){
|
||||||
|
char a[1];
|
||||||
|
a[0] = c;
|
||||||
|
return write(a, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that the internal buffer is written to the filesystem.
|
* Ensures that the internal buffer is written to the filesystem.
|
||||||
|
|
Loading…
Reference in New Issue