/* SPDX-License-Identifier: MIT */ /** * utils.h - useful macros for compile-time magic * * Inspired by similar macros in the Linux Kernel. * * Copyright (c) 2023 - Yaroslav de la Peña Smirnov */ #ifndef CWARE_UTILS_H #define CWARE_UTILS_H #include #ifndef static_assert #define static_assert(exp, msg) _Static_assert(exp, msg) #endif /** * BUILD_BUG_ON_ZERO - throws compilation error if true, expressions returns 0. * @cond: condition * * Force a compilation error if condition is true, but also produce a * result (of value 0 and type int), so the expression can be used * e.g. in a structure initializer (or where-ever else comma expressions * aren't permitted). */ #define BUILD_BUG_ON_ZERO(cond) ((int)(sizeof(struct { int : (-!!(cond)); }))) #define same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) #define container_of(ptr, T, member) \ ({ \ static_assert(same_type(*(ptr), ((T *)0)->member) \ || same_type(*(ptr), void), \ "type mismatch in container_of()"); \ (T *)((void *)(ptr)-offsetof(T, member)); \ }) /** * __ASSERT_IS_ARRAY - throw a compilation error if @arr is not an array. * @arr: variable to check. */ #define __ASSERT_IS_ARRAY(arr) BUILD_BUG_ON_ZERO(same_type((arr), &(arr)[0])) /** * ARRAY_SIZE - return the number of elements in @arr. * @arr: array of any type. */ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(*arr) + __ASSERT_IS_ARRAY(arr)) #endif