Skip to content

Repository files navigation

CCTL : C Template Library

How to use

test.h

#include "cctl/vector.h"

vector_fd(int);
vector_imp_h(int);

main.c

#include <stdio.h>
#include "test.h"

vector_imp_c(int);

int main(void) {
	// Value-returning constructor & from_items
	vector(int) v = vector_from_items(int, 10, 20, 30);
	vector_extend_items(int, &v, 40, 50);

	for (size_t i = 0; i < vector_size(int, &v); i++) {
		printf("%d\n", *vector_at(int, &v, i));
	}

	vector_foreach(int, &v, it) {
		printf("%d\n", *vector_iterator_get(int, &it));
	}

	vector_free(int, &v);
	
	return 0;
}

Data Structures

vector(T)

Dynamic array

  • cctl/vector.h

  • vector(T)T_vector

  • vector_iterator(T)T_vector_iterator

  • void vector_init(T, vector(T)* p_v)

  • vector(T) vector_new(T, [size_t size])

  • vector(T) vector_from_items(T, ...)

  • bool vector_extend_items(T, vector(T)* p_v, ...)

  • void vector_free(T, vector(T)* p_v)

  • void vector_clear(T, vector(T)* p_v)

  • bool vector_reserve(T, vector(T)* p_v, size_t capacity)

  • bool vector_resize(T, vector(T)* p_v, size_t size)

  • bool vector_shrink_to_fit(T, vector(T)* p_v)

  • bool vector_is_empty(T, vector(T)* p_v)

  • size_t vector_size(T, vector(T)* p_v)

  • size_t vector_capacity(T, vector(T)* p_v)

  • bool vector_push_back(T, vector(T)* p_v, T item)

  • bool vector_pop_back(T, vector(T)* p_v)

  • bool vector_swap_remove(T, vector(T)* p_v, size_t index)

  • T* vector_at(T, vector(T)* p_v, size_t index)

  • T* vector_front(T, vector(T)* p_v)

  • T* vector_back(T, vector(T)* p_v)

  • vector_iterator(T) vector_begin(T, vector(T)* p_v)

  • vector_iterator(T) vector_end(T, vector(T)* p_v)

  • vector_iterator(T) vector_rbegin(T, vector(T)* p_v)

  • vector_iterator(T) vector_rend(T, vector(T)* p_v)

  • vector_iterator(T) vector_seek(T, vector(T)* p_v, size_t index)

  • vector_foreach(T, vector(T)* p_v, IT_NAME)

  • vector_rforeach(T, vector(T)* p_v, IT_NAME)

  • T* vector_iterator_get(T, vector_iterator(T)* p_it)

  • bool vector_iterator_is_valid(T, vector_iterator(T)* p_it)

  • bool vector_iterator_is_equal(T, vector_iterator(T)* p_it1, vector_iterator(T)* p_it2)

  • void vector_iterator_next(T, vector_iterator(T)* p_it)

  • void vector_iterator_prev(T, vector_iterator(T)* p_it)

  • bool vector_iterator_insert_after(T, vector_iterator(T)* p_it, T item)

  • bool vector_iterator_insert_before(T, vector_iterator(T)* p_it, T item)

  • bool vector_iterator_remove(T, vector_iterator(T)* p_it)

deque(T)

