title: src/crelude/common.h
src/crelude/common.h
Classes
Name | |
---|---|
struct | _atomic_t Useful for resource counting etc. |
struct | GenericArray Array with pointer to void. |
struct | MemArray Array with pointer type to smallest addressable units of memory. |
struct | GenericSlice Slice with pointer to void. |
struct | MemSlice Slice with pointer type to smallest addressable units of memory. |
struct | GenericMap Hash-table that maps void * to void * . |
struct | string Immutable wrapper for UTF-8 encoded string (bytes are mutable). |
struct | runic Imutable warpper for UCS-4/UTF-32 encoded runic string (runes are mutable). |
struct | StringBuilder Mutable string which is built/pushed-to over time. |
struct | RunicBuilder Mutable runic string which is built/pushed-to over time. |
struct | symbol Symbols are interned strings. |
Types
Name | |
---|---|
enum | HashKeyType { 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 HashKeyType | HashKeyType |
typedef struct _atomic_t | atomic_t Useful for resource counting etc. |
typedef void | u0 |
typedef signed int | ierr |
typedef unsigned int | uerr |
typedef unsigned long | uword long is always the same size as a machine word. |
typedef signed long | iword |
typedef unsigned int | ufast |
typedef signed int | ifast |
typedef ptrdiff_t | isize |
typedef size_t | usize Use for storing array indices or object sizes. |
typedef intptr_t | iptr |
typedef uintptr_t | uptr Large enough to store a pointer, like (void *). |
typedef intmax_t | imax |
typedef uintmax_t | umax |
typedef unsigned char | umin Such that sizeof(umin) == 1 . |
typedef signed char | imin Such that sizeof(imin) == 1 . |
typedef __int8_t | i8 |
typedef __uint8_t | u8 |
typedef __uint8_t | byte Don't use char when you want byte . |
typedef __int16_t | i16 |
typedef __uint16_t | u16 |
typedef __int32_t | i32 |
typedef __uint32_t | u32 |
typedef u32 | rune |
typedef __int64_t | i64 |
typedef __uint64_t | u64 |
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)." ) | |
u0 | panic(const byte * , ... ) |
u0 * | or(const u0 * nullable, const u0 * nonnull) |
bool | is_zero(imax ) |
bool | is_zerof(f64 ) |
bool | is_zeroed(u0 * , usize ) |
u0 | zero(u0 * blk, usize width) |
u0 * | emalloc(usize , usize ) Malloc with zeros, and panics when out of memory. |
u0 | reverse(u0 * self, usize width) |
MemSlice | reverse_endianness(MemSlice bytes) |
bool | is_little_endian(void ) |
u128 | big_endian(umin * start, usize bytes) Read big-endian integer. |
u0 | swap(u0 * self, usize pivot, usize width) |
u0 | memswap(umin * a, umin * b, usize bytes) |
usize | resize(u0 * self, usize cap, usize width) |
usize | grow(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) |
usize | push(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. |
usize | insert(u0 * self, usize index, const u0 * element, usize width) |
usize | extend(u0 * self, const u0 * slice, usize width) |
usize | splice(u0 * self, usize index, const u0 * slice, usize width) |
GenericSlice | cut(u0 * self, usize from, isize upto, usize width) |
usize | null(u0 * self, usize width) |
string | from_cstring(const byte * ) NUL-terminated string to library string. |
bool | string_eq(const string, const string) Compare two strings for equality. |
i16 | string_cmp(const string, const string) Compare two strings for alphabetic rank. |
i16 | string_ncmp(const string, const string, usize n) Compare two strings for alphabetic rank upto a given number of bytes. |
u64 | hash_string(const string) Hash a string. |
u64 | hash_bytes(const MemSlice) Hash a byte slice. |
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. |
u0 * | lookup(u0 * self, const u0 * key) Look-up / get value from hash-map/table given the key. |
bool | drop(u0 * self, const u0 * key) |
GenericSlice | get_keys(u0 * self) |
bool | has_key(u0 * self, u0 * key) Checks if entry / key-value pair is present in hash-table/map given a key. |
u0 | empty_map(u0 * self) |
bool | is_empty_map(u0 * self) Checks if the hash-table / map is empty or freed. |
u0 | free_map(u0 * self) |
usize | init_hashnode(u0 * , const u0 * , u64 , const u0 * , const u0 * ) Internal use 99% of the time. |
u0 | dump_hashmap(u0 * self, byte * key_formatter, byte * value_formatter) Hashmap debugging function. |
attribute((unused) ) const | |
return | hash_bytes(extension({ __auto_type _self=(runes);MemSlice _bytes={ .len=_self.len sizeof(_self.value),.value=(umin *) _self.value };_bytes;}) ) |
return | hash_string(from_cstring(*(byte **) key) ) |
Attributes
Name | |
---|---|
u64 | hash |
u0 * | value |
struct @21 | key |
u0 * | next |
const ierr | NUL |
const byte | NUL_BYTE |
const string | NUL_STRING |
const iword | ZERO |
usize | _ |
runic | runes |
usize | size |
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
Enumerator | Value | Description |
---|---|---|
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 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)
whereT
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 forb
. - b Block of memory
b
, to be swapped fora
. - bytes The common size of block
a
andb
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)
whereT
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)
whereT
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)
whereT
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
#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
#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