Startle
Useful and efficient algorithms and facilities
Macros
macros.h File Reference

Generally useful macros. More...

#include "startle/dispatch.h"

Go to the source code of this file.

Macros

#define _CONCAT(x, y)   x##y
 concatenate tokens. More...
 
#define CONCAT(x, y)   _CONCAT(x, y)
 
#define _CONCAT_UNDERSCORE(x, y)   x##_##y
 
#define CONCAT_UNDERSCORE(x, y)   _CONCAT_UNDERSCORE(x, y)
 
#define UNIQUE   CONCAT(__unique_, __LINE__)
 Make a unique identifier. More...
 
#define _STRINGIFY(x)   #x
 Convert a token to a string. More...
 
#define STRINGIFY(x)   _STRINGIFY(x)
 
#define sizeof_field(s, f)   sizeof(((s *)0)->f)
 Size of a field. More...
 
#define offsetof(s, f)   ((uintptr_t)&(((s *)0)->f))
 Offset of a field. More...
 
#define WIDTH(a)   (sizeof((a)[0]))
 Number of bytes per array element. More...
 
#define LENGTH(a)   (sizeof(a) / WIDTH(a))
 Number of array elements. More...
 
#define RANGEUP(i, lower, upper)   for(size_t i = (lower), __upper = (upper); i < __upper; i++)
 Iterate i from lower up to upper-1. More...
 
#define RANGEDOWN(i, lower, upper)   for(size_t i = (upper), __lower = (lower); i-- > __lower; )
 Iterate i from upper-1 down to lower. More...
 
#define COUNTDOWN(i, n)   RANGEDOWN(i, 0, n)
 Iterate i from n-1 to 0. More...
 
#define COUNTUP(i, n)   RANGEUP(i, 0, n)
 Iterate i from 0 to n-1. More...
 
#define LOOP(n)   COUNTDOWN(UNIQUE, n)
 Iterate n times. More...
 
#define FOREACH(i, a)   COUNTUP(i, LENGTH(a))
 Iterate i over each index of the array a. More...
 
#define FORMAP(i, m)   for(size_t i = 1; i <= *map_cnt(m); i++)
 Iterate i over each index of map m. More...
 
#define BITSET(name, size)   uint8_t name[((size)+7)/8] = {0}
 Declare a bit set named name to store size bits. More...
 
#define BITSET_INDEX(name, array)   BITSET(name, LENGTH(array))
 Declare a bit set to hold a bit for each element of the array. More...
 
#define static_assert(expr, msg)   _Static_assert(expr, msg)
 
#define SEG(x)   {(x), sizeof(x) - 1}
 String segment initializer. More...
 
#define printseg(pre, seg, fmt, ...)
 printf that prepends a string segment More...
 
#define LIST_ADD(f, l, v)
 Add to tail of an intrusive list. More...
 
#define CONS(f, l, v)
 Add to head of an intrusive list. More...
 
#define min(a, b)
 
#define max(a, b)
 
#define csub(a, b)
 Non-negative saturating subtraction. More...
 
#define zero(a)   memset(&(a), 0, sizeof(a))
 Zero an array or struct. More...
 
#define show(x)   printf(#x " = %d\n", (int)(x))
 Trace an integer variable. More...
 
#define FLAG(s, flag)   (((s).flags & (flag)) != 0)
 Return true if the flag is set. More...
 
#define NOT_FLAG(s, flag)   (((s).flags & (flag)) == 0)
 Return true if the flag is NOT set. More...
 
#define FLAG_SET(s, flag)   ((s).flags |= (flag))
 
#define FLAG_CLEAR(s, flag)   ((s).flags &= ~(flag))
 
#define FLAG_SET_TO(s, flag, val)   ((val) ? FLAG_SET(s, flag) : FLAG_CLEAR(s, flag))
 
#define ARRAY_SHIFTR(array, offset, length)   memmove(&(array) + (offset), &(array), (length) * sizeof(array))
 Shift elements in the array to the right. More...
 
