Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_zlib.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
26#include "nilorea/n_zlib.h"
27#include "nilorea/n_log.h"
28#include "limits.h"
29
30#ifndef __windows__
31#include <arpa/inet.h>
32#else
33#include "nilorea/n_windows.h"
34#endif
35
41size_t GetMaxCompressedLen(size_t nLenSrc) {
42 size_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block
43 return (nLenSrc + 6 + (n16kBlocks * 5));
44} /* GetMaxCompressedLen */
45
54size_t CompressData(unsigned char* abSrc, size_t nLenSrc, unsigned char* abDst, size_t nLenDst) {
55 __n_assert(abSrc, return 0);
56 __n_assert(abDst, return 0);
57
58 if (nLenSrc == 0) {
59 n_log(LOG_ERR, "nLenSrc == 0");
60 return 0;
61 }
62 if (nLenDst == 0) {
63 n_log(LOG_ERR, "nLenDst == 0");
64 return 0;
65 }
66 if (nLenSrc > UINT_MAX) {
67 n_log(LOG_ERR, "nLenSrc is bigger than UINT_MAX");
68 return 0;
69 }
70 if (nLenDst > UINT_MAX) {
71 n_log(LOG_ERR, "nLenDst is bigger than UINT_MAX");
72 return 0;
73 }
74
75 z_stream zInfo;
76 memset(&zInfo, 0, sizeof(zInfo));
77 zInfo.total_in = zInfo.avail_in = (unsigned int)nLenSrc;
78 zInfo.total_out = zInfo.avail_out = (unsigned int)nLenDst;
79 zInfo.next_in = (unsigned char*)abSrc;
80 zInfo.next_out = abDst;
81
82 int nErr = 0;
83 size_t nRet = 0;
84 nErr = deflateInit(&zInfo, Z_DEFAULT_COMPRESSION); // zlib function
85 switch (nErr) {
86 case Z_OK:
87 // all is fine
88 break;
89 default:
90 n_log(LOG_ERR, "%s on string %p size %zu", zError(nErr), abSrc, nLenSrc);
91 return 0;
92 }
93 nErr = deflate(&zInfo, Z_FINISH); // zlib function
94 if (nErr == Z_STREAM_END) {
95 nRet = zInfo.total_out;
96 } else {
97 n_log(LOG_ERR, "%s on string %p size %zu", zError(nErr), abSrc, nLenSrc);
98 }
99 deflateEnd(&zInfo); // zlib function
100 return nRet;
101} /* CompressData */
102
111size_t UncompressData(unsigned char* abSrc, size_t nLenSrc, unsigned char* abDst, size_t nLenDst) {
112 __n_assert(abSrc, return 0);
113 __n_assert(abDst, return 0);
114
115 if (nLenSrc == 0) {
116 n_log(LOG_ERR, "nLenSrc == 0");
117 return 0;
118 }
119 if (nLenDst == 0) {
120 n_log(LOG_ERR, "nLenDst == 0");
121 return 0;
122 }
123 if (nLenSrc > UINT_MAX) {
124 n_log(LOG_ERR, "nLenSrc is bigger than UINT_MAX");
125 return 0;
126 }
127 if (nLenDst > UINT_MAX) {
128 n_log(LOG_ERR, "nLenDst is bigger than UINT_MAX");
129 return 0;
130 }
131
132 z_stream zInfo;
133 memset(&zInfo, 0, sizeof(zInfo));
134 zInfo.total_in = zInfo.avail_in = (unsigned int)nLenSrc;
135 zInfo.total_out = zInfo.avail_out = (unsigned int)nLenDst;
136 zInfo.next_in = (unsigned char*)abSrc;
137 zInfo.next_out = abDst;
138
139 int nErr = 0;
140 size_t nRet = 0;
141 nErr = inflateInit(&zInfo); // zlib function
142 switch (nErr) {
143 case Z_OK:
144 // all is fine
145 break;
146 default:
147 n_log(LOG_ERR, "%s on string %p size %zu", zError(nErr), abSrc, nLenSrc);
148 return 0;
149 }
150 nErr = inflate(&zInfo, Z_FINISH); // zlib function
151 if (nErr == Z_STREAM_END) {
152 nRet = zInfo.total_out;
153 } else {
154 n_log(LOG_ERR, "%s on string %p size %zu", zError(nErr), abSrc, nLenSrc);
155 }
156 inflateEnd(&zInfo); // zlib function
157 return nRet; // -1 or len of output
158} /* UncompressData */
159
166 __n_assert(src, return NULL);
167 __n_assert(src->data, return NULL);
168
169 if (src->length == 0) {
170 n_log(LOG_ERR, "length of src == 0");
171 return NULL;
172 }
173 if (src->written == 0) {
174 n_log(LOG_ERR, "written of src == 0");
175 return NULL;
176 }
177 if (src->length > UINT_MAX) {
178 n_log(LOG_ERR, "length of src > UINT_MAX");
179 return NULL;
180 }
181 if (src->written > UINT_MAX) {
182 n_log(LOG_ERR, "written of src > UINT_MAX");
183 return NULL;
184 }
185
186 /* storage for original string size + zipped string + padding */
187 size_t zip_max_size = GetMaxCompressedLen(src->length);
188
189 N_STR* zipped = new_nstr(4 + zip_max_size);
190
191 __n_assert(zipped, return NULL);
192 __n_assert(zipped->data, return NULL);
193
194 /* copying size */
195 uint32_t src_length = htonl((uint32_t)src->length);
196 memcpy(zipped->data, &src_length, sizeof(uint32_t));
197 char* dataptr = zipped->data + 4;
198
199 size_t compressed_size = CompressData((unsigned char*)src->data, src->written, (unsigned char*)dataptr, zip_max_size);
200 if (compressed_size == 0) {
201 free_nstr(&zipped);
202 n_log(LOG_ERR, "unable to zip string %p %zu/%zu bytes", src->data, src->written, src->length);
203 return NULL;
204 }
205 zipped->written = 4 + compressed_size;
206 n_log(LOG_DEBUG, "zip :%zu original: %zu", zipped->written, src->length);
207
208 return zipped;
209} /* zip_nstr */
210
217 __n_assert(src, return NULL);
218 __n_assert(src->data, return NULL);
219
220 if (src->length == 0) {
221 n_log(LOG_ERR, "length of src == 0");
222 return NULL;
223 }
224 if (src->written == 0) {
225 n_log(LOG_ERR, "written of src == 0");
226 return NULL;
227 }
228
229 if (src->written < 4) {
230 n_log(LOG_ERR, "compressed data too short");
231 return NULL;
232 }
233
234 uint32_t original_size = 0;
235 memcpy(&original_size, src->data, sizeof(uint32_t));
236 original_size = ntohl(original_size);
237 if (original_size == 0) {
238 n_log(LOG_ERR, "original_size == 0");
239 return NULL;
240 }
241 if (original_size > 256 * 1024 * 1024) {
242 n_log(LOG_ERR, "decompressed size too large: %u", original_size);
243 return NULL;
244 }
245 /* storage for original string size + zipped string + padding */
246 N_STR* unzipped = new_nstr(original_size);
247 __n_assert(unzipped, return NULL);
248 __n_assert(unzipped->data, return NULL);
249
250 /* copying size */
251 unzipped->written = UncompressData(((unsigned char*)src->data) + 4, src->written - 4, (unsigned char*)unzipped->data, original_size);
252 if (unzipped->written == 0) {
253 n_log(LOG_ERR, "unable to unzip string %p %zu/%zu bytes", unzipped->data, unzipped->written, unzipped->length);
254 free_nstr(&unzipped);
255 return NULL;
256 }
257 n_log(LOG_DEBUG, "Size: zip: %zu => unzip :%zu original:%u", src->written, unzipped->written, original_size);
258
259 return unzipped;
260} /* unzip_nstr */
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:278
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:88
#define LOG_DEBUG
debug-level messages
Definition n_log.h:83
#define LOG_ERR
error conditions
Definition n_log.h:75
size_t written
size of the written data inside the string
Definition n_str.h:66
char * data
the string
Definition n_str.h:62
size_t length
length of string (in case we wanna keep information after the 0 end of string value)
Definition n_str.h:64
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:201
N_STR * new_nstr(NSTRBYTE size)
create a new N_STR string
Definition n_str.c:206
A box including a string and his lenght.
Definition n_str.h:60
size_t GetMaxCompressedLen(size_t nLenSrc)
Return the maximum compressed size.
Definition n_zlib.c:41
size_t CompressData(unsigned char *abSrc, size_t nLenSrc, unsigned char *abDst, size_t nLenDst)
Compress a string to another.
Definition n_zlib.c:54
size_t UncompressData(unsigned char *abSrc, size_t nLenSrc, unsigned char *abDst, size_t nLenDst)
Uncompress a string to another.
Definition n_zlib.c:111
N_STR * unzip_nstr(N_STR *src)
return an uncompressed version of src
Definition n_zlib.c:216
N_STR * zip_nstr(N_STR *src)
return a compressed version of src
Definition n_zlib.c:165
Generic log system.
ZLIB compression handler.