title: src/crelude/common.h


src/crelude/common.h

More...

Classes

Name
struct_atomic_t
Useful for resource counting etc.
structGenericArray
Array with pointer to void.
structMemArray
Array with pointer type to smallest addressable units of memory.
structGenericSlice
Slice with pointer to void.
structMemSlice
Slice with pointer type to smallest addressable units of memory.
structGenericMap
Hash-table that maps void * to void *.
structstring
Immutable wrapper for UTF-8 encoded string (bytes are mutable).
structrunic
Imutable warpper for UCS-4/UTF-32 encoded runic string (runes are mutable).
structStringBuilder
Mutable string which is built/pushed-to over time.
structRunicBuilder
Mutable runic string which is built/pushed-to over time.
structsymbol
Symbols are interned strings.

Types

Name
enumHashKeyType { HKT_STRING = 1 << 0, HKT_RUNIC = 1 << 1, HKT_CSTRING = 1 << 2, HKT_MEM_SLICE = 1 << 3, HKT_RAW_BYTES = 1 << 4, HKT_SMALL_INTEGER = 1 << 5}
typedef enum HashKeyTypeHashKeyType
typedef struct _atomic_tatomic_t
Useful for resource counting etc.
typedef voidu0
typedef signed intierr
typedef unsigned intuerr
typedef unsigned longuword
long is always the same size as a machine word.
typedef signed longiword
typedef unsigned intufast
typedef signed intifast
typedef ptrdiff_tisize
typedef size_tusize
Use for storing array indices or object sizes.
typedef intptr_tiptr
typedef uintptr_tuptr
Large enough to store a pointer, like (void *).
typedef intmax_timax
typedef uintmax_tumax
typedef unsigned charumin
Such that sizeof(umin) == 1.
typedef signed charimin
Such that sizeof(imin) == 1.
typedef __int8_ti8
typedef __uint8_tu8
typedef __uint8_tbyte
Don't use char when you want byte.
typedef __int16_ti16
typedef __uint16_tu16
typedef __int32_ti32
typedef __uint32_tu32
typedef u32rune
typedef __int64_ti64
typedef __uint64_tu64

Functions

Name
_Static_assert(sizeof(umin) ==1 &&sizeof(imin)==1, "umin and [imin](/crelude/Files/common_8h.md#typedef-imin) must have size one (1)." )
u0panic(const byte * , ... )
u0 *or(const u0 * nullable, const u0 * nonnull)
boolis_zero(imax )
boolis_zerof(f64 )
boolis_zeroed(u0 * , usize )
u0zero(u0 * blk, usize width)
u0 *emalloc(usize , usize )
Malloc with zeros, and panics when out of memory.
u0reverse(u0 * self, usize width)
MemSlicereverse_endianness(MemSlice bytes)
boolis_little_endian(void )
u128big_endian(umin * start, usize bytes)
Read big-endian integer.
u0swap(u0 * self, usize pivot, usize width)
u0memswap(umin * a, umin * b, usize bytes)
usizeresize(u0 * self, usize cap, usize width)
usizegrow(u0 * self, usize count, usize width)
u0 *get(u0 * self, usize index, usize width)
u0 *set(u0 * self, usize index, const u0 * elem, usize width)
usizepush(u0 * self, const u0 * element, usize width)
u0 *pop(u0 * self, usize width)
u0 *shift(u0 * self, usize width)
Works like pop but removes from the front.
usizeinsert(u0 * self, usize index, const u0 * element, usize width)
usizeextend(u0 * self, const u0 * slice, usize width)
usizesplice(u0 * self, usize index, const u0 * slice, usize width)
GenericSlicecut(u0 * self, usize from, isize upto, usize width)
usizenull(u0 * self, usize width)
stringfrom_cstring(const byte * )
NUL-terminated string to library string.
boolstring_eq(const string, const string)
Compare two strings for equality.
i16string_cmp(const string, const string)
Compare two strings for alphabetic rank.
i16string_ncmp(const string, const string, usize n)
Compare two strings for alphabetic rank upto a given number of bytes.
u64hash_string(const string)
Hash a string.
u64hash_bytes(const MemSlice)
Hash a byte slice.
u0associate(u0 * self, const u0 * key, const u0 * value)
Map / associate a key with a value, i.e. insert into the hash-map/table.
u0 *lookup(u0 * self, const u0 * key)
Look-up / get value from hash-map/table given the key.
booldrop(u0 * self, const u0 * key)
GenericSliceget_keys(u0 * self)
boolhas_key(u0 * self, u0 * key)
Checks if entry / key-value pair is present in hash-table/map given a key.
u0empty_map(u0 * self)
boolis_empty_map(u0 * self)
Checks if the hash-table / map is empty or freed.
u0free_map(u0 * self)
usizeinit_hashnode(u0 * , const u0 * , u64 , const u0 * , const u0 * )
Internal use 99% of the time.
u0dump_hashmap(u0 * self, byte * key_formatter, byte * value_formatter)
Hashmap debugging function.
attribute((unused) ) const
returnhash_bytes(extension({ __auto_type _self=(runes);MemSlice _bytes={ .len=_self.len sizeof(_self.value),.value=(umin *) _self.value };_bytes;}) )
returnhash_string(from_cstring(*(byte **) key) )

Attributes

Defines

Name
_GNU_SOURCE
Use GNU specific source.
FREE
MALLOC
REALLOC
VA_NUM_ARGS_IMPL(_1, _2, _3, _4, _5, N, ...)
VA_NUM_ARGS(...)
_TSTR(x)
TSTR(x)
TODO(...)
crelude_V_MAJOR
crelude_V_MINOR
crelude_V_PATCH
crelude_VERSION
ARRAY_REALLOC_FACTOR
loop
whilst
unless(cond)
never
always
until(cond)
unqualify(D, T)
record(NAME)
enumerable(NAME)
overlap(NAME)
newtype(NT, T)
arrayof(T)
newarray(NT, T)
sliceof(T)
newslice(NT, T)
hashof(T)
newhashable(NT, T)
HASHMAP_LOAD_THRESHOLD
HASHMAP_GROWTH_FACTOR
newmap(NT, K, V)
mapof(K, V)
hashnode(K, V)
MMAKE(K, V, CAP)
MNEW(VARIABLE, CAP)
Create new map / initialise map from map variable.
NTH(LIST, N)
GET(LIST, N)
SET(LIST, N, V)
UNUSED1(z)
UNUSED2(y, z)
UNUSED3(x, y, z)
UNUSED4(b, x, y, z)
UNUSED5(a, b, x, y, z)
UNUSED_IMPL_(nargs)
UNUSED_IMPL(nargs)
UNUSED(...)
NO_ERROR
OK
OKAY
FAIL
NOOP
nil
FLOOR(T, N)
CEIL(T, N)
UNIT
WORD_SIZE
Size of a machine word in bytes.
UCHAR8
UCHAR8
_FLOAT_BIT
_DOUBLE_BIT
_LDOUBLE_BIT
COPY(SELF)
TO_BYTES(SELF)
Convert array/slice to slice of bytes.
FROM_BYTES(T, SELF)
Convert from a byte array/slice into an array/slice of another type.
REVERSE(SELF)
In-place reverse.
SWAP(SELF, PIVOT)
PUSH(SELF, ELEM)
POP(SELF)
SHIFT(SELF)
INSERT(SELF, INDEX, ELEM)
EXTEND(SELF, SLIC)
SPLICE(SELF, INDEX, SLIC)
CUT(SELF, FROM, UPTO)
REMOVE(SELF, INDEX)
ASSOCIATE(SELF, KEY, VAL)
LOOKUP(SELF, KEY)
DROP(SELF, KEY)
KEYS(MAP)
HAS_KEY(MAP, KEY)
APPEND(SELF, ELEM)
PREPEND(SELF, ELEM)
UNSHIFT(SELF, ELEM)
PREFIX(SELF, SLIC)
HEAD(SELF, END)
TAIL(SELF, BEG)
FIRST(SELF)
LAST(SELF)
QSORT(SELF, CMPR)
Minimal helper/wrapper around in-place qsort for arrays/slices.
SORT(SELF, SUBJ, OTHR, ...)
CMP(A, B)
ANSI(CODE)
BOLD
FAINT
DIM
ITALIC
UNDER
BLINK
RAPID
INVERT
HIDDEN
STRIKE
BOLD_OFF
FAINT_OFF
ITALIC_OFF
UNDER_OFF
BLINK_OFF
RAPID_OFF
INVERT_OFF
HIDDEN_OFF
STRIKE_OFF
RESET
min(A, B)
max(A, B)
deref(T, PTR, ALT)
WRAP(TYPE, VALUE)
Wrap value in wrapper struct.
UNWRAP(STRUCTURE)
Unwraps pointer/value in sizing wrapper struct.
PTR(ARR)
Explicitly only extract pointer from array/slice.
FREE_INSIDE(S)
Call to free of inside of slice/array/newtype, etc.
INIT(TYPE, ...)
Initialise sizing wrapper with literal.
LIST(TYPE, ...)
Can be used to make slices from literal arrays.
STRING(...)
Initialise sizing wrapper with of string literal.
STR(...)
SEMPTY(TYPE)
Empty slice of certain type.
AEMPTY(TYPE)
Empty array of certain type.
EMPTY(TYPE)
Empty / zero struct.
IS_EMPTY(ARR)
Is array empty?
AMAKE(TYPE, CAP)
Heap allocates a variable sized array.
ANEW(VARIABLE, CAP)
Create new array / initialise array from array variable.
SMAKE(TYPE, LEN)
Heap allocates a constant sized slice type.
SNEW(VARIABLE, LEN)
Create new slice / initialise slice from slice variable.
SLICE(TYPE, OBJ, START, END)
Take a slice/substring/view of sized type.
VIEW(TYPE, PTR, START, END)
Works like SLICE, but on a pointer instead of an array.
SYMBOLIC(STR)
SYMBOL_LITERAL(STR_LIT)
ACOLLECT(T, count, pointer)
C array to dynamic array wrapper.
SCOLLECT(T, count, pointer)
C array to slice wrapper.
SMAP(T, func, list)
AMAP(T, func, list)
FOR_EACH(ELEM, ELEMS)
foreach

Detailed Description

Note: Read this: unicode by Jeff Bezanson, about modern unicode in C.

Defines basic macros and datatypes which are in common through-out the whole project.

Types Documentation

enum HashKeyType

EnumeratorValueDescription
HKT_STRING1 << 0
HKT_RUNIC1 << 1
HKT_CSTRING1 << 2
HKT_MEM_SLICE1 << 3
HKT_RAW_BYTES1 << 4
HKT_SMALL_INTEGER1 << 5

typedef HashKeyType

typedef enum HashKeyType HashKeyType;

typedef atomic_t

