GRASS 8 Programmer's Manual 8.6.0dev(2026)-1a88e4eae9
Loading...
Searching...
No Matches
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 * ALGORITHM: http://www.zstd.net
14 * DATE CREATED: Dec 18 2017
15 * SPDX-FileCopyrightText: 2017 GRASS Development Team
16 * SPDX-License-Identifier: GPL-2.0-or-later
17 *
18 *****************************************************************************/
19
20/********************************************************************
21 * int *
22 * G_zstd_compress (src, srz_sz, dst, dst_sz) *
23 * int src_sz, dst_sz; *
24 * unsigned char *src, *dst; *
25 * ---------------------------------------------------------------- *
26 * This function is a wrapper around the Zstd compression function. *
27 * It uses an all or nothing call. *
28 * If you need a continuous compression scheme, you'll have to code *
29 * your own. *
30 * In order to do a single pass compression, the input src must be *
31 * copied to a buffer larger than the data. This may cause *
32 * performance degradation. *
33 * *
34 * The function either returns the number of bytes of compressed *
35 * data in dst, or an error code. *
36 * *
37 * Errors include: *
38 * -1 -- Compression failed. *
39 * -2 -- dst is too small. *
40 * *
41 * ================================================================ *
42 * int *
43 * G_zstd_expand (src, src_sz, dst, dst_sz) *
44 * int src_sz, dst_sz; *
45 * unsigned char *src, *dst; *
46 * ---------------------------------------------------------------- *
47 * This function is a wrapper around the zstd decompression *
48 * function. It uses a single pass call. If you need a continuous *
49 * expansion scheme, you'll have to code your own. *
50 * *
51 * The function returns the number of bytes expanded into 'dst' or *
52 * and error code. *
53 * *
54 * Errors include: *
55 * -1 -- Expansion failed. *
56 * *
57 ********************************************************************
58 */
59
60#include <grass/config.h>
61
62#include <limits.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
72{
73 /* ZSTD has a fast version if destLen is large enough
74 * to hold a worst case result
75 */
76#ifndef HAVE_ZSTD_H
78 _("GRASS needs to be compiled with ZSTD for ZSTD compression"));
79 return -1;
80#else
82
84 G_warning(_("ZSTD compression bound error %d: %s"), (int)compress_bound,
86 return -1;
87 }
88 if (compress_bound > INT_MAX) {
89 G_warning(_("ZSTD compression bound exceeds supported size"));
90 return -1;
91 }
92
93 return (int)compress_bound;
94#endif
95}
96
97int G_zstd_compress(unsigned char *src, int src_sz, unsigned char *dst,
98 int dst_sz)
99{
100 int err, nbytes, buf_sz;
101 size_t zstd_err;
102 unsigned char *buf;
103
104#ifndef HAVE_ZSTD_H
106 _("GRASS needs to be compiled with ZSTD for ZSTD compression"));
107 return -1;
108#else
109
110 /* Catch errors early */
111 if (src == NULL || dst == NULL) {
112 if (src == NULL)
113 G_warning(_("No source buffer"));
114
115 if (dst == NULL)
116 G_warning(_("No destination buffer"));
117 return -1;
118 }
119
120 /* Don't do anything if either of these are true */
121 if (src_sz <= 0 || dst_sz <= 0) {
122 if (src_sz <= 0)
123 G_warning(_("Invalid source buffer size %d"), src_sz);
124 if (dst_sz <= 0)
125 G_warning(_("Invalid destination buffer size %d"), dst_sz);
126 return 0;
127 }
128
129 /* Output buffer has to be larger for single pass compression */
130 buf = dst;
132 if (buf_sz < 0)
133 return -1;
134 if (buf_sz > dst_sz) {
135 G_warning(
136 "G_zstd_compress(): programmer error, destination is too small");
137 if (NULL ==
138 (buf = (unsigned char *)G_calloc(buf_sz, sizeof(unsigned char))))
139 return -1;
140 }
141 else
142 buf_sz = dst_sz;
143
144 /* Do single pass compression */
145 zstd_err = ZSTD_compress((char *)buf, buf_sz, (char *)src, src_sz, 3);
146
147 if (zstd_err == 0 || ZSTD_isError(zstd_err)) {
148 G_warning(_("ZSTD compression error %d: %s"), (int)zstd_err,
150 if (buf != dst)
151 G_free(buf);
152 return -1;
153 }
154 if (zstd_err > INT_MAX) {
155 G_warning(_("ZSTD compressed size exceeds supported size"));
156 if (buf != dst)
157 G_free(buf);
158 return -1;
159 }
160 err = (int)zstd_err;
161 if (err >= src_sz) {
162 /* compression not possible */
163 if (buf != dst)
164 G_free(buf);
165 return -2;
166 }
167
168 /* bytes of compressed data is return value */
169 nbytes = err;
170
171 if (buf != dst) {
172 /* Copy the data from buf to dst */
173 for (err = 0; err < nbytes; err++)
174 dst[err] = buf[err];
175
176 G_free(buf);
177 }
178
179 return nbytes;
180#endif
181}
182
183int G_zstd_expand(unsigned char *src, int src_sz, unsigned char *dst,
184 int dst_sz)
185{
186 int nbytes;
187 size_t zstd_err;
188
189#ifndef HAVE_ZSTD_H
191 _("GRASS needs to be compiled with ZSTD for ZSTD compression"));
192 return -1;
193#else
194
195 /* Catch error condition */
196 if (src == NULL || dst == NULL) {
197 if (src == NULL)
198 G_warning(_("No source buffer"));
199
200 if (dst == NULL)
201 G_warning(_("No destination buffer"));
202 return -2;
203 }
204
205 /* Don't do anything if either of these are true */
206 if (src_sz <= 0 || dst_sz <= 0) {
207 if (src_sz <= 0)
208 G_warning(_("Invalid source buffer size %d"), src_sz);
209 if (dst_sz <= 0)
210 G_warning(_("Invalid destination buffer size %d"), dst_sz);
211 return 0;
212 }
213
214 /* Do single pass decompress */
215 zstd_err = ZSTD_decompress((char *)dst, dst_sz, (char *)src, src_sz);
216
217 if (zstd_err == 0 || ZSTD_isError(zstd_err)) {
218 G_warning(_("ZSTD compression error %d: %s"), (int)zstd_err,
220 return -1;
221 }
222 if (zstd_err > INT_MAX) {
223 G_warning(_("ZSTD uncompressed size exceeds supported size"));
224 return -1;
225 }
226
227 /* Number of bytes inflated to output stream is return value */
228 nbytes = (int)zstd_err;
229
230 if (nbytes != dst_sz) {
231 /* TODO: it is not an error if destination is larger than needed */
232 G_warning(_("Got uncompressed size %d, expected %d"), (int)nbytes,
233 dst_sz);
234 return -1;
235 }
236
237 return nbytes;
238#endif
239}
240
241/* vim: set softtabstop=4 shiftwidth=4 expandtab: */
#define NULL
Definition ccmath.h:32
int G_zstd_compress_bound(int src_sz)
Definition cmprzstd.c:71
int G_zstd_compress(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition cmprzstd.c:97
int G_zstd_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition cmprzstd.c:183
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_calloc(m, n)
Definition defs/gis.h:137
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
void G_warning(const char *,...) __attribute__((format(printf
#define _(str)
Definition glocale.h:10
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)