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 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
27#include "nilorea/n_zlib.h"
28#include "nilorea/n_log.h"
29#include "limits.h"
30
31#ifndef __windows__
32#include <arpa/inet.h>
33#else
34#include "nilorea/n_windows.h"
35#endif
36
42size_t GetMaxCompressedLen(size_t nLenSrc) {
43 size_t n16kBlocks = (nLenSrc + 16383) / 16384; // round up any fraction of a block
44 return (nLenSrc + 6 + (n16kBlocks * 5));
45} /* GetMaxCompressedLen */
46
55size_t CompressData(unsigned char* abSrc, size_t nLenSrc, unsigned char* abDst, size_t nLenDst) {
56 __n_assert(abSrc, return 0);
57 __n_assert(abDst, return 0);
58
59 if (nLenSrc == 0) {
60 n_log(LOG_ERR, "nLenSrc == 0");
61 return 0;
62 }
63 if (nLenDst == 0) {
64 n_log(LOG_ERR, "nLenDst == 0");
65 return 0;
66 }
67 if (nLenSrc > UINT_MAX) {
68 n_log(LOG_ERR, "nLenSrc is bigger than UINT_MAX");
69 return 0;
70 }
71 if (nLenDst > UINT_MAX) {
72 n_log(LOG_ERR, "nLenDst is bigger than UINT_MAX");
73 return 0;
74 }
75
76 z_stream zInfo;
77 memset(&zInfo, 0, sizeof(zInfo));
78 zInfo.total_in = zInfo.avail_in = (unsigned int)nLenSrc;
79 zInfo.total_out = zInfo.avail_out = (unsigned int)nLenDst;
80 zInfo.next_in = (unsigned char*)abSrc;
81 zInfo.next_out = abDst;
82
83 int nErr = 0;
84 size_t nRet = 0;
85 nErr = deflateInit(&zInfo, Z_DEFAULT_COMPRESSION); // zlib function
86 switch (nErr) {
87 case Z_OK:
88 // all is fine
89 break;
90 default:
91 n_log(LOG_ERR, "%s on string %p size %zu", zError(nErr), abSrc, nLenSrc);
92 return 0;
93 }
94 nErr = deflate(&zInfo, Z_FINISH); // zlib function
95 if (nErr == Z_STREAM_END) {
96 nRet = zInfo.total_out;
97 } else {
98 n_log(LOG_ERR, "%s on string %p size %zu", zError(nErr), abSrc, nLenSrc);
99 }
100 deflateEnd(&zInfo); // zlib function
101 return nRet;
102} /* CompressData */
103
112size_t UncompressData(unsigned char* abSrc, size_t nLenSrc, unsigned char* abDst, size_t nLenDst) {
113 __n_assert(abSrc, return 0);
114 __n_assert(abDst, return 0);
115
116 if (nLenSrc == 0) {
117 n_log(LOG_ERR, "nLenSrc == 0");
118 return 0;
119 }
120 if (nLenDst == 0) {
121 n_log(LOG_ERR, "nLenDst == 0");
122 return 0;
123 }
124 if (nLenSrc > UINT_MAX) {
125 n_log(LOG_ERR, "nLenSrc is bigger than UINT_MAX");
126 return 0;
127 }
128 if (nLenDst > UINT_MAX) {
129 n_log(LOG_ERR, "nLenDst is bigger than UINT_MAX");
130 return 0;
131 }
132
133 z_stream zInfo;
134 memset(&zInfo, 0, sizeof(zInfo));
135 zInfo.total_in = zInfo.avail_in = (unsigned int)nLenSrc;
136 zInfo.total_out = zInfo.avail_out = (unsigned int)nLenDst;
137 zInfo.next_in = (unsigned char*)abSrc;
138 zInfo.next_out = abDst;
139
140 int nErr = 0;
141 size_t nRet = 0;
142 nErr = inflateInit(&zInfo); // zlib function
143 switch (nErr) {
144 case Z_OK:
145 // all is fine
146 break;
147 default:
148 n_log(LOG_ERR, "%s on string %p size %zu", zError(nErr), abSrc, nLenSrc);
149 return 0;
150 }
151 nErr = inflate(&zInfo, Z_FINISH); // zlib function
152 if (nErr == Z_STREAM_END) {
153 nRet = zInfo.total_out;
154 } else {
155 n_log(LOG_ERR, "%s on string %p size %zu", zError(nErr), abSrc, nLenSrc);
156 }
157 inflateEnd(&zInfo); // zlib function
158 return nRet; // -1 or len of output
159} /* UncompressData */
160
167 __n_assert(src, return NULL);
168 __n_assert(src->data, return NULL);
169
170 if (src->length == 0) {
171 n_log(LOG_ERR, "length of src == 0");
172 return NULL;
173 }
174 if (src->written == 0) {
175 n_log(LOG_ERR, "written of src == 0");
176 return NULL;
177 }
178 if (src->length > UINT_MAX) {
179 n_log(LOG_ERR, "length of src > UINT_MAX");
180 return NULL;
181 }
182 if (src->written > UINT_MAX) {
183 n_log(LOG_ERR, "written of src > UINT_MAX");
184 return NULL;
185 }
186
187 /* storage for original string size + zipped string + padding */
188 size_t zip_max_size = GetMaxCompressedLen(src->length);
189
190 N_STR* zipped = new_nstr(4 + zip_max_size);
191
192 __n_assert(zipped, return NULL);
193 __n_assert(zipped->data, return NULL);
194
195 /* copying size */
196 uint32_t src_length = htonl((uint32_t)src->length);
197 memcpy(zipped->data, &src_length, sizeof(uint32_t));
198 char* dataptr = zipped->data + 4;
199
200 size_t compressed_size = CompressData((unsigned char*)src->data, src->written, (unsigned char*)dataptr, zip_max_size);
201 if (compressed_size == 0) {
202 free_nstr(&zipped);
203 n_log(LOG_ERR, "unable to zip string %p %zu/%zu bytes", src->data, src->written, src->length);
204 return NULL;
205 }
206 zipped->written = 4 + compressed_size;
207 n_log(LOG_DEBUG, "zip :%zu original: %zu", zipped->written, src->length);
208
209 return zipped;
210} /* zip_nstr */
211
218 __n_assert(src, return NULL);
219 __n_assert(src->data, return NULL);
220
221 if (src->length == 0) {
222 n_log(LOG_ERR, "length of src == 0");
223 return NULL;
224 }
225 if (src->written == 0) {
226 n_log(LOG_ERR, "written of src == 0");
227 return NULL;
228 }
229
230 if (src->written < 4) {
231 n_log(LOG_ERR, "compressed data too short");
232 return NULL;
233 }
234
235 uint32_t original_size = 0;
236 memcpy(&original_size, src->data, sizeof(uint32_t));
237 original_size = ntohl(original_size);
238 if (original_size == 0) {
239 n_log(LOG_ERR, "original_size == 0");
240 return NULL;
241 }
242 if (original_size > 256 * 1024 * 1024) {
243 n_log(LOG_ERR, "decompressed size too large: %u", original_size);
244 return NULL;
245 }
246 /* storage for original string size + zipped string + padding */
247 N_STR* unzipped = new_nstr(original_size);
248 __n_assert(unzipped, return NULL);
249 __n_assert(unzipped->data, return NULL);
250
251 /* copying size */
252 unzipped->written = UncompressData(((unsigned char*)src->data) + 4, src->written - 4, (unsigned char*)unzipped->data, original_size);
253 if (unzipped->written == 0) {
254 n_log(LOG_ERR, "unable to unzip string %p %zu/%zu bytes", unzipped->data, unzipped->written, unzipped->length);
255 free_nstr(&unzipped);
256 return NULL;
257 }
258 n_log(LOG_DEBUG, "Size: zip: %zu => unzip :%zu original:%u", src->written, unzipped->written, original_size);
259
260 return unzipped;
261} /* unzip_nstr */
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:279
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:89
#define LOG_DEBUG
debug-level messages
Definition n_log.h:84
#define LOG_ERR
error conditions
Definition n_log.h:76
size_t written
number of meaningful bytes in data, excluding the null terminator; the size including the null termin...
Definition n_str.h:68
char * data
the string
Definition n_str.h:63
size_t length
total allocation (in bytes) of the data buffer, padding included
Definition n_str.h:65
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
Definition n_str.h:203
N_STR * new_nstr(NSTRBYTE size)
create a new N_STR string
Definition n_str.c:207
A box including a string and his lenght.
Definition n_str.h:61
size_t GetMaxCompressedLen(size_t nLenSrc)
Return the maximum compressed size.
Definition n_zlib.c:42
size_t CompressData(unsigned char *abSrc, size_t nLenSrc, unsigned char *abDst, size_t nLenDst)
Compress a string to another.
Definition n_zlib.c:55
size_t UncompressData(unsigned char *abSrc, size_t nLenSrc, unsigned char *abDst, size_t nLenDst)
Uncompress a string to another.
Definition n_zlib.c:112
N_STR * unzip_nstr(N_STR *src)
return an uncompressed version of src
Definition n_zlib.c:217
N_STR * zip_nstr(N_STR *src)
return a compressed version of src
Definition n_zlib.c:166
Generic log system.
ZLIB compression handler.