Dynamic double-ended queue

  • cctl/deque.h

  • deque(T)T_deque

  • deque_iterator(T)T_deque_iterator

  • void deque_init(T, deque(T)* p_d)

  • deque(T) deque_new(T, [size_t size])

  • deque(T) deque_from_items(T, ...)

  • bool deque_extend_items(T, deque(T)* p_d, ...)

  • void deque_free(T, deque(T)* p_d)

  • void deque_clear(T, deque(T)* p_d)

  • bool deque_resize(T, deque(T)* p_d, size_t size)

  • bool deque_shrink_to_fit(T, deque(T)* p_d)

  • bool deque_is_empty(T, deque(T)* p_d)

  • size_t deque_size(T, deque(T)* p_d)

  • size_t deque_capacity(T, deque(T)* p_d)

  • bool deque_push_front(T, deque(T)* p_d, T item)

  • bool deque_pop_front(T, deque(T)* p_d)

  • bool deque_push_back(T, deque(T)* p_d, T item)

  • bool deque_pop_back(T, deque(T)* p_d)

  • T* deque_at(T, deque(T)* p_d, size_t index)

  • T* deque_front(T, deque(T)* p_d)

  • T* deque_back(T, deque(T)* p_d)

  • deque_iterator(T) deque_begin(T, deque(T)* p_d)

  • deque_iterator(T) deque_end(T, deque(T)* p_d)

  • deque_iterator(T) deque_rbegin(T, deque(T)* p_d)

  • deque_iterator(T) deque_rend(T, deque(T)* p_d)

  • deque_iterator(T) deque_seek(T, deque(T)* p_d, size_t index)

  • deque_foreach(T, deque(T)* p_d, IT_NAME)

  • deque_rforeach(T, deque(T)* p_d, IT_NAME)

  • T* deque_iterator_get(T, deque_iterator(T)* p_it)

  • bool deque_iterator_is_valid(T, deque_iterator(T)* p_it)

  • bool deque_iterator_is_equal(T, deque_iterator(T)* p_it1, deque_iterator(T)* p_it2)

  • void deque_iterator_next(T, deque_iterator(T)* p_it)

  • void deque_iterator_prev(T, deque_iterator(T)* p_it)

  • bool deque_iterator_insert_after(T, deque_iterator(T)* p_it, T item)

  • bool deque_iterator_insert_before(T, deque_iterator(T)* p_it, T item)

  • bool deque_iterator_remove(T, deque_iterator(T)* p_it)

list(T)

Doubly linked list

  • cctl/list.h

  • list(T)T_list

  • list_iterator(T)T_list_iterator

  • void list_init(T, list(T)* p_l)

  • list(T) list_new(T, [size_t size])

  • list(T) list_from_items(T, ...)

  • bool list_extend_items(T, list(T)* p_l, ...)

  • void list_free(T, list(T)* p_l)

  • void list_clear(T, list(T)* p_l)

  • bool list_is_empty(T, list(T)* p_l)

  • size_t list_size(T, list(T)* p_l)

  • bool list_push_front(T, list(T)* p_l, T item)

  • bool list_pop_front(T, list(T)* p_l)

  • bool list_push_back(T, list(T)* p_l, T item)

  • bool list_pop_back(T, list(T)* p_l)

  • T* list_front(T, list(T)* p_l)

  • T* list_back(T, list(T)* p_l)

  • list_iterator(T) list_begin(T, list(T)* p_l)

  • list_iterator(T) list_end(T, list(T)* p_l)

  • list_iterator(T) list_rbegin(T, list(T)* p_l)

  • list_iterator(T) list_rend(T, list(T)* p_l)

  • list_iterator(T) list_seek(T, list(T)* p_l, size_t index)

  • list_foreach(T, list(T)* p_l, IT_NAME)

  • list_rforeach(T, list(T)* p_l, IT_NAME)

  • T* list_iterator_get(T, list_iterator(T)* p_it)

  • bool list_iterator_is_valid(T, list_iterator(T)* p_it)

  • bool list_iterator_is_equal(T, list_iterator(T)* p_it1, list_iterator(T)* p_it2)

  • void list_iterator_next(T, list_iterator(T)* p_it)

  • void list_iterator_prev(T, list_iterator(T)* p_it)

  • bool list_iterator_insert_after(T, list_iterator(T)* p_it, T item)

  • bool list_iterator_insert_before(T, list_iterator(T)* p_it, T item)

  • bool list_iterator_remove(T, list_iterator(T)* p_it)

heapq(T)

