| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 | 
							- //	Copyright (C) 2011 Michael McMaster <michael@codesrc.com>
 
- //
 
- //	This file is part of libzipper.
 
- //
 
- //	libzipper 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 3 of the License, or
 
- //	(at your option) any later version.
 
- //
 
- //	libzipper 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 libzipper.  If not, see <http://www.gnu.org/licenses/>.
 
- #include "zipper.hh"
 
- #include "deflate.hh"
 
- #include "util.hh"
 
- #include <zlib.h>
 
- #include <cassert>
 
- #include <iostream>
 
- using namespace zipper;
 
- namespace
 
- {
 
- 	struct DeflateDeleter
 
- 	{
 
- 	public:
 
- 		DeflateDeleter(z_stream* stream) : m_stream(stream) {}
 
- 		~DeflateDeleter()
 
- 		{
 
- 			deflateEnd(m_stream);
 
- 		}
 
- 	private:
 
- 		z_stream* m_stream;
 
- 	};
 
- 	struct InflateDeleter
 
- 	{
 
- 	public:
 
- 		InflateDeleter(z_stream* stream) : m_stream(stream) {}
 
- 		~InflateDeleter()
 
- 		{
 
- 			inflateEnd(m_stream);
 
- 		}
 
- 	private:
 
- 		z_stream* m_stream;
 
- 	};
 
- 	enum Constants
 
- 	{
 
- 		ChunkSize = 64*1024,
 
- 		WindowBits = 15
 
- 	};
 
- }
 
- void
 
- zipper::deflate(
 
- 	const Reader& reader,
 
- 	const WriterPtr& writer,
 
- 	zsize_t& writeOffset,
 
- 	zsize_t& uncompressedSize,
 
- 	zsize_t& compressedSize,
 
- 	uint32_t& crc)
 
- {
 
- 	uint8_t inChunk[ChunkSize];
 
- 	uint8_t outChunk[ChunkSize];
 
- 	uncompressedSize = 0;
 
- 	compressedSize = 0;
 
- 	z_stream stream;
 
- 	stream.zalloc = NULL;
 
- 	stream.zfree = NULL;
 
- 	stream.opaque = NULL;
 
- 	int zlibErr(
 
- 		deflateInit2(
 
- 			&stream,
 
- 			Z_DEFAULT_COMPRESSION,
 
- 			Z_DEFLATED,
 
- 			-WindowBits,
 
- 			MAX_MEM_LEVEL,
 
- 			Z_DEFAULT_STRATEGY)
 
- 			);
 
- 	assert(zlibErr == Z_OK);
 
- 	DeflateDeleter deleter(&stream);
 
- 	stream.next_in = NULL;
 
- 	stream.avail_in = 0;
 
- 	bool finished(false);
 
- 	zsize_t pos(0);
 
- 	zsize_t end(reader.getSize());
 
- 	crc = crc32(0, NULL, 0);
 
- 	while (!finished)
 
- 	{
 
- 		if ((stream.avail_in == 0) && (pos < end))
 
- 		{
 
- 			stream.avail_in =
 
- 				std::min(zsize_t(ChunkSize), end - pos);
 
- 			reader.readData(
 
- 				pos, stream.avail_in, &inChunk[0]);
 
- 			stream.next_in = reinterpret_cast<Bytef*>(&inChunk);
 
- 			pos += stream.avail_in;
 
- 			uncompressedSize += stream.avail_in;
 
- 			crc = crc32(crc, stream.next_in, stream.avail_in);
 
- 		}
 
- 		stream.next_out = reinterpret_cast<Bytef*>(&outChunk);
 
- 		stream.avail_out = sizeof(outChunk);
 
- 		finished = false;
 
- 		zlibErr = deflate(&stream, (pos < end) ? Z_NO_FLUSH : Z_FINISH);
 
- 		if (zlibErr == Z_STREAM_END)
 
- 		{
 
- 			if (pos < end)
 
- 			{
 
- 				assert(!"zlib buffer unexpectedly empty");
 
- 				std::terminate();
 
- 			}
 
- 			finished = true;
 
- 		}
 
- 		else if (zlibErr != Z_OK)
 
- 		{
 
- 			throw FormatException("Corrupt Data");
 
- 		}
 
- 		zsize_t bytesToWrite(sizeof(outChunk) - stream.avail_out);
 
- 		writer->writeData(writeOffset, bytesToWrite, &outChunk[0]);
 
- 		writeOffset += bytesToWrite;
 
- 		compressedSize += bytesToWrite;
 
- 	}
 
- }
 
- void
 
- zipper::inflate(
 
- 	const ReaderPtr& reader,
 
- 	Writer& writer,
 
- 	zsize_t& readOffset,
 
- 	zsize_t readEnd,
 
- 	zsize_t& writeOffset,
 
- 	uint32_t& crc)
 
- {
 
- 	uint8_t inChunk[ChunkSize];
 
- 	uint8_t outChunk[ChunkSize];
 
- 	z_stream stream;
 
- 	stream.zalloc = NULL;
 
- 	stream.zfree = NULL;
 
- 	stream.opaque = NULL;
 
- 	int zlibErr(inflateInit2(&stream, -WindowBits));
 
- 	assert(zlibErr == Z_OK);
 
- 	InflateDeleter deleter(&stream);
 
- 	stream.next_in = NULL;
 
- 	stream.avail_in = 0;
 
- 	bool finished(false);
 
- 	zsize_t pos(readOffset);
 
- 	crc = crc32(0, NULL, 0);
 
- 	while (!finished)
 
- 	{
 
- 		if (stream.avail_in == 0)
 
- 		{
 
- 			stream.avail_in = std::min(zsize_t(ChunkSize), readEnd - pos);
 
- 			if (stream.avail_in == 0)
 
- 			{
 
- 				break;
 
- 			}
 
- 			reader->readData(pos, stream.avail_in, &inChunk[0]);
 
- 			stream.next_in = reinterpret_cast<Bytef*>(&inChunk);
 
- 			pos += stream.avail_in;
 
- 		}
 
- 		stream.next_out = reinterpret_cast<Bytef*>(&outChunk);
 
- 		stream.avail_out = sizeof(outChunk);
 
- 		zlibErr = inflate(&stream, Z_SYNC_FLUSH);
 
- 		finished = false;
 
- 		if (zlibErr == Z_STREAM_END)
 
- 		{
 
- 			finished = true;
 
- 		}
 
- 		else if (zlibErr != Z_OK)
 
- 		{
 
- 			throw FormatException("Corrupt Data");
 
- 		}
 
- 		zsize_t bytesToWrite(sizeof(outChunk) - stream.avail_out);
 
- 		writer.writeData(writeOffset, bytesToWrite, &outChunk[0]);
 
- 		writeOffset += bytesToWrite;
 
- 		crc = crc32(crc, &outChunk[0], bytesToWrite);
 
- 	}
 
- 	if (!finished)
 
- 	{
 
- 		// Ran out of data to process
 
- 		throw FormatException("Corrupt Data");
 
- 	}
 
- 	// We've read data that wasn't consumed!
 
- 	readOffset = pos - stream.avail_in;
 
- }
 
 
  |