1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#include "GZFileHandler.h"
#include <cassert>
#include <string>
#include <zlib.h>
#include "FileQueryFlags.h"
#include "FileSystem.h"
#ifndef TOOLS
#include "VFSHandler.h"
#include "DataDirsAccess.h"
#include "System/Util.h"
#include "System/Platform/Misc.h"
#endif
#define BUFFER_SIZE 8192
//We must call Open from here since in the CFileHandler ctor
//virtual functions aren't called.
CGZFileHandler::CGZFileHandler(const char* fileName, const char* modes) : CFileHandler()
{
Open(fileName, modes);
}
CGZFileHandler::CGZFileHandler(const std::string& fileName, const std::string& modes): CFileHandler()
{
Open(fileName, modes);
}
bool CGZFileHandler::ReadToBuffer(const std::string& path)
{
assert(fileBuffer.empty());
gzFile file = gzopen(path.c_str(), "rb");
if (file == Z_NULL)
return false;
boost::uint8_t unzipBuffer[BUFFER_SIZE];
while (true) {
int unzippedBytes = gzread(file, unzipBuffer, BUFFER_SIZE);
if (unzippedBytes < 0) {
fileBuffer.clear();
fileSize = -1;
gzclose(file);
return false;
}
if (unzippedBytes == 0)
break;
fileBuffer.insert(fileBuffer.end(), unzipBuffer, unzipBuffer + unzippedBytes);
}
gzclose(file);
fileSize = fileBuffer.size();
return true;
}
bool CGZFileHandler::UncompressBuffer()
{
std::vector<boost::uint8_t> compressed;
std::swap(compressed, fileBuffer);
z_stream zstream;
zstream.opaque = Z_NULL;
zstream.zalloc = Z_NULL;
zstream.zfree = Z_NULL;
zstream.data_type = Z_BINARY;
//+16 marks it's a gzip header
inflateInit2(&zstream, 15 + 16);
zstream.next_in = &compressed[0];
zstream.avail_in = compressed.size();
boost::uint8_t unzipBuffer[BUFFER_SIZE];
while (true) {
zstream.avail_out = BUFFER_SIZE;
zstream.next_out = unzipBuffer;
const int ret = inflate(&zstream, Z_NO_FLUSH);
if (ret != Z_OK) {
fileBuffer.clear();
fileSize = -1;
return false;
}
const size_t unzippedBytes = BUFFER_SIZE - zstream.avail_out;
fileBuffer.insert(fileBuffer.end(), unzipBuffer, unzipBuffer + unzippedBytes);
if (ret == Z_STREAM_END)
break;
}
inflateEnd(&zstream);
fileSize = fileBuffer.size();
return true;
}
bool CGZFileHandler::TryReadFromPWD(const std::string& fileName)
{
#ifndef TOOLS
if (FileSystem::IsAbsolutePath(fileName))
return false;
const std::string fullpath(Platform::GetOrigCWD() + fileName);
#else
const std::string fullpath(fileName);
#endif
return ReadToBuffer(fullpath);
}
bool CGZFileHandler::TryReadFromRawFS(const std::string& fileName)
{
#ifndef TOOLS
const std::string rawpath = dataDirsAccess.LocateFile(fileName);
return ReadToBuffer(rawpath);
#else
return false;
#endif
}
bool CGZFileHandler::TryReadFromModFS(const std::string& fileName)
{
return CFileHandler::TryReadFromModFS(fileName) && UncompressBuffer();
}
|