#define ARRAY_SHIFTL(array, offset, length)   memmove(&(array), &(array) + (offset), (length) * sizeof(array))
 Shift elements in the array to the left. More...
 
#define ARRAY_COPY(dst, src, length)   memcpy(&(dst), &(src), (length) * sizeof(dst))
 
#define COLOR(c, str)   "\x1b[" CONCAT(COLOR_, c) "m" str "\x1b[0m"
 
#define COLORs(str)   "\x1b[%sm" str "\x1b[0m"
 
#define COLOR_red   "37;41"
 
#define COLOR_blue   "37;44"
 
#define COLOR_gray   "38;5;8"
 
#define COLOR_normal   "0"
 
#define MARK(x)   COLOR(red, x)
 
#define NOTE(x)   COLOR(blue, x)
 
#define FADE(x)   COLOR(gray, x)
 
#define TODO   MARK("TODO")
 
#define HACK   MARK("HACK")
 
#define DISABLE(...)
 
#define unlikely(c)   (__builtin_expect((c), 0))
 Hint that the condition is unlikely. More...
 
#define likely(c)   (__builtin_expect((c), 1))
 Hint that the condition is likely. More...
 
#define TEST(name)   int test_##name()
 Define a test. More...
 
#define FORMAT(name, c)   void format_##name(intptr_t i)
 Define a new format string specifier (for logging). More...
 

Detailed Description

Generally useful macros.

Macro Definition Documentation

◆ _CONCAT

#define _CONCAT (   x,
 
)    x##y

concatenate tokens.

◆ _STRINGIFY

#define _STRINGIFY (   x)    #x

Convert a token to a string.

◆ ARRAY_SHIFTL

#define ARRAY_SHIFTL (   array,
  offset,
  length 
)    memmove(&(array), &(array) + (offset), (length) * sizeof(array))

Shift elements in the array to the left.

◆ ARRAY_SHIFTR

#define ARRAY_SHIFTR (   array,
  offset,
  length 
)    memmove(&(array) + (offset), &(array), (length) * sizeof(array))

Shift elements in the array to the right.

◆ BITSET

#define BITSET (   name,
  size 
)    uint8_t name[((size)+7)/8] = {0}

Declare a bit set named name to store size bits.

◆ BITSET_INDEX

#define BITSET_INDEX (   name,
  array 
)    BITSET(name, LENGTH(array))

Declare a bit set to hold a bit for each element of the array.

◆ CONS

#define CONS (   f,
  l,
 
)
Value:
({ \
__typeof__(l) __l = (l); \
__typeof__(v) __v = (v); \
__v->f = *__l; \
*__l = __v; \
})

Add to head of an intrusive list.

Parameters
ffield to store link.
lpointer to list head pointer to update.
vstruct to add.

◆ COUNTDOWN

#define COUNTDOWN (   i,
 
)    RANGEDOWN(i, 0, n)

Iterate i from n-1 to 0.

COUNTUP(i, 3) {
printf("up: %d\n", (unsigned int)i);
}
COUNTDOWN(i, 3) {
printf("down: %d\n", (unsigned int)i);
}
COUNTUP(i, 0) {
printf("down: shouldn't print this\n");
}
COUNTDOWN(i, 0) {
printf("down: shouldn't print this\n");
}
unsigned int arr[] = {1, 4, 9};
FOREACH(i, arr) {
printf("arr[%d] = %d\n", (unsigned int)i, arr[i]);
}
LOOP(3) {
LOOP(3) {
putchar('x');
}
putchar('\n');
}

◆ COUNTUP

#define COUNTUP (   i,
 
)    RANGEUP(i, 0, n)

Iterate i from 0 to n-1.

◆ csub

#define csub (   a,
 
)
Value:
({ \
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_b > _a ? 0 : _a - _b; \
})

Non-negative saturating subtraction.

