karlos/include/util.h

89 lines
2.9 KiB
C

#ifndef KARLOS_UTIL_H
#define KARLOS_UTIL_H
#include <stdint.h>
#define LIST_INSERT_TAIL(head, elem) do { \
if ((head) == NULL) { \
(elem)->next = (elem); \
(elem)->prev = (elem); \
(head) = (elem); \
} else { \
(elem)->next = (head); \
(elem)->prev = (head)->prev; \
(head)->prev->next = (elem); \
(head)->prev = (elem); \
} \
} while (0)
#define LIST_REMOVE(head, elem) do { \
if ((elem)->next == (elem)) { \
ASSERT((head) == (elem)); \
ASSERT((elem)->prev == (elem)); \
(head) = NULL; \
} else { \
(elem)->prev->next = (elem)->next; \
(elem)->next->prev = (elem)->prev; \
if ((elem) == (head)) { \
(head)= (elem)->next; \
} \
} \
(elem)->next = (elem)->prev = NULL; \
} while (0)
#define BIT_GET(bitmap, bit) (((bitmap) >> (bit)) & (__typeof__(bitmap))1)
#define BIT_SET(bitmap, bit) ((bitmap) |= ((__typeof__(bitmap))1 << (bit)))
#define BIT_CLR(bitmap, bit) ((bitmap) &= ~((__typeof__(bitmap))1 << (bit)))
#define IS_ALIGNED_16(sz) (((uint64_t)(sz) & (uint64_t)15) == 0)
#define ROUND_UP_SHIFT(n, shift) ((((uint64_t)n) + ((1ull << shift) - 1)) & ~(uint64_t)((1ull << shift) - 1))
#define ROUND_UP_8(n) ROUND_UP_SHIFT(n, 3)
#define ROUND_UP_16(n) ROUND_UP_SHIFT(n, 4)
// TODO gcc says popcount cannot be found. Use manual version for now.
#ifdef POPCOUNT_USE_BUILTIN
#define IS_POWER_OF_2(n) (__builtin_popcountl(n) == 1)
#else
#define IS_POWER_OF_2(n) ((n ^ (n - 1)) > (n - 1))
#endif
// Highest bit set (0-indexed).
// - 4 (100) has highest bit 2.
// - 10 (1010) has highest bit 3.
// The following holds: (1 << HIGHEST_BIT_SET(sz)) <= sz
// Don't use for `sz == 0`.
#define HIGHEST_BIT_SET(sz) (63 - __builtin_clzl((uint64_t)sz))
// Don't use for `n == 0`.
#define LOG2(n) HIGHEST_BIT_SET(n)
// newtype so you don't accidentally access the value; use following macros to read/write
// TODO these are aligned, we have no way to specify unaligned ints currently
typedef struct le16 {
uint16_t value;
} le16;
typedef struct le32 {
uint32_t value;
} le32;
typedef struct le64 {
uint64_t value;
} le64;
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define CPU_TO_LE16(n) ((struct le16) { .value = n })
#define CPU_TO_LE32(n) ((struct le32) { .value = n })
#define CPU_TO_LE64(n) ((struct le64) { .value = n })
#define LE16_TO_CPU(n) (n).value
#define LE32_TO_CPU(n) (n).value
#define LE64_TO_CPU(n) (n).value
#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN)
#define CPU_TO_LE16(n) ((struct le16) { .value = __builtin_bswap16(n) })
#define CPU_TO_LE32(n) ((struct le32) { .value = __builtin_bswap32(n) })
#define CPU_TO_LE64(n) ((struct le64) { .value = __builtin_bswap64(n) })
#define LE16_TO_CPU(n) __builtin_bswap16((n).value)
#define LE32_TO_CPU(n) __builtin_bswap32((n).value)
#define LE64_TO_CPU(n) __builtin_bswap64((n).value)
#endif
#endif