GRASS GIS 8 Programmer's Manual 8.2.1(2023)-exported
cmprzstd.c
Go to the documentation of this file.
1/*
2 ****************************************************************************
3 * -- GRASS Development Team --
4 *
5 * MODULE: GRASS gis library
6 * FILENAME: cmprzstd.c
7 * AUTHOR(S): Eric G. Miller <egm2@jps.net>
8 * Markus Metz
9 * PURPOSE: To provide an interface to ZSTD for compressing and
10 * decompressing data using ZSTD. It's primary use is in
11 * the storage and reading of GRASS floating point rasters.
12 *
13 * DATE CREATED: Dec 18 2017
14 * COPYRIGHT: (C) 2017 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_zstd_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 Zstd compression function. *
29 * 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 larger than the data. This may cause *
34 * 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_zstd_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 zstd decompression *
50 * function. It uses a single pass call. If you need a continuous *
51 * expansion scheme, you'll have to code your own. *
52 * *
53 * The function returns the number of bytes expanded into 'dst' or *
54 * and error code. *
55 * *
56 * Errors include: *
57 * -1 -- Expansion failed. *
58 * *
59 ********************************************************************
60 */
61
62#include <grass/config.h>
63
64#ifdef HAVE_ZSTD_H
65#include <zstd.h>
66#endif
67
68#include <grass/gis.h>
69#include <grass/glocale.h>
70
71
72int
74{
75 /* ZSTD has a fast version if destLen is large enough
76 * to hold a worst case result
77 */
78#ifndef HAVE_ZSTD_H
79 G_fatal_error(_("GRASS needs to be compiled with ZSTD for ZSTD compression"));
80 return -1;
81#else
82 return ZSTD_compressBound(src_sz);
83#endif
84}
85
86int
87G_zstd_compress(unsigned char *src, int src_sz, unsigned char *dst,
88 int dst_sz)
89{
90 int err, nbytes, buf_sz;
91 unsigned char *buf;
92
93#ifndef HAVE_ZSTD_H
94 G_fatal_error(_("GRASS needs to be compiled with ZSTD for ZSTD compression"));
95 return -1;
96#else
97
98 /* Catch errors early */
99 if (src == NULL || dst == NULL) {
100 if (src == NULL)
101 G_warning(_("No source buffer"));
102
103 if (dst == NULL)
104 G_warning(_("No destination buffer"));
105 return -1;
106 }
107
108 /* Don't do anything if either of these are true */
109 if (src_sz <= 0 || dst_sz <= 0) {
110 if (src_sz <= 0)
111 G_warning(_("Invalid source buffer size %d"), src_sz);
112 if (dst_sz <= 0)
113 G_warning(_("Invalid destination buffer size %d"), dst_sz);
114 return 0;
115 }
116
117 /* Output buffer has to be larger for single pass compression */
118 buf = dst;
119 buf_sz = G_zstd_compress_bound(src_sz);
120 if (buf_sz > dst_sz) {
121 G_warning("G_zstd_compress(): programmer error, destination is too small");
122 if (NULL == (buf = (unsigned char *)
123 G_calloc(buf_sz, sizeof(unsigned char))))
124 return -1;
125 }
126 else
127 buf_sz = dst_sz;
128
129 /* Do single pass compression */
130 err = ZSTD_compress((char *)buf, buf_sz, (char *)src, src_sz, 3);
131
132 if (err <= 0 || ZSTD_isError(err)) {
133 G_warning(_("ZSTD compression error %d: %s"),
134 err, ZSTD_getErrorName(err));
135 if (buf != dst)
136 G_free(buf);
137 return -1;
138 }
139 if (err >= src_sz) {
140 /* compression not possible */
141 if (buf != dst)
142 G_free(buf);
143 return -2;
144 }
145
146 /* bytes of compressed data is return value */
147 nbytes = err;
148
149 if (buf != dst) {
150 /* Copy the data from buf to dst */
151 for (err = 0; err < nbytes; err++)
152 dst[err] = buf[err];
153
154 G_free(buf);
155 }
156
157 return nbytes;
158#endif
159}
160
161int
162G_zstd_expand(unsigned char *src, int src_sz, unsigned char *dst,
163 int dst_sz)
164{
165 int err, nbytes;
166
167#ifndef HAVE_ZSTD_H
168 G_fatal_error(_("GRASS needs to be compiled with ZSTD for ZSTD compression"));
169 return -1;
170#else
171
172 /* Catch error condition */
173 if (src == NULL || dst == NULL) {
174 if (src == NULL)
175 G_warning(_("No source buffer"));
176
177 if (dst == NULL)
178 G_warning(_("No destination buffer"));
179 return -2;
180 }
181
182 /* Don't do anything if either of these are true */
183 if (src_sz <= 0 || dst_sz <= 0) {
184 if (src_sz <= 0)
185 G_warning(_("Invalid source buffer size %d"), src_sz);
186 if (dst_sz <= 0)
187 G_warning(_("Invalid destination buffer size %d"), dst_sz);
188 return 0;
189 }
190
191 /* Do single pass decompress */
192 err = ZSTD_decompress((char *)dst, dst_sz, (char *)src, src_sz);
193
194 if (err <= 0 || ZSTD_isError(err)) {
195 G_warning(_("ZSTD compression error %d: %s"),
196 err, ZSTD_getErrorName(err));
197 return -1;
198 }
199
200 /* Number of bytes inflated to output stream is return value */
201 nbytes = err;
202
203 if (nbytes != dst_sz) {
204 /* TODO: it is not an error if destination is larger than needed */
205 G_warning(_("Got uncompressed size %d, expected %d"), (int)nbytes, dst_sz);
206 return -1;
207 }
208
209 return nbytes;
210#endif
211}
212
213
214/* vim: set softtabstop=4 shiftwidth=4 expandtab: */
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
#define NULL
Definition: ccmath.h:32
int G_zstd_compress_bound(int src_sz)
Definition: cmprzstd.c:73
int G_zstd_compress(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition: cmprzstd.c:87
int G_zstd_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition: cmprzstd.c:162
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition: gis/error.c:160
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:204
char * dst
Definition: lz4.h:599
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:220