Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
147
Src/external_dependencies/openmpt-trunk/unarchiver/ungzip.cpp
Normal file
147
Src/external_dependencies/openmpt-trunk/unarchiver/ungzip.cpp
Normal file
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* ungzip.cpp
|
||||
* ----------
|
||||
* Purpose: Implementation file for extracting modules from .gz archives
|
||||
* Notes : (currently none)
|
||||
* Authors: OpenMPT Devs
|
||||
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
|
||||
*/
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "../common/FileReader.h"
|
||||
#include "ungzip.h"
|
||||
|
||||
#if defined(MPT_WITH_ZLIB) || defined(MPT_WITH_MINIZ)
|
||||
|
||||
#if defined(MPT_WITH_ZLIB)
|
||||
#include <zlib.h>
|
||||
#elif defined(MPT_WITH_MINIZ)
|
||||
#include <miniz/miniz.h>
|
||||
#endif
|
||||
|
||||
#endif // MPT_WITH_ZLIB || MPT_WITH_MINIZ
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
#if defined(MPT_WITH_ZLIB) || defined(MPT_WITH_MINIZ)
|
||||
|
||||
|
||||
CGzipArchive::CGzipArchive(const FileReader &file) : ArchiveBase(file)
|
||||
{
|
||||
inFile.Rewind();
|
||||
inFile.ReadStruct(header);
|
||||
|
||||
// Check header data + file size
|
||||
if(header.magic1 != GZ_HMAGIC1 || header.magic2 != GZ_HMAGIC2 || header.method != GZ_HMDEFLATE || (header.flags & GZ_FRESERVED) != 0
|
||||
|| inFile.GetLength() <= sizeof(GZheader) + sizeof(GZtrailer))
|
||||
{
|
||||
return;
|
||||
}
|
||||
ArchiveFileInfo info;
|
||||
info.type = ArchiveFileType::Normal;
|
||||
contents.push_back(info);
|
||||
}
|
||||
|
||||
|
||||
CGzipArchive::~CGzipArchive()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool CGzipArchive::ExtractFile(std::size_t index)
|
||||
{
|
||||
if(index >= contents.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read trailer
|
||||
GZtrailer trailer;
|
||||
inFile.Seek(inFile.GetLength() - sizeof(GZtrailer));
|
||||
inFile.ReadStruct(trailer);
|
||||
|
||||
// Continue reading header
|
||||
inFile.Seek(sizeof(GZheader));
|
||||
|
||||
// Extra block present? (skip the extra data)
|
||||
if(header.flags & GZ_FEXTRA)
|
||||
{
|
||||
inFile.Skip(inFile.ReadUint16LE());
|
||||
}
|
||||
|
||||
// Filename present? (ignore)
|
||||
if(header.flags & GZ_FNAME)
|
||||
{
|
||||
while(inFile.ReadUint8() != 0);
|
||||
}
|
||||
|
||||
// Comment present? (ignore)
|
||||
if(header.flags & GZ_FCOMMENT)
|
||||
{
|
||||
while(inFile.ReadUint8() != 0);
|
||||
}
|
||||
|
||||
// CRC16 present? (ignore)
|
||||
if(header.flags & GZ_FHCRC)
|
||||
{
|
||||
inFile.Skip(2);
|
||||
}
|
||||
|
||||
// Well, this is a bit small when deflated.
|
||||
if(!inFile.CanRead(sizeof(GZtrailer)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
data.reserve(inFile.BytesLeft());
|
||||
} catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Inflate!
|
||||
z_stream strm{};
|
||||
strm.zalloc = Z_NULL;
|
||||
strm.zfree = Z_NULL;
|
||||
strm.opaque = Z_NULL;
|
||||
strm.avail_in = 0;
|
||||
strm.next_in = Z_NULL;
|
||||
if(inflateInit2(&strm, -15) != Z_OK)
|
||||
return false;
|
||||
int retVal = Z_OK;
|
||||
uint32 crc = 0;
|
||||
auto bytesLeft = inFile.BytesLeft() - sizeof(GZtrailer);
|
||||
do
|
||||
{
|
||||
std::array<char, mpt::IO::BUFFERSIZE_SMALL> inBuffer, outBuffer;
|
||||
strm.avail_in = static_cast<uInt>(std::min(static_cast<FileReader::pos_type>(inBuffer.size()), bytesLeft));
|
||||
inFile.ReadStructPartial(inBuffer, strm.avail_in);
|
||||
strm.next_in = reinterpret_cast<Bytef *>(inBuffer.data());
|
||||
bytesLeft -= strm.avail_in;
|
||||
do
|
||||
{
|
||||
strm.avail_out = static_cast<uInt>(outBuffer.size());
|
||||
strm.next_out = reinterpret_cast<Bytef *>(outBuffer.data());
|
||||
retVal = inflate(&strm, Z_NO_FLUSH);
|
||||
const auto output = mpt::as_span(outBuffer.data(), outBuffer.data() + outBuffer.size() - strm.avail_out);
|
||||
crc = crc32(crc, reinterpret_cast<Bytef *>(output.data()), static_cast<uInt>(output.size()));
|
||||
data.insert(data.end(), output.begin(), output.end());
|
||||
} while(strm.avail_out == 0);
|
||||
} while(retVal == Z_OK && bytesLeft);
|
||||
inflateEnd(&strm);
|
||||
|
||||
// Everything went OK? Check return code, number of written bytes and CRC32.
|
||||
return retVal == Z_STREAM_END && trailer.isize == static_cast<uint32>(strm.total_out) && trailer.crc32_ == crc;
|
||||
}
|
||||
|
||||
|
||||
#endif // MPT_WITH_ZLIB || MPT_WITH_MINIZ
|
||||
|
||||
|
||||
OPENMPT_NAMESPACE_END
|
Loading…
Add table
Add a link
Reference in a new issue