libutil++  1.9.3
 All Classes Functions Variables
Compress.cpp
1 /*
2 ** libutil++
3 ** $Id: Compress.cpp 1653 2016-02-28 19:54:59Z sella $
4 ** Copyright (c) 2011-2016 Digital Genesis, LLC. All Rights Reserved.
5 ** Released under the LGPL Version 2.1 License.
6 ** http://www.digitalgenesis.com
7 */
8 
9 static const char rcsid[] __attribute__((used)) = "$Id: Compress.cpp 1653 2016-02-28 19:54:59Z sella $";
10 
11 #include "Compress.h"
12 #include "CommonMacro.h"
13 
14 #include <zlib.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <signal.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <pthread.h>
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <assert.h>
24 
25 #define SET_BINARY_MODE(file)
26 
27 #define CHUNK 16384
28 //#define DUMP
29 
30 using namespace sella::util;
31 
32 Compress::Compress(int level) : c(NULL), un(NULL), clen(0), unlen(0) {
33  setLevel(level);
34 }
35 
36 Compress::Compress(const Compress &other) :
37  level(other.level),
38  c(malloc(other.clen)),
39  un(malloc(other.unlen)),
40 
41  clen(other.clen),
42  unlen(other.unlen)
43 {
44  memcpy(this->c, other.c, this->clen);
45  memcpy(this->un, other.un, this->unlen);
46 }
47 
48 Compress::~Compress() {
49  clear();
50 }
51 
52 Compress& Compress::operator=(const Compress &other) throw () {
53  if (this != &other) {
54  this->level = other.level;
55  this->clen = other.clen;
56  this->unlen = other.unlen;
57  }
58 
59  c = malloc(this->clen);
60  memcpy(this->c, other.c, this->clen);
61 
62  un = malloc(this->unlen);
63  memcpy(this->un, other.un, this->unlen);
64 
65  return *this;
66 }
67 
68 void Compress::clear(void) {
69  SAFE_FREE(c);
70  SAFE_FREE(un);
71 
72  clen = 0;
73  unlen = 0;
74 }
75 
76 void Compress::setLevel(int level) {
77  this->level = level;
78 }
79 
80 int Compress::getLevel(void) const {
81  return level;
82 }
83 
84 bool Compress::deflate(const void *uncompressed, size_t len) {
85  bool retval = true;
86  int ret;
87  unsigned int avail_out;
88  z_stream strm;
89 
90  SAFE_FREE(c);
91  clen = 0;
92 
93 #ifdef DUMP
94  printf("deflate: uncompressed(%d): 0x", len);
95  for (int i = 0; i < len; i++) {
96  printf("%.2x", ((unsigned char*) uncompressed)[i]);
97  }
98  printf("\n");
99 #endif
100 
101  if (uncompressed == NULL || len < 1) {
102  return false;
103  }
104 
105  /* allocate deflate state */
106  strm.zalloc = Z_NULL;
107  strm.zfree = Z_NULL;
108  strm.opaque = Z_NULL;
109 
110  if ((ret = deflateInit(&strm, level)) != Z_OK) {
111  return false;
112  }
113 
114  avail_out = deflateBound(&strm, len);
115 
116  if ((c = malloc(avail_out)) == NULL) {
117  retval = false;
118 
119  goto cleanup;
120  }
121 
122  strm.next_in = (Bytef*) uncompressed;
123  strm.avail_in = len;
124  strm.next_out = (Bytef*) c;
125  strm.avail_out = avail_out;
126 
127  if ((ret = ::deflate(&strm, Z_FINISH)) == Z_STREAM_ERROR) {
128  retval = false;
129 
130  goto cleanup;
131  }
132 
133  if (strm.avail_out == 0) {
134  retval = false;
135 
136  goto cleanup;
137  }
138 
139  clen = strm.total_out;
140 
141 #ifdef DUMP
142  printf("deflate: compressed(%d): 0x", clen);
143  for (int i = 0; i < clen; i++) {
144  printf("%.2x", ((unsigned char*) c)[i]);
145  }
146  printf("\n");
147 #endif
148 
149 cleanup:
150  (void) deflateEnd(&strm);
151 
152  if (!retval) {
153  SAFE_FREE(c);
154  clen = 0;
155  }
156 
157  return retval;
158 }
159 
160 bool Compress::inflate(const void *compressed, size_t len) {
161  bool retval = true;
162  int ret;
163  unsigned int delta;
164  z_stream strm;
165  unsigned char buf[CHUNK];
166  void *ptr;
167 
168  SAFE_FREE(un);
169  unlen = 0;
170 
171 #ifdef DUMP
172  printf("inflate: compressed(%d): 0x", len);
173  for (int i = 0; i < len; i++) {
174  printf("%.2x", ((unsigned char*) compressed)[i]);
175  }
176  printf("\n");
177 #endif
178 
179  if (compressed == NULL || len < 1) {
180  return false;
181  }
182 
183  /* allocate deflate state */
184  strm.zalloc = Z_NULL;
185  strm.zfree = Z_NULL;
186  strm.opaque = Z_NULL;
187  strm.avail_in = 0;
188  strm.next_in = Z_NULL;
189 
190  if ((ret = inflateInit(&strm)) != Z_OK) {
191  return false;
192  }
193 
194  strm.avail_in = len;
195  strm.next_in = (Bytef*) compressed;
196 
197  do {
198  strm.avail_out = CHUNK;
199  strm.next_out = buf;
200 
201  ret = ::inflate(&strm, Z_NO_FLUSH);
202  if (ret != Z_OK && ret != Z_STREAM_END) {
203  retval = false;
204 
205  goto error;
206  }
207 
208  /* Resize and append next_out. */
209  un = realloc(un, strm.total_out);
210  delta = CHUNK - strm.avail_out;
211  ptr = (Bytef*) un + (strm.total_out - delta);
212  memcpy(ptr, buf, delta);
213  } while (strm.avail_out == 0);
214 
215 error:
216  (void) inflateEnd(&strm);
217 
218  if (!retval) {
219  SAFE_FREE(un);
220  unlen = 0;
221  }
222 
223  return retval;
224 }
225 
226 const void* Compress::getCompressed(void) const {
227  return c;
228 }
229 
230 const void* Compress::getUncompressed(void) const {
231  return un;
232 }
233 
234 size_t Compress::getCompressedLen(void) const {
235  return clen;
236 }
237 
238 size_t Compress::getUncompressedLen(void) const {
239  return unlen;
240 }
241 
242 /*
243 ** vim: noet ts=3 sw=3
244 */