GRASS GIS 8 Programmer's Manual 8.2.1(2023)-exported
cmprlz4.c
Go to the documentation of this file.
1/*
2 ****************************************************************************
3 * -- GRASS Development Team --
4 *
5 * MODULE: GRASS gis library
6 * FILENAME: cmprlz4.c
7 * AUTHOR(S): Eric G. Miller <egm2@jps.net>
8 * Markus Metz
9 * PURPOSE: To provide an interface to lz4 for compressing and
10 * decompressing data using LZ4. It's primary use is in
11 * the storage and reading of GRASS floating point rasters.
12 *
13 * ALGORITHM: https://code.google.com/p/lz4/
14 * DATE CREATED: Dec 18 2015
15 * COPYRIGHT: (C) 2015 by the GRASS Development Team
16 *
17 * This program is free software under the GNU General Public
18 * License (version 2 or greater). Read the file COPYING that
19 * comes with GRASS for details.
20 *
21 *****************************************************************************/
22
23/********************************************************************
24 * int *
25 * G_lz4_compress (src, srz_sz, dst, dst_sz) *
26 * int src_sz, dst_sz; *
27 * unsigned char *src, *dst; *
28 * ---------------------------------------------------------------- *
29 * This function is a wrapper around the LZ4 compression function. *
30 * It uses an all or nothing call. *
31 * If you need a continuous compression scheme, you'll have to code *
32 * your own. *
33 * In order to do a single pass compression, the input src must be *
34 * copied to a buffer larger than the data. This may cause *
35 * performance degradation. *
36 * *
37 * The function either returns the number of bytes of compressed *
38 * data in dst, or an error code. *
39 * *
40 * Errors include: *
41 * -1 -- Compression failed. *
42 * -2 -- dst is too small. *
43 * *
44 * ================================================================ *
45 * int *
46 * G_lz4_expand (src, src_sz, dst, dst_sz) *
47 * int src_sz, dst_sz; *
48 * unsigned char *src, *dst; *
49 * ---------------------------------------------------------------- *
50 * This function is a wrapper around the lz4 decompression *
51 * function. It uses a single pass call. If you need a continuous *
52 * expansion scheme, you'll have to code 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#include <grass/gis.h>
66#include <grass/glocale.h>
67
68#include "lz4.h"
69
70int
72{
73 /* LZ4 has a fast version if destLen is large enough
74 * to hold a worst case result
75 */
76 return LZ4_compressBound(src_sz);
77}
78
79int
80G_lz4_compress(unsigned char *src, int src_sz, unsigned char *dst,
81 int dst_sz)
82{
83 int err, nbytes, buf_sz;
84 unsigned char *buf;
85
86 /* Catch errors early */
87 if (src == NULL || dst == NULL) {
88 if (src == NULL)
89 G_warning(_("No source buffer"));
90
91 if (dst == NULL)
92 G_warning(_("No destination buffer"));
93 return -1;
94 }
95
96 /* Don't do anything if either of these are true */
97 if (src_sz <= 0 || dst_sz <= 0) {
98 if (src_sz <= 0)
99 G_warning(_("Invalid source buffer size %d"), src_sz);
100 if (dst_sz <= 0)
101 G_warning(_("Invalid destination buffer size %d"), dst_sz);
102 return 0;
103 }
104
105 /* Output buffer should be large enough for single pass compression */
106 buf = dst;
107 buf_sz = G_lz4_compress_bound(src_sz);
108 if (buf_sz > dst_sz) {
109 G_warning("G_lz4_compress(): programmer error, destination is too small");
110 if (NULL == (buf = (unsigned char *)
111 G_calloc(buf_sz, sizeof(unsigned char))))
112 return -1;
113 }
114 else
115 buf_sz = dst_sz;
116
117 /* Do single pass compression */
118 err = LZ4_compress_default((char *)src, (char *)buf, src_sz, buf_sz);
119
120 if (err <= 0) {
121 G_warning(_("LZ4 compression error"));
122 if (buf != dst)
123 G_free(buf);
124 return -1;
125 }
126 if (err >= src_sz) {
127 /* compression not possible */
128 if (buf != dst)
129 G_free(buf);
130 return -2;
131 }
132
133 /* bytes of compressed data is return value */
134 nbytes = err;
135
136 if (buf != dst) {
137 /* Copy the data from buf to dst */
138 for (err = 0; err < nbytes; err++)
139 dst[err] = buf[err];
140
141 G_free(buf);
142 }
143
144 return nbytes;
145}
146
147int
148G_lz4_expand(unsigned char *src, int src_sz, unsigned char *dst,
149 int dst_sz)
150{
151 int err, nbytes;
152
153 /* Catch error condition */
154 if (src == NULL || dst == NULL) {
155 if (src == NULL)
156 G_warning(_("No source buffer"));
157
158 if (dst == NULL)
159 G_warning(_("No destination buffer"));
160 return -2;
161 }
162
163 /* Don't do anything if either of these are true */
164 if (src_sz <= 0 || dst_sz <= 0) {
165 if (src_sz <= 0)
166 G_warning(_("Invalid source buffer size %d"), src_sz);
167 if (dst_sz <= 0)
168 G_warning(_("Invalid destination buffer size %d"), dst_sz);
169 return 0;
170 }
171
172 /* Do single pass decompress */
173 err = LZ4_decompress_safe((char *)src, (char *)dst, src_sz, dst_sz);
174 /* err = LZ4_decompress_fast(src, dst, src_sz); */
175
176 if (err <= 0) {
177 G_warning(_("LZ4 decompression error"));
178 return -1;
179 }
180
181 /* Number of bytes inflated to output stream is return value */
182 nbytes = err;
183
184 if (nbytes != dst_sz) {
185 /* TODO: it is not an error if destination is larger than needed */
186 G_warning(_("Got uncompressed size %d, expected %d"), (int)nbytes, dst_sz);
187 return -1;
188 }
189
190 return nbytes;
191}
192
193
194/* 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_lz4_compress(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition: cmprlz4.c:80
int G_lz4_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition: cmprlz4.c:148
int G_lz4_compress_bound(int src_sz)
Definition: cmprlz4.c:71
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:204
int LZ4_compressBound(int isize)
Definition: lz4.c:495
int LZ4_compress_default(const char *source, char *dest, int inputSize, int maxOutputSize)
Definition: lz4.c:1084
LZ4_FORCE_O2_GCC_PPC64LE int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize)
Definition: lz4.c:1598
char * dst
Definition: lz4.h:599
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:220