libacfutils
A general purpose library of utility functions designed to make it easier to develop addons for the X-Plane flight simulator.
Loading...
Searching...
No Matches
compress_zlib.c
1/*
2 * CDDL HEADER START
3 *
4 * This file and its contents are supplied under the terms of the
5 * Common Development and Distribution License ("CDDL"), version 1.0.
6 * You may only use this file in accordance with the terms of version
7 * 1.0 of the CDDL.
8 *
9 * A full copy of the text of the CDDL should have accompanied this
10 * source. A copy of the CDDL is also available via the Internet at
11 * http://www.illumos.org/license/CDDL.
12 *
13 * CDDL HEADER END
14*/
15/*
16 * Copyright 2023 Saso Kiselkov. All rights reserved.
17 */
18
19#include <string.h>
20#include <stdlib.h>
21
22#include <stdio.h>
23
24#include <zlib.h>
25
26#include "acfutils/assert.h"
27#include "acfutils/compress.h"
28#include "acfutils/safe_alloc.h"
29
39bool_t
40zlib_test(const void *in_buf, size_t len)
41{
42 const uint8_t *buf8 = in_buf;
43 if (len < 2)
44 return (B_FALSE);
45 return (buf8[0] == 0x78 &&
46 (buf8[1] == 0x01 || buf8[1] == 0x9c || buf8[1] == 0xda));
47}
48
64void *
65zlib_compress(void *in_buf, size_t len, size_t *out_len)
66{
67 enum { CHUNK = 16384 };
68 z_stream strm;
69 void *out_buf = safe_malloc(len);
70 size_t consumed = 0;
71 size_t output = 0;
72
73 strm.zalloc = Z_NULL;
74 strm.zfree = Z_NULL;
75 strm.opaque = Z_NULL;
76 VERIFY3S(deflateInit(&strm, Z_DEFAULT_COMPRESSION), ==, Z_OK);
77
78 for (;;) {
79 int flush;
80 int res;
81 int have_in = MIN(len - consumed, CHUNK);
82 int have_out = len - output;
83
84 strm.next_in = in_buf + consumed;
85 strm.avail_in = have_in;
86 strm.next_out = out_buf + output;
87 strm.avail_out = have_out;
88
89 flush = (have_in == 0 ? Z_FINISH : Z_NO_FLUSH);
90
91 res = deflate(&strm, flush);
92 switch (res) {
93 case Z_OK:
94 case Z_STREAM_END:
95 consumed += have_in;
96 output += have_out - strm.avail_out;
97 *out_len = output;
98 if (res == Z_STREAM_END)
99 goto out;
100 break;
101 case Z_BUF_ERROR:
102 /*
103 * Compression would expand the data,
104 * so don't compress.
105 */
106 free(out_buf);
107 out_buf = NULL;
108 *out_len = 0;
109 goto out;
110 default:
111 VERIFY_MSG(0, "Invalid result: %d", res);
112 }
113 }
114out:
115 deflateEnd(&strm);
116
117 return (out_buf);
118}
119
127void *
128zlib_decompress(void *in_buf, size_t len, size_t *out_len_p)
129{
130 enum { OUT_BUF_SZ = 32768 };
131 z_stream strm;
132 void *out_buf = NULL;
133 size_t out_len = 0, out_cap = 0;
134 size_t in_prog = 0;
135
136 strm.zalloc = Z_NULL;
137 strm.zfree = Z_NULL;
138 strm.opaque = Z_NULL;
139 strm.next_in = Z_NULL;
140 strm.avail_in = 0;
141 VERIFY3S(inflateInit(&strm), ==, Z_OK);
142
143 for (;;) {
144 int ret, avail_in;
145
146 out_cap += OUT_BUF_SZ;
147 out_buf = realloc(out_buf, out_cap);
148
149 strm.next_in = in_buf + in_prog;
150 avail_in = len - in_prog;
151 strm.avail_in = avail_in;
152 strm.next_out = out_buf + out_len;
153 strm.avail_out = out_cap - out_len;
154 ret = inflate(&strm, Z_NO_FLUSH);
155 ASSERT(ret != Z_STREAM_ERROR);
156 switch (ret) {
157 case Z_NEED_DICT:
158 ret = Z_DATA_ERROR;
159 /* fallthrough */
160 case Z_DATA_ERROR:
161 case Z_MEM_ERROR:
162 free(out_buf);
163 out_buf = NULL;
164 out_len = 0;
165 goto out;
166 }
167 in_prog += (avail_in - strm.avail_in);
168 out_len += (out_cap - out_len) - strm.avail_out;
169 if (ret == Z_STREAM_END)
170 break;
171 }
172
173out:
174 inflateEnd(&strm);
175 *out_len_p = out_len;
176
177 return (out_buf);
178}
#define ASSERT(x)
Definition assert.h:208
#define VERIFY3S(x, op, y)
Definition assert.h:125
#define VERIFY_MSG(x, fmt,...)
Definition assert.h:91
void * zlib_decompress(void *in_buf, size_t len, size_t *out_len_p)
bool_t zlib_test(const void *in_buf, size_t len)
void * zlib_compress(void *in_buf, size_t len, size_t *out_len)
static void * safe_malloc(size_t size)
Definition safe_alloc.h:56