Binary Heap based Priority Queue (Min-Heap / Max-Heap)

  • cctl/heapq.h

  • heapq(T)T_heapq

  • bool heapq_init(T, heapq(T)* p_h, bool is_min_heap)

  • heapq(T) heapq_new(T, bool is_min_heap)

  • heapq(T) heapq_from_items(T, bool is_min_heap, ...)

  • bool heapq_extend_items(T, heapq(T)* p_h, ...)

  • void heapq_set_compare_func(T, heapq(T)* p_h, int (*fp_comp_func)(T, T))

  • void heapq_free(T, heapq(T)* p_h)

  • void heapq_clear(T, heapq(T)* p_h)

  • bool heapq_reserve(T, heapq(T)* p_h, size_t capacity)

  • bool heapq_shrink_to_fit(T, heapq(T)* p_h)

  • bool heapq_is_empty(T, heapq(T)* p_h)

  • size_t heapq_size(T, heapq(T)* p_h)

  • size_t heapq_capacity(T, heapq(T)* p_h)

  • bool heapq_push(T, heapq(T)* p_h, T item)

  • bool heapq_pop(T, heapq(T)* p_h)

  • bool heapq_pushpop(T, heapq(T)* p_h, T item, T* p_out)

  • T* heapq_top(T, heapq(T)* p_h)

rbt(K, V)

Red-Black Tree (Ordered Key-Value Map)

  • cctl/rbt.h

  • rbt(K, V)K_V_rbt

  • rbt_pair(K, V)K_V_rbt_pair

  • rbt_iterator(K, V)K_V_rbt_iterator

  • bool rbt_init(K, V, rbt(K, V)* p_r)

  • rbt(K, V) rbt_new(K, V)

  • rbt(K, V) rbt_from_items(K, V, ...)

  • bool rbt_extend_items(K, V, rbt(K, V)* p_r, ...)

  • void rbt_set_compare_func(K, V, rbt(K, V)* p_r, int (*fp_comp_func)(K, K))

  • void rbt_set_copy_func(K, V, rbt(K, V)* p_r, K (*fp_copy_func)(K))

  • void rbt_set_free_func(K, V, rbt(K, V)* p_r, void (*fp_free_func)(K))

  • void rbt_free(K, V, rbt(K, V)* p_r)

  • void rbt_clear(K, V, rbt(K, V)* p_r)

  • bool rbt_is_empty(K, V, rbt(K, V)* p_r)

  • size_t rbt_size(K, V, rbt(K, V)* p_r)

  • bool rbt_insert(K, V, rbt(K, V)* p_r, K key, V value)

  • void rbt_remove(K, V, rbt(K, V)* p_r, K key)

  • bool rbt_contains(K, V, rbt(K, V)* p_r, K key)

  • V* rbt_find(K, V, rbt(K, V)* p_r, K key)

  • V rbt_get_or_default(K, V, rbt(K, V)* p_r, K key, V default_value)

  • K* rbt_min_key(K, V, rbt(K, V)* p_r)

  • K* rbt_min_key_ref(K, V, rbt(K, V)* p_r)

  • K* rbt_max_key(K, V, rbt(K, V)* p_r)

  • K* rbt_max_key_ref(K, V, rbt(K, V)* p_r)

  • rbt_iterator(K, V) rbt_lower_bound(K, V, rbt(K, V)* p_r, K key)

  • rbt_iterator(K, V) rbt_upper_bound(K, V, rbt(K, V)* p_r, K key)

  • rbt_iterator(K, V) rbt_begin(K, V, rbt(K, V)* p_r)

  • rbt_iterator(K, V) rbt_end(K, V, rbt(K, V)* p_r)

  • rbt_iterator(K, V) rbt_rbegin(K, V, rbt(K, V)* p_r)

  • rbt_iterator(K, V) rbt_rend(K, V, rbt(K, V)* p_r)

  • rbt_foreach(K, V, rbt(K, V)* p_r, IT_NAME)

  • rbt_rforeach(K, V, rbt(K, V)* p_r, IT_NAME)

  • rbt_pair(K, V)* rbt_iterator_get(K, V, rbt_iterator(K, V)* p_it)

  • K* rbt_iterator_get_key(K, V, rbt_iterator(K, V)* p_it)

  • K* rbt_iterator_get_key_ref(K, V, rbt_iterator(K, V)* p_it)

  • bool rbt_iterator_is_valid(K, V, rbt_iterator(K, V)* p_it)

  • bool rbt_iterator_is_equal(K, V, rbt_iterator(K, V)* p_it1, rbt_iterator(K, V)* p_it2)

  • void rbt_iterator_next(K, V, rbt_iterator(K, V)* p_it)

  • void rbt_iterator_prev(K, V, rbt_iterator(K, V)* p_it)

