ohmu
·
2026-10-15
1#include "common/zlib.h"
2#include "common/debug.h"
3
4#if FF_HAVE_ZLIB && !FF_DISABLE_DLOPEN
5
6struct FFZlibData zlibData;
7
8// Opens the library and leaves the handle in zlibData, so the groups that follow resolve against the
9// same mapping instead of opening their own.
10static const char* openZlib(void) {
11 #ifdef _WIN32
12 FF_LIBRARY_LOAD_MESSAGE(zlib, "zlib1" FF_LIBRARY_EXTENSION, 2)
13 #else
14 FF_LIBRARY_LOAD_MESSAGE(zlib, "libz" FF_LIBRARY_EXTENSION, 2)
15 #endif
16
17 zlibData.handle = zlib;
18 zlib = nullptr; // the handle is kept in zlibData, so the cleanup must not close it
19 return nullptr;
20}
21
22const char* ffZlibLoad(FFZlibGroup group) {
23 FF_DEBUG("Loading zlib group: %x", group);
24
25 // Opened once, by whichever group is asked for first; the later ones reuse that mapping. A
26 // failed open is retried by the next group rather than cached, so a system without libz pays at
27 // most one attempt per group -- not one per call.
28 if (zlibData.handle == nullptr) {
29 if (zlibData.attempted == UINT8_MAX) {
30 return "Previous attempt to open zlib failed";
31 }
32
33 const char* error = openZlib();
34 if (error != nullptr) {
35 static_assert(sizeof(zlibData.attempted) == 1, "zlibData.attempted must be 1 byte");
36 zlibData.attempted = UINT8_MAX;
37 return error;
38 }
39 }
40
41 if (group & FF_ZLIB_COMPRESS) {
42 if (zlibData.attempted & FF_ZLIB_COMPRESS) {
43 if (!zlibData.ffcompress2) {
44 return "Previous attempt to load compress failed";
45 }
46 } else {
47 zlibData.attempted |= FF_ZLIB_COMPRESS;
48 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, compressBound)
49 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, compress2)
50 }
51 }
52 if (group & FF_ZLIB_INFLATE) {
53 if (zlibData.attempted & FF_ZLIB_INFLATE) {
54 if (!zlibData.ffinflateEnd) {
55 return "Previous attempt to load inflate failed";
56 }
57 } else {
58 zlibData.attempted |= FF_ZLIB_INFLATE;
59 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, inflateInit2_)
60 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, inflate)
61 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, inflateEnd)
62 }
63 }
64
65 if (group & FF_ZLIB_GZFILE) {
66 if (zlibData.attempted & FF_ZLIB_GZFILE) {
67 if (!zlibData.ffgzclose) {
68 return "Previous attempt to load gzfile failed";
69 }
70 } else {
71 zlibData.attempted |= FF_ZLIB_GZFILE;
72 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, gzopen)
73 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, gzread)
74 FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(zlibData.handle, zlibData, gzclose)
75 }
76 }
77
78 return nullptr;
79}
80
81#endif