GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-f622271e7a
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 G_lz4_compress_bound(int src_sz)
71 {
72  /* LZ4 has a fast version if destLen is large enough
73  * to hold a worst case result
74  */
75  return LZ4_compressBound(src_sz);
76 }
77 
78 int G_lz4_compress(unsigned char *src, int src_sz, unsigned char *dst,
79  int dst_sz)
80 {
81  int err, nbytes, buf_sz;
82  unsigned char *buf;
83 
84  /* Catch errors early */
85  if (src == NULL || dst == NULL) {
86  if (src == NULL)
87  G_warning(_("No source buffer"));
88 
89  if (dst == NULL)
90  G_warning(_("No destination buffer"));
91  return -1;
92  }
93 
94  /* Don't do anything if either of these are true */
95  if (src_sz <= 0 || dst_sz <= 0) {
96  if (src_sz <= 0)
97  G_warning(_("Invalid source buffer size %d"), src_sz);
98  if (dst_sz <= 0)
99  G_warning(_("Invalid destination buffer size %d"), dst_sz);
100  return 0;
101  }
102 
103  /* Output buffer should be large enough for single pass compression */
104  buf = dst;
105  buf_sz = G_lz4_compress_bound(src_sz);
106  if (buf_sz > dst_sz) {
107  G_warning(
108  "G_lz4_compress(): programmer error, destination is too small");
109  if (NULL ==
110  (buf = (unsigned char *)G_calloc(buf_sz, sizeof(unsigned char))))
111  return -1;
112  }
113  else
114  buf_sz = dst_sz;
115 
116  /* Do single pass compression */
117  err = LZ4_compress_default((char *)src, (char *)buf, src_sz, buf_sz);
118 
119  if (err <= 0) {
120  G_warning(_("LZ4 compression error"));
121  if (buf != dst)
122  G_free(buf);
123  return -1;
124  }
125  if (err >= src_sz) {
126  /* compression not possible */
127  if (buf != dst)
128  G_free(buf);
129  return -2;
130  }
131 
132  /* bytes of compressed data is return value */
133  nbytes = err;
134 
135  if (buf != dst) {
136  /* Copy the data from buf to dst */
137  for (err = 0; err < nbytes; err++)
138  dst[err] = buf[err];
139 
140  G_free(buf);
141  }
142 
143  return nbytes;
144 }
145 
146 int G_lz4_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
147 {
148  int err, nbytes;
149 
150  /* Catch error condition */
151  if (src == NULL || dst == NULL) {
152  if (src == NULL)
153  G_warning(_("No source buffer"));
154 
155  if (dst == NULL)
156  G_warning(_("No destination buffer"));
157  return -2;
158  }
159 
160  /* Don't do anything if either of these are true */
161  if (src_sz <= 0 || dst_sz <= 0) {
162  if (src_sz <= 0)
163  G_warning(_("Invalid source buffer size %d"), src_sz);
164  if (dst_sz <= 0)
165  G_warning(_("Invalid destination buffer size %d"), dst_sz);
166  return 0;
167  }
168 
169  /* Do single pass decompress */
170  err = LZ4_decompress_safe((char *)src, (char *)dst, src_sz, dst_sz);
171  /* err = LZ4_decompress_fast(src, dst, src_sz); */
172 
173  if (err <= 0) {
174  G_warning(_("LZ4 decompression error"));
175  return -1;
176  }
177 
178  /* Number of bytes inflated to output stream is return value */
179  nbytes = err;
180 
181  if (nbytes != dst_sz) {
182  /* TODO: it is not an error if destination is larger than needed */
183  G_warning(_("Got uncompressed size %d, expected %d"), (int)nbytes,
184  dst_sz);
185  return -1;
186  }
187 
188  return nbytes;
189 }
190 
191 /* vim: set softtabstop=4 shiftwidth=4 expandtab: */
#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:78
int G_lz4_expand(unsigned char *src, int src_sz, unsigned char *dst, int dst_sz)
Definition: cmprlz4.c:146
int G_lz4_compress_bound(int src_sz)
Definition: cmprlz4.c:70
void G_free(void *)
Free allocated memory.
Definition: gis/alloc.c:150
#define G_calloc(m, n)
Definition: defs/gis.h:95
void G_warning(const char *,...) __attribute__((format(printf
#define _(str)
Definition: glocale.h:10
int LZ4_compressBound(int isize)
Definition: lz4.c:879
int LZ4_compress_default(const char *src, char *dst, int srcSize, int dstCapacity)
Definition: lz4.c:1808
LZ4_FORCE_O2 int LZ4_decompress_safe(const char *source, char *dest, int compressedSize, int maxDecompressedSize)
Definition: lz4.c:3010
char * dst
Definition: lz4.h:981
const char * src
Definition: lz4.h:989
SYMBOL * err(FILE *fp, SYMBOL *s, char *msg)
Definition: symbol/read.c:216