diff options
| author | Alejandro Colomar <alx@nginx.com> | 2023-08-19 12:43:39 +0200 |
|---|---|---|
| committer | Alejandro Colomar <alx@kernel.org> | 2023-10-25 13:37:31 +0200 |
| commit | a084e2bc8066ce2fed852bf04e5168e289bf834b (patch) | |
| tree | 72cc4a025ae508b2461b20f8371a186c380600ac /src/nxt_unit_cdefs.h | |
| parent | fb33ec86a3b6ca6a844dfa6980bb9e083094abec (diff) | |
| download | unit-a084e2bc8066ce2fed852bf04e5168e289bf834b.tar.gz unit-a084e2bc8066ce2fed852bf04e5168e289bf834b.tar.bz2 | |
Libunit: added macros that enhance type safety.
nxt_min()
nxt_max()
Return the minimum/maximum of two values.
nxt_swap()
Swap the values of two variables passed by their addresses.
nxt_sizeof_array()
Return the size (in bytes) of an array.
nxt_nitems()
Return the number of elements in an array.
nxt_memberof()
Expand to a member of a structure. It uses a compound literal for
the object.
nxt_sizeof_incomplete()
Calculate the size of an incomplete type, as if sizeof() could be
applied to it.
nxt_sizeof_fam0()
Calculate the size of each element of a FAM of a structure.
nxt_sizeof_fam()
Calculate the size of a FAM of a structure.
nxt_offsetof_fam()
Calculate the offset of the nth element of the FAM from the start of
the containing structure.
nxt_sizeof_struct()
Calculate the total size of a structure containing a FAM. This
value is the one that should be used for allocating the structure.
Suggested-by: Andrew Clayton <a.clayton@nginx.com>
nxt_is_near_end()
Evaluate to true if the member is near the end of a structure. This
is only designed to be used with FAMs, to make sure that the FAM is
near the end of the structure (a zero-length array near the end of
the structure would still pass this test, but it's a reasonable
assertion to do.
Suggested-by: David Laight <David.Laight@ACULAB.COM>
nxt_is_zero_sizeof()
Evaluate to true if the size of 'x' is 0.
nxt_is_same_type()
Evaluate to true if the both arguments are compatible types.
nxt_is_same_typeof()
Evaluate to true if the types of both arguments are compatible.
nxt_is_array()
Evaluate to true if the argument is an array.
nxt_must_be()
It's like static_assert(3), but implemented as an expression. It's
necessary for writing the must_be_array() macro. It's always
evaluates to (int) 0.
nxt_must_be_array()
Statically assert that the argument is an array. It is an
expression that always evaluates to (int) 0.
nxt_must_be_zero_sizeof()
Statically assert that the argument has a size of 0.
nxt_must_be_near_end()
Statically assert that a member of a structure is near the end of
it.
Suggested-by: David Laight <David.Laight@ACULAB.COM>
nxt_must_be_fam()
Statically assert that the argument is a flexible array member
(FAM). It's an expression that always evaluates to (int) 0.
Link: <https://gustedt.wordpress.com/2011/03/14/flexible-array-member/>
Link: <https://lore.kernel.org/lkml/202308161913.91369D4A@keescook/T/>
Link: <https://inbox.sourceware.org/gcc/dac8afb7-5026-c702-85d2-c3ad977d9a48@kernel.org/T/>
Link: <https://stackoverflow.com/a/57537491>
Link: <https://github.com/shadow-maint/shadow/pull/762>
Cc: Andrew Clayton <a.clayton@nginx.com>
Cc: Zhidao Hong <z.hong@f5.com>
Signed-off-by: Alejandro Colomar <alx@nginx.com>
Signed-off-by: Alejandro Colomar <alx@kernel.org>
Diffstat (limited to 'src/nxt_unit_cdefs.h')
| -rw-r--r-- | src/nxt_unit_cdefs.h | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/nxt_unit_cdefs.h b/src/nxt_unit_cdefs.h new file mode 100644 index 00000000..48389117 --- /dev/null +++ b/src/nxt_unit_cdefs.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019-2023, Alejandro Colomar <alx@kernel.org> + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_UNIT_CDEFS_H_INCLUDED_ +#define _NXT_UNIT_CDEFS_H_INCLUDED_ + + +#include <stddef.h> + + +#define nxt_max(a, b) (((a) > (b)) ? (a) : (b)) +#define nxt_min(a, b) (((a) < (b)) ? (a) : (b)) + + +#define nxt_swap(ap, bp) \ + do { \ + __auto_type ap_ = (ap); \ + __auto_type bp_ = (bp); \ + typeof(*ap_) tmp_; \ + \ + _Static_assert(nxt_is_same_typeof(ap_, bp_), ""); \ + \ + tmp_ = *ap_; \ + *ap_ = *bp_; \ + *bp_ = tmp_; \ + } while (0) + + +#define nxt_sizeof_array(a) (sizeof(a) + nxt_must_be_array(a)) +#define nxt_nitems(a) (nxt_sizeof_array(a) / sizeof((a)[0])) +#define nxt_memberof(T, member) ((T){}.member) + +#define nxt_sizeof_incomplete(x) \ + ( \ + sizeof( \ + struct { \ + max_align_t a; \ + typeof(x) inc; \ + } \ + ) \ + - sizeof(max_align_t) \ + ) + +#define nxt_sizeof_fam0(T, fam) \ + (sizeof(nxt_memberof(T, fam[0])) + nxt_must_be_fam(T, fam)) + +#define nxt_sizeof_fam(T, fam, n) \ + (nxt_sizeof_fam0(T, fam) * (n)) + +#define nxt_offsetof_fam(T, fam, n) \ + (offsetof(T, fam) + nxt_sizeof_fam(T, fam, n)) + +#define nxt_sizeof_struct(T, fam, n) \ + nxt_max(sizeof(T), nxt_offsetof_fam(T, fam, n)) + + +#define nxt_is_near_end(T, m) (offsetof(T, m) > (sizeof(T) - _Alignof(T))) +#define nxt_is_zero_sizeof(z) (nxt_sizeof_incomplete(z) == 0) +#define nxt_is_same_type(a, b) __builtin_types_compatible_p(a, b) +#define nxt_is_same_typeof(a, b) nxt_is_same_type(typeof(a), typeof(b)) +#define nxt_is_array(a) (!nxt_is_same_typeof(a, &(a)[0])) + + +#define nxt_must_be(e) \ + ( \ + 0 * (int) sizeof( \ + struct { \ + _Static_assert(e, ""); \ + int ISO_C_forbids_a_struct_with_no_members_; \ + } \ + ) \ + ) + + +#define nxt_must_be_array(a) nxt_must_be(nxt_is_array(a)) +#define nxt_must_be_zero_sizeof(z) nxt_must_be(nxt_is_zero_sizeof(z)) +#define nxt_must_be_near_end(T, m) nxt_must_be(nxt_is_near_end(T, m)) + +#define nxt_must_be_fam(T, fam) \ + (nxt_must_be_array(nxt_memberof(T, fam)) \ + + nxt_must_be_zero_sizeof(nxt_memberof(T, fam)) \ + + nxt_must_be_near_end(T, fam)) + + +#endif /* _NXT_UNIT_CDEFS_H_INCLUDED_ */ |
