summaryrefslogtreecommitdiff
path: root/src/resources/mapreader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/resources/mapreader.cpp')
-rw-r--r--src/resources/mapreader.cpp124
1 files changed, 113 insertions, 11 deletions
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index abd269d0..bf6ecdce 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -28,10 +28,11 @@
#include "../graphic/spriteset.h"
#include "../base64.h"
+#include <zlib.h>
#include <iostream>
-#define DEFAULT_TILE_WIDTH 32
-#define DEFAULT_TILE_HEIGHT 32
+const unsigned int DEFAULT_TILE_WIDTH = 32;
+const unsigned int DEFAULT_TILE_HEIGHT = 32;
// MSVC libxml2 at the moment doesn't work right when using MinGW, missing this
// function at link time.
@@ -40,6 +41,77 @@
#define xmlFree(x) ;
#endif
+/**
+ * Inflates either zlib or gzip deflated memory. The inflated memory is
+ * expected to be freed by the caller.
+ */
+int
+inflateMemory(
+ unsigned char *in, unsigned int inLength,
+ unsigned char *&out, unsigned int &outLength)
+{
+ int bufferSize = 256 * 1024;
+ int ret;
+ z_stream strm;
+
+ out = (unsigned char*)malloc(bufferSize);
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+ strm.next_in = in;
+ strm.avail_in = inLength;
+ strm.next_out = out;
+ strm.avail_out = bufferSize;
+
+ ret = inflateInit2(&strm, 15 + 32);
+
+ if (ret != Z_OK)
+ return ret;
+
+ do
+ {
+ if (strm.next_out == NULL)
+ {
+ inflateEnd(&strm);
+ return Z_MEM_ERROR;
+ }
+
+ ret = inflate(&strm, Z_NO_FLUSH);
+ assert(ret != Z_STREAM_ERROR);
+
+ switch (ret) {
+ case Z_NEED_DICT:
+ ret = Z_DATA_ERROR;
+ case Z_DATA_ERROR:
+ case Z_MEM_ERROR:
+ (void)inflateEnd(&strm);
+ return ret;
+ }
+
+ if (ret != Z_STREAM_END)
+ {
+ out = (unsigned char*)realloc(out, bufferSize * 2);
+
+ if (out == NULL)
+ {
+ inflateEnd(&strm);
+ return Z_MEM_ERROR;
+ }
+
+ strm.next_out = out + bufferSize;
+ strm.avail_out = bufferSize;
+ bufferSize *= 2;
+ }
+ }
+ while (ret != Z_STREAM_END);
+ assert(strm.avail_in == 0);
+
+ outLength = bufferSize - strm.avail_out;
+ (void)inflateEnd(&strm);
+ return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
+}
+
std::vector<Tileset*> MapReader::tilesets;
Tileset::Tileset(Image *img, int w, int h, int firstGid):
@@ -56,24 +128,54 @@ int Tileset::getFirstGid()
Map *MapReader::readMap(const std::string &filename)
{
- std::string name = /*std::string("data/") +*/ filename;
+ // Load the file through resource manager
+ ResourceManager *resman = ResourceManager::getInstance();
+ int fileSize;
+ void *buffer = resman->loadFile(filename, fileSize);
+
+ if (buffer == NULL)
+ {
+ logger->log("Map file not found (%s)\n", filename.c_str());
+ return NULL;
+ }
- // Check that file exists before trying to parse it
- std::fstream fin;
- fin.open(name.c_str(), std::ios::in);
- if (!fin.is_open()) {
- logger->log("No such file!");
+ // Inflate the gzipped map data
+ unsigned char *inflated;
+ unsigned int inflatedSize = 0;
+ int ret = inflateMemory(
+ (unsigned char*)buffer, fileSize, inflated, inflatedSize);
+ free(buffer);
+
+ if (ret == Z_MEM_ERROR)
+ {
+ logger->log("Error: Out of memory while decompressing map data!");
+ return NULL;
+ }
+ else if (ret == Z_VERSION_ERROR)
+ {
+ logger->log("Error: Incompatible zlib version!");
+ return NULL;
+ }
+ else if (ret == Z_DATA_ERROR)
+ {
+ logger->log("Error: Incorrect zlib compressed data!");
+ return NULL;
+ }
+ else if (ret != Z_OK || inflated == NULL)
+ {
+ logger->log("Error: Unknown error while decompressing map data!");
return NULL;
}
- fin.close();
- xmlDocPtr doc = xmlParseFile(name.c_str());
+ xmlDocPtr doc = xmlParseMemory((char*)inflated, inflatedSize);
+ free(inflated);
+ // Parse the inflated map data
if (doc) {
xmlNodePtr node = xmlDocGetRootElement(doc);
if (!node || !xmlStrEqual(node->name, BAD_CAST "map")) {
- logger->log("Warning: Not a map file (%s)!", filename.c_str());
+ logger->log("Error: Not a map file (%s)!", filename.c_str());
return NULL;
}