summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJared Adams <jaxad0127@gmail.com>2010-08-13 14:45:52 -0600
committerJared Adams <jaxad0127@gmail.com>2010-08-13 18:43:16 -0600
commit8eadc834ed3e8439836f7dc87390a56a1164ec11 (patch)
tree36cf9915914517b137d488a40d1f61265867723d /src
parent6d315d0e61f419636021476582a49ab0b1f1b5e9 (diff)
downloadmana-8eadc834ed3e8439836f7dc87390a56a1164ec11.tar.gz
mana-8eadc834ed3e8439836f7dc87390a56a1164ec11.tar.bz2
mana-8eadc834ed3e8439836f7dc87390a56a1164ec11.tar.xz
mana-8eadc834ed3e8439836f7dc87390a56a1164ec11.zip
Simplify handling of compressed files
ResourceManager will now check for ".gz" and act appropriately (unless told not to). Compression handling functions are now in new utils/zlib files, along with a function to load a file from drive, uncompressing it if it ends in ".gz". Reviewed-by: Freeyorp
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/resources/mapreader.cpp142
-rw-r--r--src/resources/resourcemanager.cpp45
-rw-r--r--src/resources/resourcemanager.h9
-rw-r--r--src/utils/xml.cpp25
-rw-r--r--src/utils/zlib.cpp184
-rw-r--r--src/utils/zlib.h48
8 files changed, 283 insertions, 174 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9b38b496..6c470aef 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -402,6 +402,8 @@ SET(SRCS
utils/mkdir.h
utils/xml.cpp
utils/xml.h
+ utils/zlib.cpp
+ utils/zlib.h
animatedsprite.cpp
animatedsprite.h
animationparticle.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index d12a9a56..1f2391a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -301,6 +301,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
utils/mutex.h \
utils/xml.cpp \
utils/xml.h \
+ utils/zlib.cpp \
+ utils/zlib.h \
animatedsprite.cpp \
animatedsprite.h \
animationparticle.cpp \
diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp
index a8582c9b..b7c4fd72 100644
--- a/src/resources/mapreader.cpp
+++ b/src/resources/mapreader.cpp
@@ -33,10 +33,9 @@
#include "utils/base64.h"
#include "utils/stringutils.h"
#include "utils/xml.h"
+#include "utils/zlib.h"
-#include <cassert>
#include <iostream>
-#include <zlib.h>
// DO NOT CHANGE THESE STRINGS TO BE PASSED BY REFERENCE, AS THIS METHOD ALTERS
// (THAT IS, DESTROYS) THEM.
@@ -66,149 +65,12 @@ static std::string resolveRelativePath(std::string base, std::string relative)
return base + relative;
}
-/**
- * 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;
-}
-
-int inflateMemory(unsigned char *in, unsigned int inLength,
- unsigned char *&out)
-{
- unsigned int outLength = 0;
- int ret = inflateMemory(in, inLength, out, outLength);
-
- if (ret != Z_OK || out == NULL)
- {
- if (ret == Z_MEM_ERROR)
- {
- logger->log("Error: Out of memory while decompressing map data!");
- }
- else if (ret == Z_VERSION_ERROR)
- {
- logger->log("Error: Incompatible zlib version!");
- }
- else if (ret == Z_DATA_ERROR)
- {
- logger->log("Error: Incorrect zlib compressed data!");
- }
- else
- {
- logger->log("Error: Unknown error while decompressing map data!");
- }
-
- free(out);
- out = NULL;
- outLength = 0;
- }
-
- return outLength;
-}
-
Map *MapReader::readMap(const std::string &filename)
{
logger->log("Attempting to read map %s", filename.c_str());
- // Load the file through resource manager
- ResourceManager *resman = ResourceManager::getInstance();
- int fileSize;
- void *buffer = resman->loadFile(filename, fileSize);
Map *map = NULL;
- if (buffer == NULL)
- {
- logger->log("Map file not found (%s)", filename.c_str());
- return NULL;
- }
-
- unsigned char *inflated;
- unsigned int inflatedSize;
-
- if (filename.find(".gz", filename.length() - 3) != std::string::npos)
- {
- // Inflate the gzipped map data
- inflatedSize =
- inflateMemory((unsigned char*) buffer, fileSize, inflated);
- free(buffer);
-
- if (inflated == NULL)
- {
- logger->log("Could not decompress map file (%s)",
- filename.c_str());
- return NULL;
- }
- }
- else
- {
- inflated = (unsigned char*) buffer;
- inflatedSize = fileSize;
- }
-
- XML::Document doc((char*) inflated, inflatedSize);
- free(inflated);
+ XML::Document doc(filename);
xmlNodePtr node = doc.rootNode();
diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp
index f785f20a..c63b626e 100644
--- a/src/resources/resourcemanager.cpp
+++ b/src/resources/resourcemanager.cpp
@@ -31,6 +31,8 @@
#include "resources/soundeffect.h"
#include "resources/spritedef.h"
+#include "utils/zlib.h"
+
#include <physfs.h>
#include <SDL_image.h>
@@ -411,34 +413,59 @@ void ResourceManager::deleteInstance()
instance = NULL;
}
-void *ResourceManager::loadFile(const std::string &fileName, int &fileSize)
+void *ResourceManager::loadFile(const std::string &filename, int &filesize,
+ bool inflate)
{
// Attempt to open the specified file using PhysicsFS
- PHYSFS_file *file = PHYSFS_openRead(fileName.c_str());
+ PHYSFS_file *file = PHYSFS_openRead(filename.c_str());
// If the handler is an invalid pointer indicate failure
if (file == NULL)
{
logger->log("Warning: Failed to load %s: %s",
- fileName.c_str(), PHYSFS_getLastError());
+ filename.c_str(), PHYSFS_getLastError());
return NULL;
}
// Log the real dir of the file
- logger->log("Loaded %s/%s", PHYSFS_getRealDir(fileName.c_str()),
- fileName.c_str());
+ logger->log("Loaded %s/%s", PHYSFS_getRealDir(filename.c_str()),
+ filename.c_str());
// Get the size of the file
- fileSize = PHYSFS_fileLength(file);
+ filesize = PHYSFS_fileLength(file);
// Allocate memory and load the file
- void *buffer = malloc(fileSize);
- PHYSFS_read(file, buffer, 1, fileSize);
+ void *buffer = malloc(filesize);
+ PHYSFS_read(file, buffer, 1, filesize);
// Close the file and let the user deallocate the memory
PHYSFS_close(file);
- return buffer;
+ unsigned char *inflated;
+ unsigned int inflatedSize;
+
+ if (inflate && filename.find(".gz", filename.length() - 3)
+ != std::string::npos)
+ {
+ // Inflate the gzipped map data
+ inflatedSize =
+ inflateMemory((unsigned char*) buffer, filesize, inflated);
+ free(buffer);
+
+ if (inflated == NULL)
+ {
+ logger->log("Could not decompress file: %s",
+ filename.c_str());
+ return NULL;
+ }
+
+ filesize = inflatedSize;
+ return inflated;
+ }
+ else
+ {
+ return buffer;
+ }
}
bool ResourceManager::copyFile(const std::string &src, const std::string &dst)
diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h
index e1aed521..28ab4725 100644
--- a/src/resources/resourcemanager.h
+++ b/src/resources/resourcemanager.h
@@ -183,13 +183,16 @@ class ResourceManager
* Allocates data into a buffer pointer for raw data loading. The
* returned data is expected to be freed using <code>free()</code>.
*
- * @param fileName The name of the file to be loaded.
- * @param fileSize The size of the file that was loaded.
+ * @param filename The name of the file to be loaded.
+ * @param filesize The size of the file that was loaded.
+ * @param inflate True to uncompress the file if the filename ends in
+ * ".gz", false to ignore that.
*
* @return An allocated byte array containing the data that was loaded,
* or <code>NULL</code> on fail.
*/
- void *loadFile(const std::string &fileName, int &fileSize);
+ void *loadFile(const std::string &filename, int &filesize,
+ bool inflate = true);
/**
* Retrieves the contents of a text file.
diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp
index 8d444fab..9835f88c 100644
--- a/src/utils/xml.cpp
+++ b/src/utils/xml.cpp
@@ -25,12 +25,11 @@
#include "resources/resourcemanager.h"
+#include "utils/zlib.h"
+
#include <libxml/parser.h>
#include <libxml/xmlerror.h>
-#include <fstream>
-#include <iostream>
-
namespace XML
{
static void xmlLogger(void *ctx, xmlErrorPtr error);
@@ -58,25 +57,7 @@ namespace XML
}
else
{
- std::ifstream file;
- file.open(filename.c_str(), std::ios::in);
-
- if (file.is_open())
- {
- // Get length of file
- file.seekg (0, std::ios::end);
- size = file.tellg();
- file.seekg(0, std::ios::beg);
-
- data = (char*) malloc(size);
-
- file.read(data, size);
- file.close();
- }
- else
- {
- logger->log("Error loading XML file %s", filename.c_str());
- }
+ data = (char *) loadCompressedFile(filename, size);
}
if (data)
diff --git a/src/utils/zlib.cpp b/src/utils/zlib.cpp
new file mode 100644
index 00000000..8e2a1795
--- /dev/null
+++ b/src/utils/zlib.cpp
@@ -0,0 +1,184 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils/zlib.h"
+
+#include "log.h"
+
+#include <cassert>
+#include <cstdlib>
+#include <fstream>
+#include <iostream>
+#include <zlib.h>
+
+/**
+ * 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;
+}
+
+int inflateMemory(unsigned char *in, unsigned int inLength,
+ unsigned char *&out)
+{
+ unsigned int outLength = 0;
+ int ret = inflateMemory(in, inLength, out, outLength);
+
+ if (ret != Z_OK || out == NULL)
+ {
+ if (ret == Z_MEM_ERROR)
+ {
+ logger->log("Error: Out of memory while decompressing data!");
+ }
+ else if (ret == Z_VERSION_ERROR)
+ {
+ logger->log("Error: Incompatible zlib version!");
+ }
+ else if (ret == Z_DATA_ERROR)
+ {
+ logger->log("Error: Incorrect zlib compressed data!");
+ }
+ else
+ {
+ logger->log("Error: Unknown error while decompressing data!");
+ }
+
+ free(out);
+ out = NULL;
+ outLength = 0;
+ }
+
+ return outLength;
+}
+
+void *loadCompressedFile(const std::string &filename, int &filesize)
+{
+ std::ifstream file;
+ file.open(filename.c_str(), std::ios::in);
+
+ if (file.is_open())
+ {
+ // Get length of file
+ file.seekg (0, std::ios::end);
+ filesize = file.tellg();
+ file.seekg(0, std::ios::beg);
+
+ char *buffer = (char *) malloc(filesize);
+
+ file.read(buffer, filesize);
+ file.close();
+
+ unsigned char *inflated;
+ unsigned int inflatedSize;
+
+ if (inflated && filename.find(".gz", filename.length() - 3)
+ != std::string::npos)
+ {
+ // Inflate the gzipped map data
+ inflatedSize =
+ inflateMemory((unsigned char*) buffer, filesize, inflated);
+ free(buffer);
+
+ if (inflated == NULL)
+ {
+ logger->log("Could not decompress file: %s",
+ filename.c_str());
+ return NULL;
+ }
+
+ filesize = inflatedSize;
+ return inflated;
+ }
+ else
+ {
+ return buffer;
+ }
+ }
+ else
+ {
+ logger->log("Error loading file from drive: %s", filename.c_str());
+ }
+
+ return NULL;
+}
diff --git a/src/utils/zlib.h b/src/utils/zlib.h
new file mode 100644
index 00000000..003e64b6
--- /dev/null
+++ b/src/utils/zlib.h
@@ -0,0 +1,48 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2007-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_ZLIB_H
+#define UTILS_ZLIB_H
+
+#include <string>
+
+/**
+ * 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 inflateMemory(unsigned char *in, unsigned int inLength,
+ unsigned char *&out);
+
+/**
+ * Loads the given file from the filesystem, uncompressing if it ends in ".gz".
+ *
+ * @param filename The name of the file to be loaded and uncompressed
+ * @param filesize The size of the file that was loaded and uncompressed.
+ *
+ * @return An allocated byte array containing the data that was loaded and
+ * uncompressed, or <code>NULL</code> on fail.
+ */
+void *loadCompressedFile(const std::string &filename, int &filesize);
+
+#endif // UTILS_ZLIB_H