GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-e5379bbd7
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 
70 int
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 
79 int
80 G_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 
147 int
148 G_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: */
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_free(void *)
Free allocated memory.
Definition: gis/alloc.c:149
char * dst
Definition: lz4.h:599
int LZ4_compress_default(const char *source, char *dest, int inputSize, int maxOutputSize)
Definition: lz4.c:1084
#define NULL
Definition: ccmath.h:32
#define G_calloc(m, n)
Definition: defs/gis.h:113
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:220
int G_lz4_compress(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition: cmprlz4.c:80
LZ4_FORCE_O2_GCC_PPC64LE int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize)
Definition: lz4.c:1598
void G_warning(const char *,...) __attribute__((format(printf
#define _(str)
Definition: glocale.h:10
int LZ4_compressBound(int isize)
Definition: lz4.c:495