mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-05 17:44:52 +01:00
Parse chunk data on demand
This commit is contained in:
parent
fc1fc8fbbc
commit
8a8a41a800
14 changed files with 74 additions and 98 deletions
|
@ -40,34 +40,47 @@ private:
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static uint16_t parse16(const uint8_t *buf) {
|
||||||
|
return (buf[0] << 8) | buf[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t parse32(const uint8_t *buf) {
|
||||||
|
return (uint32_t(buf[0]) << 24) | (uint32_t(buf[1]) << 16) | (uint32_t(buf[2]) << 8) | uint32_t(buf[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t parse64(const uint8_t *buf) {
|
||||||
|
return (uint64_t(buf[0]) << 56) | (uint64_t(buf[1]) << 48) | (uint64_t(buf[2]) << 40) | (uint64_t(buf[3]) << 32)
|
||||||
|
| (uint64_t(buf[4]) << 24) | (uint64_t(buf[5]) << 16) | (uint64_t(buf[6]) << 8) | uint64_t(buf[7]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Buffer(const uint8_t *data0, size_t len0) : data(data0), len(len0) {}
|
Buffer(const uint8_t *data0, size_t len0) : data(data0), len(len0) {}
|
||||||
|
|
||||||
uint8_t get() {
|
const uint8_t * get(size_t n) {
|
||||||
if (!len)
|
|
||||||
throw std::runtime_error("Buffer::get(): buffer underrun");
|
|
||||||
|
|
||||||
data++;
|
|
||||||
len--;
|
|
||||||
return data[-1];
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getString(size_t n) {
|
|
||||||
if (n > len)
|
if (n > len)
|
||||||
throw std::runtime_error("Buffer::get(): buffer underrun");
|
throw std::runtime_error("Buffer::get(): buffer underrun");
|
||||||
|
|
||||||
data += n;
|
data += n;
|
||||||
len -= n;
|
len -= n;
|
||||||
return std::string(reinterpret_cast<const char *>(data - n), n);
|
return (data - n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getData(void *buf, size_t n) {
|
uint8_t get8() {
|
||||||
if (n > len)
|
return *get(1);
|
||||||
throw std::runtime_error("Buffer::get(): buffer underrun");
|
|
||||||
|
|
||||||
data += n;
|
|
||||||
len -= n;
|
|
||||||
std::memcpy(buf, data - n, n);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t get16() {
|
||||||
|
return parse16(get(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get32() {
|
||||||
|
return parse32(get(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t get64() {
|
||||||
|
return parse64(get(8));
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,22 +38,26 @@ class ByteArrayTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
std::vector<uint8_t> value;
|
uint32_t len;
|
||||||
|
const uint8_t *value;
|
||||||
|
|
||||||
ByteArrayTag(Buffer *buffer) {
|
ByteArrayTag(Buffer *buffer) {
|
||||||
uint32_t len = uint32_t(buffer->get()) << 24;
|
len = buffer->get32();
|
||||||
len |= uint32_t(buffer->get()) << 16;
|
value = buffer->get(len);
|
||||||
len |= uint32_t(buffer->get()) << 8;
|
|
||||||
len |= uint32_t(buffer->get());
|
|
||||||
|
|
||||||
value.resize(len);
|
|
||||||
buffer->getData(value.data(), len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Type getType() const {
|
virtual Type getType() const {
|
||||||
return Type::ByteArray;
|
return Type::ByteArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t getLength() const {
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t & operator[](size_t i) const {
|
||||||
|
return value[i];
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ private:
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
|
||||||
ByteTag(Buffer *buffer) {
|
ByteTag(Buffer *buffer) {
|
||||||
value = buffer->get();
|
value = buffer->get8();
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -36,17 +36,10 @@ class DoubleTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
DoubleTag(Buffer *buffer) {
|
const uint8_t *ptr;
|
||||||
uint64_t value;
|
|
||||||
|
|
||||||
value = uint64_t(buffer->get()) << 56;
|
DoubleTag(Buffer *buffer) {
|
||||||
value |= uint64_t(buffer->get()) << 48;
|
ptr = buffer->get(8);
|
||||||
value |= uint64_t(buffer->get()) << 40;
|
|
||||||
value |= uint64_t(buffer->get()) << 32;
|
|
||||||
value |= uint64_t(buffer->get()) << 24;
|
|
||||||
value |= uint64_t(buffer->get()) << 16;
|
|
||||||
value |= uint64_t(buffer->get()) << 8;
|
|
||||||
value |= uint64_t(buffer->get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -36,13 +36,10 @@ class FloatTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
FloatTag(Buffer *buffer) {
|
const uint8_t *ptr;
|
||||||
uint32_t value;
|
|
||||||
|
|
||||||
value = uint32_t(buffer->get()) << 24;
|
FloatTag(Buffer *buffer) {
|
||||||
value |= uint32_t(buffer->get()) << 16;
|
ptr = buffer->get(4);
|
||||||
value |= uint32_t(buffer->get()) << 8;
|
|
||||||
value |= uint32_t(buffer->get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -38,24 +38,12 @@ class IntArrayTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
std::vector<uint32_t> value;
|
uint32_t len;
|
||||||
|
const uint8_t *ptr;
|
||||||
|
|
||||||
IntArrayTag(Buffer *buffer) {
|
IntArrayTag(Buffer *buffer) {
|
||||||
uint32_t len = uint32_t(buffer->get()) << 24;
|
len = buffer->get32();
|
||||||
len |= uint32_t(buffer->get()) << 16;
|
ptr = buffer->get(4*len);
|
||||||
len |= uint32_t(buffer->get()) << 8;
|
|
||||||
len |= uint32_t(buffer->get());
|
|
||||||
|
|
||||||
value.resize(len);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < len; i++) {
|
|
||||||
uint32_t v = uint32_t(buffer->get()) << 24;
|
|
||||||
v |= uint32_t(buffer->get()) << 16;
|
|
||||||
v |= uint32_t(buffer->get()) << 8;
|
|
||||||
v |= uint32_t(buffer->get());
|
|
||||||
|
|
||||||
value[i] = v;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -36,13 +36,10 @@ class IntTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
uint32_t value;
|
const uint8_t *ptr;
|
||||||
|
|
||||||
IntTag(Buffer *buffer) {
|
IntTag(Buffer *buffer) {
|
||||||
value = uint32_t(buffer->get()) << 24;
|
ptr = buffer->get(4);
|
||||||
value |= uint32_t(buffer->get()) << 16;
|
|
||||||
value |= uint32_t(buffer->get()) << 8;
|
|
||||||
value |= uint32_t(buffer->get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -51,7 +48,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getValue() const {
|
uint32_t getValue() const {
|
||||||
return value;
|
return Buffer::parse32(ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -53,10 +53,7 @@ private:
|
||||||
Type type;
|
Type type;
|
||||||
|
|
||||||
ListTag(Type type0, Buffer *buffer) : type(type0) {
|
ListTag(Type type0, Buffer *buffer) : type(type0) {
|
||||||
uint32_t len = uint32_t(buffer->get()) << 24;
|
uint32_t len = buffer->get32();
|
||||||
len |= uint32_t(buffer->get()) << 16;
|
|
||||||
len |= uint32_t(buffer->get()) << 8;
|
|
||||||
len |= uint32_t(buffer->get());
|
|
||||||
|
|
||||||
this->resize(len);
|
this->resize(len);
|
||||||
|
|
||||||
|
|
|
@ -36,17 +36,10 @@ class LongTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
uint64_t value;
|
const uint8_t *ptr;
|
||||||
|
|
||||||
LongTag(Buffer *buffer) {
|
LongTag(Buffer *buffer) {
|
||||||
value = uint64_t(buffer->get()) << 56;
|
ptr = buffer->get(8);
|
||||||
value |= uint64_t(buffer->get()) << 48;
|
|
||||||
value |= uint64_t(buffer->get()) << 40;
|
|
||||||
value |= uint64_t(buffer->get()) << 32;
|
|
||||||
value |= uint64_t(buffer->get()) << 24;
|
|
||||||
value |= uint64_t(buffer->get()) << 16;
|
|
||||||
value |= uint64_t(buffer->get()) << 8;
|
|
||||||
value |= uint64_t(buffer->get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -55,7 +48,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t getValue() const {
|
uint64_t getValue() const {
|
||||||
return value;
|
return Buffer::parse64(ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,11 +36,10 @@ class ShortTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
uint16_t value;
|
const uint8_t *ptr;
|
||||||
|
|
||||||
ShortTag(Buffer *buffer) {
|
ShortTag(Buffer *buffer) {
|
||||||
value = buffer->get() << 8;
|
ptr = buffer->get(2);
|
||||||
value |= buffer->get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -49,7 +48,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t getValue() const {
|
uint16_t getValue() const {
|
||||||
return value;
|
return Buffer::parse16(ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -36,23 +36,18 @@ class StringTag : public Tag {
|
||||||
private:
|
private:
|
||||||
friend class Tag;
|
friend class Tag;
|
||||||
|
|
||||||
std::string value;
|
uint16_t len;
|
||||||
|
const uint8_t *ptr;
|
||||||
|
|
||||||
StringTag(Buffer *buffer) {
|
StringTag(Buffer *buffer) {
|
||||||
uint16_t len = buffer->get() << 8;
|
len = buffer->get16();
|
||||||
len |= buffer->get();
|
ptr = buffer->get(len);
|
||||||
|
|
||||||
value = buffer->getString(len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual Type getType() const {
|
virtual Type getType() const {
|
||||||
return Type::String;
|
return Type::String;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string & getValue() const {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,7 +90,7 @@ std::shared_ptr<const Tag> Tag::readTag(Type type, Buffer *buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const Tag> Tag::readList(Buffer *buffer) {
|
std::shared_ptr<const Tag> Tag::readList(Buffer *buffer) {
|
||||||
Type type = static_cast<Type>(buffer->get());
|
Type type = static_cast<Type>(buffer->get8());
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::End:
|
case Type::End:
|
||||||
|
@ -135,13 +135,12 @@ std::shared_ptr<const Tag> Tag::readList(Buffer *buffer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<std::string, std::shared_ptr<const Tag>> Tag::readNamedTag(Buffer *buffer) {
|
std::pair<std::string, std::shared_ptr<const Tag>> Tag::readNamedTag(Buffer *buffer) {
|
||||||
Type type = static_cast<Type>(buffer->get());
|
Type type = static_cast<Type>(buffer->get8());
|
||||||
if (type == Type::End)
|
if (type == Type::End)
|
||||||
return std::make_pair("", std::shared_ptr<EndTag>(new EndTag()));
|
return std::make_pair("", std::shared_ptr<EndTag>(new EndTag()));
|
||||||
|
|
||||||
uint16_t len = buffer->get() << 8;
|
uint16_t len = buffer->get16();
|
||||||
len |= buffer->get();
|
std::string name(reinterpret_cast<const char*>(buffer->get(len)), len);
|
||||||
std::string name = buffer->getString(len);
|
|
||||||
|
|
||||||
return std::make_pair(name, readTag(type, buffer));
|
return std::make_pair(name, readTag(type, buffer));
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,6 @@ Chunk::Chunk(uint8_t *buffer, size_t buflen) {
|
||||||
if (format != 2)
|
if (format != 2)
|
||||||
throw std::invalid_argument("unknown chunk format");
|
throw std::invalid_argument("unknown chunk format");
|
||||||
|
|
||||||
UniqueCPtr<uint8_t[]> data;
|
|
||||||
size_t len;
|
size_t len;
|
||||||
std::tie(data, len) = inflateChunk(buffer+5, size-1);
|
std::tie(data, len) = inflateChunk(buffer+5, size-1);
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,8 @@ public:
|
||||||
static const size_t SIZE = 16;
|
static const size_t SIZE = 16;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
UniqueCPtr<uint8_t[]> data;
|
||||||
|
|
||||||
static std::pair<UniqueCPtr<uint8_t[]>, size_t> inflateChunk(uint8_t *data, size_t len);
|
static std::pair<UniqueCPtr<uint8_t[]>, size_t> inflateChunk(uint8_t *data, size_t len);
|
||||||
|
|
||||||
std::shared_ptr<const NBT::ListTag<NBT::CompoundTag>> sections;
|
std::shared_ptr<const NBT::ListTag<NBT::CompoundTag>> sections;
|
||||||
|
|
Loading…
Add table
Reference in a new issue