xref: /aosp_15_r20/external/erofs-utils/include/erofs/flex-array.h (revision 33b1fccf6a0fada2c2875d400ed01119b7676ee5)
1*33b1fccfSAndroid Build Coastguard Worker /* SPDX-License-Identifier: GPL-2.0 */
2*33b1fccfSAndroid Build Coastguard Worker #ifndef __EROFS_FLEX_ARRAY_H
3*33b1fccfSAndroid Build Coastguard Worker #define __EROFS_FLEX_ARRAY_H
4*33b1fccfSAndroid Build Coastguard Worker 
5*33b1fccfSAndroid Build Coastguard Worker #ifdef __cplusplus
6*33b1fccfSAndroid Build Coastguard Worker extern "C"
7*33b1fccfSAndroid Build Coastguard Worker {
8*33b1fccfSAndroid Build Coastguard Worker #endif
9*33b1fccfSAndroid Build Coastguard Worker 
10*33b1fccfSAndroid Build Coastguard Worker #include <stdio.h>
11*33b1fccfSAndroid Build Coastguard Worker #include <stdlib.h>
12*33b1fccfSAndroid Build Coastguard Worker #include <limits.h>
13*33b1fccfSAndroid Build Coastguard Worker #include <stdint.h>
14*33b1fccfSAndroid Build Coastguard Worker 
15*33b1fccfSAndroid Build Coastguard Worker #include "defs.h"
16*33b1fccfSAndroid Build Coastguard Worker #include "print.h"
17*33b1fccfSAndroid Build Coastguard Worker 
18*33b1fccfSAndroid Build Coastguard Worker /*
19*33b1fccfSAndroid Build Coastguard Worker  * flex-array.h
20*33b1fccfSAndroid Build Coastguard Worker  *
21*33b1fccfSAndroid Build Coastguard Worker  * Some notes to make sense of the code.
22*33b1fccfSAndroid Build Coastguard Worker  *
23*33b1fccfSAndroid Build Coastguard Worker  * Flex-arrays:
24*33b1fccfSAndroid Build Coastguard Worker  *   - Flex-arrays became standard in C99 and are defined by "array[]" (at the
25*33b1fccfSAndroid Build Coastguard Worker  *     end of a struct)
26*33b1fccfSAndroid Build Coastguard Worker  *   - Pre-C99 flex-arrays can be accomplished by "array[1]"
27*33b1fccfSAndroid Build Coastguard Worker  *   - There is a GNU extension where they are defined using "array[0]"
28*33b1fccfSAndroid Build Coastguard Worker  *     Allegedly there is/was a bug in gcc whereby foo[1] generated incorrect
29*33b1fccfSAndroid Build Coastguard Worker  *     code, so it's safest to use [0] (https://lkml.org/lkml/2015/2/18/407).
30*33b1fccfSAndroid Build Coastguard Worker  *
31*33b1fccfSAndroid Build Coastguard Worker  * For C89 and C90, __STDC__ is 1
32*33b1fccfSAndroid Build Coastguard Worker  * For later standards, __STDC_VERSION__ is defined according to the standard.
33*33b1fccfSAndroid Build Coastguard Worker  * For example: 199901L or 201112L
34*33b1fccfSAndroid Build Coastguard Worker  *
35*33b1fccfSAndroid Build Coastguard Worker  * Whilst we're on the subject, in version 5 of gcc, the default std was
36*33b1fccfSAndroid Build Coastguard Worker  * changed from gnu89 to gnu11. In jgmenu, CFLAGS therefore contains -std=gnu89
37*33b1fccfSAndroid Build Coastguard Worker  * You can check your default gcc std by doing:
38*33b1fccfSAndroid Build Coastguard Worker  * gcc -dM -E - </dev/null | grep '__STDC_VERSION__\|__STDC__'
39*33b1fccfSAndroid Build Coastguard Worker  *
40*33b1fccfSAndroid Build Coastguard Worker  * The code below is copied from git's git-compat-util.h in support of
41*33b1fccfSAndroid Build Coastguard Worker  * hashmap.c
42*33b1fccfSAndroid Build Coastguard Worker  */
43*33b1fccfSAndroid Build Coastguard Worker 
44*33b1fccfSAndroid Build Coastguard Worker #ifndef FLEX_ARRAY
45*33b1fccfSAndroid Build Coastguard Worker #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
46*33b1fccfSAndroid Build Coastguard Worker 	(!defined(__SUNPRO_C) || (__SUNPRO_C > 0x580))
47*33b1fccfSAndroid Build Coastguard Worker # define FLEX_ARRAY /* empty */
48*33b1fccfSAndroid Build Coastguard Worker #elif defined(__GNUC__)
49*33b1fccfSAndroid Build Coastguard Worker # if (__GNUC__ >= 3)
50*33b1fccfSAndroid Build Coastguard Worker #  define FLEX_ARRAY /* empty */
51*33b1fccfSAndroid Build Coastguard Worker # else
52*33b1fccfSAndroid Build Coastguard Worker #  define FLEX_ARRAY 0 /* older GNU extension */
53*33b1fccfSAndroid Build Coastguard Worker # endif
54*33b1fccfSAndroid Build Coastguard Worker #endif
55*33b1fccfSAndroid Build Coastguard Worker 
56*33b1fccfSAndroid Build Coastguard Worker /* Otherwise, default to safer but a bit wasteful traditional style */
57*33b1fccfSAndroid Build Coastguard Worker #ifndef FLEX_ARRAY
58*33b1fccfSAndroid Build Coastguard Worker # define FLEX_ARRAY 1
59*33b1fccfSAndroid Build Coastguard Worker #endif
60*33b1fccfSAndroid Build Coastguard Worker #endif
61*33b1fccfSAndroid Build Coastguard Worker 
62*33b1fccfSAndroid Build Coastguard Worker #define bitsizeof(x) (CHAR_BIT * sizeof(x))
63*33b1fccfSAndroid Build Coastguard Worker 
64*33b1fccfSAndroid Build Coastguard Worker #define maximum_signed_value_of_type(a) \
65*33b1fccfSAndroid Build Coastguard Worker 	(INTMAX_MAX >> (bitsizeof(intmax_t) - bitsizeof(a)))
66*33b1fccfSAndroid Build Coastguard Worker 
67*33b1fccfSAndroid Build Coastguard Worker #define maximum_unsigned_value_of_type(a) \
68*33b1fccfSAndroid Build Coastguard Worker 	(UINTMAX_MAX >> (bitsizeof(uintmax_t) - bitsizeof(a)))
69*33b1fccfSAndroid Build Coastguard Worker 
70*33b1fccfSAndroid Build Coastguard Worker /*
71*33b1fccfSAndroid Build Coastguard Worker  * Signed integer overflow is undefined in C, so here's a helper macro
72*33b1fccfSAndroid Build Coastguard Worker  * to detect if the sum of two integers will overflow.
73*33b1fccfSAndroid Build Coastguard Worker  * Requires: a >= 0, typeof(a) equals typeof(b)
74*33b1fccfSAndroid Build Coastguard Worker  */
75*33b1fccfSAndroid Build Coastguard Worker #define signed_add_overflows(a, b) \
76*33b1fccfSAndroid Build Coastguard Worker 	((b) > maximum_signed_value_of_type(a) - (a))
77*33b1fccfSAndroid Build Coastguard Worker 
78*33b1fccfSAndroid Build Coastguard Worker #define unsigned_add_overflows(a, b) \
79*33b1fccfSAndroid Build Coastguard Worker 	((b) > maximum_unsigned_value_of_type(a) - (a))
80*33b1fccfSAndroid Build Coastguard Worker 
st_add(size_t a,size_t b)81*33b1fccfSAndroid Build Coastguard Worker static inline size_t st_add(size_t a, size_t b)
82*33b1fccfSAndroid Build Coastguard Worker {
83*33b1fccfSAndroid Build Coastguard Worker 	if (unsigned_add_overflows(a, b)) {
84*33b1fccfSAndroid Build Coastguard Worker 		erofs_err("size_t overflow: %llu + %llu", a | 0ULL, b | 0ULL);
85*33b1fccfSAndroid Build Coastguard Worker 		BUG_ON(1);
86*33b1fccfSAndroid Build Coastguard Worker 		return -1;
87*33b1fccfSAndroid Build Coastguard Worker 	}
88*33b1fccfSAndroid Build Coastguard Worker 	return a + b;
89*33b1fccfSAndroid Build Coastguard Worker }
90*33b1fccfSAndroid Build Coastguard Worker 
91*33b1fccfSAndroid Build Coastguard Worker #define st_add3(a, b, c) st_add(st_add((a), (b)), (c))
92*33b1fccfSAndroid Build Coastguard Worker #define st_add4(a, b, c, d) st_add(st_add3((a), (b), (c)), (d))
93*33b1fccfSAndroid Build Coastguard Worker 
94*33b1fccfSAndroid Build Coastguard Worker /*
95*33b1fccfSAndroid Build Coastguard Worker  * These functions help you allocate structs with flex arrays, and copy
96*33b1fccfSAndroid Build Coastguard Worker  * the data directly into the array. For example, if you had:
97*33b1fccfSAndroid Build Coastguard Worker  *
98*33b1fccfSAndroid Build Coastguard Worker  *   struct foo {
99*33b1fccfSAndroid Build Coastguard Worker  *     int bar;
100*33b1fccfSAndroid Build Coastguard Worker  *     char name[FLEX_ARRAY];
101*33b1fccfSAndroid Build Coastguard Worker  *   };
102*33b1fccfSAndroid Build Coastguard Worker  *
103*33b1fccfSAndroid Build Coastguard Worker  * you can do:
104*33b1fccfSAndroid Build Coastguard Worker  *
105*33b1fccfSAndroid Build Coastguard Worker  *   struct foo *f;
106*33b1fccfSAndroid Build Coastguard Worker  *   FLEX_ALLOC_MEM(f, name, src, len);
107*33b1fccfSAndroid Build Coastguard Worker  *
108*33b1fccfSAndroid Build Coastguard Worker  * to allocate a "foo" with the contents of "src" in the "name" field.
109*33b1fccfSAndroid Build Coastguard Worker  * The resulting struct is automatically zero'd, and the flex-array field
110*33b1fccfSAndroid Build Coastguard Worker  * is NUL-terminated (whether the incoming src buffer was or not).
111*33b1fccfSAndroid Build Coastguard Worker  *
112*33b1fccfSAndroid Build Coastguard Worker  * The FLEXPTR_* variants operate on structs that don't use flex-arrays,
113*33b1fccfSAndroid Build Coastguard Worker  * but do want to store a pointer to some extra data in the same allocated
114*33b1fccfSAndroid Build Coastguard Worker  * block. For example, if you have:
115*33b1fccfSAndroid Build Coastguard Worker  *
116*33b1fccfSAndroid Build Coastguard Worker  *   struct foo {
117*33b1fccfSAndroid Build Coastguard Worker  *     char *name;
118*33b1fccfSAndroid Build Coastguard Worker  *     int bar;
119*33b1fccfSAndroid Build Coastguard Worker  *   };
120*33b1fccfSAndroid Build Coastguard Worker  *
121*33b1fccfSAndroid Build Coastguard Worker  * you can do:
122*33b1fccfSAndroid Build Coastguard Worker  *
123*33b1fccfSAndroid Build Coastguard Worker  *   struct foo *f;
124*33b1fccfSAndroid Build Coastguard Worker  *   FLEXPTR_ALLOC_STR(f, name, src);
125*33b1fccfSAndroid Build Coastguard Worker  *
126*33b1fccfSAndroid Build Coastguard Worker  * and "name" will point to a block of memory after the struct, which will be
127*33b1fccfSAndroid Build Coastguard Worker  * freed along with the struct (but the pointer can be repointed anywhere).
128*33b1fccfSAndroid Build Coastguard Worker  *
129*33b1fccfSAndroid Build Coastguard Worker  * The *_STR variants accept a string parameter rather than a ptr/len
130*33b1fccfSAndroid Build Coastguard Worker  * combination.
131*33b1fccfSAndroid Build Coastguard Worker  *
132*33b1fccfSAndroid Build Coastguard Worker  * Note that these macros will evaluate the first parameter multiple
133*33b1fccfSAndroid Build Coastguard Worker  * times, and it must be assignable as an lvalue.
134*33b1fccfSAndroid Build Coastguard Worker  */
135*33b1fccfSAndroid Build Coastguard Worker #define FLEX_ALLOC_MEM(x, flexname, buf, len) do { \
136*33b1fccfSAndroid Build Coastguard Worker 	size_t flex_array_len_ = (len); \
137*33b1fccfSAndroid Build Coastguard Worker 	(x) = calloc(1, st_add3(sizeof(*(x)), flex_array_len_, 1)); \
138*33b1fccfSAndroid Build Coastguard Worker 	BUG_ON(!(x)); \
139*33b1fccfSAndroid Build Coastguard Worker 	memcpy((void *)(x)->flexname, (buf), flex_array_len_); \
140*33b1fccfSAndroid Build Coastguard Worker } while (0)
141*33b1fccfSAndroid Build Coastguard Worker #define FLEXPTR_ALLOC_MEM(x, ptrname, buf, len) do { \
142*33b1fccfSAndroid Build Coastguard Worker 	size_t flex_array_len_ = (len); \
143*33b1fccfSAndroid Build Coastguard Worker 	(x) = xcalloc(1, st_add3(sizeof(*(x)), flex_array_len_, 1)); \
144*33b1fccfSAndroid Build Coastguard Worker 	memcpy((x) + 1, (buf), flex_array_len_); \
145*33b1fccfSAndroid Build Coastguard Worker 	(x)->ptrname = (void *)((x) + 1); \
146*33b1fccfSAndroid Build Coastguard Worker } while (0)
147*33b1fccfSAndroid Build Coastguard Worker #define FLEX_ALLOC_STR(x, flexname, str) \
148*33b1fccfSAndroid Build Coastguard Worker 	FLEX_ALLOC_MEM((x), flexname, (str), strlen(str))
149*33b1fccfSAndroid Build Coastguard Worker #define FLEXPTR_ALLOC_STR(x, ptrname, str) \
150*33b1fccfSAndroid Build Coastguard Worker 	FLEXPTR_ALLOC_MEM((x), ptrname, (str), strlen(str))
151*33b1fccfSAndroid Build Coastguard Worker 
152*33b1fccfSAndroid Build Coastguard Worker #ifdef __cplusplus
153*33b1fccfSAndroid Build Coastguard Worker }
154*33b1fccfSAndroid Build Coastguard Worker #endif
155*33b1fccfSAndroid Build Coastguard Worker 
156*33b1fccfSAndroid Build Coastguard Worker #endif
157