hashmap(K, V)

Open addressing hash table

  • cctl/hashmap.h

  • hashmap(K, V)K_V_hashmap

  • hashmap_pair(K, V)K_V_hashmap_pair

  • hashmap_iterator(K, V)K_V_hashmap_iterator

  • void hashmap_init(K, V, hashmap(K, V)* p_hm)

  • hashmap(K, V) hashmap_new(K, V)

  • hashmap(K, V) hashmap_from_items(K, V, ...)

  • bool hashmap_extend_items(K, V, hashmap(K, V)* p_hm, ...)

  • void hashmap_set_hash_func(K, V, hashmap(K, V)* p_hm, size_t (*fp_hash_func)(K))

  • void hashmap_set_compare_func(K, V, hashmap(K, V)* p_hm, int (*fp_comp_func)(K, K))

  • void hashmap_set_copy_func(K, V, hashmap(K, V)* p_hm, K (*fp_copy_func)(K))

  • void hashmap_set_free_func(K, V, hashmap(K, V)* p_hm, void (*fp_free_func)(K))

  • void hashmap_free(K, V, hashmap(K, V)* p_hm)

  • void hashmap_clear(K, V, hashmap(K, V)* p_hm)

  • bool hashmap_reserve(K, V, hashmap(K, V)* p_hm, size_t capacity)

  • bool hashmap_shrink_to_fit(K, V, hashmap(K, V)* p_hm)

  • bool hashmap_is_empty(K, V, hashmap(K, V)* p_hm)

  • size_t hashmap_size(K, V, hashmap(K, V)* p_hm)

  • size_t hashmap_capacity(K, V, hashmap(K, V)* p_hm)

  • bool hashmap_insert(K, V, hashmap(K, V)* p_hm, K key, V value)

  • bool hashmap_remove(K, V, hashmap(K, V)* p_hm, K key)

  • bool hashmap_contains(K, V, hashmap(K, V)* p_hm, K key)

  • V* hashmap_find(K, V, hashmap(K, V)* p_hm, K key)

  • V hashmap_get_or_default(K, V, hashmap(K, V)* p_hm, K key, V default_value)

  • hashmap_iterator(K, V) hashmap_begin(K, V, hashmap(K, V)* p_hm)

  • hashmap_iterator(K, V) hashmap_end(K, V, hashmap(K, V)* p_hm)

  • hashmap_iterator(K, V) hashmap_rbegin(K, V, hashmap(K, V)* p_hm)

  • hashmap_iterator(K, V) hashmap_rend(K, V, hashmap(K, V)* p_hm)

  • hashmap_foreach(K, V, hashmap(K, V)* p_hm, IT_NAME)

  • hashmap_rforeach(K, V, hashmap(K, V)* p_hm, IT_NAME)

  • hashmap_pair(K, V)* hashmap_iterator_get(K, V, hashmap_iterator(K, V)* p_it)

  • K* hashmap_iterator_get_key(K, V, hashmap_iterator(K, V)* p_it)

  • K* hashmap_iterator_get_key_ref(K, V, hashmap_iterator(K, V)* p_it)

  • bool hashmap_iterator_is_valid(K, V, hashmap_iterator(K, V)* p_it)

  • bool hashmap_iterator_is_equal(K, V, hashmap_iterator(K, V)* p_it1, hashmap_iterator(K, V)* p_it2)

  • void hashmap_iterator_next(K, V, hashmap_iterator(K, V)* p_it)

  • void hashmap_iterator_prev(K, V, hashmap_iterator(K, V)* p_it)

trie(T)