◆ DISABLE

#define DISABLE (   ...)
Value:
do { \
LOG(MARK("DISABLED") " %s", __func__); \
return __VA_ARGS__; \
} while(0) \

◆ FLAG

#define FLAG (   s,
  flag 
)    (((s).flags & (flag)) != 0)

Return true if the flag is set.

◆ FOREACH

#define FOREACH (   i,
 
)    COUNTUP(i, LENGTH(a))

Iterate i over each index of the array a.

◆ FORMAP

#define FORMAP (   i,
 
)    for(size_t i = 1; i <= *map_cnt(m); i++)

Iterate i over each index of map m.

◆ FORMAT

#define FORMAT (   name,
 
)    void format_##name(intptr_t i)

Define a new format string specifier (for logging).

◆ LENGTH

#define LENGTH (   a)    (sizeof(a) / WIDTH(a))

Number of array elements.

◆ likely

#define likely (   c)    (__builtin_expect((c), 1))

Hint that the condition is likely.

if likely(...) { ...

◆ LIST_ADD

#define LIST_ADD (   f,
  l,
 
)
Value:
({ \
__typeof__(v) __v = (v); \
*(l) = __v; \
(l) = &__v->f; \
})

Add to tail of an intrusive list.

Parameters
ffield to store link.
lpointer to list tail pointer to update.
vstruct to add.

◆ LOOP

#define LOOP (   n)    COUNTDOWN(UNIQUE, n)

Iterate n times.

◆ max

#define max (   a,
 
)
Value:
({ \
__typeof__(a) __a = (a); \
__typeof__(b) __b = (b); \
__a >= __b ? __a : __b; \
})

◆ min

#define min (   a,
 
)
Value:
({ \
__typeof__(a) __a = (a); \
__typeof__(b) __b = (b); \
__a <= __b ? __a : __b; \
})

◆ NOT_FLAG

#define NOT_FLAG (   s,
  flag 
)    (((s).flags & (flag)) == 0)

Return true if the flag is NOT set.

◆ offsetof

#define offsetof (   s,
 
)    ((uintptr_t)&(((s *)0)->f))

Offset of a field.

◆ printseg

#define printseg (   pre,
  seg,
  fmt,
  ... 
)
Value:
do { \
seg_t __seg = seg; \
printf(pre "%.*s" fmt, (int)__seg.n, __seg.s , ##__VA_ARGS__); \
} while(0)

printf that prepends a string segment

Parameters
preprint this string first
segstring segment to print next
fmtformat string for remaining arguments

◆ RANGEDOWN

#define RANGEDOWN (   i,
  lower,
  upper 
)    for(size_t i = (upper), __lower = (lower); i-- > __lower; )

Iterate i from upper-1 down to lower.

◆ RANGEUP

#define RANGEUP (   i,
  lower,
  upper 
)    for(size_t i = (lower), __upper = (upper); i < __upper; i++)

Iterate i from lower up to upper-1.

◆ SEG

#define SEG (   x)    {(x), sizeof(x) - 1}

String segment initializer.

Example: seg_t s = SEG("Hello");

◆ show

#define show (   x)    printf(#x " = %d\n", (int)(x))

Trace an integer variable.

show(name) will print name = <value>

◆ sizeof_field

#define sizeof_field (   s,
 
)    sizeof(((s *)0)->f)

Size of a field.

◆ TEST

#define TEST (   name)    int test_##name()

Define a test.

◆ UNIQUE

#define UNIQUE   CONCAT(__unique_, __LINE__)

Make a unique identifier.

◆ unlikely

#define unlikely (   c)    (__builtin_expect((c), 0))

Hint that the condition is unlikely.

if unlikely(...) { ...

◆ WIDTH

#define WIDTH (   a)    (sizeof((a)[0]))

Number of bytes per array element.

◆ zero

#define zero (   a)    memset(&(a), 0, sizeof(a))

Zero an array or struct.