Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
n_lz4.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 <limits.h>
28#include <stdint.h>
29#include <string.h>
30
31#include "nilorea/n_log.h"
32#include "nilorea/n_common.h"
33#include "nilorea/n_str.h"
34#include "nilorea/n_lz4.h"
35
36/* htonl / ntohl, winsock2.h on Windows, arpa/inet.h everywhere else.
37 * n_common.h defines __windows__ on _WIN32/_WIN64. */
38#ifdef __windows__
39#include "nilorea/n_windows.h"
40#else
41#include <arpa/inet.h>
42#endif
43
44#include "lz4.h"
45
56 __n_assert(src, return NULL);
57 __n_assert(src->data, return NULL);
58
59 if (src->length == 0) {
60 n_log(LOG_ERR, "length of src == 0");
61 return NULL;
62 }
63 if (src->written == 0) {
64 n_log(LOG_ERR, "written of src == 0");
65 return NULL;
66 }
67 /* LZ4's API is int-sized. Reject anything that would overflow. */
68 if (src->written > (size_t)INT_MAX) {
69 n_log(LOG_ERR, "written of src > INT_MAX");
70 return NULL;
71 }
72
73 int src_len = (int)src->written;
74 int max_compressed = LZ4_compressBound(src_len);
75 if (max_compressed <= 0) {
76 n_log(LOG_ERR, "LZ4_compressBound(%d) failed", src_len);
77 return NULL;
78 }
79
80 N_STR* zipped = new_nstr((size_t)(4 + max_compressed));
81 __n_assert(zipped, return NULL);
82 __n_assert(zipped->data, return NULL);
83
84 /* Original length header (network byte order). */
85 uint32_t src_length_be = htonl((uint32_t)src->written);
86 memcpy(zipped->data, &src_length_be, sizeof(uint32_t));
87 char* dataptr = zipped->data + 4;
88
89 int compressed = LZ4_compress_default(src->data, dataptr, src_len, max_compressed);
90 if (compressed <= 0) {
91 n_log(LOG_ERR, "LZ4_compress_default failed (src=%d bytes)", src_len);
92 free_nstr(&zipped);
93 return NULL;
94 }
95 zipped->written = (size_t)(4 + compressed);
96 n_log(LOG_DEBUG, "lz4 zip: %d -> %zu (header incl.)", src_len, zipped->written);
97 return zipped;
98} /* zip4_nstr */
99
108 __n_assert(src, return NULL);
109 __n_assert(src->data, return NULL);
110
111 if (src->written < 4) {
112 n_log(LOG_ERR, "compressed data too short (%zu bytes)", src->written);
113 return NULL;
114 }
115
116 uint32_t original_size = 0;
117 memcpy(&original_size, src->data, sizeof(uint32_t));
118 original_size = ntohl(original_size);
119 if (original_size == 0) {
120 n_log(LOG_ERR, "lz4 frame declares original_size == 0");
121 return NULL;
122 }
123 if (original_size > 256u * 1024u * 1024u) {
124 n_log(LOG_ERR, "lz4 frame declares absurd original_size %u", original_size);
125 return NULL;
126 }
127
128 N_STR* unzipped = new_nstr(original_size);
129 __n_assert(unzipped, return NULL);
130 __n_assert(unzipped->data, return NULL);
131
132 size_t compressed_bytes = src->written - 4;
133 if (compressed_bytes > (size_t)INT_MAX) {
134 n_log(LOG_ERR, "compressed payload > INT_MAX");
135 free_nstr(&unzipped);
136 return NULL;
137 }
138
139 int decoded = LZ4_decompress_safe(src->data + 4, unzipped->data,
140 (int)compressed_bytes, (int)original_size);
141 if (decoded < 0) {
142 n_log(LOG_ERR, "LZ4_decompress_safe failed (compressed=%zu, original=%u)",
143 compressed_bytes, original_size);
144 free_nstr(&unzipped);
145 return NULL;
146 }
147 unzipped->written = (size_t)decoded;
148 n_log(LOG_DEBUG, "lz4 unzip: %zu -> %zu (original=%u)",
149 src->written, unzipped->written, original_size);
150 return unzipped;
151} /* unzip4_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
N_STR * zip4_nstr(N_STR *src)
Compress src with LZ4 block format.
Definition n_lz4.c:55
N_STR * unzip4_nstr(N_STR *src)
Decompress an N_STR produced by zip4_nstr.
Definition n_lz4.c:107
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
Common headers and low-level functions & define.
Generic log system.
LZ4 block-compression handler.
N_STR and string function declaration.