typedef struct _atomic_t atomic_t;

Useful for resource counting etc.

typedef u0

typedef void u0;

The type that occupies no space. Thanks to Terry for this one.

typedef ierr

typedef signed int ierr;

Explicitly mark functions that return error-codes as returning ierr instead of just int.

typedef uerr

typedef unsigned int uerr;

Not something very common.

typedef uword

typedef unsigned long uword;

long is always the same size as a machine word.

Unsigned machine word integer.

typedef iword

typedef signed long iword;

Signed machine word integer.

typedef ufast

typedef unsigned int ufast;

int in most cases is going to have the natural size suggested by the target architecture, optimal for most things.

typedef ifast

typedef signed int ifast;

typedef isize

typedef ptrdiff_t isize;

typedef usize

typedef size_t usize;

Use for storing array indices or object sizes.

typedef iptr

typedef intptr_t iptr;

typedef uptr

typedef uintptr_t uptr;

Large enough to store a pointer, like (void *).

typedef imax

typedef intmax_t imax;

typedef umax

typedef uintmax_t umax;

typedef umin

typedef unsigned char umin;

Such that sizeof(umin) == 1.

typedef imin

typedef signed char imin;

Such that sizeof(imin) == 1.

typedef i8

typedef __int8_t i8;

typedef u8

typedef __uint8_t u8;

typedef byte

typedef __uint8_t byte;

Don't use char when you want byte.

typedef i16

typedef __int16_t i16;

typedef u16

typedef __uint16_t u16;

typedef i32

typedef __int32_t i32;

typedef u32

typedef __uint32_t u32;

typedef rune

typedef u32 rune;

Unicode codepoint (USC-4) (32 bits), don't use char[4], and definitely do not use wchar_t.

typedef i64

typedef __int64_t i64;

typedef u64

typedef __uint64_t u64;

Functions Documentation

function _Static_assert

_Static_assert(
    sizeof(umin)  ==1 &&sizeof(imin)==1,
    "`umin` and `imin` must have size one (1)." 
)

function panic

u0 panic(
    const byte * ,
    ... 
)

function or

u0 * or(
    const u0 * nullable,
    const u0 * nonnull
)

function is_zero

bool is_zero(
    imax 
)

function is_zerof

bool is_zerof(
    f64 
)

function is_zeroed

bool is_zeroed(
    u0 * ,
    usize 
)

function zero

u0 zero(
    u0 * blk,
    usize width
)

Parameters:

  • blk Pointer to start of block.
  • width How many bytes to zero. e.g., for an array width = lenght * sizeof(elem).

Zero a block of memory.

function emalloc

u0 * emalloc(
    usize ,
    usize 
)

Malloc with zeros, and panics when out of memory.

function reverse

u0 reverse(
    u0 * self,
    usize width
)

Parameters:

  • self A pointer to an array or slice, cast to u0 *.
  • width The width/sizeof of an element in the array.

Reverse an array or slice in-place.

function reverse_endianness

MemSlice reverse_endianness(
    MemSlice bytes
)

Note: Heap allocates, remember to free.

Reverse a slice of bytes. Not in-place.

function is_little_endian

bool is_little_endian(
    void 
)

Return: true if little endian, false if big endian.

Check if system/CPU is using little endian.

function big_endian

u128 big_endian(
    umin * start,
    usize bytes
)

Read big-endian integer.

function swap

u0 swap(
    u0 * self,
    usize pivot,
    usize width
)

Parameters:

  • self Pointer to the slice, cast to (u0 *).
  • pivot The index of the slice that divides the blocks to swap.
  • width The sizeof(T) where T is the type of element in the slice.

Given a slice, swap the two blocks within the slice formed by selecting a pivot point (in-place).

[----A----|---B---] -> [---B---|----A----]
          ^ pivot

function memswap

u0 memswap(
    umin * a,
    umin * b,
    usize bytes
)

Parameters:

  • a Block of memory a, to be swapped for b.
  • b Block of memory b, to be swapped for a.
  • bytes The common size of block a and b in bytes.

Swaps two equally sized blocks of memory, overwriting each other.

function resize

usize resize(
    u0 * self,
    usize cap,
    usize width
)

Return: How much of the array is empty (i.e. cap - len).

Resizes the array, i.e. changes the capacity to a given value. Akin to realloc.

function grow

usize grow(
    u0 * self,
    usize count,
    usize width
)

Parameters:

  • self Void-pointer to array structure.
  • count Number of spaces to grow by.
  • width Size of the individual elements in the array, in bytes.

Return: How much capacity increased.

Grows the array length by count, reallocates if necessary. Does nothing else.

function get

u0 * get(
    u0 * self,
    usize index,
    usize width
)

Parameters:

  • self Pointer to slice or array.
  • index Index of element you wish to retrieve.
  • width Size of single array element in bytes.

Return: Pointer to element, or NULL if not present / out of bounds.

Get pointer to element at index in slice/array.

function set

u0 * set(
    u0 * self,
    usize index,
    const u0 * elem,
    usize width
)

Parameters:

  • self Pointer to slice or array.
  • index Index of element you wish to set.
  • width Size of single array element in bytes.

Return: Pointer to element just set, or NULL if out of bounds.

Set element at index in slice/array.

function push

usize push(
    u0 * self,
    const u0 * element,
    usize width
)

Parameters:

  • self Pointer to the dynamic array, cast to (u0 *).
  • element Pointer to element to be pushed, cast to (u0 *).
  • width The sizeof(T) where T is the type of the element that is being pushed.

Return: How much capacity increased.

Push element to array.

function pop

u0 * pop(
    u0 * self,
    usize width
)

Return: Pointer to popped element.

Pops/removes element from top of the stack (dynamic array).

function shift

u0 * shift(
    u0 * self,
    usize width
)

Works like pop but removes from the front.

function insert

usize insert(
    u0 * self,
    usize index,
    const u0 * element,
    usize width
)

Return: How much capacity increased.

Exactly like push, except position of element is arbitrary, with index specified in second argument.

function extend

usize extend(
    u0 * self,
    const u0 * slice,
    usize width
)

Parameters:

  • self A pointer to a dynamic array, of any type.
  • slice A pointer to a slice, and a slice only (not an array, dynamic array, etc.).
  • width The sizeof(T) where T is the type of the individual elements that are being appended to the array.

Return: How much capacity increased.

Works like push, but extends the array by multiple elements.

function splice

usize splice(
    u0 * self,
    usize index,
    const u0 * slice,
    usize width
)

Parameters:

  • self A pointer to the dynamic array, of any type.
  • index The location for inserting in the slice.
  • slice The slice you wish to insert at index.
  • width The sizeof(T) where T is the type of the individual elements stored within the array and slice.

Return: How much capacity increased.

Works like extend, but extends or splices the array with a slice at some given, arbitrary position.

function cut

GenericSlice cut(
    u0 * self,
    usize from,
    isize upto,
    usize width
)

Parameters:

  • self A pointer to the array.
  • from Index to start removing from.
  • upto Index of final element to remove in the range. If parameter is negative, it indicates an index from the end of the array.

Return: A slice holding a void-pointer to the removed elements,

Deletes a range of elements from an array, starting from some index.

function null

usize null(
    u0 * self,
    usize width
)

Return: Number of bytes nulled.

Zero out an array.

function from_cstring

string from_cstring(
    const byte * 
)

NUL-terminated string to library string.

function string_eq

bool string_eq(
    const string,
    const string
)

Compare two strings for equality.

function string_cmp

i16 string_cmp(
    const string,
    const string
)

Compare two strings for alphabetic rank.

function string_ncmp

i16 string_ncmp(
    const string,
    const string,
    usize n
)

Compare two strings for alphabetic rank upto a given number of bytes.

function hash_string

u64 hash_string(
    const string
)

Hash a string.

function hash_bytes

u64 hash_bytes(
    const MemSlice
)

Hash a byte slice.

function associate

u0 associate(
    u0 * self,
    const u0 * key,
    const u0 * value
)

Map / associate a key with a value, i.e. insert into the hash-map/table.

function lookup

u0 * lookup(
    u0 * self,
    const u0 * key
)

Look-up / get value from hash-map/table given the key.

function drop

bool drop(
    u0 * self,
    const u0 * key
)

Return: true if key was present, and node was deleted, false if not.

Drop / delete / remove key-value pair from the hash-table. This frees/deallocates the node, and the key and value are deleted. Does nothing if key did not exist in the table.

function get_keys

GenericSlice get_keys(
    u0 * self
)

Note: Returns a heap allocated slice, remember to free.

Get slice of key pointers of all keys in map/hash-table.

function has_key

bool has_key(
    u0 * self,
    u0 * key
)

Checks if entry / key-value pair is present in hash-table/map given a key.

function empty_map

u0 empty_map(
    u0 * self
)

Empties out / deallocates all key-value pairs from the map. Map may still be repopulated again after this.

function is_empty_map

bool is_empty_map(
    u0 * self
)

Checks if the hash-table / map is empty or freed.

function free_map

u0 free_map(
    u0 * self
)

Frees the map. Not only empties it, but deallocates bucket array such that the map may not be used again.

function init_hashnode

usize init_hashnode(
    u0 * ,
    const u0 * ,
    u64 ,
    const u0 * ,
    const u0 * 
)

Internal use 99% of the time.

function dump_hashmap

u0 dump_hashmap(
    u0 * self,
    byte * key_formatter,
    byte * value_formatter
)

Hashmap debugging function.

function attribute

__attribute__(
    (unused) 
) const

function hash_bytes

return hash_bytes(
    __extension__({ __auto_type _self=(runes);MemSlice _bytes={ .len=_self.len *sizeof(*_self.value),.value=(umin *) _self.value };_bytes;}) 
)

function hash_string

return hash_string(
    from_cstring(*(byte **) key) 
)

Attributes Documentation

variable hash

u64 hash;

variable value

u0 * value;

variable key

struct @21 key;

variable next

u0 * next;

variable NUL

static const ierr NUL = 0;

variable NUL_BYTE

static const byte NUL_BYTE = '\0';

variable NUL_STRING

