summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/StringCompression.cpp62
-rw-r--r--src/StringCompression.h2
-rw-r--r--src/WorldStorage/WSSAnvil.cpp24
3 files changed, 70 insertions, 18 deletions
diff --git a/src/StringCompression.cpp b/src/StringCompression.cpp
index 71d64e71e..af9f1687f 100644
--- a/src/StringCompression.cpp
+++ b/src/StringCompression.cpp
@@ -180,3 +180,65 @@ extern int UncompressStringGZIP(const char * a_Data, size_t a_Length, AString &
+
+extern int InflateString(const char * a_Data, size_t a_Length, AString & a_Uncompressed)
+{
+ a_Uncompressed.reserve(a_Length);
+
+ char Buffer[64 KiB];
+ z_stream strm;
+ memset(&strm, 0, sizeof(strm));
+ strm.next_in = (Bytef *)a_Data;
+ strm.avail_in = (uInt)a_Length;
+ strm.next_out = (Bytef *)Buffer;
+ strm.avail_out = sizeof(Buffer);
+
+ int res = inflateInit(&strm); // Force GZIP decoding
+ if (res != Z_OK)
+ {
+ LOG("%s: inflation initialization failed: %d (\"%s\").", __FUNCTION__, res, strm.msg);
+ return res;
+ }
+
+ for (;;)
+ {
+ res = inflate(&strm, Z_NO_FLUSH);
+ switch (res)
+ {
+ case Z_OK:
+ {
+ // Some data has been uncompressed. Consume the buffer and continue uncompressing
+ a_Uncompressed.append(Buffer, sizeof(Buffer) - strm.avail_out);
+ strm.next_out = (Bytef *)Buffer;
+ strm.avail_out = sizeof(Buffer);
+ if (strm.avail_in == 0)
+ {
+ // All data has been uncompressed
+ inflateEnd(&strm);
+ return Z_OK;
+ }
+ break;
+ }
+
+ case Z_STREAM_END:
+ {
+ // Finished uncompressing. Consume the rest of the buffer and return
+ a_Uncompressed.append(Buffer, sizeof(Buffer) - strm.avail_out);
+ inflateEnd(&strm);
+ return Z_OK;
+ }
+
+ default:
+ {
+ // An error has occurred, log it and return the error value
+ LOG("%s: inflation failed: %d (\"%s\").", __FUNCTION__, res, strm.msg);
+ inflateEnd(&strm);
+ return res;
+ }
+ } // switch (res)
+ } // while (true)
+}
+
+
+
+
diff --git a/src/StringCompression.h b/src/StringCompression.h
index 038240797..dde17ce30 100644
--- a/src/StringCompression.h
+++ b/src/StringCompression.h
@@ -21,5 +21,7 @@ extern int CompressStringGZIP(const char * a_Data, size_t a_Length, AString & a_
/// Uncompresses a_Data into a_Uncompressed using GZIP; returns Z_OK for success or Z_XXX error constants same as zlib
extern int UncompressStringGZIP(const char * a_Data, size_t a_Length, AString & a_Uncompressed);
+/** Uncompresses a_Data into a_Uncompressed using Inflate; returns Z_OK for success or Z_XXX error constants same as zlib */
+extern int InflateString(const char * a_Data, size_t a_Length, AString & a_Uncompressed);
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index 815b6544f..239f4a155 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -66,9 +66,6 @@ Since only the header is actually in the memory, this number can be high, but st
*/
#define MAX_MCA_FILES 32
-/// The maximum size of an inflated chunk; raw chunk data is 192 KiB, allow 64 KiB more of entities
-#define CHUNK_INFLATE_MAX 256 KiB
-
#define LOAD_FAILED(CHX, CHZ) \
{ \
const int RegionX = FAST_FLOOR_DIV(CHX, 32); \
@@ -260,27 +257,18 @@ cWSSAnvil::cMCAFile * cWSSAnvil::LoadMCAFile(const cChunkCoords & a_Chunk)
bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const AString & a_Data)
{
- // Decompress the data:
- char Uncompressed[CHUNK_INFLATE_MAX];
- z_stream strm;
- strm.zalloc = (alloc_func)NULL;
- strm.zfree = (free_func)NULL;
- strm.opaque = NULL;
- inflateInit(&strm);
- strm.next_out = (Bytef *)Uncompressed;
- strm.avail_out = sizeof(Uncompressed);
- strm.next_in = (Bytef *)a_Data.data();
- strm.avail_in = (uInt)a_Data.size();
- int res = inflate(&strm, Z_FINISH);
- inflateEnd(&strm);
- if (res != Z_STREAM_END)
+ // Uncompress the data:
+ AString Uncompressed;
+ int res = InflateString(a_Data.data(), a_Data.size(), Uncompressed);
+ if (res != Z_OK)
{
+ LOGWARNING("Uncompressing chunk [%d, %d] failed: %d", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, res);
LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
// Parse the NBT data:
- cParsedNBT NBT(Uncompressed, strm.total_out);
+ cParsedNBT NBT(Uncompressed.data(), Uncompressed.size());
if (!NBT.IsValid())
{
// NBT Parsing failed