GRASS GIS 8 Programmer's Manual 8.4.1(2025)-45ca3179ab
Loading...
Searching...
No Matches
cmprbzip.c
Go to the documentation of this file.
1/*
2 ****************************************************************************
3 * -- GRASS Development Team --
4 *
5 * MODULE: GRASS gis library
6 * FILENAME: cmprbzip.c
7 * AUTHOR(S): Markus Metz
8 * PURPOSE: To provide an interface to libbzip2 for compressing and
9 * decompressing data. Its primary use is in
10 * the storage and reading of GRASS rasters.
11 *
12 * ALGORITHM: http://www.bzip.org
13 * DATE CREATED: Nov 19 2015
14 * COPYRIGHT: (C) 2015 by the GRASS Development Team
15 *
16 * This program is free software under the GNU General Public
17 * License (version 2 or greater). Read the file COPYING that
18 * comes with GRASS for details.
19 *
20 *****************************************************************************/
21
22/********************************************************************
23 * int *
24 * G_bz2_compress (src, srz_sz, dst, dst_sz) *
25 * int src_sz, dst_sz; *
26 * unsigned char *src, *dst; *
27 * ---------------------------------------------------------------- *
28 * This function is a wrapper around the bzip2 compression *
29 * function. It uses an all or nothing call. *
30 * If you need a continuous compression scheme, you'll have to code *
31 * your own. *
32 * In order to do a single pass compression, the input src must be *
33 * copied to a buffer 1% + 600 bytes larger than the data. This *
34 * may cause performance degradation. *
35 * *
36 * The function either returns the number of bytes of compressed *
37 * data in dst, or an error code. *
38 * *
39 * Errors include: *
40 * -1 -- Compression failed. *
41 * -2 -- dst is too small. *
42 * *
43 * ================================================================ *
44 * int *
45 * G_bz2_expand (src, src_sz, dst, dst_sz) *
46 * int src_sz, dst_sz; *
47 * unsigned char *src, *dst; *
48 * ---------------------------------------------------------------- *
49 * This function is a wrapper around the bzip2 decompression *
50 * function. It uses a single pass call to inflate(). *
51 * If you need a continuous expansion scheme, you'll have to code *
52 * your own. *
53 * *
54 * The function returns the number of bytes expanded into 'dst' or *
55 * and error code. *
56 * *
57 * Errors include: *
58 * -1 -- Expansion failed. *
59 * *
60 ********************************************************************
61 */
62
63#include <grass/config.h>
64
65#ifdef HAVE_BZLIB_H
66#include <bzlib.h>
67#endif
68
69#include <grass/gis.h>
70#include <grass/glocale.h>
71
72int G_bz2_compress_bound(int src_sz)
73{
74 /* from the documentation:
75 * To guarantee that the compressed data will fit in its buffer,
76 * allocate an output buffer of size 1% larger than the uncompressed data,
77 * plus six hundred extra bytes.
78 * bzip2 does not provide a compressbound fn
79 * and apparently does not have a fast version if destLen is
80 * large enough to hold a worst case result
81 */
82 return src_sz;
83}
84
85int G_bz2_compress(unsigned char *src, int src_sz, unsigned char *dst,
86 int dst_sz)
87{
88 int err;
89 int buf_sz;
90 unsigned int i, nbytes;
91 unsigned char *buf;
92
93#ifndef HAVE_BZLIB_H
95 _("GRASS needs to be compiled with BZIP2 for BZIP2 compression"));
96 return -1;
97#else
98
99 /* Catch errors early */
100 if (src == NULL || dst == NULL) {
101 if (src == NULL)
102 G_warning(_("No source buffer"));
103
104 if (dst == NULL)
105 G_warning(_("No destination buffer"));
106 return -1;
107 }
108
109 /* Don't do anything if either of these are true */
110 if (src_sz <= 0 || dst_sz <= 0) {
111 if (src_sz <= 0)
112 G_warning(_("Invalid source buffer size %d"), src_sz);
113 if (dst_sz <= 0)
114 G_warning(_("Invalid destination buffer size %d"), dst_sz);
115 return 0;
116 }
117
118 /* Output buffer has to be 1% + 600 bytes bigger for single pass compression
119 */
120 buf = dst;
121 buf_sz = G_bz2_compress_bound(src_sz);
122 if (buf_sz > dst_sz) {
123 G_warning(
124 "G_bz2_compress(): programmer error, destination is too small");
125 if (NULL ==
126 (buf = (unsigned char *)G_calloc(buf_sz, sizeof(unsigned char))))
127 return -1;
128 }
129 else
130 buf_sz = dst_sz;
131
132 /* Do single pass compression */
133 nbytes = buf_sz;
134 err = BZ2_bzBuffToBuffCompress((char *)buf, &nbytes, /* destination */
135 (char *)src, src_sz, /* source */
136 9, /* blockSize100k */
137 0, /* verbosity */
138 100); /* workFactor */
139
140 if (err != BZ_OK) {
141 G_warning(_("BZIP2 version %s compression error %d"),
142 BZ2_bzlibVersion(), err);
143 if (buf != dst)
144 G_free(buf);
145 return -1;
146 }
147
148 /* updated buf_sz is bytes of compressed data */
149 if (nbytes >= (unsigned int)src_sz) {
150 /* compression not possible */
151 if (buf != dst)
152 G_free(buf);
153 return -2;
154 }
155
156 if (buf != dst) {
157 /* Copy the data from buf to dst */
158 for (i = 0; i < nbytes; i++)
159 dst[i] = buf[i];
160
161 G_free(buf);
162 }
163
164 return nbytes;
165#endif
166} /* G_bz2_compress() */
167
168int G_bz2_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
169{
170 int err;
171 unsigned int nbytes;
172
173#ifndef HAVE_BZLIB_H
175 _("GRASS needs to be compiled with BZIP2 for BZIP2 compression"));
176 return -2;
177#else
178
179 /* Catch error condition */
180 if (src == NULL || dst == NULL) {
181 if (src == NULL)
182 G_warning(_("No source buffer"));
183
184 if (dst == NULL)
185 G_warning(_("No destination buffer"));
186 return -2;
187 }
188
189 /* Don't do anything if either of these are true */
190 if (src_sz <= 0 || dst_sz <= 0) {
191 if (src_sz <= 0)
192 G_warning(_("Invalid source buffer size %d"), src_sz);
193 if (dst_sz <= 0)
194 G_warning(_("Invalid destination buffer size %d"), dst_sz);
195 return 0;
196 }
197
198 /* Do single pass decompression */
199 nbytes = dst_sz;
200 err = BZ2_bzBuffToBuffDecompress((char *)dst, &nbytes, /* destination */
201 (char *)src, src_sz, /* source */
202 0, /* small */
203 0); /* verbosity */
204
205 if (err != BZ_OK) {
206 G_warning(_("BZIP2 version %s decompression error %d"),
207 BZ2_bzlibVersion(), err);
208 return -1;
209 }
210
211 /* Number of bytes inflated to output stream is
212 * updated buffer size
213 */
214
215 if (dst_sz < 0 || nbytes != (unsigned int)dst_sz) {
216 /* TODO: it is not an error if destination is larger than needed */
217 G_warning(_("Got uncompressed size %d, expected %d"), (int)nbytes,
218 dst_sz);
219 return -1;
220 }
221
222 return nbytes;
223#endif
224}
225
226/* vim: set softtabstop=4 shiftwidth=4 expandtab: */
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:150
#define NULL
Definition ccmath.h:32
int G_bz2_compress(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition cmprbzip.c:85
int G_bz2_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition cmprbzip.c:168
int G_bz2_compress_bound(int src_sz)
Definition cmprbzip.c:72
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition gis/error.c:159
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition gis/error.c:203
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)