ail now builds on Linux
[ail.git] / ail / zlib.cpp
blob70ed4f826023dfbca69c2351daf72ea33cc34617
1 #include <iostream>
2 #include <zlib.h>
3 #include <ail/zlib.hpp>
5 namespace ail
7 namespace
9 std::size_t const buffer_size = 16 * 1024;
10 int gzip_window_bits = 16 + MAX_WBITS;
13 std::string get_zlib_error_string(int error)
15 switch(error)
17 case Z_BUF_ERROR:
18 return "zlib: Buffer error";
20 case Z_MEM_ERROR:
21 return "zlib: Insufficient memory";
23 case Z_STREAM_ERROR:
24 return "zlib: Stream error";
26 case Z_NEED_DICT:
27 return "zlib: Need dictionary";
29 case Z_DATA_ERROR:
30 return "zlib: Invalid input";
32 default:
33 return "zlib: Unknown inflation error occured";
37 void deflate_data(char const * input, std::size_t size, bool is_gzip, std::string & output)
39 char buffer[buffer_size];
41 z_stream stream;
43 stream.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(input));
44 stream.avail_in = static_cast<uInt>(size);
45 stream.next_out = reinterpret_cast<Bytef *>(buffer);
46 stream.avail_out = static_cast<uInt>(sizeof(buffer));
47 stream.zalloc = Z_NULL;
48 stream.zfree = Z_NULL;
49 stream.opaque = Z_NULL;
51 int result;
52 if(is_gzip)
53 result = ::deflateInit2(&stream, Z_BEST_COMPRESSION, Z_DEFLATED, gzip_window_bits, 8, Z_DEFAULT_STRATEGY);
54 else
55 result = ::deflateInit(&stream, Z_BEST_COMPRESSION);
57 if(result != Z_OK)
58 throw exception("zlib: Deflate initialisation error");
60 while(true)
62 stream.next_out = reinterpret_cast<Bytef *>(buffer);
63 stream.avail_out = static_cast<uInt>(sizeof(buffer));
65 int result = ::deflate(&stream, Z_SYNC_FLUSH);
66 if(result == Z_OK)
67 output.append(buffer, static_cast<uInt>(sizeof(buffer)) - stream.avail_out);
68 else
70 ::deflateEnd(&stream);
71 throw exception(get_zlib_error_string(result));
74 if(stream.total_in == size)
75 break;
78 ::deflateEnd(&stream);
81 void inflate_data(char const * input, std::size_t size, bool is_gzip, std::string & output)
83 char buffer[buffer_size];
85 z_stream stream;
87 stream.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(input));
88 stream.avail_in = static_cast<uInt>(size);
89 stream.next_out = reinterpret_cast<Bytef *>(buffer);
90 stream.avail_out = static_cast<uInt>(sizeof(buffer));
91 stream.zalloc = Z_NULL;
92 stream.zfree = Z_NULL;
93 stream.opaque = Z_NULL;
95 int result;
97 if(is_gzip)
98 result = ::inflateInit2(&stream, gzip_window_bits);
99 else
100 result = ::inflateInit(&stream);
102 if(result != Z_OK)
103 throw exception("zlib: Inflate initialisation error");
105 while(true)
107 stream.next_out = reinterpret_cast<Bytef *>(buffer);
108 stream.avail_out = static_cast<uInt>(sizeof(buffer));
110 int result = ::inflate(&stream, Z_SYNC_FLUSH);
111 switch(result)
113 case Z_OK:
114 case Z_STREAM_END:
115 output.append(buffer, static_cast<uInt>(sizeof(buffer)) - stream.avail_out);
116 break;
118 default:
119 ::inflateEnd(&stream);
120 throw exception(get_zlib_error_string(result));
123 if(stream.total_in == size)
124 break;
127 ::inflateEnd(&stream);
130 void deflate(char const * input, std::size_t size, std::string & output)
132 deflate_data(input, size, false, output);
135 void compress_gzip(char const * input, std::size_t size, std::string & output)
137 deflate_data(input, size, true, output);
140 void deflate(std::string const & input, std::string & output)
142 deflate(input.c_str(), input.size(), output);
145 void compress_gzip(std::string const & input, std::string & output)
147 compress_gzip(input.c_str(), input.size(), output);
150 void inflate(char const * input, std::size_t size, std::string & output)
152 inflate_data(input, size, false, output);
155 void decompress_gzip(char const * input, std::size_t size, std::string & output)
157 inflate_data(input, size, true, output);
160 void inflate(std::string const & input, std::string & output)
162 inflate(input.c_str(), input.size(), output);
165 void decompress_gzip(std::string const & input, std::string & output)
167 decompress_gzip(input.c_str(), input.size(), output);