1 // After editing this file, run "go generate" in the parent directory.
2
3 // Copyright 2017 The Wuffs Authors.
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 // https://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 implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 static inline wuffs_base__empty_struct //
wuffs_base__ignore_status(wuffs_base__status z)18 wuffs_base__ignore_status(wuffs_base__status z) {
19 return wuffs_base__make_empty_struct();
20 }
21
22 // WUFFS_BASE__MAGIC is a magic number to check that initializers are called.
23 // It's not foolproof, given C doesn't automatically zero memory before use,
24 // but it should catch 99.99% of cases.
25 //
26 // Its (non-zero) value is arbitrary, based on md5sum("wuffs").
27 #define WUFFS_BASE__MAGIC ((uint32_t)0x3CCB6C71)
28
29 // WUFFS_BASE__DISABLED is a magic number to indicate that a non-recoverable
30 // error was previously encountered.
31 //
32 // Its (non-zero) value is arbitrary, based on md5sum("disabled").
33 #define WUFFS_BASE__DISABLED ((uint32_t)0x075AE3D2)
34
35 // Denote intentional fallthroughs for -Wimplicit-fallthrough.
36 //
37 // The order matters here. Clang also defines "__GNUC__".
38 #if defined(__clang__) && defined(__cplusplus) && (__cplusplus >= 201103L)
39 #define WUFFS_BASE__FALLTHROUGH [[clang::fallthrough]]
40 #elif !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 7)
41 #define WUFFS_BASE__FALLTHROUGH __attribute__((fallthrough))
42 #else
43 #define WUFFS_BASE__FALLTHROUGH
44 #endif
45
46 // Use switch cases for coroutine suspension points, similar to the technique
47 // in https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
48 //
49 // We use trivial macros instead of an explicit assignment and case statement
50 // so that clang-format doesn't get confused by the unusual "case"s.
51 #define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0 case 0:;
52 #define WUFFS_BASE__COROUTINE_SUSPENSION_POINT(n) \
53 coro_susp_point = n; \
54 WUFFS_BASE__FALLTHROUGH; \
55 case n:;
56
57 #define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(n) \
58 if (!status) { \
59 goto ok; \
60 } else if (*status != '$') { \
61 goto exit; \
62 } \
63 coro_susp_point = n; \
64 goto suspend; \
65 case n:;
66
67 // Clang also defines "__GNUC__".
68 #if defined(__GNUC__)
69 #define WUFFS_BASE__LIKELY(expr) (__builtin_expect(!!(expr), 1))
70 #define WUFFS_BASE__UNLIKELY(expr) (__builtin_expect(!!(expr), 0))
71 #else
72 #define WUFFS_BASE__LIKELY(expr) (expr)
73 #define WUFFS_BASE__UNLIKELY(expr) (expr)
74 #endif
75
76 // The helpers below are functions, instead of macros, because their arguments
77 // can be an expression that we shouldn't evaluate more than once.
78 //
79 // They are static, so that linking multiple wuffs .o files won't complain about
80 // duplicate function definitions.
81 //
82 // They are explicitly marked inline, even if modern compilers don't use the
83 // inline attribute to guide optimizations such as inlining, to avoid the
84 // -Wunused-function warning, and we like to compile with -Wall -Werror.
85
86 // ---------------- Numeric Types
87
88 static inline uint8_t //
wuffs_base__load_u8be(uint8_t * p)89 wuffs_base__load_u8be(uint8_t* p) {
90 return p[0];
91 }
92
93 static inline uint16_t //
wuffs_base__load_u16be(uint8_t * p)94 wuffs_base__load_u16be(uint8_t* p) {
95 return (uint16_t)(((uint16_t)(p[0]) << 8) | ((uint16_t)(p[1]) << 0));
96 }
97
98 static inline uint16_t //
wuffs_base__load_u16le(uint8_t * p)99 wuffs_base__load_u16le(uint8_t* p) {
100 return (uint16_t)(((uint16_t)(p[0]) << 0) | ((uint16_t)(p[1]) << 8));
101 }
102
103 static inline uint32_t //
wuffs_base__load_u24be(uint8_t * p)104 wuffs_base__load_u24be(uint8_t* p) {
105 return ((uint32_t)(p[0]) << 16) | ((uint32_t)(p[1]) << 8) |
106 ((uint32_t)(p[2]) << 0);
107 }
108
109 static inline uint32_t //
wuffs_base__load_u24le(uint8_t * p)110 wuffs_base__load_u24le(uint8_t* p) {
111 return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
112 ((uint32_t)(p[2]) << 16);
113 }
114
115 static inline uint32_t //
wuffs_base__load_u32be(uint8_t * p)116 wuffs_base__load_u32be(uint8_t* p) {
117 return ((uint32_t)(p[0]) << 24) | ((uint32_t)(p[1]) << 16) |
118 ((uint32_t)(p[2]) << 8) | ((uint32_t)(p[3]) << 0);
119 }
120
121 static inline uint32_t //
wuffs_base__load_u32le(uint8_t * p)122 wuffs_base__load_u32le(uint8_t* p) {
123 return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
124 ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24);
125 }
126
127 static inline uint64_t //
wuffs_base__load_u40be(uint8_t * p)128 wuffs_base__load_u40be(uint8_t* p) {
129 return ((uint64_t)(p[0]) << 32) | ((uint64_t)(p[1]) << 24) |
130 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 8) |
131 ((uint64_t)(p[4]) << 0);
132 }
133
134 static inline uint64_t //
wuffs_base__load_u40le(uint8_t * p)135 wuffs_base__load_u40le(uint8_t* p) {
136 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
137 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
138 ((uint64_t)(p[4]) << 32);
139 }
140
141 static inline uint64_t //
wuffs_base__load_u48be(uint8_t * p)142 wuffs_base__load_u48be(uint8_t* p) {
143 return ((uint64_t)(p[0]) << 40) | ((uint64_t)(p[1]) << 32) |
144 ((uint64_t)(p[2]) << 24) | ((uint64_t)(p[3]) << 16) |
145 ((uint64_t)(p[4]) << 8) | ((uint64_t)(p[5]) << 0);
146 }
147
148 static inline uint64_t //
wuffs_base__load_u48le(uint8_t * p)149 wuffs_base__load_u48le(uint8_t* p) {
150 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
151 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
152 ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40);
153 }
154
155 static inline uint64_t //
wuffs_base__load_u56be(uint8_t * p)156 wuffs_base__load_u56be(uint8_t* p) {
157 return ((uint64_t)(p[0]) << 48) | ((uint64_t)(p[1]) << 40) |
158 ((uint64_t)(p[2]) << 32) | ((uint64_t)(p[3]) << 24) |
159 ((uint64_t)(p[4]) << 16) | ((uint64_t)(p[5]) << 8) |
160 ((uint64_t)(p[6]) << 0);
161 }
162
163 static inline uint64_t //
wuffs_base__load_u56le(uint8_t * p)164 wuffs_base__load_u56le(uint8_t* p) {
165 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
166 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
167 ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) |
168 ((uint64_t)(p[6]) << 48);
169 }
170
171 static inline uint64_t //
wuffs_base__load_u64be(uint8_t * p)172 wuffs_base__load_u64be(uint8_t* p) {
173 return ((uint64_t)(p[0]) << 56) | ((uint64_t)(p[1]) << 48) |
174 ((uint64_t)(p[2]) << 40) | ((uint64_t)(p[3]) << 32) |
175 ((uint64_t)(p[4]) << 24) | ((uint64_t)(p[5]) << 16) |
176 ((uint64_t)(p[6]) << 8) | ((uint64_t)(p[7]) << 0);
177 }
178
179 static inline uint64_t //
wuffs_base__load_u64le(uint8_t * p)180 wuffs_base__load_u64le(uint8_t* p) {
181 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
182 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
183 ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) |
184 ((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56);
185 }
186
187 // --------
188
189 static inline void //
wuffs_base__store_u8be(uint8_t * p,uint8_t x)190 wuffs_base__store_u8be(uint8_t* p, uint8_t x) {
191 p[0] = x;
192 }
193
194 static inline void //
wuffs_base__store_u16be(uint8_t * p,uint16_t x)195 wuffs_base__store_u16be(uint8_t* p, uint16_t x) {
196 p[0] = (uint8_t)(x >> 8);
197 p[1] = (uint8_t)(x >> 0);
198 }
199
200 static inline void //
wuffs_base__store_u16le(uint8_t * p,uint16_t x)201 wuffs_base__store_u16le(uint8_t* p, uint16_t x) {
202 p[0] = (uint8_t)(x >> 0);
203 p[1] = (uint8_t)(x >> 8);
204 }
205
206 static inline void //
wuffs_base__store_u24be(uint8_t * p,uint32_t x)207 wuffs_base__store_u24be(uint8_t* p, uint32_t x) {
208 p[0] = (uint8_t)(x >> 16);
209 p[1] = (uint8_t)(x >> 8);
210 p[2] = (uint8_t)(x >> 0);
211 }
212
213 static inline void //
wuffs_base__store_u24le(uint8_t * p,uint32_t x)214 wuffs_base__store_u24le(uint8_t* p, uint32_t x) {
215 p[0] = (uint8_t)(x >> 0);
216 p[1] = (uint8_t)(x >> 8);
217 p[2] = (uint8_t)(x >> 16);
218 }
219
220 static inline void //
wuffs_base__store_u32be(uint8_t * p,uint32_t x)221 wuffs_base__store_u32be(uint8_t* p, uint32_t x) {
222 p[0] = (uint8_t)(x >> 24);
223 p[1] = (uint8_t)(x >> 16);
224 p[2] = (uint8_t)(x >> 8);
225 p[3] = (uint8_t)(x >> 0);
226 }
227
228 static inline void //
wuffs_base__store_u32le(uint8_t * p,uint32_t x)229 wuffs_base__store_u32le(uint8_t* p, uint32_t x) {
230 p[0] = (uint8_t)(x >> 0);
231 p[1] = (uint8_t)(x >> 8);
232 p[2] = (uint8_t)(x >> 16);
233 p[3] = (uint8_t)(x >> 24);
234 }
235
236 static inline void //
wuffs_base__store_u40be(uint8_t * p,uint64_t x)237 wuffs_base__store_u40be(uint8_t* p, uint64_t x) {
238 p[0] = (uint8_t)(x >> 32);
239 p[1] = (uint8_t)(x >> 24);
240 p[2] = (uint8_t)(x >> 16);
241 p[3] = (uint8_t)(x >> 8);
242 p[4] = (uint8_t)(x >> 0);
243 }
244
245 static inline void //
wuffs_base__store_u40le(uint8_t * p,uint64_t x)246 wuffs_base__store_u40le(uint8_t* p, uint64_t x) {
247 p[0] = (uint8_t)(x >> 0);
248 p[1] = (uint8_t)(x >> 8);
249 p[2] = (uint8_t)(x >> 16);
250 p[3] = (uint8_t)(x >> 24);
251 p[4] = (uint8_t)(x >> 32);
252 }
253
254 static inline void //
wuffs_base__store_u48be(uint8_t * p,uint64_t x)255 wuffs_base__store_u48be(uint8_t* p, uint64_t x) {
256 p[0] = (uint8_t)(x >> 40);
257 p[1] = (uint8_t)(x >> 32);
258 p[2] = (uint8_t)(x >> 24);
259 p[3] = (uint8_t)(x >> 16);
260 p[4] = (uint8_t)(x >> 8);
261 p[5] = (uint8_t)(x >> 0);
262 }
263
264 static inline void //
wuffs_base__store_u48le(uint8_t * p,uint64_t x)265 wuffs_base__store_u48le(uint8_t* p, uint64_t x) {
266 p[0] = (uint8_t)(x >> 0);
267 p[1] = (uint8_t)(x >> 8);
268 p[2] = (uint8_t)(x >> 16);
269 p[3] = (uint8_t)(x >> 24);
270 p[4] = (uint8_t)(x >> 32);
271 p[5] = (uint8_t)(x >> 40);
272 }
273
274 static inline void //
wuffs_base__store_u56be(uint8_t * p,uint64_t x)275 wuffs_base__store_u56be(uint8_t* p, uint64_t x) {
276 p[0] = (uint8_t)(x >> 48);
277 p[1] = (uint8_t)(x >> 40);
278 p[2] = (uint8_t)(x >> 32);
279 p[3] = (uint8_t)(x >> 24);
280 p[4] = (uint8_t)(x >> 16);
281 p[5] = (uint8_t)(x >> 8);
282 p[6] = (uint8_t)(x >> 0);
283 }
284
285 static inline void //
wuffs_base__store_u56le(uint8_t * p,uint64_t x)286 wuffs_base__store_u56le(uint8_t* p, uint64_t x) {
287 p[0] = (uint8_t)(x >> 0);
288 p[1] = (uint8_t)(x >> 8);
289 p[2] = (uint8_t)(x >> 16);
290 p[3] = (uint8_t)(x >> 24);
291 p[4] = (uint8_t)(x >> 32);
292 p[5] = (uint8_t)(x >> 40);
293 p[6] = (uint8_t)(x >> 48);
294 }
295
296 static inline void //
wuffs_base__store_u64be(uint8_t * p,uint64_t x)297 wuffs_base__store_u64be(uint8_t* p, uint64_t x) {
298 p[0] = (uint8_t)(x >> 56);
299 p[1] = (uint8_t)(x >> 48);
300 p[2] = (uint8_t)(x >> 40);
301 p[3] = (uint8_t)(x >> 32);
302 p[4] = (uint8_t)(x >> 24);
303 p[5] = (uint8_t)(x >> 16);
304 p[6] = (uint8_t)(x >> 8);
305 p[7] = (uint8_t)(x >> 0);
306 }
307
308 static inline void //
wuffs_base__store_u64le(uint8_t * p,uint64_t x)309 wuffs_base__store_u64le(uint8_t* p, uint64_t x) {
310 p[0] = (uint8_t)(x >> 0);
311 p[1] = (uint8_t)(x >> 8);
312 p[2] = (uint8_t)(x >> 16);
313 p[3] = (uint8_t)(x >> 24);
314 p[4] = (uint8_t)(x >> 32);
315 p[5] = (uint8_t)(x >> 40);
316 p[6] = (uint8_t)(x >> 48);
317 p[7] = (uint8_t)(x >> 56);
318 }
319
320 // --------
321
322 extern const uint8_t wuffs_base__low_bits_mask__u8[9];
323 extern const uint16_t wuffs_base__low_bits_mask__u16[17];
324 extern const uint32_t wuffs_base__low_bits_mask__u32[33];
325 extern const uint64_t wuffs_base__low_bits_mask__u64[65];
326
327 #define WUFFS_BASE__LOW_BITS_MASK__U8(n) (wuffs_base__low_bits_mask__u8[n])
328 #define WUFFS_BASE__LOW_BITS_MASK__U16(n) (wuffs_base__low_bits_mask__u16[n])
329 #define WUFFS_BASE__LOW_BITS_MASK__U32(n) (wuffs_base__low_bits_mask__u32[n])
330 #define WUFFS_BASE__LOW_BITS_MASK__U64(n) (wuffs_base__low_bits_mask__u64[n])
331
332 // --------
333
334 static inline void //
wuffs_base__u8__sat_add_indirect(uint8_t * x,uint8_t y)335 wuffs_base__u8__sat_add_indirect(uint8_t* x, uint8_t y) {
336 *x = wuffs_base__u8__sat_add(*x, y);
337 }
338
339 static inline void //
wuffs_base__u8__sat_sub_indirect(uint8_t * x,uint8_t y)340 wuffs_base__u8__sat_sub_indirect(uint8_t* x, uint8_t y) {
341 *x = wuffs_base__u8__sat_sub(*x, y);
342 }
343
344 static inline void //
wuffs_base__u16__sat_add_indirect(uint16_t * x,uint16_t y)345 wuffs_base__u16__sat_add_indirect(uint16_t* x, uint16_t y) {
346 *x = wuffs_base__u16__sat_add(*x, y);
347 }
348
349 static inline void //
wuffs_base__u16__sat_sub_indirect(uint16_t * x,uint16_t y)350 wuffs_base__u16__sat_sub_indirect(uint16_t* x, uint16_t y) {
351 *x = wuffs_base__u16__sat_sub(*x, y);
352 }
353
354 static inline void //
wuffs_base__u32__sat_add_indirect(uint32_t * x,uint32_t y)355 wuffs_base__u32__sat_add_indirect(uint32_t* x, uint32_t y) {
356 *x = wuffs_base__u32__sat_add(*x, y);
357 }
358
359 static inline void //
wuffs_base__u32__sat_sub_indirect(uint32_t * x,uint32_t y)360 wuffs_base__u32__sat_sub_indirect(uint32_t* x, uint32_t y) {
361 *x = wuffs_base__u32__sat_sub(*x, y);
362 }
363
364 static inline void //
wuffs_base__u64__sat_add_indirect(uint64_t * x,uint64_t y)365 wuffs_base__u64__sat_add_indirect(uint64_t* x, uint64_t y) {
366 *x = wuffs_base__u64__sat_add(*x, y);
367 }
368
369 static inline void //
wuffs_base__u64__sat_sub_indirect(uint64_t * x,uint64_t y)370 wuffs_base__u64__sat_sub_indirect(uint64_t* x, uint64_t y) {
371 *x = wuffs_base__u64__sat_sub(*x, y);
372 }
373
374 // ---------------- Slices and Tables
375
376 // wuffs_base__slice_u8__prefix returns up to the first up_to bytes of s.
377 static inline wuffs_base__slice_u8 //
wuffs_base__slice_u8__prefix(wuffs_base__slice_u8 s,uint64_t up_to)378 wuffs_base__slice_u8__prefix(wuffs_base__slice_u8 s, uint64_t up_to) {
379 if ((uint64_t)(s.len) > up_to) {
380 s.len = up_to;
381 }
382 return s;
383 }
384
385 // wuffs_base__slice_u8__suffix returns up to the last up_to bytes of s.
386 static inline wuffs_base__slice_u8 //
wuffs_base__slice_u8__suffix(wuffs_base__slice_u8 s,uint64_t up_to)387 wuffs_base__slice_u8__suffix(wuffs_base__slice_u8 s, uint64_t up_to) {
388 if ((uint64_t)(s.len) > up_to) {
389 s.ptr += (uint64_t)(s.len) - up_to;
390 s.len = up_to;
391 }
392 return s;
393 }
394
395 // wuffs_base__slice_u8__copy_from_slice calls memmove(dst.ptr, src.ptr, len)
396 // where len is the minimum of dst.len and src.len.
397 //
398 // Passing a wuffs_base__slice_u8 with all fields NULL or zero (a valid, empty
399 // slice) is valid and results in a no-op.
400 static inline uint64_t //
wuffs_base__slice_u8__copy_from_slice(wuffs_base__slice_u8 dst,wuffs_base__slice_u8 src)401 wuffs_base__slice_u8__copy_from_slice(wuffs_base__slice_u8 dst,
402 wuffs_base__slice_u8 src) {
403 size_t len = dst.len < src.len ? dst.len : src.len;
404 if (len > 0) {
405 memmove(dst.ptr, src.ptr, len);
406 }
407 return len;
408 }
409
410 // --------
411
412 static inline wuffs_base__slice_u8 //
wuffs_base__table_u8__row(wuffs_base__table_u8 t,uint32_t y)413 wuffs_base__table_u8__row(wuffs_base__table_u8 t, uint32_t y) {
414 if (y < t.height) {
415 return wuffs_base__make_slice_u8(t.ptr + (t.stride * y), t.width);
416 }
417 return wuffs_base__make_slice_u8(NULL, 0);
418 }
419
420 // ---------------- Slices and Tables (Utility)
421
422 #define wuffs_base__utility__empty_slice_u8 wuffs_base__empty_slice_u8
423