annotate src/libmlk-core/core/zfile.c @ 343:9eb25198d706

js: add sound bindings
author David Demelier <markand@malikania.fr>
date Sat, 16 Oct 2021 22:17:09 +0200
parents 8f9937403749
children 7d7991f97acf
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 * zfile.c -- load potentially ZSTD compressed file
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 *
314
d01e83210ca2 misc: update years
David Demelier <markand@malikania.fr>
parents: 313
diff changeset
4 * Copyright (c) 2020-2021 David Demelier <markand@malikania.fr>
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 *
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 * Permission to use, copy, modify, and/or distribute this software for any
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 * purpose with or without fee is hereby granted, provided that the above
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 * copyright notice and this permission notice appear in all copies.
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 *
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
17 */
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
18
303
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
19 #include "config.h"
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
20
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
21 #include <sys/stat.h>
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
22 #include <assert.h>
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 #include <errno.h>
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 #include <fcntl.h>
302
f09c166fd4d4 core: fix zfile_close crash
David Demelier <markand@malikania.fr>
parents: 295
diff changeset
25 #include <stdint.h>
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 #include <stdlib.h>
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
27 #include <string.h>
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 #include <unistd.h>
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
29
303
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
30 /*
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
31 * If not enabled, we still need to check if a file is in zstandard so we use
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
32 * the magic number defined in the zstd.h file or copy it if zstd is disabled.
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
33 */
313
dbfe05b88627 cmake: bring back for good
David Demelier <markand@malikania.fr>
parents: 310
diff changeset
34 #if defined(MLK_WITH_ZSTD)
303
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
35 # include <zstd.h>
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
36 #else
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
37 # define ZSTD_MAGICNUMBER 0xFD2FB528
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
38 #endif
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
39
309
0858e33a762d misc: initial windows support
David Demelier <markand@malikania.fr>
parents: 303
diff changeset
40 /* Windows thing. */
0858e33a762d misc: initial windows support
David Demelier <markand@malikania.fr>
parents: 303
diff changeset
41 #if !defined(O_BINARY)
310
b271a0e8ce52 misc: fix O_BINARY
David Demelier <markand@malikania.fr>
parents: 309
diff changeset
42 # define O_BINARY 0
309
0858e33a762d misc: initial windows support
David Demelier <markand@malikania.fr>
parents: 303
diff changeset
43 #endif
0858e33a762d misc: initial windows support
David Demelier <markand@malikania.fr>
parents: 303
diff changeset
44
315
3bfaaf5342a9 cmake: add support for Visual Studio 2019
David Demelier <markand@malikania.fr>
parents: 314
diff changeset
45 #include <port/port.h>
3bfaaf5342a9 cmake: add support for Visual Studio 2019
David Demelier <markand@malikania.fr>
parents: 314
diff changeset
46
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
47 #include "zfile.h"
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
48
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
49 static int
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
50 is_zstd(int fd)
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
51 {
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
52 uint32_t magic = 0;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
53
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
54 read(fd, &magic, sizeof (magic));
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
55 lseek(fd, 0, SEEK_SET);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
56
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
57 #if SDL_BYTEORDER != SDL_LIL_ENDIAN
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 magic = SDL_Swap32(magic);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
59 #endif
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
60
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
61 return magic == ZSTD_MAGICNUMBER;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
62 }
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
63
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 static int
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
65 decompress(int fd, struct zfile *zf)
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
66 {
313
dbfe05b88627 cmake: bring back for good
David Demelier <markand@malikania.fr>
parents: 310
diff changeset
67 #if defined(MLK_WITH_ZSTD)
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
68 char *in = NULL;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 unsigned long long datasz;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
70 struct stat st;
309
0858e33a762d misc: initial windows support
David Demelier <markand@malikania.fr>
parents: 303
diff changeset
71 ssize_t nr;
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
72
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 /* Load uncompressed data. */
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
74 if (fstat(fd, &st) < 0)
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 goto fail;
309
0858e33a762d misc: initial windows support
David Demelier <markand@malikania.fr>
parents: 303
diff changeset
76 if (!(in = calloc(1, st.st_size)) || (nr = read(fd, in, st.st_size)) != st.st_size)
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 goto fail;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
78
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
79 switch ((datasz = ZSTD_getFrameContentSize(in, st.st_size))) {
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 case ZSTD_CONTENTSIZE_ERROR:
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 errno = EINVAL;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
82 goto fail;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
83 case ZSTD_CONTENTSIZE_UNKNOWN:
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
84 errno = ENOTSUP;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
85 goto fail;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
86 default:
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
87 break;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
88 }
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
89
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
90 /* Finally decompress. */
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 if (!(zf->data = calloc(1, datasz + 1)))
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
92 goto fail;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
93 if (ZSTD_isError(ZSTD_decompress(zf->data, datasz, in, st.st_size))) {
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
94 errno = EINVAL;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
95 goto fail;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 }
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
97 if (!(zf->fp = fmemopen(zf->data, datasz, "r")))
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
98 goto fail;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
99
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
100 close(fd);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
101 free(in);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
102
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
103 return 0;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
104
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
105 fail:
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
106 close(fd);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
107 free(zf->data);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 free(in);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
109
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 return -1;
303
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
111 #else
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
112 (void)fd;
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
113 (void)zf;
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
114
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
115 errno = ENOTSUP;
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
116
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
117 return -1;
48a09c9d3d00 core: make zstd optional
David Demelier <markand@malikania.fr>
parents: 302
diff changeset
118 #endif
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 }
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
120
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
121 static int
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
122 reopen(int fd, struct zfile *zf)
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
123 {
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
124 if (!(zf->fp = fdopen(fd, "r")))
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
125 return close(fd), -1;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
126
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
127 return 0;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
128 }
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
129
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
130 int
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 zfile_open(struct zfile *zf, const char *path)
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
132 {
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
133 assert(zf);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 assert(path);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
135
316
1a6125ffebff misc: fix many warnings and build on macOS
David Demelier <markand@malikania.fr>
parents: 315
diff changeset
136 int fd;
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
137
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
138 memset(zf, 0, sizeof (*zf));
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
139
309
0858e33a762d misc: initial windows support
David Demelier <markand@malikania.fr>
parents: 303
diff changeset
140 if ((fd = open(path, O_RDONLY | O_BINARY)) < 0)
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
141 return -1;
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
142
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
143 return is_zstd(fd) ? decompress(fd, zf) : reopen(fd, zf);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
144 }
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
145
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
146 void
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
147 zfile_close(struct zfile *zf)
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
148 {
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
149 assert(zf);
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
150
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
151 free(zf->data);
302
f09c166fd4d4 core: fix zfile_close crash
David Demelier <markand@malikania.fr>
parents: 295
diff changeset
152
f09c166fd4d4 core: fix zfile_close crash
David Demelier <markand@malikania.fr>
parents: 295
diff changeset
153 if (zf->fp)
f09c166fd4d4 core: fix zfile_close crash
David Demelier <markand@malikania.fr>
parents: 295
diff changeset
154 fclose(zf->fp);
f09c166fd4d4 core: fix zfile_close crash
David Demelier <markand@malikania.fr>
parents: 295
diff changeset
155
295
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
156 memset(zf, 0, sizeof (*zf));
aec448037320 rpg: add support for compressed tilesets/maps
David Demelier <markand@malikania.fr>
parents:
diff changeset
157 }