Update documentation
This commit is contained in:
1 parent
14845d9b23
commit
952292462a
57 files changed
+3027
-204
No files matched your search
@@ -0,0 +1,60 @@
|
||||
# Callbacks
|
||||
|
||||
Every collection can have an optional callback node. In this node there are five functions:
|
||||
|
||||
| Callback | Description |
|
||||
| -------- | ----------------------------------------------------------------------- |
|
||||
| `create` | Is called when an element was successfully added to the collection |
|
||||
| `read` | Is called when the collection was successfully queried about an element |
|
||||
| `update` | Is called when an element in the collection was successfully updated |
|
||||
| `delete` | Is called when an element was successfully removed from the collection |
|
||||
| `resize` | Is called when the collection was full and successfully resized |
|
||||
|
||||
Check the documentation for each collection to see which functions call which callbacks.
|
||||
|
||||
## cmc_callbacks
|
||||
|
||||
Every collection has a pointer to this `struct`. If it is `NULL` then the collection has no callbacks. Also, individual callbacks can be optional if set to `NULL`.
|
||||
|
||||
```c
|
||||
struct cmc_callbacks
|
||||
{
|
||||
void (*create)(void);
|
||||
void (*read)(void);
|
||||
void (*update)(void);
|
||||
void (*delete)(void);
|
||||
void (*resize)(void);
|
||||
};
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```c
|
||||
#include "cmc/heap.h"
|
||||
#include "utl/futils.h" // cmc_i32_cmp
|
||||
|
||||
// Generate a heap of integers
|
||||
CMC_GENERATE_HEAP(i32h, i32heap, int)
|
||||
|
||||
void heap_on_create(void)
|
||||
{
|
||||
printf("An element was added to the heap\n");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// create() is set but the other callbacks are not
|
||||
struct cmc_callbacks my_callbacks = { .create = heap_on_create, NULL };
|
||||
|
||||
// Create a max heap with the callbacks
|
||||
struct i32heap *heap = i32h_new_custom(
|
||||
100, cmc_max_heap, &(struct i32heap_fval){ .cmp = cmc_i32_cmp }, NULL,
|
||||
&my_callbacks);
|
||||
|
||||
i32h_insert(heap, 10);
|
||||
i32h_insert(heap, 11);
|
||||
i32h_insert(heap, 12);
|
||||
|
||||
i32h_free(heap);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,91 @@
|
||||
# Custom Allocation
|
||||
|
||||
All collections have an allocation node. This node can be modified so that every allocation and de-allocation can be done with custom functions. Every custom allocation function must follow the same prototype of the `stdlib.h` functions.
|
||||
|
||||
## cmc_alloc_node
|
||||
|
||||
```c
|
||||
struct cmc_alloc_node
|
||||
{
|
||||
void *(*malloc)(size_t);
|
||||
void *(*calloc)(size_t, size_t);
|
||||
void *(*realloc)(void *, size_t);
|
||||
void (*free)(void *);
|
||||
};
|
||||
```
|
||||
|
||||
## cmc_alloc_node_default
|
||||
|
||||
The default allocation node. If a collections is not initialized with a custom allocation node, this will be the default one using the functions from the C standard library.
|
||||
|
||||
```c
|
||||
static struct cmc_alloc_node cmc_alloc_node_default = { malloc, calloc,
|
||||
realloc, free };
|
||||
```
|
||||
|
||||
## Example
|
||||
|
||||
```c
|
||||
#include "cmc/heap.h"
|
||||
#include "utl/futils.h" // cmc_i32_cmp
|
||||
|
||||
// Total bytes allocated
|
||||
size_t total = 0;
|
||||
|
||||
void *my_malloc(size_t size)
|
||||
{
|
||||
void *result = malloc(size);
|
||||
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
total += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *my_calloc(size_t count, size_t size)
|
||||
{
|
||||
void *result = calloc(count, size);
|
||||
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
total += count * size;
|
||||
return result;
|
||||
}
|
||||
|
||||
void *my_realloc(void *block, size_t size)
|
||||
{
|
||||
void *result = realloc(block, size);
|
||||
|
||||
if (!result)
|
||||
return result;
|
||||
|
||||
total += size;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Generate a heap of integers
|
||||
CMC_GENERATE_HEAP(i32h, i32heap, int)
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// My custom allocation node
|
||||
struct cmc_alloc_node node = { .malloc = my_malloc,
|
||||
.calloc = my_calloc,
|
||||
.realloc = my_realloc,
|
||||
.free = free };
|
||||
|
||||
// Create a max heap with the custom allocation node
|
||||
struct i32heap *heap = i32h_new_custom(
|
||||
100, cmc_max_heap, &(struct i32heap_fval){ .cmp = cmc_i32_cmp }, &node,
|
||||
NULL);
|
||||
|
||||
for (int i = 0; i < 100000; i++)
|
||||
i32h_insert(heap, i);
|
||||
|
||||
i32h_free(heap);
|
||||
|
||||
printf("Total bytes allocated : %" PRIuMAX "\n", total);
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,127 @@
|
||||
# Functions Table
|
||||
|
||||
Functions Table is a `struct` with function pointers that are used to extract behavior from a custom data type. This exists because an `int` or a `char *` or `struct my_data_type` don't have default hash functions or ways to compare between them. This could be achieved with [operator overloading](https://en.wikipedia.org/wiki/Operator_overloading) but C doesn't have that. Hence, Functions Table was created to provide a single access point to extract these behaviors for __any__ data type.
|
||||
|
||||
Some functions are optional and others are needed in order for a collection to operate. Say you want a HashMap. There are two required functions: `hash` and `cmp` (comparator). Without them it is impossible to know how to hash your custom that type (it could be anything). This means you can also customize the collection by using different hash functions.
|
||||
|
||||
Many required functions are simply mundane. Like a comparator function between integers or between floats. The header [`utl/futils.h`](../../utl/futils.h/index.html) defines many of these functions for basic C data types.
|
||||
|
||||
Some collections generate two functions table. One for `K` and one for `V` (maps). Others simply generate one for `V`. A Functions Table `struct` is always going to be called:
|
||||
|
||||
* `struct SNAME##_fkey` for the `K` type
|
||||
* `struct SNAME##_fval` for the `V` type
|
||||
|
||||
Their definition is defined as follows:
|
||||
|
||||
```c
|
||||
\
|
||||
struct SNAME##_fkey \
|
||||
{ \
|
||||
/* Comparator function */ \
|
||||
int (*cmp)(K, K); \
|
||||
\
|
||||
/* Copy function */ \
|
||||
K (*cpy)(K); \
|
||||
\
|
||||
/* To string function */ \
|
||||
bool (*str)(FILE *, K); \
|
||||
\
|
||||
/* Free from memory function */ \
|
||||
void (*free)(K); \
|
||||
\
|
||||
/* Hash function */ \
|
||||
size_t (*hash)(K); \
|
||||
\
|
||||
/* Priority function */ \
|
||||
int (*pri)(K, K); \
|
||||
}; \
|
||||
\
|
||||
```
|
||||
|
||||
### CMP
|
||||
|
||||
* `K` - `int (*cmp)(K, K)`
|
||||
* `V` - `int (*cmp)(V, V)`
|
||||
|
||||
A comparator function is used in sorted collections or when an equality is being checked like when trying to find a certain element in a list. It is responsible for taking two arguments of the same data type and comparing them. The return value is an `int` with the following definitions:
|
||||
|
||||
* Return `1` if the first argument is greater than the second;
|
||||
* Return `0` if the first argument equals the second;
|
||||
* Return `-1` if the first argument is less than the second.
|
||||
|
||||
Note that certain collections require a total ordering of its elements (sorted collections) while others only require to know if one data equals another. Check out the documentation for each collection to know more.
|
||||
|
||||
### CPY
|
||||
|
||||
* `K` - `K (*cpy)(K)`
|
||||
* `V` - `V (*cpy)(V)`
|
||||
|
||||
A copy function is used when a collection is being copied. It can be used to make a deep copy of of your custom data type. It must take a single parameter and return a new copy of that same data type. If this function is absent (`NULL`) the data type will be copied by assignment (for pointers this is a shallow copy).
|
||||
|
||||
Note that it doesn't makes sense to define a `cpy` function for data types that are not pointers. This function is useful for deep copies of a pointer in case you don't want two collections holding the same reference to the data.
|
||||
|
||||
### STR
|
||||
|
||||
* `K` - `bool (*str)(FILE *, K)`
|
||||
* `V` - `bool (*str)(FILE *, V)`
|
||||
|
||||
A string function is responsible for taking a `FILE` pointer and a custom data type and outputting the string representation of that data returning a `bool` indication success or failure. It is useful for debugging and doesn't necessarily needs to print all the data that the specific type holds.
|
||||
|
||||
### FREE
|
||||
|
||||
* `K` - `void (*free)(K)`
|
||||
* `V` - `void (*free)(V)`
|
||||
|
||||
The free function is called when a collection is cleared (all elements removed) or freed (all elements removed and the collection is freed from memory) and it is responsible for completely freeing all resources that are usually acquired by your data type.
|
||||
|
||||
This function only makes sense to be used when the data type has dynamically allocated memory. It is the only completely optional function.
|
||||
|
||||
### HASH
|
||||
|
||||
* `K` - `size_t (*hash)(K)`
|
||||
* `V` - `size_t (*hash)(V)`
|
||||
|
||||
This function receives a custom data type as parameter and returns a `size_t` [hash](https://en.wikipedia.org/wiki/Hash_function) that represents that data. Used by collections with an underlying hash tables.
|
||||
|
||||
### PRI
|
||||
|
||||
* `K` - `int (*cmp)(K, K)`
|
||||
* `V` - `int (*cmp)(V, V)`
|
||||
|
||||
A priority function works much like the comparator function except that it compares the priority between two elements. It is used in collections whose structure is based on the priority of elements and not in their general comparison (heaps).
|
||||
|
||||
* Return `1` if the first argument has a greater priority than the second;
|
||||
* Return `0` if the first argument has the same priority as second;
|
||||
* Return `-1` if the first argument has a lower priority than the second.
|
||||
|
||||
Why use both `cmp` and `pri`? Heaps have their internal structure based in the priority of elements. This priority is not necessarily how each element is compared to each other. Maybe their equality is defined differently for an equality of priorities. Maybe the rules for their priorities is different for when comparing an element against another.
|
||||
|
||||
The following table shows which functions are required, optional or never used for each Collection:
|
||||
|
||||
| Collection | CMP | CPY | STR | FREE | HASH | PRI |
|
||||
| ---------- | :-: | :-: | :-: | :--: | :--: | :-: |
|
||||
| BidiMap |  |  |  |  |  |  |
|
||||
| Deque |  |  |  |  |  |  |
|
||||
| HashMap |  |  |  |  |  |  |
|
||||
| HashSet |  |  |  |  |  |  |
|
||||
| Heap |  |  |  |  |  |  |
|
||||
| IntervalHeap |  |  |  |  |  |  |
|
||||
| List |  |  |  |  |  |  |
|
||||
| LinkedList |  |  |  |  |  |  |
|
||||
| MultiMap |  |  |  |  |  |  |
|
||||
| MultiSet |  |  |  |  |  |  |
|
||||
| Queue |  |  |  |  |  |  |
|
||||
| SortedList |  |  |  |  |  |  |
|
||||
| Stack |  |  |  |  |  |  |
|
||||
| TreeMap |  |  |  |  |  |  |
|
||||
| TreeSet |  |  |  |  |  |  |
|
||||
|
||||
<br>
|
||||
|
||||
| Color | Label |
|
||||
| :---: | ----- |
|
||||
|  | Required for basic functionality. |
|
||||
|  | Required for specific functions. |
|
||||
|  | Required for non-core specific functions. |
|
||||
|  | Optional. |
|
||||
|  | Not Used. |
|
||||
@@ -0,0 +1,4 @@
|
||||
# COR
|
||||
|
||||
Core functionalities of the C Macro Collections Library.
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Iterators
|
||||
|
||||
Every collection comes with an interface of iterators where you can easily access the elements of a collection. These can move at any direction, can start at any 'end' of a collection and can move any amount of steps per iteration. Every collection generated comes with an iterator.
|
||||
|
||||
By design choice these iterators do not support modifications to the collection. If a collection is modified, all iterators that have been initialized will most likely be invalidated and may cause undefined behavior if used afterwards.
|
||||
Reference in new issue
Block a user