Support: quest -f cjk_ngram
[xapian.git] / xapian-core / common / compression_stream.cc
blob24571e0cde957d352309533559c6674a0d15f512
1 /** @file compression_stream.cc
2 * @brief class wrapper around zlib
3 */
4 /* Copyright (C) 2007,2009,2012,2013,2014 Olly Betts
5 * Copyright (C) 2009 Richard Boulton
6 * Copyright (C) 2012 Dan Colish
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 #include <config.h>
24 #include "compression_stream.h"
25 #include "str.h"
26 #include "stringutils.h"
28 #include "xapian/error.h"
30 using namespace std;
32 CompressionStream::CompressionStream(int compress_strategy_)
33 : compress_strategy(compress_strategy_),
34 zerr(0),
35 out_len(0),
36 out(NULL),
37 deflate_zstream(NULL),
38 inflate_zstream(NULL)
40 // LOGCALL_CTOR()
43 CompressionStream::~CompressionStream() {
44 if (deflate_zstream) {
45 // Errors which we care about have already been handled, so just ignore
46 // any which get returned here.
47 (void) deflateEnd(deflate_zstream);
48 delete deflate_zstream;
51 if (inflate_zstream) {
52 // Errors which we care about have already been handled, so just ignore
53 // any which get returned here.
54 (void) inflateEnd(inflate_zstream);
55 delete inflate_zstream;
58 delete [] out;
62 void
63 CompressionStream::compress(string & buf) {
64 if (!out || out_len < buf.size() - 1) {
65 delete [] out;
66 out = NULL;
67 out_len = buf.size() - 1;
68 out = new unsigned char[out_len];
70 deflate_zstream->avail_in = (uInt)buf.size();
71 deflate_zstream->next_in = (Bytef *)const_cast<char *>(buf.data());
72 deflate_zstream->next_out = out;
73 deflate_zstream->avail_out = (uInt)(buf.size() - 1);
74 zerr = deflate(deflate_zstream, Z_FINISH);
78 void
79 CompressionStream::compress(const byte * buf, int size) {
80 if (!out || out_len < unsigned(size - 1)) {
81 delete [] out;
82 out = NULL;
83 out_len = size - 1;
84 out = new unsigned char[out_len];
86 deflate_zstream->avail_in = (uInt)size;
87 deflate_zstream->next_in = (Bytef *)const_cast<byte *>(buf);
88 deflate_zstream->next_out = out;
89 deflate_zstream->avail_out = (uInt)(size - 1);
90 zerr = deflate(deflate_zstream, Z_FINISH);
93 void
94 CompressionStream::lazy_alloc_deflate_zstream() const {
95 if (usual(deflate_zstream)) {
96 if (usual(deflateReset(deflate_zstream) == Z_OK)) return;
97 // Try to recover by deleting the stream and starting from scratch.
98 delete deflate_zstream;
101 deflate_zstream = new z_stream;
103 deflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
104 deflate_zstream->zfree = reinterpret_cast<free_func>(0);
105 deflate_zstream->opaque = (voidpf)0;
107 // -15 means raw deflate with 32K LZ77 window (largest)
108 // memLevel 9 is the highest (8 is default)
109 int err;
110 // FIXME:dc: this needs to really use compress_strategy if set
111 err = deflateInit2(deflate_zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
112 -15, 9, Z_DEFAULT_STRATEGY);
113 if (rare(err != Z_OK)) {
114 if (err == Z_MEM_ERROR) {
115 delete deflate_zstream;
116 deflate_zstream = 0;
117 throw std::bad_alloc();
119 string msg = "deflateInit2 failed (";
120 if (deflate_zstream->msg) {
121 msg += deflate_zstream->msg;
122 } else {
123 msg += str(err);
125 msg += ')';
126 delete deflate_zstream;
127 deflate_zstream = 0;
128 throw Xapian::DatabaseError(msg);
132 void
133 CompressionStream::lazy_alloc_inflate_zstream() const {
134 if (usual(inflate_zstream)) {
135 if (usual(inflateReset(inflate_zstream) == Z_OK)) return;
136 // Try to recover by deleting the stream and starting from scratch.
137 delete inflate_zstream;
140 inflate_zstream = new z_stream;
142 inflate_zstream->zalloc = reinterpret_cast<alloc_func>(0);
143 inflate_zstream->zfree = reinterpret_cast<free_func>(0);
145 inflate_zstream->next_in = Z_NULL;
146 inflate_zstream->avail_in = 0;
148 int err = inflateInit2(inflate_zstream, -15);
149 if (rare(err != Z_OK)) {
150 if (err == Z_MEM_ERROR) {
151 delete inflate_zstream;
152 inflate_zstream = 0;
153 throw std::bad_alloc();
155 string msg = "inflateInit2 failed (";
156 if (inflate_zstream->msg) {
157 msg += inflate_zstream->msg;
158 } else {
159 msg += str(err);
161 msg += ')';
162 delete inflate_zstream;
163 inflate_zstream = 0;
164 throw Xapian::DatabaseError(msg);