File: GzipWriter.h

package info (click to toggle)
libopenmpt 0.8.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 9,844 kB
  • sloc: cpp: 129,366; sh: 4,695; ansic: 1,107; makefile: 712
file content (94 lines) | stat: -rw-r--r-- 2,294 bytes parent folder | download
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
/*
 * GzipWriter.h
 * ------------
 * Purpose: Simple wrapper around zlib's Gzip writer
 * Notes  : miniz doesn't implement Gzip writing, so this is only compatible with zlib.
 * Authors: OpenMPT Devs
 * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
 */


#pragma once

#include "openmpt/all/BuildSettings.hpp"

#include "mpt/io/io.hpp"
#include "mpt/io/io_stdstream.hpp"

#include "mptString.h"

#ifdef MPT_WITH_ZLIB

#include <ctime>

#include <zlib.h>

OPENMPT_NAMESPACE_BEGIN

inline void WriteGzip(std::ostream &output, std::string &outData, const mpt::ustring &fileName)
{
	z_stream strm{};
	int zlib_errc = Z_OK;
	strm.avail_in = static_cast<uInt>(outData.size());
	strm.next_in = reinterpret_cast<Bytef *>(outData.data());
	zlib_errc = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, 15 | 16, 9, Z_DEFAULT_STRATEGY);
	if(zlib_errc == Z_MEM_ERROR)
	{
		mpt::throw_out_of_memory();
	} else if(zlib_errc < Z_OK)
	{
		throw std::runtime_error{"zlib: deflateInit2() failed"};
	}
	gz_header gzHeader{};
	gzHeader.time = static_cast<uLong>(std::time(nullptr));
	std::string filenameISO = mpt::ToCharset(mpt::Charset::ISO8859_1, fileName);
	gzHeader.name = reinterpret_cast<Bytef *>(filenameISO.data());
	zlib_errc = deflateSetHeader(&strm, &gzHeader);
	if(zlib_errc == Z_MEM_ERROR)
	{
		deflateEnd(&strm);
		mpt::throw_out_of_memory();
	} else if(zlib_errc < Z_OK)
	{
		deflateEnd(&strm);
		throw std::runtime_error{"zlib: deflateSetHeader() failed"};
	}
	try
	{
		do
		{
			std::array<Bytef, mpt::IO::BUFFERSIZE_TINY> buffer;
			strm.avail_out = static_cast<uInt>(buffer.size());
			strm.next_out = buffer.data();
			zlib_errc = deflate(&strm, Z_FINISH);
			if(zlib_errc == Z_BUF_ERROR)
			{
				// expected
			} else if(zlib_errc == Z_MEM_ERROR)
			{
				mpt::throw_out_of_memory();
			} else if(zlib_errc < Z_OK)
			{
				throw std::runtime_error{"zlib: deflate() failed"};
			}
			mpt::IO::WritePartial(output, buffer, buffer.size() - strm.avail_out);
		} while(strm.avail_out == 0);
	} catch(mpt::out_of_memory e)
	{
		deflateEnd(&strm);
		mpt::rethrow_out_of_memory(e);
	} catch(const std::exception &)
	{
		deflateEnd(&strm);
		throw;
	} catch(...)
	{
		deflateEnd(&strm);
		throw;
	}
	deflateEnd(&strm);
}

OPENMPT_NAMESPACE_END

#endif