Radix-256 Trie

  • cctl/trie.h

  • trie(T)T_trie

  • trie_pair(T)T_trie_pair

  • trie_iterator(T)T_trie_iterator

  • void trie_init(T, trie(T)* p_t)

  • trie(T) trie_new(T)

  • trie(T) trie_from_items(T, ...)

  • bool trie_extend_items(T, trie(T)* p_t, ...)

  • void trie_free(T, trie(T)* p_t)

  • void trie_clear(T, trie(T)* p_t)

  • bool trie_is_empty(T, trie(T)* p_t)

  • size_t trie_size(T, trie(T)* p_t)

  • T* trie_insert(T, trie(T)* p_t, const char* p_key, T item)

  • void trie_remove(T, trie(T)* p_t, const char* p_key)

  • bool trie_contains(T, trie(T)* p_t, const char* p_key)

  • T* trie_find(T, trie(T)* p_t, const char* p_key)

  • T trie_get_or_default(T, trie(T)* p_t, const char* p_key, T default_value)

  • char* trie_min_key(T, trie(T)* p_t)

  • char* trie_max_key(T, trie(T)* p_t)

  • char* trie_get_key(T, trie(T)* p_node)

  • trie_iterator(T) trie_lower_bound(T, trie(T)* p_t, const char* p_key)

  • trie_iterator(T) trie_upper_bound(T, trie(T)* p_t, const char* p_key)

  • trie_iterator(T) trie_begin(T, trie(T)* p_t)

  • trie_iterator(T) trie_end(T, trie(T)* p_t)

  • trie_iterator(T) trie_rbegin(T, trie(T)* p_t)

  • trie_iterator(T) trie_rend(T, trie(T)* p_t)

  • trie_foreach(T, trie(T)* p_t, IT_NAME)

  • trie_rforeach(T, trie(T)* p_t, IT_NAME)

  • T* trie_iterator_get(T, trie_iterator(T)* p_it)

  • bool trie_iterator_is_valid(T, trie_iterator(T)* p_it)

  • bool trie_iterator_is_equal(T, trie_iterator(T)* p_it1, trie_iterator(T)* p_it2)

  • void trie_iterator_next(T, trie_iterator(T)* p_it)

  • void trie_iterator_prev(T, trie_iterator(T)* p_it)

  • char* trie_iterator_get_key(T, trie_iterator(T)* p_it)

critbit(V)

CritBit Tree (DJB Compressed Binary Trie for String Keys)

  • cctl/critbit.h

  • critbit(V)V_critbit

  • critbit_pair(V)V_critbit_pair

  • critbit_leaf(V)V_critbit_leaf

  • critbit_iterator(V)V_critbit_iterator

  • void critbit_init(V, critbit(V)* p_tree)

  • critbit(V) critbit_new(V)

  • critbit(V) critbit_from_items(V, ...)

  • bool critbit_extend_items(V, critbit(V)* p_tree, ...)

  • void critbit_free(V, critbit(V)* p_tree)

  • void critbit_clear(V, critbit(V)* p_tree)

  • bool critbit_is_empty(V, critbit(V)* p_tree)

  • size_t critbit_size(V, critbit(V)* p_tree)

  • bool critbit_insert(V, critbit(V)* p_tree, const char* p_key, V value)

  • bool critbit_remove(V, critbit(V)* p_tree, const char* p_key)

  • bool critbit_contains(V, critbit(V)* p_tree, const char* p_key)

  • V* critbit_get(V, critbit(V)* p_tree, const char* p_key)

  • V critbit_get_or_default(V, critbit(V)* p_tree, const char* p_key, V default_value)

  • char* critbit_min_key(V, critbit(V)* p_tree)

  • const char* critbit_min_key_ref(V, critbit(V)* p_tree)

  • char* critbit_max_key(V, critbit(V)* p_tree)

  • const char* critbit_max_key_ref(V, critbit(V)* p_tree)

  • char* critbit_get_key(V, critbit_leaf(V)* p_leaf)

  • const char* critbit_get_key_ref(V, critbit_leaf(V)* p_leaf)

  • critbit_iterator(V) critbit_lower_bound(V, critbit(V)* p_tree, const char* p_key)

  • critbit_iterator(V) critbit_upper_bound(V, critbit(V)* p_tree, const char* p_key)

  • critbit_iterator(V) critbit_begin(V, critbit(V)* p_tree)

  • critbit_iterator(V) critbit_end(V, critbit(V)* p_tree)

  • critbit_iterator(V) critbit_rbegin(V, critbit(V)* p_tree)

  • critbit_iterator(V) critbit_rend(V, critbit(V)* p_tree)

  • critbit_foreach(V, critbit(V)* p_tree, IT_NAME)

  • critbit_rforeach(V, critbit(V)* p_tree, IT_NAME)

  • critbit_leaf(V)* critbit_iterator_get(V, critbit_iterator(V)* p_it)

  • char* critbit_iterator_get_key(V, critbit_iterator(V)* p_it)

  • const char* critbit_iterator_get_key_ref(V, critbit_iterator(V)* p_it)

  • V* critbit_iterator_get_value(V, critbit_iterator(V)* p_it)

  • bool critbit_iterator_is_valid(V, critbit_iterator(V)* p_it)

  • bool critbit_iterator_is_equal(V, critbit_iterator(V)* p_it1, critbit_iterator(V)* p_it2)

  • void critbit_iterator_next(V, critbit_iterator(V)* p_it)

  • void critbit_iterator_prev(V, critbit_iterator(V)* p_it)

