Save states using gzip, load either way.

Could implement an option to save states uncompressed.  There's
a small performance hit.

Test files were 8% - 14% the size, but these are just from menus/etc.
This commit is contained in:
Unknown W. Brackets
2012-12-28 18:13:32 -08:00
parent da551d71c3
commit df627f7738
3 changed files with 104 additions and 28 deletions
+7 -7
View File
@@ -369,7 +369,7 @@ public:
if (!File::Exists(_rFilename))
return false;
// Check file size
// Check file size - most probably it can't compress THAT well.
const u64 fileSize = File::GetSize(_rFilename);
static const u64 headerSize = sizeof(SChunkHeader);
if (fileSize < headerSize)
@@ -378,7 +378,7 @@ public:
return false;
}
File::IOFile pFile(_rFilename, "rb");
File::IOFile pFile(_rFilename, "rb", File::METHOD_GZIP);
if (!pFile)
{
ERROR_LOG(COMMON,"ChunkReader: Can't open file for reading");
@@ -402,11 +402,11 @@ public:
}
// get size
const int sz = (int)(fileSize - headerSize);
if (header.ExpectedSize != sz)
const int sz = header.ExpectedSize;
if (sz > 128 * 1024 * 1024)
{
ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d",
sz, header.ExpectedSize);
ERROR_LOG(COMMON,"ChunkReader: File too large, got %d bytes",
header.ExpectedSize);
return false;
}
@@ -432,7 +432,7 @@ public:
static bool Save(const std::string& _rFilename, int _Revision, T& _class)
{
INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str());
File::IOFile pFile(_rFilename, "wb");
File::IOFile pFile(_rFilename, "wb9", File::METHOD_GZIP);
if (!pFile)
{
ERROR_LOG(COMMON,"ChunkReader: Error opening file for write");
+63 -14
View File
@@ -767,17 +767,17 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str)
}
IOFile::IOFile()
: m_file(NULL), m_good(true)
: m_file(NULL), m_zFile(NULL), m_good(true)
{}
IOFile::IOFile(std::FILE* file)
: m_file(file), m_good(true)
: m_file(file), m_zFile(NULL), m_good(true)
{}
IOFile::IOFile(const std::string& filename, const char openmode[])
: m_file(NULL), m_good(true)
IOFile::IOFile(const std::string& filename, const char openmode[], IOFileMethod method)
: m_file(NULL), m_zFile(NULL), m_good(true), m_method(method)
{
Open(filename, openmode);
Open(filename, openmode, method);
}
IOFile::~IOFile()
@@ -785,14 +785,21 @@ IOFile::~IOFile()
Close();
}
bool IOFile::Open(const std::string& filename, const char openmode[])
bool IOFile::Open(const std::string& filename, const char openmode[], IOFileMethod method)
{
Close();
m_method = method;
if (0 != (m_method & METHOD_GZIP))
m_zFile = gzopen(filename.c_str(), openmode);
else
{
#ifdef _WIN32
fopen_s(&m_file, filename.c_str(), openmode);
fopen_s(&m_file, filename.c_str(), openmode);
#else
m_file = fopen(filename.c_str(), openmode);
m_file = fopen(filename.c_str(), openmode);
#endif
}
m_good = IsOpen();
return m_good;
@@ -800,10 +807,19 @@ bool IOFile::Open(const std::string& filename, const char openmode[])
bool IOFile::Close()
{
if (!IsOpen() || 0 != std::fclose(m_file))
m_good = false;
if (0 != (m_method & METHOD_GZIP))
{
if (Z_OK != gzclose(m_zFile))
m_good = false;
m_zFile = NULL;
}
else
{
if (!IsOpen() || 0 != std::fclose(m_file))
m_good = false;
m_file = NULL;
}
m_file = NULL;
return m_good;
}
@@ -819,19 +835,32 @@ void IOFile::SetHandle(std::FILE* file)
Close();
Clear();
m_file = file;
m_method = METHOD_STANDARD;
}
u64 IOFile::GetSize()
{
if (IsOpen())
{
// Not supported.
if (0 != (m_method & METHOD_GZIP))
return 0;
return File::GetSize(m_file);
}
else
return 0;
}
bool IOFile::Seek(s64 off, int origin)
{
if (!IsOpen() || 0 != fseeko(m_file, off, origin))
if (!IsOpen())
m_good = false;
else if (0 != (m_method & METHOD_GZIP))
{
if (-1 == gzseek(m_zFile, (z_off_t) off, origin))
m_good = false;
}
else if (0 != fseeko(m_file, off, origin))
m_good = false;
return m_good;
@@ -840,14 +869,26 @@ bool IOFile::Seek(s64 off, int origin)
u64 IOFile::Tell()
{
if (IsOpen())
{
if (0 != (m_method & METHOD_GZIP))
return gztell(m_zFile);
return ftello(m_file);
}
else
return -1;
}
bool IOFile::Flush()
{
if (!IsOpen() || 0 != std::fflush(m_file))
if (!IsOpen())
m_good = false;
else if (0 != (m_method & METHOD_GZIP))
{
if (-1 == gzflush(m_zFile, Z_PARTIAL_FLUSH))
m_good = false;
}
else if (0 != std::fflush(m_file))
m_good = false;
return m_good;
@@ -855,7 +896,15 @@ bool IOFile::Flush()
bool IOFile::Resize(u64 size)
{
if (!IsOpen() || 0 !=
if (!IsOpen())
m_good = false;
else if (0 != (m_method & METHOD_GZIP))
{
// gzseek() adds nulls to the seeked location.
if (-1 == gzseek(m_zFile, (z_off_t) size, SEEK_SET))
m_good = false;
}
else if (0 !=
#ifdef _WIN32
// ector: _chsize sucks, not 64-bit safe
// F|RES: changed to _chsize_s. i think it is 64-bit safe
+34 -7
View File
@@ -25,6 +25,7 @@
#include <string.h>
#include "Common.h"
#include "../ext/zlib/zlib.h"
// User directory indices for GetUserPath
enum {
@@ -124,6 +125,13 @@ std::string &GetExeDirectory();
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename);
bool ReadFileToString(bool text_file, const char *filename, std::string &str);
enum IOFileMethod
{
METHOD_STANDARD = 0x00,
// Warning: may not be 64-bit safe.
METHOD_GZIP = 0x01,
};
// simple wrapper for cstdlib file functions to
// hopefully will make error checking easier
// and make forgetting an fclose() harder
@@ -132,17 +140,24 @@ class IOFile : NonCopyable
public:
IOFile();
IOFile(std::FILE* file);
IOFile(const std::string& filename, const char openmode[]);
IOFile(const std::string& filename, const char openmode[], IOFileMethod method = METHOD_STANDARD);
~IOFile();
bool Open(const std::string& filename, const char openmode[]);
bool Open(const std::string& filename, const char openmode[], IOFileMethod method = METHOD_STANDARD);
bool Close();
template <typename T>
bool ReadArray(T* data, size_t length)
{
if (!IsOpen() || length != std::fread(data, sizeof(T), length, m_file))
if (!IsOpen())
m_good = false;
else if (0 != (m_method & METHOD_GZIP))
{
if (sizeof(T) * length != gzread(m_zFile, data, sizeof(T) * length))
m_good = false;
}
else if (length != std::fread(data, sizeof(T), length, m_file))
m_good = false;
return m_good;
@@ -151,7 +166,14 @@ public:
template <typename T>
bool WriteArray(const T* data, size_t length)
{
if (!IsOpen() || length != std::fwrite(data, sizeof(T), length, m_file))
if (!IsOpen())
m_good = false;
else if (0 != (m_method & METHOD_GZIP))
{
if (sizeof(T) * length != gzwrite(m_zFile, data, sizeof(T) * length))
m_good = false;
}
else if (length != std::fwrite(data, sizeof(T), length, m_file))
m_good = false;
return m_good;
@@ -167,11 +189,11 @@ public:
return WriteArray(reinterpret_cast<const char*>(data), length);
}
bool IsOpen() { return NULL != m_file; }
bool IsOpen() { return NULL != m_file || NULL != m_zFile; }
// m_good is set to false when a read, write or other function fails
bool IsGood() { return m_good; }
operator void*() { return m_good ? m_file : NULL; }
operator void*() { return m_good ? (NULL != m_file ? m_file : m_zFile) : NULL; }
std::FILE* ReleaseHandle();
@@ -189,13 +211,18 @@ public:
void Clear() {
m_good = true;
#undef clearerr
std::clearerr(m_file);
if (NULL != m_file)
std::clearerr(m_file);
if (NULL != m_zFile)
gzclearerr(m_zFile);
}
private:
IOFile& operator=(const IOFile&) /*= delete*/;
std::FILE* m_file;
gzFile m_zFile;
IOFileMethod m_method;
bool m_good;
};