static const string NUL_STRING = { .[len](/crelude/Files/base64_8h.md#variable-len) = 0, .[value](/crelude/Files/common_8h.md#variable-value) = ([byte](/crelude/Files/common_8h.md#typedef-byte) *)&[NUL_BYTE](/crelude/Files/common_8h.md#variable-nul_byte) };

variable ZERO

static const iword ZERO = 0;

variable _

usize _ {
	[UNUSED1](/crelude/Files/common_8h.md#define-unused1);

variable runes

runic runes = *([runic](/crelude/Classes/structrunic.md) *)[key](/crelude/Files/common_8h.md#variable-key);

variable size

usize size {
	[u64](/crelude/Files/common_8h.md#typedef-u64)[hash](/crelude/Files/common_8h.md#variable-hash) = 0;

Macros Documentation

define _GNU_SOURCE

#define _GNU_SOURCE 1

Use GNU specific source.

define FREE

#define FREE free

define MALLOC

#define MALLOC malloc

define REALLOC

#define REALLOC realloc

define VA_NUM_ARGS_IMPL

#define VA_NUM_ARGS_IMPL(
    _1,
    _2,
    _3,
    _4,
    _5,
    N,
    ...
)
N

define VA_NUM_ARGS

#define VA_NUM_ARGS(
    ...
)
[VA_NUM_ARGS_IMPL](/crelude/Files/common_8h.md#define-va_num_args_impl)(__VA_ARGS__, 5, 4, 3, 2, 1)

define _TSTR

#define _TSTR(
    x
)
#x

define TSTR

#define TSTR(
    x
)
[_TSTR](/crelude/Files/common_8h.md#define-_tstr)(x)

define TODO

#define TODO(
    ...
)
                            DO_PRAGMA(message("TODO: " #__VA_ARGS__ \
                            " (" __FILE__ ":" [TSTR](/crelude/Files/common_8h.md#define-tstr)(__LINE__)")"))

define crelude_V_MAJOR

#define crelude_V_MAJOR 0

define crelude_V_MINOR

#define crelude_V_MINOR 1

define crelude_V_PATCH

#define crelude_V_PATCH 0

define crelude_VERSION

#define crelude_VERSION 	"v" TSTR([crelude_V_MAJOR](/crelude/Files/common_8h.md#define-crelude_v_major)) \
	"." [TSTR](/crelude/Files/common_8h.md#define-tstr)([crelude_V_MINOR](/crelude/Files/common_8h.md#define-crelude_v_minor)) \
	"." [TSTR](/crelude/Files/common_8h.md#define-tstr)([crelude_V_PATCH](/crelude/Files/common_8h.md#define-crelude_v_patch))

define ARRAY_REALLOC_FACTOR

#define ARRAY_REALLOC_FACTOR 1.5

define loop

#define loop while (1)

define whilst

#define whilst while

define unless

#define unless(
    cond
)
if (!(cond))

define never

#define never if (0)

define always

#define always if (1)

define until

#define until(
    cond
)
while (!(cond))

define unqualify

#define unqualify(
    D,
    T
)
typedef D T T

define record

#define record(
    NAME
)
typedef struct [_](/crelude/Files/common_8h.md#variable-_)##NAME NAME; struct [_](/crelude/Files/common_8h.md#variable-_)##NAME

define enumerable

#define enumerable(
    NAME
)
typedef   enum [_](/crelude/Files/common_8h.md#variable-_)##NAME NAME;   enum [_](/crelude/Files/common_8h.md#variable-_)##NAME

define overlap

#define overlap(
    NAME
)
typedef  union [_](/crelude/Files/common_8h.md#variable-_)##NAME NAME;  union [_](/crelude/Files/common_8h.md#variable-_)##NAME

define newtype

#define newtype(
    NT,
    T
)
typedef struct [_](/crelude/Files/common_8h.md#variable-_)##NT { T [value](/crelude/Files/common_8h.md#variable-value); } NT

define arrayof

#define arrayof(
    T
)
	struct { \
	T (*[value](/crelude/Files/common_8h.md#variable-value)); \
	[usize](/crelude/Files/common_8h.md#typedef-usize)[len](/crelude/Files/base64_8h.md#variable-len);  \
	[usize](/crelude/Files/common_8h.md#typedef-usize) cap;  \
}

define newarray

#define newarray(
    NT,
    T
)
typedef [arrayof](/crelude/Files/common_8h.md#define-arrayof)(T) NT

define sliceof

#define sliceof(
    T
)
	struct { \
	T (*[value](/crelude/Files/common_8h.md#variable-value)); \
	[usize](/crelude/Files/common_8h.md#typedef-usize)[len](/crelude/Files/base64_8h.md#variable-len);  \
}

define newslice

#define newslice(
    NT,
    T
)
typedef [sliceof](/crelude/Files/common_8h.md#define-sliceof)(T) NT

define hashof

#define hashof(
    T
)
	struct { \
	[u64](/crelude/Files/common_8h.md#typedef-u64)[hash](/crelude/Files/common_8h.md#variable-hash); \
	T [value](/crelude/Files/common_8h.md#variable-value);  \
}

define newhashable

#define newhashable(
    NT,
    T
)
typedef [hashof](/crelude/Files/common_8h.md#define-hashof)(T) NT

define HASHMAP_LOAD_THRESHOLD

#define HASHMAP_LOAD_THRESHOLD 0.85

define HASHMAP_GROWTH_FACTOR

#define HASHMAP_GROWTH_FACTOR 2

define newmap

#define newmap(
    NT,
    K,
    V
)
typedef [mapof](/crelude/Files/common_8h.md#define-mapof)(K, V) NT

define mapof

#define mapof(
    K,
    V
)
	struct { \
	[usize](/crelude/Files/common_8h.md#typedef-usize)[len](/crelude/Files/base64_8h.md#variable-len); \
	[arrayof](/crelude/Files/common_8h.md#define-arrayof)([hashnode](/crelude/Files/common_8h.md#define-hashnode)(K, V)) buckets; /* a [hash](/crelude/Files/common_8h.md#variable-hash)[value](/crelude/Files/common_8h.md#variable-value) of [zero](/crelude/Files/common_8h.md#function-zero) indicates absence. */\
	[usize](/crelude/Files/common_8h.md#typedef-usize) value_size; \
	[usize](/crelude/Files/common_8h.md#typedef-usize)   key_size; \
	[usize](/crelude/Files/common_8h.md#typedef-usize)  node_size; \
	/* offsets of `[hashnode](/crelude/Files/common_8h.md#define-hashnode)` struct. */ \
	[usize](/crelude/Files/common_8h.md#typedef-usize)  hash_offset; \
	[usize](/crelude/Files/common_8h.md#typedef-usize)   key_offset; \
	[usize](/crelude/Files/common_8h.md#typedef-usize) value_offset; \
	[usize](/crelude/Files/common_8h.md#typedef-usize)  next_offset; \
	[HashKeyType](/crelude/Files/common_8h.md#enum-hashkeytype) key_type; /* < how should the [hash](/crelude/Files/common_8h.md#variable-hash)-function [hash](/crelude/Files/common_8h.md#variable-hash) the key. */ \
	[u64](/crelude/Files/common_8h.md#typedef-u64) (*hasher)(const [u0](/crelude/Files/common_8h.md#typedef-u0) *, [usize](/crelude/Files/common_8h.md#typedef-usize)); \
}

define hashnode

#define hashnode(
    K,
    V
)
	struct { \
	[hashof](/crelude/Files/common_8h.md#define-hashof)(K) [key](/crelude/Files/common_8h.md#variable-key); \
	V [value](/crelude/Files/common_8h.md#variable-value);  /* < [value](/crelude/Files/common_8h.md#variable-value) stored.   */ \
	[u0](/crelude/Files/common_8h.md#typedef-u0) *[next](/crelude/Files/common_8h.md#variable-next); /* < [next](/crelude/Files/common_8h.md#variable-next)[hash](/crelude/Files/common_8h.md#variable-hash)-node. */ \
}

define MMAKE

#define MMAKE(
    K,
    V,
    CAP
)

define MNEW

#define MNEW(
    VARIABLE,
    CAP
)
	(typeof(VARIABLE))[MMAKE](/crelude/Files/common_8h.md#define-mmake)( \
	typeof((VARIABLE).[buckets.value](/crelude/Files/common_8h.md#variable-value)[0].[key.value](/crelude/Files/common_8h.md#variable-value)), \
	typeof((VARIABLE).[buckets.value](/crelude/Files/common_8h.md#variable-value)[0].[value](/crelude/Files/common_8h.md#variable-value)), \
	CAP)

Create new map / initialise map from map variable.

define NTH

#define NTH(
    LIST,
    N
)
[UNWRAP](/crelude/Files/common_8h.md#define-unwrap)(([LIST](/crelude/Files/common_8h.md#define-list)))[(N)]

define GET

#define GET(
    LIST,
    N
)
	__extension__\
	({ __auto_type _list = ([LIST](/crelude/Files/common_8h.md#define-list)); \
	   __auto_type _n = (N); \
	   [usize](/crelude/Files/common_8h.md#typedef-usize) _index = _n < 0 ? ([usize](/crelude/Files/common_8h.md#typedef-usize))([_list.len](/crelude/Files/base64_8h.md#variable-len) + _n) : ([usize](/crelude/Files/common_8h.md#typedef-usize))_n; \
	   [UNWRAP](/crelude/Files/common_8h.md#define-unwrap)(_list)[_index]; })

define SET

#define SET(
    LIST,
    N,
    V
)
	__extension__\
	({ __auto_type _list = ([LIST](/crelude/Files/common_8h.md#define-list)); \
	   __auto_type _n = (N); \
	   [usize](/crelude/Files/common_8h.md#typedef-usize) _index = _n < 0 ? ([usize](/crelude/Files/common_8h.md#typedef-usize))([_list.len](/crelude/Files/base64_8h.md#variable-len) + _n) : ([usize](/crelude/Files/common_8h.md#typedef-usize))_n; \
	   [UNWRAP](/crelude/Files/common_8h.md#define-unwrap)(_list)[_index] = (V); })

define UNUSED1

#define UNUSED1(
    z
)
(void)(z)

define UNUSED2

#define UNUSED2(
    y,
    z
)
[UNUSED1](/crelude/Files/common_8h.md#define-unused1)(y),[UNUSED1](/crelude/Files/common_8h.md#define-unused1)(z)

define UNUSED3

#define UNUSED3(
    x,
    y,
    z
)
[UNUSED1](/crelude/Files/common_8h.md#define-unused1)(x),[UNUSED2](/crelude/Files/common_8h.md#define-unused2)(y,z)

define UNUSED4

#define UNUSED4(
    b,
    x,
    y,
    z
)
[UNUSED2](/crelude/Files/common_8h.md#define-unused2)(b,x),[UNUSED2](/crelude/Files/common_8h.md#define-unused2)(y,z)

define UNUSED5

#define UNUSED5(
    a,
    b,
    x,
    y,
    z
)
[UNUSED2](/crelude/Files/common_8h.md#define-unused2)(a,b),[UNUSED3](/crelude/Files/common_8h.md#define-unused3)(x,y,z)

define UNUSED_IMPL_

#define UNUSED_IMPL_(
    nargs
)
[UNUSED](/crelude/Files/common_8h.md#define-unused) ## nargs

define UNUSED_IMPL

#define UNUSED_IMPL(
    nargs
)
[UNUSED_IMPL_](/crelude/Files/common_8h.md#define-unused_impl_)(nargs)

define UNUSED

#define UNUSED(
    ...
)
[UNUSED_IMPL](/crelude/Files/common_8h.md#define-unused_impl)([VA_NUM_ARGS](/crelude/Files/common_8h.md#define-va_num_args)(__VA_ARGS__))(__VA_ARGS__)

define NO_ERROR

#define NO_ERROR EXIT_SUCCESS

define OK

#define OK EXIT_SUCCESS

define OKAY

#define OKAY EXIT_SUCCESS

define FAIL

#define FAIL EXIT_FAILURE

define NOOP

#define NOOP ((void)0)

define nil

#define nil ((void *)NULL)

define FLOOR

#define FLOOR(
    T,
    N
)
	__extension__\
	({ typeof(N) _n = (N); \
	   (T)_n - (_n < 0 ? 1 : 0); })

define CEIL

#define CEIL(
    T,
    N
)
	__extension__\
	({ typeof(N) _n = (N); \
	   (T)_n + (_n < 0 ? 0 : 1); })

define UNIT

#define UNIT ;

define WORD_SIZE

#define WORD_SIZE sizeof(long)

Size of a machine word in bytes.

define UCHAR8

#define __UCHAR8__ char

define UCHAR8

#define __UCHAR8__ char

define _FLOAT_BIT

#define _FLOAT_BIT (__SIZEOF_FLOAT__       * CHAR_BIT)

define _DOUBLE_BIT

#define _DOUBLE_BIT (__SIZEOF_DOUBLE__      * CHAR_BIT)

define _LDOUBLE_BIT

#define _LDOUBLE_BIT (__SIZEOF_LONG_DOUBLE__ * CHAR_BIT)

define COPY

#define COPY(
    SELF
)
	__extension__\
	({ __auto_type _self = (SELF); \
	   __auto_type _copy = _self; \
	   [PTR](/crelude/Files/common_8h.md#define-ptr)(_copy) = [emalloc](/crelude/Files/common_8h.md#function-emalloc)([_self.len](/crelude/Files/base64_8h.md#variable-len), sizeof(*[PTR](/crelude/Files/common_8h.md#define-ptr)(_self))); \
	   memcpy([PTR](/crelude/Files/common_8h.md#define-ptr)(_copy), [PTR](/crelude/Files/common_8h.md#define-ptr)(_self), sizeof(*[PTR](/crelude/Files/common_8h.md#define-ptr)(_copy)) * [_copy.len](/crelude/Files/base64_8h.md#variable-len)); \
	   _copy; })

Note: Allocates on the heap.

Copy an array or slice.

define TO_BYTES

#define TO_BYTES(
    SELF
)
	__extension__\
	({ __auto_type _self = (SELF); \
	   [MemSlice](/crelude/Classes/structMemSlice.md) _bytes = { \
		  .[len](/crelude/Files/base64_8h.md#variable-len) = [_self.len](/crelude/Files/base64_8h.md#variable-len) * sizeof(*[_self.value](/crelude/Files/common_8h.md#variable-value)), \
		  .[value](/crelude/Files/common_8h.md#variable-value) = ([umin](/crelude/Files/common_8h.md#typedef-umin) *)[_self.value](/crelude/Files/common_8h.md#variable-value) \
	   }; _bytes; })

Convert array/slice to slice of bytes.

define FROM_BYTES

#define FROM_BYTES(
    T,
    SELF
)
	__extension__\
	({ __auto_type _self = (SELF); \
	   T _normal = { \
		  .[len](/crelude/Files/base64_8h.md#variable-len) = [_self.len](/crelude/Files/base64_8h.md#variable-len) / sizeof(*[_self.value](/crelude/Files/common_8h.md#variable-value)), \
		  .[value](/crelude/Files/common_8h.md#variable-value) = ([u0](/crelude/Files/common_8h.md#typedef-u0) *)[_self.value](/crelude/Files/common_8h.md#variable-value) \
	   }; _normal; })

Convert from a byte array/slice into an array/slice of another type.

define REVERSE

#define REVERSE(
    SELF
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   [reverse](/crelude/Files/common_8h.md#function-reverse)(_self, sizeof(*_self->[value](/crelude/Files/common_8h.md#variable-value))); \
	   *_self; })

In-place reverse.

define SWAP

#define SWAP(
    SELF,
    PIVOT
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   [swap](/crelude/Files/common_8h.md#function-swap)(_self, (PIVOT), sizeof(*_self->[value](/crelude/Files/common_8h.md#variable-value))); })

define PUSH

#define PUSH(
    SELF,
    ELEM
)
	__extension__\
	({ __auto_type           _self = &(SELF); \
	   typeof(*_self->[value](/crelude/Files/common_8h.md#variable-value)) _elem =  (ELEM); \
	   [push](/crelude/Files/common_8h.md#function-push)(_self, &_elem, sizeof(_elem)); })

define POP

#define POP(
    SELF
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   (typeof(_self->[value](/crelude/Files/common_8h.md#variable-value)))[pop](/crelude/Files/common_8h.md#function-pop)(_self, sizeof(*_self->[value](/crelude/Files/common_8h.md#variable-value))); })

define SHIFT

#define SHIFT(
    SELF
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   (typeof(_self->[value](/crelude/Files/common_8h.md#variable-value)))[shift](/crelude/Files/common_8h.md#function-shift)(_self, sizeof(*_self->[value](/crelude/Files/common_8h.md#variable-value))); })

define INSERT

#define INSERT(
    SELF,
    INDEX,
    ELEM
)
	__extension__\
	({ __auto_type           _self = &(SELF); \
	   typeof(*_self->[value](/crelude/Files/common_8h.md#variable-value)) _elem =  (ELEM); \
	   [insert](/crelude/Files/common_8h.md#function-insert)(_self, (INDEX), &_elem, sizeof(_elem)); })

define EXTEND

#define EXTEND(
    SELF,
    SLIC
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   __auto_type _slic =  (SLIC); \
	   [extend](/crelude/Files/common_8h.md#function-extend)(_self, &_slic, sizeof(*[_slic.value](/crelude/Files/common_8h.md#variable-value))); })

define SPLICE

#define SPLICE(
    SELF,
    INDEX,
    SLIC
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   __auto_type _slic =  (SLIC); \
	   [splice](/crelude/Files/common_8h.md#function-splice)(_self, (INDEX), &_slic, sizeof(*[_slic.value](/crelude/Files/common_8h.md#variable-value))); })

define CUT

#define CUT(
    SELF,
    FROM,
    UPTO
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   static [GenericSlice](/crelude/Classes/structGenericSlice.md) _cut; \
	   _cut = [cut](/crelude/Files/common_8h.md#function-cut)(_self, (FROM), (UPTO), sizeof(*_self->[value](/crelude/Files/common_8h.md#variable-value))); \
	   ([u0](/crelude/Files/common_8h.md#typedef-u0) *)&_cut; })

define REMOVE

#define REMOVE(
    SELF,
    INDEX
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   [usize](/crelude/Files/common_8h.md#typedef-usize) _indx = (INDEX); \
	   [GenericSlice](/crelude/Classes/structGenericSlice.md) _cut \
	       = [cut](/crelude/Files/common_8h.md#function-cut)(_self, _indx, _indx, sizeof(*_self->[value](/crelude/Files/common_8h.md#variable-value))); \
	   (typeof(_self->[value](/crelude/Files/common_8h.md#variable-value)))[PTR](/crelude/Files/common_8h.md#define-ptr)(_cut); })

define ASSOCIATE

#define ASSOCIATE(
    SELF,
    KEY,
    VAL
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   __auto_type _key = (KEY); \
	   __auto_type _val = (VAL); \
	   [associate](/crelude/Files/common_8h.md#function-associate)(_self, &_key, &_val); })

define LOOKUP

#define LOOKUP(
    SELF,
    KEY
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   __auto_type _key = (KEY); \
	   (typeof(_self->[buckets.value](/crelude/Files/common_8h.md#variable-value)[0].[value](/crelude/Files/common_8h.md#variable-value)) *)[lookup](/crelude/Files/common_8h.md#function-lookup)(_self, &_key); })

define DROP

#define DROP(
    SELF,
    KEY
)
	__extension__\
	({ __auto_type _self = &(SELF); \
	   __auto_type _key = (KEY); \
	   [drop](/crelude/Files/common_8h.md#function-drop)(_self, &_key); })

define KEYS

#define KEYS(
    MAP
)
	__extension__\
	({ __auto_type _map = &(MAP); \
	   static [GenericSlice](/crelude/Classes/structGenericSlice.md) _keys; \
	   _keys = [get_keys](/crelude/Files/common_8h.md#function-get_keys)(_map); \
	   ([u0](/crelude/Files/common_8h.md#typedef-u0) *)&_keys; })

define HAS_KEY

#define HAS_KEY(
    MAP,
    KEY
)
	__extension__\
	({ __auto_type _map = &(MAP); \
	   __auto_type _key = (KEY); \
	   [has_key](/crelude/Files/common_8h.md#function-has_key)(_map, &_key); })

define APPEND

#define APPEND(
    SELF,
    ELEM
)
[PUSH](/crelude/Files/common_8h.md#define-push)(SELF, ELEM)

define PREPEND

#define PREPEND(
    SELF,
    ELEM
)
[INSERT](/crelude/Files/common_8h.md#define-insert)(SELF, 0, ELEM)

define UNSHIFT

#define UNSHIFT(
    SELF,
    ELEM
)
[PREPEND](/crelude/Files/common_8h.md#define-prepend)(SELF, ELEM)

define PREFIX

#define PREFIX(
    SELF,
    SLIC
)
[SPLICE](/crelude/Files/common_8h.md#define-splice)(SELF, 0, SLIC)

define HEAD

#define HEAD(
    SELF,
    END
)
[SLICE](/crelude/Files/common_8h.md#define-slice)(SELF, 0, END)

define TAIL

#define TAIL(
    SELF,
    BEG
)
[SLICE](/crelude/Files/common_8h.md#define-slice)(SELF, BEG, -1)

define FIRST

#define FIRST(
    SELF
)
[NTH](/crelude/Files/common_8h.md#define-nth)(SELF, 0)

define LAST

#define LAST(
    SELF
)
[GET](/crelude/Files/common_8h.md#define-get)(SELF, -1)

define QSORT

#define QSORT(
    SELF,
    CMPR
)
	__extension__\
	({ __auto_type _self = (SELF); \
	   qsort([PTR](/crelude/Files/common_8h.md#define-ptr)(_self), [_self.len](/crelude/Files/base64_8h.md#variable-len), sizeof(*[_self.value](/crelude/Files/common_8h.md#variable-value)), CMPR); \
	   _self; })

Minimal helper/wrapper around in-place qsort for arrays/slices.

define SORT

#define SORT(
    SELF,
    SUBJ,
    OTHR,
    ...
)
	__extension__\
	({ int compar_fn_(const [u0](/crelude/Files/common_8h.md#typedef-u0) *SUBJ, const [u0](/crelude/Files/common_8h.md#typedef-u0) *OTHR) __VA_ARGS__ \
	   __auto_type _self = (SELF); \
	   qsort([PTR](/crelude/Files/common_8h.md#define-ptr)(_self), [_self.len](/crelude/Files/base64_8h.md#variable-len), sizeof(*[_self.value](/crelude/Files/common_8h.md#variable-value)), compar_fn_); \
	   _self; })

Wrapper around in-place qsort for arrays and slices. Creates a nested function within a statement-expression that is defined by the function body passed in as VA_ARGS to the macro, which defines the comparison function for the sort. This makes use of two GNU extensions: 'nested functions', and 'statement expressions'. e.g. SORT(arr, self, other, { if ((Struct *)self->x == (Struct *)other->x) return 0; if ((Struct *)self->x < (Struct *)other->x) return -1; if ((Struct *)self->x > (Struct *)other->x) return +1; }); SORT(arr, self, other, { return my_compare(self, other); }); SORT(arr, self, other, CMP((Struct *)self->x, (Struct *)other->x));

define CMP

#define CMP(
    A,
    B
)
	{ if ((A) <  (B)) return -1; \
	  if ((A) == (B)) return  0; \
	  if ((A) >  (B)) return +1; }

Function body for comparison of items which have '>', '=' and '<' defined, e.g. int comparef(float a, float b) CMP(a, b)

define ANSI

#define ANSI(
    CODE
)
"\x1b[" CODE "m"

define BOLD

#define BOLD "1"

define FAINT

#define FAINT "2"

define DIM

#define DIM [FAINT](/crelude/Files/common_8h.md#define-faint)

define ITALIC

#define ITALIC "3"

define UNDER

#define UNDER "4"
#define BLINK "5"

define RAPID

#define RAPID "6"

define INVERT

#define INVERT "7"

define HIDDEN

#define HIDDEN "8"

define STRIKE

#define STRIKE "9"

define BOLD_OFF

#define BOLD_OFF "21"

define FAINT_OFF

#define FAINT_OFF "22"

define ITALIC_OFF

#define ITALIC_OFF "23"

define UNDER_OFF

#define UNDER_OFF "24"
#define BLINK_OFF "25"

define RAPID_OFF

#define RAPID_OFF "26"

define INVERT_OFF

#define INVERT_OFF "27"

define HIDDEN_OFF

#define HIDDEN_OFF "28"

define STRIKE_OFF

#define STRIKE_OFF "29"

define RESET

#define RESET "0"

define min

#define min(
    A,
    B
)
	__extension__({ \
	typeof(A) _a = (A); \
	typeof(B) _b = (B); \
	_a > _b ? _b : _a; })

define max

#define max(
    A,
    B
)
	__extension__({ \
	typeof(A) _a = (A); \
	typeof(B) _b = (B); \
	_b > _a ? _b : _a; })

define deref

#define deref(
    T,
    PTR,
    ALT
)
	__extension__\
	({ T _alt = (ALT); \
	   *(T *)[or](/crelude/Files/common_8h.md#function-or)([PTR](/crelude/Files/common_8h.md#define-ptr), &_alt); })

define WRAP

#define WRAP(
    TYPE,
    VALUE
)
= ((TYPE){ .[value](/crelude/Files/common_8h.md#variable-value) = (VALUE) })

Wrap value in wrapper struct.

define UNWRAP

#define UNWRAP(
    STRUCTURE
)
(STRUCTURE).[value](/crelude/Files/common_8h.md#variable-value)

Unwraps pointer/value in sizing wrapper struct.

define PTR

#define PTR(
    ARR
)
(ARR).[value](/crelude/Files/common_8h.md#variable-value)

Explicitly only extract pointer from array/slice.

define FREE_INSIDE

#define FREE_INSIDE(
    S
)
[FREE](/crelude/Files/common_8h.md#define-free)((S).[value](/crelude/Files/common_8h.md#variable-value))

Call to free of inside of slice/array/newtype, etc.

define INIT

#define INIT(
    TYPE,
    ...
)
	{ \
	.[len](/crelude/Files/base64_8h.md#variable-len) = sizeof((TYPE[])__VA_ARGS__)/sizeof(TYPE), \
	.[value](/crelude/Files/common_8h.md#variable-value) = (TYPE[])__VA_ARGS__ \
}

Initialise sizing wrapper with literal.

define LIST

#define LIST(
    TYPE,
    ...
)
	__extension__({ \
	TYPE _slice; \
	typeof(*[_slice.value](/crelude/Files/common_8h.md#variable-value)) _elem; \
	static typeof(_elem) _list[] = __VA_ARGS__; \
	_slice = ((typeof(_slice)){ \
		.[len](/crelude/Files/base64_8h.md#variable-len) = sizeof(_list)/sizeof(_elem), \
		.[value](/crelude/Files/common_8h.md#variable-value) = _list \
	}); _slice; })

Can be used to make slices from literal arrays.

define STRING

#define STRING(
    ...
)
	{ \
	.[len](/crelude/Files/base64_8h.md#variable-len) = sizeof(([byte](/crelude/Files/common_8h.md#typedef-byte)[]){ __VA_ARGS__ }) - 1, \
	.[value](/crelude/Files/common_8h.md#variable-value) = ([byte](/crelude/Files/common_8h.md#typedef-byte)[]){ __VA_ARGS__ } \
}

Initialise sizing wrapper with of string literal.

define STR

#define STR(
    ...
)
(([string](/crelude/Classes/structstring.md))[STRING](/crelude/Files/common_8h.md#define-string)(__VA_ARGS__))

define SEMPTY

#define SEMPTY(
    TYPE
)
((TYPE){ .[len](/crelude/Files/base64_8h.md#variable-len) = 0, .[value](/crelude/Files/common_8h.md#variable-value) = [nil](/crelude/Files/common_8h.md#define-nil) })

Empty slice of certain type.

define AEMPTY

#define AEMPTY(
    TYPE
)
((TYPE){ .[len](/crelude/Files/base64_8h.md#variable-len) = 0, .cap = 0, .[value](/crelude/Files/common_8h.md#variable-value) = [nil](/crelude/Files/common_8h.md#define-nil) })

Empty array of certain type.

define EMPTY

#define EMPTY(
    TYPE
)
((TYPE){ 0 })

Empty / zero struct.

define IS_EMPTY

#define IS_EMPTY(
    ARR
)
((ARR).[len](/crelude/Files/base64_8h.md#variable-len) == 0)

Is array empty?

define AMAKE

#define AMAKE(
    TYPE,
    CAP
)
	{ \
	.[len](/crelude/Files/base64_8h.md#variable-len) = 0, \
	.cap = (CAP), \
	.[value](/crelude/Files/common_8h.md#variable-value) = [emalloc](/crelude/Files/common_8h.md#function-emalloc)((CAP), sizeof(TYPE)) \
}

Heap allocates a variable sized array.

define ANEW

#define ANEW(
    VARIABLE,
    CAP
)
(typeof(VARIABLE))[AMAKE](/crelude/Files/common_8h.md#define-amake)(typeof((VARIABLE).[value](/crelude/Files/common_8h.md#variable-value)[0]), CAP)

Create new array / initialise array from array variable.

define SMAKE

#define SMAKE(
    TYPE,
    LEN
)
	{ \
	.[len](/crelude/Files/base64_8h.md#variable-len) = (LEN), \
	.[value](/crelude/Files/common_8h.md#variable-value) = [emalloc](/crelude/Files/common_8h.md#function-emalloc)((LEN), sizeof(TYPE)) \
}

Heap allocates a constant sized slice type.

define SNEW

#define SNEW(
    VARIABLE,
    LEN
)
(typeof(VARIABLE))[SMAKE](/crelude/Files/common_8h.md#define-smake)(typeof((VARIABLE).[value](/crelude/Files/common_8h.md#variable-value)[0]), LEN)

Create new slice / initialise slice from slice variable.

define SLICE

#define SLICE(
    TYPE,
    OBJ,
    START,
    END
)
	((TYPE){ \
	.[len](/crelude/Files/base64_8h.md#variable-len) = ((([isize](/crelude/Files/common_8h.md#typedef-isize))(END) < 0) ? (OBJ).[len](/crelude/Files/base64_8h.md#variable-len) + 1 : 0) + (END) - (START), \
	.[value](/crelude/Files/common_8h.md#variable-value) = (OBJ).[value](/crelude/Files/common_8h.md#variable-value) + (START) \
})

Take a slice/substring/view of sized type.

define VIEW

#define VIEW(
    TYPE,
    PTR,
    START,
    END
)
	((TYPE){ \
	.[len](/crelude/Files/base64_8h.md#variable-len) = (END) - (START), \
	.[value](/crelude/Files/common_8h.md#variable-value) = ([PTR](/crelude/Files/common_8h.md#define-ptr)) + (START) \
})

Works like SLICE, but on a pointer instead of an array.

define SYMBOLIC

#define SYMBOLIC(
    STR
)
	(([symbol](/crelude/Classes/structsymbol.md)){ \
	.[hash](/crelude/Files/common_8h.md#variable-hash) = [hash_string](/crelude/Files/common_8h.md#function-hash_string)([STR](/crelude/Files/common_8h.md#define-str)), \
	.[value](/crelude/Files/common_8h.md#variable-value) = [STR](/crelude/Files/common_8h.md#define-str) \
})

define SYMBOL_LITERAL

#define SYMBOL_LITERAL(
    STR_LIT
)
	(([symbol](/crelude/Classes/structsymbol.md)){ \
	.[hash](/crelude/Files/common_8h.md#variable-hash) = [hash_string](/crelude/Files/common_8h.md#function-hash_string)([STRING](/crelude/Files/common_8h.md#define-string)(STR_LIT)), \
	.[value](/crelude/Files/common_8h.md#variable-value) = [STRING](/crelude/Files/common_8h.md#define-string)(STR_LIT) \
})

define ACOLLECT

#define ACOLLECT(
    T,
    count,
    pointer
)
	((T){ \
	.[len](/crelude/Files/base64_8h.md#variable-len) = count,     \
	.cap = count,     \
	.[value](/crelude/Files/common_8h.md#variable-value) = pointer, \
})

C array to dynamic array wrapper.

define SCOLLECT

#define SCOLLECT(
    T,
    count,
    pointer
)
	((T){ \
	.[len](/crelude/Files/base64_8h.md#variable-len) = count,     \
	.[value](/crelude/Files/common_8h.md#variable-value) = pointer, \
})

C array to slice wrapper.

define SMAP

#define SMAP(
    T,
    func,
    list
)
	__extension__({ \
	T _mapped; \
	_mapped = ((T)[SMAKE](/crelude/Files/common_8h.md#define-smake)(typeof(*[_mapped.value](/crelude/Files/common_8h.md#variable-value)), (list).[len](/crelude/Files/base64_8h.md#variable-len))); \
	for ([usize](/crelude/Files/common_8h.md#typedef-usize) _i = 0; _i < (list).[len](/crelude/Files/base64_8h.md#variable-len); ++_i) \
		[_mapped.value](/crelude/Files/common_8h.md#variable-value)[_i] = (func)((list).[value](/crelude/Files/common_8h.md#variable-value)[_i]); \
	_mapped; \
})

define AMAP

#define AMAP(
    T,
    func,
    list
)
	__extension__({ \
	T _mapped; \
	_mapped = ((T)[AMAKE](/crelude/Files/common_8h.md#define-amake)(typeof(*[_mapped.value](/crelude/Files/common_8h.md#variable-value)), (list).[len](/crelude/Files/base64_8h.md#variable-len))); \
	for ([usize](/crelude/Files/common_8h.md#typedef-usize) _i = 0; _i < (list).[len](/crelude/Files/base64_8h.md#variable-len); ++_i, ++[_mapped.len](/crelude/Files/base64_8h.md#variable-len)) \
		[_mapped.value](/crelude/Files/common_8h.md#variable-value)[_i] = (func)((list).[value](/crelude/Files/common_8h.md#variable-value)[_i]); \
	_mapped; \
})

define FOR_EACH

#define FOR_EACH(
    ELEM,
    ELEMS
)
	for (struct { typeof(*(ELEMS).[value](/crelude/Files/common_8h.md#variable-value)) item; \
			      typeof((ELEMS).[value](/crelude/Files/common_8h.md#variable-value)) ptr, start; \
				  [usize](/crelude/Files/common_8h.md#typedef-usize) index; \
				  bool first, once; \
				} it = { .item = *(ELEMS).[value](/crelude/Files/common_8h.md#variable-value), \
				         .ptr = (ELEMS).[value](/crelude/Files/common_8h.md#variable-value), \
				         .start = (ELEMS).[value](/crelude/Files/common_8h.md#variable-value), \
				         .index = 0, \
						 .first = true, \
						 .once = true \
				       }; it.once; it.once = false) \
		for (typeof(*(ELEMS).[value](/crelude/Files/common_8h.md#variable-value)) ELEM = *(ELEMS).[value](/crelude/Files/common_8h.md#variable-value); \
		    it.index < (ELEMS).[len](/crelude/Files/base64_8h.md#variable-len); \
			++it.ptr, it.index = (it.ptr - it.start), \
			  it.item = *it.ptr, it.first = false, ELEM = it.item)

For-each loop, iterates across an array or slice. It creates an it variable, that holds:

  • it.index (index in array);
  • it.item (current item of array);
  • it.ptr (pointer to current item in array);
  • it.first (pointer to frist item in array);
  • it.once (a bool, true if we are on the first iteration). For example:
newarray(IntArray, int);
IntArray xs = AMAKE(IntArray, 2);

int elem1 = 5;
int elem2 = 3;
sliceof(int) elems = INIT(int, { 6, 9, 1 });

push(&xs, &elem1, sizeof(int));
push(&xs, &elem2, sizeof(int));
extend(&xs, &elems, sizeof(int));

FOR_EACH(x, xs) {
    printf("xs[%zu] = %d\n", it.index, x);
}

Filename: .c

Will print:

xs[0] = 5
xs[1] = 3
xs[2] = 6
xs[3] = 9
xs[4] = 1

define foreach

#define foreach [FOR_EACH](/crelude/Files/common_8h.md#define-for_each)

Source code


#ifndef COMMON_HEADER_
#define COMMON_HEADER_

#undef  _GNU_SOURCE
#define _GNU_SOURCE 1 

#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <stdarg.h>
#include <limits.h>
#include <string.h>
#include <assert.h>
#ifdef __linux__
    #include <unistd.h>
#endif

/* Default macros */
#ifndef FREE
    #define FREE free
#endif
#ifndef MALLOC
    #define MALLOC malloc
#endif
#ifndef REALLOC
    #define REALLOC realloc
#endif

/* Misc macros */
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5, N,...) N
#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1)

#define _TSTR(x) #x
#define TSTR(x) _TSTR(x)

#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
    #define DO_PRAGMA(x) __pragma(x)
    #define PRAGMA_NO_WARNING __pragma(warning(push, 0))
    #define PRAGMA_POP_WARNING __pragma(warning(pop))
    #define WARNING(...) __pragma(message(Warning: __VA_ARGS__))
#elif defined(__clang__)
    #define DO_PRAGMA(x) _Pragma(#x)
    #define PRAGMA_NO_WARNING \
        _Pragma("clang diagnostic push") \
        _Pragma("clang diagnostic ignored \"-Wall\"") \
        _Pragma("clang diagnostic ignored \"-Wextra\"") \
        _Pragma("clang diagnostic ignored \"-Wpedantic\"")
    #define PRAGMA_POP_WARNING _Pragma("clang diagnostic pop")
    #define WARNING(S) DO_PRAGMA(clang warning S)
#elif defined(__GNUC__)
    #define DO_PRAGMA(x) _Pragma(#x)
    // Does not behave as nicely as CLANG version does.
    #define PRAGMA_NO_WARNING \
        _Pragma("GCC diagnostic push") \
        _Pragma("GCC diagnostic ignored \"-Wall\"") \
        _Pragma("GCC diagnostic ignored \"-Wextra\"") \
        _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
    #define PRAGMA_POP_WARNING _Pragma("GCC diagnostic pop")
    #define WARNING(S) DO_PRAGMA(GCC warning S)
#endif

#define TODO(...) DO_PRAGMA(message("TODO: " #__VA_ARGS__ \
                            " (" __FILE__ ":" TSTR(__LINE__)")"))

/* Version number */
#define crelude_V_MAJOR 0
#define crelude_V_MINOR 1
#define crelude_V_PATCH 0

#define crelude_VERSION \
    "v" TSTR(crelude_V_MAJOR) \
    "." TSTR(crelude_V_MINOR) \
    "." TSTR(crelude_V_PATCH)

#define ARRAY_REALLOC_FACTOR 1.5

/* Syntax helpers */
#define loop while (1)
#define whilst while
#define unless(cond) if (!(cond))
#define never if (0)
#define always if (1)
#define until(cond) while (!(cond))
// Newtypes and arrays, slices, maps, etc.
#define unqualify(D, T)  typedef D T T
#define record(NAME)     typedef struct _##NAME NAME; struct _##NAME
#define enumerable(NAME) typedef   enum _##NAME NAME;   enum _##NAME
#define overlap(NAME)    typedef  union _##NAME NAME;  union _##NAME
#define newtype(NT, T) typedef struct _##NT { T value; } NT
#define arrayof(T) struct { \
    T (*value); \
    usize len;  \
    usize cap;  \
}
#define newarray(NT, T) typedef arrayof(T) NT
#define sliceof(T) struct { \
    T (*value); \
    usize len;  \
}
#define newslice(NT, T) typedef sliceof(T) NT
#define hashof(T) struct { \
    u64 hash; \
    T value;  \
}
#define newhashable(NT, T) typedef hashof(T) NT
enum HashKeyType {  // Use this to pick a default hash method/function.
    HKT_STRING  = 1 << 0,
    HKT_RUNIC   = 1 << 1,
    HKT_CSTRING = 1 << 2,
    HKT_MEM_SLICE = 1 << 3, //< can be used for any slice, convert with TO_BYTES(...).
    HKT_RAW_BYTES = 1 << 4,  //< just hash the raw bytes.
    HKT_SMALL_INTEGER = 1 << 5  //< integer size ≤ than hash size, just upcast.
}; unqualify(enum, HashKeyType);
#define HASHMAP_LOAD_THRESHOLD 0.85
#define HASHMAP_GROWTH_FACTOR  2
#define newmap(NT, K, V) typedef mapof(K, V) NT
#define mapof(K, V) struct { \
    usize len; \
    arrayof(hashnode(K, V)) buckets; /* a hash value of zero indicates absence. */\
    usize value_size; \
    usize   key_size; \
    usize  node_size; \
    /* offsets of `hashnode` struct. */ \
    usize  hash_offset; \
    usize   key_offset; \
    usize value_offset; \
    usize  next_offset; \
    HashKeyType key_type; /* < how should the hash-function hash the key. */ \
    u64 (*hasher)(const u0 *, usize); \
}
#define hashnode(K, V) struct { \
    hashof(K) key; \
    V value;  /* < value stored.   */ \
    u0 *next; /* < next hash-node. */ \
}
#define MMAKE(K, V, CAP) { \
    .len = 0, \
    .buckets = AMAKE(hashnode(K, V), CAP), \
    .key_size = sizeof(K), \
    .value_size = sizeof(V), \
    .node_size = sizeof(hashnode(K, V)), \
    .hash_offset  = offsetof(hashnode(K, V), key) + offsetof(hashof(K), hash), \
    .key_offset   = offsetof(hashnode(K, V), key) + offsetof(hashof(K), value), \
    .value_offset = offsetof(hashnode(K, V), value), \
    .next_offset  = offsetof(hashnode(K, V), next), \
    .key_type = _Generic(*(K *)NULL, \
        string: HKT_STRING, \
        runic: HKT_RUNIC, \
        byte *: HKT_CSTRING, \
        MemSlice: HKT_MEM_SLICE, \
        char[8]: HKT_SMALL_INTEGER, \
        char[7]: HKT_SMALL_INTEGER, \
        char[6]: HKT_SMALL_INTEGER, \
        char[5]: HKT_SMALL_INTEGER, \
        char[4]: HKT_SMALL_INTEGER, \
        char[3]: HKT_SMALL_INTEGER, \
        char[2]: HKT_SMALL_INTEGER, \
        char[1]: HKT_SMALL_INTEGER, \
        signed char:        HKT_SMALL_INTEGER, \
        signed short:       HKT_SMALL_INTEGER, \
        signed int:         HKT_SMALL_INTEGER, \
        signed long:        HKT_SMALL_INTEGER, \
        signed long long:   HKT_SMALL_INTEGER, \
        unsigned char:      HKT_SMALL_INTEGER, \
        unsigned short:     HKT_SMALL_INTEGER, \
        unsigned int:       HKT_SMALL_INTEGER, \
        unsigned long:      HKT_SMALL_INTEGER, \
        unsigned long long: HKT_SMALL_INTEGER, \
        float:  HKT_SMALL_INTEGER, \
        double: HKT_SMALL_INTEGER, \
        default: HKT_RAW_BYTES), \
    .hasher = _Generic(*(K *)NULL, \
        string: string_hash, \
        runic: runic_hash, \
        byte *: cstring_hash, \
        MemSlice: mem_hash, \
        char[8]: upcast_hash, \
        char[7]: upcast_hash, \
        char[6]: upcast_hash, \
        char[5]: upcast_hash, \
        char[4]: upcast_hash, \
        char[3]: upcast_hash, \
        char[2]: upcast_hash, \
        char[1]: upcast_hash, \
        signed char:        upcast_hash, \
        signed short:       upcast_hash, \
        signed int:         upcast_hash, \
        signed long:        upcast_hash, \
        signed long long:   upcast_hash, \
        unsigned char:      upcast_hash, \
        unsigned short:     upcast_hash, \
        unsigned int:       upcast_hash, \
        unsigned long:      upcast_hash, \
        unsigned long long: upcast_hash, \
        float:  upcast_hash, \
        double: upcast_hash, \
        default: default_hash) \
}
#define MNEW(VARIABLE, CAP) (typeof(VARIABLE))MMAKE( \
    typeof((VARIABLE).buckets.value[0].key.value), \
    typeof((VARIABLE).buckets.value[0].value), \
    CAP)

#define NTH(LIST, N) UNWRAP((LIST))[(N)]
#define GET(LIST, N) __extension__\
    ({ __auto_type _list = (LIST); \
       __auto_type _n = (N); \
       usize _index = _n < 0 ? (usize)(_list.len + _n) : (usize)_n; \
       UNWRAP(_list)[_index]; })
#define SET(LIST, N, V) __extension__\
    ({ __auto_type _list = (LIST); \
       __auto_type _n = (N); \
       usize _index = _n < 0 ? (usize)(_list.len + _n) : (usize)_n; \
       UNWRAP(_list)[_index] = (V); })

#define UNUSED1(z) (void)(z)
#define UNUSED2(y,z) UNUSED1(y),UNUSED1(z)
#define UNUSED3(x,y,z) UNUSED1(x),UNUSED2(y,z)
#define UNUSED4(b,x,y,z) UNUSED2(b,x),UNUSED2(y,z)
#define UNUSED5(a,b,x,y,z) UNUSED2(a,b),UNUSED3(x,y,z)
#define UNUSED_IMPL_(nargs) UNUSED ## nargs
#define UNUSED_IMPL(nargs) UNUSED_IMPL_(nargs)
#define UNUSED(...) UNUSED_IMPL(VA_NUM_ARGS(__VA_ARGS__))(__VA_ARGS__)

#define NO_ERROR EXIT_SUCCESS
#define OK EXIT_SUCCESS
#define OKAY EXIT_SUCCESS
#define FAIL EXIT_FAILURE

#define NOOP ((void)0)
#define nil ((void *)NULL)

#define FLOOR(T, N) __extension__\
    ({ typeof(N) _n = (N); \
       (T)_n - (_n < 0 ? 1 : 0); })
#define CEIL(T, N) __extension__\
    ({ typeof(N) _n = (N); \
       (T)_n + (_n < 0 ? 0 : 1); })

/* Types */
newtype(atomic_t, int);

typedef void u0;
#define UNIT ;

typedef   signed int ierr;
typedef unsigned int uerr;  
typedef unsigned long uword;  
typedef   signed long iword;  
#define WORD_SIZE sizeof(long)

typedef unsigned int ufast;
typedef   signed int ifast;

typedef ptrdiff_t isize;
typedef    size_t usize; 

typedef  intptr_t iptr;
typedef uintptr_t uptr; 

typedef  intmax_t imax;
typedef uintmax_t umax;

typedef unsigned char umin;
typedef   signed char imin;

_Static_assert(sizeof(umin) == 1 && sizeof(imin) == 1,
               "`umin` and `imin` must have size one (1).");

#define __UCHAR8__ char
#if (CHAR_BIT == 8)
    typedef   signed char i8;
    typedef unsigned char u8;

    #if (CHAR_MIN < 0)
        WARNING("Crelude works best with -funsigned-char.")
        #undef  __UCHAR8__
        #define __UCHAR8__ unsigned char
    #endif
#else
    typedef  __int8_t i8;
    typedef __uint8_t u8;

    #undef  __UCHAR8__
    #define __UCHAR8__ __uint8_t;
#endif

#ifndef IMPLEMENTATION
    typedef __UCHAR8__ byte;
#else
    typedef __uint8_t byte;  
#endif

typedef  __int16_t i16;
typedef __uint16_t u16;

typedef  __int32_t i32;
typedef __uint32_t u32;

typedef u32 rune;

#if (__LONG_WIDTH__ == 64)
    typedef   signed long i64;
    typedef unsigned long u64;
#elif (__LONG_LONG_WIDTH__ == 64)
    typedef   signed long long i64;
    typedef unsigned long long u64;
#else
    typedef  __int64_t i64;
    typedef __uint64_t u64;
#endif

#ifdef __SIZEOF_INT128__
    typedef  __int128_t i128;
    typedef __uint128_t u128;
#endif

#define   _FLOAT_BIT (__SIZEOF_FLOAT__       * CHAR_BIT)
#define  _DOUBLE_BIT (__SIZEOF_DOUBLE__      * CHAR_BIT)
#define _LDOUBLE_BIT (__SIZEOF_LONG_DOUBLE__ * CHAR_BIT)

#ifdef __STDC_IEC_559__
    typedef  float f32;
    typedef double f64;
#else
    #if _FLOAT_BIT == 32
        typedef float f32;
    #endif
    #if _DOUBLE_BIT == 64
        typedef double f64;
    #endif
#endif

#if (_LDOUBLE_BIT == 80)
    typedef long double f80;
#elif (_LDOUBLE_BIT == 128)
    typedef long double f128;
#endif

newarray(GenericArray, u0);
newarray(MemArray, umin);
newslice(GenericSlice, u0);
newslice(MemSlice, umin);
newmap(GenericMap, u0 *, u0 *);

newslice(string, byte);
newslice(runic, rune);

newarray(StringBuilder, byte);
newarray(RunicBuilder, rune);

newhashable(symbol, string);

/* Common Constants */
static const ierr NUL = 0;
static const byte NUL_BYTE = '\0';
static const string NUL_STRING = { .len = 0, .value = (byte *)&NUL_BYTE };
static const iword ZERO = 0;

/* Common Functions */
extern u0 panic(const byte *, ...) __attribute__((noreturn));
extern u0 *or(const u0 *nullable, const u0 *nonnull);
extern bool is_zero(imax);
extern bool is_zerof(f64);
extern bool is_zeroed(u0 *, usize);
extern u0 zero(u0 *blk, usize width);
extern u0 *emalloc(usize, usize);
extern u0 reverse(u0 *self, usize width);
extern MemSlice reverse_endianness(MemSlice bytes);
bool is_little_endian(void);
u128 big_endian(umin *start, usize bytes);
extern u0 swap(u0 *self, usize pivot, usize width);
extern u0 memswap(umin *a, umin *b, usize bytes);
extern usize resize(u0 *self, usize cap, usize width);
extern usize grow(u0 *self, usize count, usize width);
extern u0 *get(u0 *self, usize index, usize width);
extern u0 *set(u0 *self, usize index, const u0 *elem, usize width);
extern usize push(u0 *self, const u0 *element, usize width);
extern u0 *pop(u0 *self, usize width);
extern u0 *shift(u0 *self, usize width);
extern usize insert(u0 *self, usize index, const u0 *element, usize width);
extern usize extend(u0 *self, const u0 *slice, usize width);
extern usize splice(u0 *self, usize index, const u0 *slice, usize width);
//           along with the number of removed bytes (`len` of slice).
extern GenericSlice cut(u0 *self, usize from, isize upto, usize width);
extern usize null(u0 *self, usize width);
extern string from_cstring(const byte *);
extern bool string_eq(const string, const string);
extern i16 string_cmp(const string, const string);
extern i16 string_ncmp(const string, const string, usize n);
extern u64 hash_string(const string);
extern u64 hash_bytes(const MemSlice);
extern u0 associate(u0 *self, const u0 *key, const u0 *value);
extern u0 *lookup(u0 *self, const u0 *key);
extern bool drop(u0 *self, const u0 *key);
extern GenericSlice get_keys(u0 *self);
extern bool has_key(u0 *self, u0 *key);
extern u0 empty_map(u0 *self);
extern bool is_empty_map(u0 *self);
extern u0 free_map(u0 *self);
extern usize init_hashnode(u0 *, const u0 *, u64, const u0 *, const u0 *);
extern u0 dump_hashmap(u0 *self, byte *key_formatter, byte *value_formatter);

/* Common Macros */

#define COPY(SELF) __extension__\
    ({ __auto_type _self = (SELF); \
       __auto_type _copy = _self; \
       PTR(_copy) = emalloc(_self.len, sizeof(*PTR(_self))); \
       memcpy(PTR(_copy), PTR(_self), sizeof(*PTR(_copy)) * _copy.len); \
       _copy; })

#define TO_BYTES(SELF) __extension__\
    ({ __auto_type _self = (SELF); \
       MemSlice _bytes = { \
          .len = _self.len * sizeof(*_self.value), \
          .value = (umin *)_self.value \
       }; _bytes; })

#define FROM_BYTES(T, SELF) __extension__\
    ({ __auto_type _self = (SELF); \
       T _normal = { \
          .len = _self.len / sizeof(*_self.value), \
          .value = (u0 *)_self.value \
       }; _normal; })

// ---
// Macros for array functions to avoid use of `sizeof(T)` everywhere.
// These macros do the referencing and void-pointer casting for you, and thus
// let you use non-LVALUES as input (except SELF, SELF must sill be an LVALUE).
// ---

#define REVERSE(SELF) __extension__\
    ({ __auto_type _self = &(SELF); \
       reverse(_self, sizeof(*_self->value)); \
       *_self; })

#define SWAP(SELF, PIVOT) __extension__\
    ({ __auto_type _self = &(SELF); \
       swap(_self, (PIVOT), sizeof(*_self->value)); })

#define PUSH(SELF, ELEM) __extension__\
    ({ __auto_type           _self = &(SELF); \
       typeof(*_self->value) _elem =  (ELEM); \
       push(_self, &_elem, sizeof(_elem)); })

#define POP(SELF) __extension__\
    ({ __auto_type _self = &(SELF); \
       (typeof(_self->value))pop(_self, sizeof(*_self->value)); })

#define SHIFT(SELF) __extension__\
    ({ __auto_type _self = &(SELF); \
       (typeof(_self->value))shift(_self, sizeof(*_self->value)); })

#define INSERT(SELF, INDEX, ELEM) __extension__\
    ({ __auto_type           _self = &(SELF); \
       typeof(*_self->value) _elem =  (ELEM); \
       insert(_self, (INDEX), &_elem, sizeof(_elem)); })

#define EXTEND(SELF, SLIC) __extension__\
    ({ __auto_type _self = &(SELF); \
       __auto_type _slic =  (SLIC); \
       extend(_self, &_slic, sizeof(*_slic.value)); })

#define SPLICE(SELF, INDEX, SLIC) __extension__\
    ({ __auto_type _self = &(SELF); \
       __auto_type _slic =  (SLIC); \
       splice(_self, (INDEX), &_slic, sizeof(*_slic.value)); })

#define CUT(SELF, FROM, UPTO) __extension__\
    ({ __auto_type _self = &(SELF); \
       static GenericSlice _cut; \
       _cut = cut(_self, (FROM), (UPTO), sizeof(*_self->value)); \
       (u0 *)&_cut; })

#define REMOVE(SELF, INDEX) __extension__\
    ({ __auto_type _self = &(SELF); \
       usize _indx = (INDEX); \
       GenericSlice _cut \
           = cut(_self, _indx, _indx, sizeof(*_self->value)); \
       (typeof(_self->value))PTR(_cut); })

/* macros for hash-tables (maps) */
#define ASSOCIATE(SELF, KEY, VAL) __extension__\
    ({ __auto_type _self = &(SELF); \
       __auto_type _key = (KEY); \
       __auto_type _val = (VAL); \
       associate(_self, &_key, &_val); })

#define LOOKUP(SELF, KEY) __extension__\
    ({ __auto_type _self = &(SELF); \
       __auto_type _key = (KEY); \
       (typeof(_self->buckets.value[0].value) *)lookup(_self, &_key); })

#define DROP(SELF, KEY) __extension__\
    ({ __auto_type _self = &(SELF); \
       __auto_type _key = (KEY); \
       drop(_self, &_key); })

#define KEYS(MAP) __extension__\
    ({ __auto_type _map = &(MAP); \
       static GenericSlice _keys; \
       _keys = get_keys(_map); \
       (u0 *)&_keys; })

#define HAS_KEY(MAP, KEY) __extension__\
    ({ __auto_type _map = &(MAP); \
       __auto_type _key = (KEY); \
       has_key(_map, &_key); })

// Some aliases and shortcuts:
#define APPEND(SELF, ELEM) PUSH(SELF, ELEM)
#define PREPEND(SELF, ELEM) INSERT(SELF, 0, ELEM)
#define UNSHIFT(SELF, ELEM) PREPEND(SELF, ELEM)
#define PREFIX(SELF, SLIC) SPLICE(SELF, 0, SLIC)
#define HEAD(SELF, END) SLICE(SELF, 0, END)
#define TAIL(SELF, BEG) SLICE(SELF, BEG, -1)
#define FIRST(SELF) NTH(SELF, 0)
#define LAST(SELF) GET(SELF, -1)

#define QSORT(SELF, CMPR) __extension__\
    ({ __auto_type _self = (SELF); \
       qsort(PTR(_self), _self.len, sizeof(*_self.value), CMPR); \
       _self; })

#define SORT(SELF, SUBJ, OTHR, ...) __extension__\
    ({ int compar_fn_(const u0 *SUBJ, const u0 *OTHR) __VA_ARGS__ \
       __auto_type _self = (SELF); \
       qsort(PTR(_self), _self.len, sizeof(*_self.value), compar_fn_); \
       _self; })

#define CMP(A, B) \
    { if ((A) <  (B)) return -1; \
      if ((A) == (B)) return  0; \
      if ((A) >  (B)) return +1; }

// --- ANSI colour codes. ---

#define ANSI(CODE) "\x1b[" CODE "m"
#define BOLD   "1"
#define FAINT  "2"
#define DIM FAINT
#define ITALIC "3"
#define UNDER  "4"
#define BLINK  "5"
#define RAPID  "6"
#define INVERT "7"
#define HIDDEN "8"
#define STRIKE "9"
#define BOLD_OFF   "21"  // Or sometimes, double-underline...
#define FAINT_OFF  "22"
#define ITALIC_OFF "23"
#define UNDER_OFF  "24"
#define BLINK_OFF  "25"
#define RAPID_OFF  "26"
#define INVERT_OFF "27"
#define HIDDEN_OFF "28"
#define STRIKE_OFF "29"
#define RESET "0"

#define min(A, B) __extension__({ \
    typeof(A) _a = (A); \
    typeof(B) _b = (B); \
    _a > _b ? _b : _a; })
#define max(A, B) __extension__({ \
    typeof(A) _a = (A); \
    typeof(B) _b = (B); \
    _b > _a ? _b : _a; })

#define deref(T, PTR, ALT) __extension__\
    ({ T _alt = (ALT); \
       *(T *)or(PTR, &_alt); })

#define WRAP(TYPE, VALUE) = ((TYPE){ .value = (VALUE) })
#define UNWRAP(STRUCTURE) (STRUCTURE).value
#define PTR(ARR) (ARR).value
#define FREE_INSIDE(S) FREE((S).value)
#define INIT(TYPE, ...) { \
    .len = sizeof((TYPE[])__VA_ARGS__)/sizeof(TYPE), \
    .value = (TYPE[])__VA_ARGS__ \
}
#define LIST(TYPE, ...) __extension__({ \
    TYPE _slice; \
    typeof(*_slice.value) _elem; \
    static typeof(_elem) _list[] = __VA_ARGS__; \
    _slice = ((typeof(_slice)){ \
        .len = sizeof(_list)/sizeof(_elem), \
        .value = _list \
    }); _slice; })

#define STRING(...) { \
    .len = sizeof((byte[]){ __VA_ARGS__ }) - 1, \
    .value = (byte[]){ __VA_ARGS__ } \
}

#define STR(...) ((string)STRING(__VA_ARGS__))

#define SEMPTY(TYPE) ((TYPE){ .len = 0, .value = nil })
#define AEMPTY(TYPE) ((TYPE){ .len = 0, .cap = 0, .value = nil })
#define EMPTY(TYPE) ((TYPE){ 0 })

#define IS_EMPTY(ARR) ((ARR).len == 0)

#define AMAKE(TYPE, CAP) { \
    .len = 0, \
    .cap = (CAP), \
    .value = emalloc((CAP), sizeof(TYPE)) \
}
#define ANEW(VARIABLE, CAP) (typeof(VARIABLE))AMAKE(typeof((VARIABLE).value[0]), CAP)

#define SMAKE(TYPE, LEN) { \
    .len = (LEN), \
    .value = emalloc((LEN), sizeof(TYPE)) \
}
#define SNEW(VARIABLE, LEN) (typeof(VARIABLE))SMAKE(typeof((VARIABLE).value[0]), LEN)

#define SLICE(TYPE, OBJ, START, END) ((TYPE){ \
    .len = (((isize)(END) < 0) ? (OBJ).len + 1 : 0) + (END) - (START), \
    .value = (OBJ).value + (START) \
})

#define VIEW(TYPE, PTR, START, END) ((TYPE){ \
    .len = (END) - (START), \
    .value = (PTR) + (START) \
})

#define SYMBOLIC(STR) ((symbol){ \
    .hash = hash_string(STR), \
    .value = STR \
})

#define SYMBOL_LITERAL(STR_LIT) ((symbol){ \
    .hash = hash_string(STRING(STR_LIT)), \
    .value = STRING(STR_LIT) \
})

#define ACOLLECT(T, count, pointer) ((T){ \
    .len = count,     \
    .cap = count,     \
    .value = pointer, \
})

#define SCOLLECT(T, count, pointer) ((T){ \
    .len = count,     \
    .value = pointer, \
})

#define SMAP(T, func, list) __extension__({ \
    T _mapped; \
    _mapped = ((T)SMAKE(typeof(*_mapped.value), (list).len)); \
    for (usize _i = 0; _i < (list).len; ++_i) \
        _mapped.value[_i] = (func)((list).value[_i]); \
    _mapped; \
})

#define AMAP(T, func, list) __extension__({ \
    T _mapped; \
    _mapped = ((T)AMAKE(typeof(*_mapped.value), (list).len)); \
    for (usize _i = 0; _i < (list).len; ++_i, ++_mapped.len) \
        _mapped.value[_i] = (func)((list).value[_i]); \
    _mapped; \
})

#define FOR_EACH(ELEM, ELEMS) \
    for (struct { typeof(*(ELEMS).value) item; \
                  typeof((ELEMS).value) ptr, start; \
                  usize index; \
                  bool first, once; \
                } it = { .item = *(ELEMS).value, \
                         .ptr = (ELEMS).value, \
                         .start = (ELEMS).value, \
                         .index = 0, \
                         .first = true, \
                         .once = true \
                       }; it.once; it.once = false) \
        for (typeof(*(ELEMS).value) ELEM = *(ELEMS).value; \
            it.index < (ELEMS).len; \
            ++it.ptr, it.index = (it.ptr - it.start), \
              it.item = *it.ptr, it.first = false, ELEM = it.item)

#define foreach FOR_EACH

/* static functions */
/* |- default hash functions */

 __attribute__((unused))
static u64 string_hash(const u0 *key, usize _)
{
    UNUSED(_);
    return hash_string(*(string *)key);
}

 __attribute__((unused))
static u64 runic_hash(const u0 *key, usize _)
{
    UNUSED(_);
    runic runes = *(runic *)key;
    return hash_bytes(TO_BYTES(runes));
}

 __attribute__((unused))
static u64 mem_hash(const u0 *key, usize _)
{
    UNUSED(_);
    return hash_bytes(*(MemSlice *)key);
}

 __attribute__((unused))
static u64 upcast_hash(const u0 *key, usize size)
{
    u64 hash = 0;
    memcpy(&hash, key, size);
    return hash;  // no hashing, just cast the key to a u64.
}

 __attribute__((unused))
static u64 cstring_hash(const u0 *key, usize _)
{
    UNUSED(_);
    return hash_string(from_cstring(*(byte **)key));
}

 __attribute__((unused))
static u64 default_hash(const u0 *key, usize size)
{  // just hashes the plain raw bytes.
    return hash_bytes(VIEW(MemSlice, (umin *)key, 0, size));
}

/* Only define a `main` if ENTRY_FUNCTION is defined */
#ifdef ENTRY_FUNCTION
    newslice(Arguments, string);
    newslice(CArguments, const char *);

    ierr (ENTRY_FUNCTION)(Arguments);

    ierr main(ifast argc, const char **argv)
    {
        Arguments args;
        ierr res;

        args = SMAP(Arguments,
            from_cstring, SCOLLECT(CArguments, argc, argv));
        res = (ENTRY_FUNCTION)(args);

        free(UNWRAP(args));
        return res;
    }
#endif

#endif

Updated on 23 August 2022 at 00:54:19 UTC