optional(T)

Optional value container

  • cctl/optional.h

  • optional(T)T_optional

  • void optional_init(T, optional(T)* p_opt)

  • void optional_reset(T, optional(T)* p_opt)

  • void optional_set(T, optional(T)* p_opt, T value)

  • optional(T) optional_some(T, T value)

  • optional(T) optional_none(T)

  • T* optional_get(T, optional(T)* p_opt)

  • T optional_value(T, const optional(T)* p_opt)

  • T optional_value_or(T, const optional(T)* p_opt, T default_value)

  • bool optional_has_value(T, const optional(T)* p_opt)

  • bool optional_is_empty(T, const optional(T)* p_opt)

result(T, E)

Result (Success/Error) value container

  • cctl/result.h

  • result(T, E)T_E_result

  • void result_init(T, E, result(T, E)* p_res)

  • void result_reset(T, E, result(T, E)* p_res)

  • void result_set_ok(T, E, result(T, E)* p_res, T value)

  • void result_set_err(T, E, result(T, E)* p_res, E error)

  • result(T, E) result_ok(T, E, T value)

  • result(T, E) result_err(T, E, E error)

  • T* result_get_ok(T, E, result(T, E)* p_res)

  • E* result_get_err(T, E, result(T, E)* p_res)

  • T result_unwrap(T, E, const result(T, E)* p_res)

  • E result_unwrap_err(T, E, const result(T, E)* p_res)

  • T result_unwrap_or(T, E, const result(T, E)* p_res, T default_value)

  • bool result_is_ok(T, E, const result(T, E)* p_res)

  • bool result_is_err(T, E, const result(T, E)* p_res)

Macros

Utility macros for template generation, dispatching, and type manipulation

  • cctl/cctl.h

  • cctl_concat(A, B)AB

  • cctl_join(PREFIX, NAME)PREFIX_NAME

  • cctl_join3(A, B, C)A_B_C

  • cctl_join4(A, B, C, D)A_B_C_D

  • cctl_stringify(TOKEN)"TOKEN"

  • size_t cctl_va_count(...) ⇒ Number of variadic arguments (0 to 64)

  • cctl_dispatch(BASE, ...) ⇒ Dispatches to BASE_N based on variadic argument count

  • size_t cctl_num_args(...)

  • cctl_ptr(T)T_ptr

  • cctl_ptr_def(T)typedef T* T_ptr;

  • cstringchar*

  • u16cstringchar16_t*

  • u32cstringchar32_t*

About

C Template Library

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages