Use buffer API for chunk decompression

This commit is contained in:
Matthias Schiffer 2015-02-01 06:04:56 +01:00
parent 18ed3d4c5d
commit 2d2671a686
4 changed files with 16 additions and 14 deletions

View file

@ -56,6 +56,10 @@ public:
Buffer(const uint8_t *data0, size_t len0) : data(data0), len(len0) {} Buffer(const uint8_t *data0, size_t len0) : data(data0), len(len0) {}
size_t getRemaining() const {
return len;
}
const uint8_t * get(size_t n) { const uint8_t * get(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");

View file

@ -39,7 +39,7 @@
namespace MinedMap { namespace MinedMap {
namespace World { namespace World {
void Chunk::inflateChunk(uint8_t *buffer, size_t buflen) { void Chunk::inflateChunk(Buffer buffer) {
size_t outlen = 0; size_t outlen = 0;
uint8_t *output = nullptr; uint8_t *output = nullptr;
@ -48,8 +48,8 @@ void Chunk::inflateChunk(uint8_t *buffer, size_t buflen) {
if (ret != Z_OK) if (ret != Z_OK)
throw std::runtime_error("inflateInit() failed"); throw std::runtime_error("inflateInit() failed");
stream.next_in = buffer; stream.avail_in = buffer.getRemaining();
stream.avail_in = buflen; stream.next_in = const_cast<uint8_t *>(buffer.get(stream.avail_in));
while (stream.avail_in) { while (stream.avail_in) {
outlen += 65536; outlen += 65536;
@ -111,19 +111,16 @@ uint8_t Chunk::getDataAt(const std::shared_ptr<const NBT::CompoundTag> &section,
return (v & 0xf); return (v & 0xf);
} }
Chunk::Chunk(uint8_t *buffer, size_t buflen) { Chunk::Chunk(Buffer buffer) {
if (buflen < 5) size_t size = buffer.get32();
throw std::invalid_argument("short chunk");
size_t size = (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; Buffer buffer2(buffer.get(size), size);
if (size < 1 || size > (buflen - 4))
throw std::invalid_argument("invalid chunk size");
uint8_t format = buffer[4]; uint8_t format = buffer2.get8();
if (format != 2) if (format != 2)
throw std::invalid_argument("unknown chunk format"); throw std::invalid_argument("unknown chunk format");
inflateChunk(buffer+5, size-1); inflateChunk(buffer2);
parseChunk(); parseChunk();
analyzeChunk(); analyzeChunk();
} }

View file

@ -27,6 +27,7 @@
#pragma once #pragma once
#include "../Buffer.hpp"
#include "../UniqueCPtr.hpp" #include "../UniqueCPtr.hpp"
#include "../NBT/CompoundTag.hpp" #include "../NBT/CompoundTag.hpp"
#include "../NBT/ListTag.hpp" #include "../NBT/ListTag.hpp"
@ -51,7 +52,7 @@ private:
unsigned maxY; unsigned maxY;
void inflateChunk(uint8_t *data, size_t len); void inflateChunk(Buffer buffer);
void parseChunk(); void parseChunk();
void analyzeChunk(); void analyzeChunk();
@ -66,7 +67,7 @@ private:
uint8_t getDataAt(const std::shared_ptr<const NBT::CompoundTag> &section, size_t x, size_t y, size_t z); uint8_t getDataAt(const std::shared_ptr<const NBT::CompoundTag> &section, size_t x, size_t y, size_t z);
public: public:
Chunk(uint8_t *buffer, size_t buflen); Chunk(Buffer buffer);
const NBT::ListTag<NBT::CompoundTag> & getSections() const { const NBT::ListTag<NBT::CompoundTag> & getSections() const {
return *sections; return *sections;

View file

@ -86,7 +86,7 @@ Region::Region(const char *filename) {
uint8_t buffer[len * 4096]; uint8_t buffer[len * 4096];
file.read((char *)buffer, len * 4096); file.read((char *)buffer, len * 4096);
chunks[x][z].reset(new Chunk(buffer, len * 4096)); chunks[x][z].reset(new Chunk(Buffer(buffer, len * 4096)));
i += len; i += len;
c++; c++;