The SWORD Project  1.9.0.svnversion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
xzcomprs.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * xzcomprs.cpp - XzCompress, a driver class that provides xz (LZMA2)
4  * compression
5  *
6  * $Id: xzcomprs.cpp 3775 2020-08-15 10:28:11Z scribe $
7  *
8  * Copyright 2000-2014 CrossWire Bible Society (http://www.crosswire.org)
9  * CrossWire Bible Society
10  * P. O. Box 2528
11  * Tempe, AZ 85280-2528
12  *
13  * This program is free software; you can redistribute it and/or modify it
14  * under the terms of the GNU General Public License as published by the
15  * Free Software Foundation version 2.
16  *
17  * This program is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * General Public License for more details.
21  *
22  */
23 
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <xzcomprs.h>
28 
29 #define LZMA_API_STATIC
30 #include <lzma.h>
31 
33 
34 /******************************************************************************
35  * XzCompress Constructor - Initializes data for instance of XzCompress
36  *
37  */
38 
40  level = 3;
41 
42  // start with the estimated memory usage for our preset
43  memlimit = lzma_easy_decoder_memusage(level | LZMA_PRESET_EXTREME);
44 
45  // and round up to a power of 2--
46  // bit twiddle hack to determine next greatest power of 2 from:
47  // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
48  memlimit--;
49  memlimit |= memlimit >> 1;
50  memlimit |= memlimit >> 2;
51  memlimit |= memlimit >> 4;
52  memlimit |= memlimit >> 8;
53  memlimit |= memlimit >> 16;
54  memlimit++;
55 
56  // double that for safety's sake
57  memlimit <<= 1;
58 }
59 
60 
61 /******************************************************************************
62  * XzCompress Destructor - Cleans up instance of XzCompress
63  */
64 
66 }
67 
68 
69 /******************************************************************************
70  * XzCompress::Encode - This function "encodes" the input stream into the
71  * output stream.
72  * The GetChars() and SendChars() functions are
73  * used to separate this method from the actual
74  * i/o.
75  * NOTE: must set zlen for parent class to know length of
76  * compressed buffer.
77  */
78 
79 void XzCompress::encode(void) {
80 
81  direct = 0; // set direction needed by parent [Get|Send]Chars()
82 
83  // get buffer
84  char chunk[1024];
85  char *buf = (char *)calloc(1, 1024);
86  char *chunkbuf = buf;
87  unsigned long chunklen;
88  unsigned long len = 0;
89  while((chunklen = getChars(chunk, 1023))) {
90  memcpy(chunkbuf, chunk, chunklen);
91  len += chunklen;
92  if (chunklen < 1023)
93  break;
94  else buf = (char *)realloc(buf, len + 1024);
95  chunkbuf = buf+len;
96  }
97 
98  zlen = (long)lzma_stream_buffer_bound(len);
99  char *zbuf = new char[zlen+1];
100  size_t zpos = 0;
101 
102  if (len) {
103  //printf("Doing compress\n");
104  switch (lzma_easy_buffer_encode(level | LZMA_PRESET_EXTREME, LZMA_CHECK_CRC64, NULL, (const uint8_t*)buf, (size_t)len, (uint8_t*)zbuf, &zpos, (size_t)zlen)) {
105  case LZMA_OK: sendChars(zbuf, zpos); break;
106  case LZMA_BUF_ERROR: fprintf(stderr, "ERROR: not enough room in the out buffer during compression.\n"); break;
107  case LZMA_UNSUPPORTED_CHECK: fprintf(stderr, "ERROR: unsupported_check error encountered during decompression.\n"); break;
108  case LZMA_OPTIONS_ERROR: fprintf(stderr, "ERROR: options error encountered during decompression.\n"); break;
109  case LZMA_MEM_ERROR: fprintf(stderr, "ERROR: not enough memory during compression.\n"); break;
110  case LZMA_DATA_ERROR: fprintf(stderr, "ERROR: corrupt data during compression.\n"); break;
111  case LZMA_PROG_ERROR: fprintf(stderr, "ERROR: program error encountered during decompression.\n"); break;
112  default: fprintf(stderr, "ERROR: an unknown error occurred during compression.\n"); break;
113  }
114  }
115  else {
116  fprintf(stderr, "ERROR: no buffer to compress\n");
117  }
118  delete [] zbuf;
119  free (buf);
120 }
121 
122 
123 /******************************************************************************
124  * XzCompress::Decode - This function "decodes" the input stream into the
125  * output stream.
126  * The GetChars() and SendChars() functions are
127  * used to separate this method from the actual
128  * i/o.
129  */
130 
131 void XzCompress::decode(void) {
132  direct = 1; // set direction needed by parent [Get|Send]Chars()
133 
134  // get buffer
135  char chunk[1024];
136  char *zbuf = (char *)calloc(1, 1024);
137  char *chunkbuf = zbuf;
138  int chunklen;
139  unsigned long zlen = 0;
140  while((chunklen = getChars(chunk, 1023))) {
141  memcpy(chunkbuf, chunk, chunklen);
142  zlen += chunklen;
143  if (chunklen < 1023)
144  break;
145  else zbuf = (char *)realloc(zbuf, zlen + 1024);
146  chunkbuf = zbuf + zlen;
147  }
148 
149  //printf("Decoding complength{%ld} uncomp{%ld}\n", zlen, blen);
150  if (zlen) {
151  unsigned long blen = zlen*20; // trust compression is less than 2000%
152  char *buf = new char[blen];
153  //printf("Doing decompress {%s}\n", zbuf);
154  slen = 0;
155  size_t zpos = 0;
156  size_t bpos = 0;
157 
158  switch (lzma_stream_buffer_decode((uint64_t *)&memlimit, 0, NULL, (const uint8_t*)zbuf, &zpos, (size_t)zlen, (uint8_t*)buf, &bpos, (size_t)&blen)){
159  case LZMA_OK: sendChars(buf, bpos); slen = bpos; break;
160  case LZMA_FORMAT_ERROR: fprintf(stderr, "ERROR: format error encountered during decompression.\n"); break;
161  case LZMA_OPTIONS_ERROR: fprintf(stderr, "ERROR: options error encountered during decompression.\n"); break;
162  case LZMA_DATA_ERROR: fprintf(stderr, "ERROR: corrupt data during decompression.\n"); break;
163  case LZMA_NO_CHECK: fprintf(stderr, "ERROR: no_check error encountered during decompression.\n"); break;
164  case LZMA_UNSUPPORTED_CHECK: fprintf(stderr, "ERROR: unsupported_check error encountered during decompression.\n"); break;
165  case LZMA_MEMLIMIT_ERROR: fprintf(stderr, "ERROR: memlimit error encountered during decompression.\n"); break;
166  case LZMA_MEM_ERROR: fprintf(stderr, "ERROR: not enough memory during decompression.\n"); break;
167  case LZMA_BUF_ERROR: fprintf(stderr, "ERROR: not enough room in the out buffer during decompression.\n"); break;
168  case LZMA_PROG_ERROR: fprintf(stderr, "ERROR: program error encountered during decompression.\n"); break;
169  default: fprintf(stderr, "ERROR: an unknown error occurred during decompression.\n"); break;
170  }
171  delete [] buf;
172  }
173  else {
174  fprintf(stderr, "ERROR: no buffer to decompress!\n");
175  }
176  //printf("Finished decoding\n");
177  free (zbuf);
178 }
179 
180 
181 /******************************************************************************
182  * XzCompress::SetLevel - This function sets the compression level of the
183  * compressor.
184  */
185 
186 void XzCompress::setLevel(int l) {
187  level = l;
188 
189  // having changed the compression level, we need to adjust our memlimit accordingly,
190  // as in the constructor:
191 
192  // start with the estimated memory usage for our preset
193  memlimit = lzma_easy_decoder_memusage(level | LZMA_PRESET_EXTREME);
194 
195  // and round up to a power of 2--
196  // bit twiddle hack to determine next greatest power of 2 from:
197  // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
198  memlimit--;
199  memlimit |= memlimit >> 1;
200  memlimit |= memlimit >> 2;
201  memlimit |= memlimit >> 4;
202  memlimit |= memlimit >> 8;
203  memlimit |= memlimit >> 16;
204  memlimit++;
205 
206  // double that for safety's sake
207  memlimit <<= 1;
208 };
209 
#define SWORD_NAMESPACE_START
Definition: defs.h:39
unsigned long zlen
Definition: swcomprs.h:39
SW_u64 memlimit
Definition: xzcomprs.h:37
unsigned long slen
Definition: swcomprs.h:39
virtual void encode(void)
Definition: xzcomprs.cpp:79
int level
Definition: swcomprs.h:40
return NULL
Definition: regex.c:7953
free(preg->fastmap)
char * realloc()
char * buf
Definition: swcomprs.h:38
unsigned long zpos
Definition: swcomprs.h:39
virtual void setLevel(int l)
Definition: xzcomprs.cpp:186
virtual unsigned long getChars(char *buf, unsigned long len)
Definition: swcomprs.cpp:121
char direct
Definition: swcomprs.h:38
char * zbuf
Definition: swcomprs.h:38
virtual void decode(void)
Definition: xzcomprs.cpp:131
#define SWORD_NAMESPACE_END
Definition: defs.h:40
virtual ~XzCompress()
Definition: xzcomprs.cpp:65
virtual unsigned long sendChars(char *buf, unsigned long len)
Definition: swcomprs.cpp:141