Utilities¶
This page contains reference documentation for <sys/util.h>
, which provides
miscellaneous utility functions and macros.
-
group
sys-util
Defines
-
POINTER_TO_UINT
(x)¶ Cast
x
, a pointer, to an unsigned integer.
-
UINT_TO_POINTER
(x)¶ Cast
x
, an unsigned integer, to avoid*
.
-
POINTER_TO_INT
(x)¶ Cast
x
, a pointer, to a signed integer.
-
INT_TO_POINTER
(x)¶ Cast
x
, a signed integer, to avoid*
.
-
BITS_PER_LONG
¶ Number of bits in a long int.
-
GENMASK
(h, l)¶ Create a contiguous bitmask starting at bit position
l
and ending at positionh
.
-
ZERO_OR_COMPILE_ERROR
(cond)¶ 0 if
cond
is true-ish; causes a compile error otherwise.
-
IS_ARRAY
(array)¶ Zero if
array
has an array type, a compile error otherwise.This macro is available only from C, not C++.
-
ARRAY_SIZE
(array)¶ Number of elements in the given
array
.In C++, due to language limitations, this will accept as
array
any type that implementsoperator[]
. The results may not be particulary meaningful in this case.In C, passing a pointer as
array
causes a compile error.
-
PART_OF_ARRAY
(array, ptr)¶ Check if a pointer
ptr
lies withinarray
.In C but not C++, this causes a compile error if
array
is not an array (e.g. ifptr
andarray
are mixed up).- Return
1 if
ptr
is part ofarray
, 0 otherwise- Parameters
ptr
: a pointerarray
: an array
-
CONTAINER_OF
(ptr, type, field)¶ Get a pointer to a container structure from an element.
Example:
struct foo { int bar; }; struct foo my_foo; int *ptr = &my_foo.bar; struct foo *container = CONTAINER_OF(ptr, struct foo, bar);
Above,
container
points atmy_foo
.- Return
a pointer to the structure that contains
ptr
- Parameters
ptr
: pointer to a structure elementtype
: name of the type thatptr
is an element offield
: the name of the field within the structptr
points to
-
ROUND_UP
(x, align)¶ Value of
x
rounded up to the next multiple ofalign
, which must be a power of 2.
-
ROUND_DOWN
(x, align)¶ Value of
x
rounded down to the previous multiple ofalign
, which must be a power of 2.
-
WB_UP
(x)¶ Value of
x
rounded up to the next word boundary.
-
WB_DN
(x)¶ Value of
x
rounded down to the previous word boundary.
-
ceiling_fraction
(numerator, divider)¶ Ceiling function applied to
numerator
/divider
as a fraction.
-
MAX
(a, b)¶ The larger value between
a
andb
.- Note
Arguments are evaluated twice.
-
MIN
(a, b)¶ The smaller value between
a
andb
.- Note
Arguments are evaluated twice.
-
CLAMP
(val, low, high)¶ Clamp a value to a given range.
- Note
Arguments are evaluated multiple times.
-
KB
(x)¶ Number of bytes in
x
kibibytes.
-
MB
(x)¶ Number of bytes in
x
mebibytes.
-
GB
(x)¶ Number of bytes in
x
gibibytes.
-
KHZ
(x)¶ Number of Hz in
x
kHz.
-
MHZ
(x)¶ Number of Hz in
x
MHz.
-
BIT
(n)¶ Unsigned integer with bit position
n
set (signed in assembly language).
-
BIT64
(_n)¶ 64-bit unsigned integer with bit position
_n
set.
-
WRITE_BIT
(var, bit, set)¶ Set or clear a bit depending on a boolean value.
The argument
var
is a variable whose value is written to as a side effect.- Parameters
var
: Variable to be alteredbit
: Bit numberset
: if 0, clearsbit
invar
; any other value setsbit
-
BIT_MASK
(n)¶ Bit mask with bits 0 through
n-1
(inclusive) set, or 0 ifn
is 0.
-
BIT64_MASK
(n)¶ 64-bit bit mask with bits 0 through
n-1
(inclusive) set, or 0 ifn
is 0.
-
IS_ENABLED
(config_macro)¶ Check for macro definition in compiler-visible expressions.
This trick was pioneered in Linux as the config_enabled() macro. It has the effect of taking a macro value that may be defined to “1” or may not be defined at all and turning it into a literal expression that can be handled by the C compiler instead of just the preprocessor. It is often used with a
CONFIG_FOO
macro which may be defined to 1 via Kconfig, or left undefined.That is, it works similarly to
#if defined(CONFIG_FOO)
except that its expansion is a C expression. Thus, much#ifdef
usage can be replaced with equivalents like:if (IS_ENABLED(CONFIG_FOO)) { do_something_with_foo }
This is cleaner since the compiler can generate errors and warnings for
do_something_with_foo
even whenCONFIG_FOO
is undefined.- Return
1 if
config_macro
is defined to 1, 0 otherwise (including ifconfig_macro
is not defined)- Parameters
config_macro
: Macro to check
-
COND_CODE_1
(_flag, _if_1_code, _else_code)¶ Insert code depending on whether
_flag
expands to 1 or not.This relies on similar tricks as IS_ENABLED(), but as the result of
_flag
expansion, results in either_if_1_code
or_else_code
is expanded.To prevent the preprocessor from treating commas as argument separators, the
_if_1_code
and_else_code
expressions must be inside brackets/parentheses:()
. These are stripped away during macro expansion.Example:
COND_CODE_1(CONFIG_FLAG, (uint32_t x;), (there_is_no_flag();))
If
CONFIG_FLAG
is defined to 1, this expands to:uint32_t x;
It expands to
there_is_no_flag();
otherwise.This could be used as an alternative to:
#if defined(CONFIG_FLAG) && (CONFIG_FLAG == 1) #define MAYBE_DECLARE(x) uint32_t x #else #define MAYBE_DECLARE(x) there_is_no_flag() #endif MAYBE_DECLARE(x);
However, the advantage of COND_CODE_1() is that code is resolved in place where it is used, while the
#if
method definesMAYBE_DECLARE
on two lines and requires it to be invoked again on a separate line. This makes COND_CODE_1() more concise and also sometimes more useful when used within another macro’s expansion.- Note
_flag
can be the result of preprocessor expansion, e.g. an expression involvingNUM_VA_ARGS_LESS_1(…)
. However,_if_1_code
is only expanded if_flag
expands to the integer literal 1. Integer expressions that evaluate to 1, e.g. after doing some arithmetic, will not work.- Parameters
_flag
: evaluated flag_if_1_code
: result if_flag
expands to 1; must be in parentheses_else_code
: result otherwise; must be in parentheses
-
COND_CODE_0
(_flag, _if_0_code, _else_code)¶ Like COND_CODE_1() except tests if
_flag
is 0.This is like COND_CODE_1(), except that it tests whether
_flag
expands to the integer literal 0. It expands to_if_0_code
if so, and_else_code
otherwise; both of these must be enclosed in parentheses.- See
- Parameters
_flag
: evaluated flag_if_0_code
: result if_flag
expands to 0; must be in parentheses_else_code
: result otherwise; must be in parentheses
-
IF_ENABLED
(_flag, _code)¶ Insert code if
_flag
is defined and equals 1.Like COND_CODE_1(), this expands to
_code
if_flag
is defined to 1; it expands to nothing otherwise.Example:
IF_ENABLED(CONFIG_FLAG, (uint32_t foo;))
If
CONFIG_FLAG
is defined to 1, this expands to:uint32_t foo;
and to nothing otherwise.
It can be considered as a more compact alternative to:
#if defined(CONFIG_FLAG) && (CONFIG_FLAG == 1) uint32_t foo; #endif
- Parameters
_flag
: evaluated flag_code
: result if_flag
expands to 1; must be in parentheses
-
IS_EMPTY
(a)¶ Check if a macro has a replacement expression.
If
a
is a macro defined to a nonempty value, this will return true, otherwise it will return false. It only works with defined macros, so an additional#ifdef
test may be needed in some cases.This macro may be used with COND_CODE_1() and COND_CODE_0() while processing
__VA_ARGS__
to avoid processing empty arguments.Note that this macro is intended to check macro names that evaluate to replacement lists being empty or containing numbers or macro name like tokens.
Example:
#define EMPTY #define NON_EMPTY 1 #undef UNDEFINED IS_EMPTY(EMPTY) IS_EMPTY(NON_EMPTY) IS_EMPTY(UNDEFINED) #if defined(EMPTY) && IS_EMPTY(EMPTY) == true some_conditional_code #endif
- Note
Not all arguments are accepted by this macro and compilation will fail if argument cannot be concatenated with literal constant. That will happen if argument does not start with letter or number. Example arguments that will fail during compilation: .arg, (arg), “arg”, {arg}.
In above examples, the invocations of IS_EMPTY(…) return
true
,false
, andtrue
;some_conditional_code
is included.- Parameters
a
: macro to check for emptiness
-
LIST_DROP_EMPTY
(...)¶ Remove empty arguments from list.
During macro expansion,
__VA_ARGS__
and other preprocessor generated lists may contain empty elements, e.g.:#define LIST ,a,b,,d,
Using EMPTY to show each empty element, LIST contains:
EMPTY, a, b, EMPTY, d
When processing such lists, e.g. using FOR_EACH(), all empty elements will be processed, and may require filtering out. To make that process easier, it is enough to invoke LIST_DROP_EMPTY which will remove all empty elements.
Example:
LIST_DROP_EMPTY(LIST)
expands to:
a, b, d
- Parameters
...
: list to be processed
-
EMPTY
¶ Macro with an empty expansion.
This trivial definition is provided for readability when a macro should expand to an empty result, which e.g. is sometimes needed to silence checkpatch.
Example:
#define LIST_ITEM(n) , item##n
The above would cause checkpatch to complain, but:
#define LIST_ITEM(n) EMPTY, item##n
would not.
-
IDENTITY
(V)¶ Macro that expands to its argument.
This is useful in macros like
FOR_EACH()
when there is no transformation required on the list elements.- Parameters
V
: any value
-
GET_ARG_N
(N, ...)¶ Get nth argument from argument list.
- Return
Nth argument.
- Parameters
N
: Argument index to fetch. Counter from 1....
: Variable list of argments from which one argument is returned.
-
GET_ARGS_LESS_N
(N, ...)¶ Strips n first arguments from the argument list.
- Return
argument list without N first arguments.
- Parameters
N
: Number of arguments to discard....
: Variable list of argments.
-
GET_ARG1
(...)¶ Expands to the first argument.
-
GET_ARG2
(...)¶ Expands to the second argument.
-
GET_ARGS_LESS_1
(...)¶ Expands to all arguments except the first one.
-
UTIL_OR
(a, b)¶ Like
a || b
, but does evaluation and short-circuiting at C preprocessor time.This is not the same as the binary
||
operator; in particular,a
should expand to an integer literal 0 or 1. However,b
can be any value.This can be useful when
b
is an expression that would cause a build error whena
is 1.
-
UTIL_AND
(a, b)¶ Like
a && b
, but does evaluation and short-circuiting at C preprocessor time.This is not the same as the binary
&&
, however; in particular,a
should expand to an integer literal 0 or 1. However,b
can be any value.This can be useful when
b
is an expression that would cause a build error whena
is 0.
-
UTIL_LISTIFY
(LEN, F, ...)¶ Generates a sequence of code.
Example:
#define FOO(i, _) MY_PWM ## i , { UTIL_LISTIFY(PWM_COUNT, FOO) }
The above two lines expand to:
{ MY_PWM0 , MY_PWM1 , }
- Note
Calling UTIL_LISTIFY with undefined arguments has undefined behavior.
- Parameters
LEN
: The length of the sequence. Must be an integer literal less than 255.F
: A macro function that accepts at least two arguments:F(i, ...)
.F
is called repeatedly in the expansion. Its first argumenti
is the index in the sequence, and the variable list of arguments passed to UTIL_LISTIFY are passed through toF
.
-
FOR_EACH
(F, sep, ...)¶ Call a macro
F
on each provided argument with a given separator between each call.Example:
#define F(x) int a##x FOR_EACH(F, (;), 4, 5, 6);
This expands to:
int a4; int a5; int a6;
- Parameters
F
: Macro to invokesep
: Separator (e.g. comma or semicolon). Must be in parentheses; this is required to enable providing a comma as separator....
: Variable argument list. The macroF
is invoked asF(element)
for each element in the list.
-
FOR_EACH_NONEMPTY_TERM
(F, term, ...)¶ Like FOR_EACH(), but with a terminator instead of a separator, and drops empty elements from the argument list.
The
sep
argument toFOR_EACH(F, (sep), a, b)
is a separator which is placed between calls toF
, like this:FOR_EACH(F, (sep), a, b) // F(a) sep F(b) // ^^^ no sep here!
By contrast, the
term
argument toFOR_EACH_NONEMPTY_TERM(F, (term), a, b)
is added after each timeF
appears in the expansion:FOR_EACH_NONEMPTY_TERM(F, (term), a, b) // F(a) term F(b) term // ^^^^
Further, any empty elements are dropped:
FOR_EACH_NONEMPTY_TERM(F, (term), a, EMPTY, b) // F(a) term F(b) term
This is more convenient in some cases, because FOR_EACH_NONEMPTY_TERM() expands to nothing when given an empty argument list, and it’s often cumbersome to write a macro
F
that does the right thing even when given an empty argument.One example is when
__VA_ARGS__
may or may not be empty, and the results are embedded in a larger initializer:#define SQUARE(x) ((x)*(x)) int my_array[] = { FOR_EACH_NONEMPTY_TERM(SQUARE, (,), FOO(...)) FOR_EACH_NONEMPTY_TERM(SQUARE, (,), BAR(...)) FOR_EACH_NONEMPTY_TERM(SQUARE, (,), BAZ(...)) };
This is more convenient than:
figuring out whether the
FOO
,BAR
, andBAZ
expansions are empty and adding a comma manually (or not) between FOR_EACH() callsrewriting SQUARE so it reacts appropriately when “x” is empty (which would be necessary if e.g.
FOO
expands to nothing)
- Parameters
F
: Macro to invoke on each nonempty element of the variable argumentsterm
: Terminator (e.g. comma or semicolon) placed after each invocation of F. Must be in parentheses; this is required to enable providing a comma as separator....
: Variable argument list. The macroF
is invoked asF(element)
for each nonempty element in the list.
-
FOR_EACH_IDX
(F, sep, ...)¶ Call macro
F
on each provided argument, with the argument’s index as an additional parameter.This is like FOR_EACH(), except
F
should be a macro which takes two arguments:F(index, variable_arg)
.Example:
#define F(idx, x) int a##idx = x FOR_EACH_IDX(F, (;), 4, 5, 6);
This expands to:
int a0 = 4; int a1 = 5; int a2 = 6;
- Parameters
F
: Macro to invokesep
: Separator (e.g. comma or semicolon). Must be in parentheses; this is required to enable providing a comma as separator....
: Variable argument list. The macroF
is invoked asF(index, element)
for each element in the list.
-
FOR_EACH_FIXED_ARG
(F, sep, fixed_arg, ...)¶ Call macro
F
on each provided argument, with an additional fixed argument as a parameter.This is like FOR_EACH(), except
F
should be a macro which takes two arguments:F(variable_arg, fixed_arg)
.Example:
static void func(int val, void *dev); FOR_EACH_FIXED_ARG(func, (;), dev, 4, 5, 6);
This expands to:
func(4, dev); func(5, dev); func(6, dev);
- Parameters
F
: Macro to invokesep
: Separator (e.g. comma or semicolon). Must be in parentheses; this is required to enable providing a comma as separator.fixed_arg
: Fixed argument passed toF
as the second macro parameter....
: Variable argument list. The macroF
is invoked asF(element, fixed_arg)
for each element in the list.
-
FOR_EACH_IDX_FIXED_ARG
(F, sep, fixed_arg, ...)¶ Calls macro
F
for each variable argument with an index and fixed argument.This is like the combination of FOR_EACH_IDX() with FOR_EACH_FIXED_ARG().
Example:
#define F(idx, x, fixed_arg) int fixed_arg##idx = x FOR_EACH_IDX_FIXED_ARG(F, (;), a, 4, 5, 6);
This expands to:
int a0 = 4; int a1 = 5; int a2 = 6;
- Parameters
F
: Macro to invokesep
: Separator (e.g. comma or semicolon). Must be in parentheses; This is required to enable providing a comma as separator.fixed_arg
: Fixed argument passed toF
as the third macro parameter....
: Variable list of arguments. The macroF
is invoked asF(index, element, fixed_arg)
for each element in the list.
-
NUM_VA_ARGS_LESS_1
(...)¶ Number of arguments in the variable arguments list minus one.
- Return
Number of variadic arguments in the argument list, minus one
- Parameters
...
: List of arguments
-
MACRO_MAP_CAT
(...)¶ Mapping macro that pastes results together.
This is similar to FOR_EACH() in that it invokes a macro repeatedly on each element of
__VA_ARGS__
. However, unlike FOR_EACH(), MACRO_MAP_CAT() pastes the results together into a single token.For example, with this macro FOO:
#define FOO(x) item_##x##_
MACRO_MAP_CAT(FOO, a, b, c),
expands to the token:item_a_item_b_item_c_
- Return
The results of expanding the macro on each argument, all pasted together
- Parameters
...
: Macro to expand on each argument, followed by its arguments. (The macro should take exactly one argument.)
-
MACRO_MAP_CAT_N
(N, ...)¶ Mapping macro that pastes a fixed number of results together.
Similar to MACRO_MAP_CAT(), but expects a fixed number of arguments. If more arguments are given than are expected, the rest are ignored.
- Return
The results of expanding the macro on each argument, all pasted together
- Parameters
N
: Number of arguments to map...
: Macro to expand on each argument, followed by its arguments. (The macro should take exactly one argument.)
Functions
-
bool
is_power_of_two
(unsigned int x)¶ Is
x
a power of two?- Return
true if
x
is a power of two, false otherwise- Parameters
x
: value to check
-
int64_t
arithmetic_shift_right
(int64_t value, uint8_t shift)¶ Arithmetic shift right.
- Return
value
shifted right byshift
; opened bit positions are filled with the sign bit- Parameters
value
: value to shiftshift
: number of bits to shift
-
int
char2hex
(char c, uint8_t *x)¶ Convert a single character into a hexadecimal nibble.
- Return
Zero on success or (negative) error code otherwise.
- Parameters
c
: The character to convertx
: The address of storage for the converted number.
-
int
hex2char
(uint8_t x, char *c)¶ Convert a single hexadecimal nibble into a character.
- Return
Zero on success or (negative) error code otherwise.
- Parameters
c
: The number to convertx
: The address of storage for the converted character.
-
size_t
bin2hex
(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen)¶ Convert a binary array into string representation.
- Return
The length of the converted string, or 0 if an error occurred.
- Parameters
buf
: The binary array to convertbuflen
: The length of the binary array to converthex
: Address of where to store the string representation.hexlen
: Size of the storage area for string representation.
-
size_t
hex2bin
(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen)¶ Convert a hexadecimal string into a binary array.
- Return
The length of the binary array, or 0 if an error occurred.
- Parameters
hex
: The hexadecimal string to converthexlen
: The length of the hexadecimal string to convert.buf
: Address of where to store the binary databuflen
: Size of the storage area for binary data
-
uint8_t
u8_to_dec
(char *buf, uint8_t buflen, uint8_t value)¶ Convert a uint8_t into a decimal string representation.
Convert a uint8_t value into its ASCII decimal string representation. The string is terminated if there is enough space in buf.
- Return
The length of the converted string (excluding terminator if any), or 0 if an error occurred.
- Parameters
buf
: Address of where to store the string representation.buflen
: Size of the storage area for string representation.value
: The value to convert to decimal string
-