building instructions, remove old docs

This commit is contained in:
Evan Burkey 2025-02-15 11:05:01 -08:00
parent 34ec1943e1
commit ba6e929b4f
19 changed files with 16 additions and 1514 deletions

View File

@ -1,63 +0,0 @@
---
name: Test and Deploy
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y libbsd-dev cmake build-essential netcat
- name: Build and test
run: |
mkdir build
cd build
cmake ..
make
./tests
docs:
runs-on: ubuntu-latest
if: gitea.ref == 'refs/heads/master'
timeout-minutes: 5
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install SSH client
run: |
sudo apt-get update
sudo apt-get install -y openssh-client
- name: Setup SSH
run: |
mkdir -p ~/.ssh
ssh-keyscan -H burkey.co >> ~/.ssh/known_hosts
echo "${{ secrets.BURKEY_CO_KEY}}" >> ~/.ssh/id_rsa
chmod -R 700 ~/.ssh
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa
- name: Install mkdocs
run: |
pip install mkdocs
- name: Build documentation
run: |
mkdocs build
- name: Deploy documentation
run: |
ssh debian@burkey.co "rm -rf /var/www/docs/libflint"
ssh debian@burkey.co "mkdir -p /var/www/docs/libflint"
ssh debian@burkey.co "chmod 755 /var/www/docs/libflint"
scp -r ./site/* debian@burkey.co:/var/www/docs/libflint/

View File

@ -7,10 +7,25 @@ My personal library of common C data structures and algorithms. Supports Linux,
Extensive documentation can be found [here](https://wiki.burkey.co/doku.php?id=libflint:start). You can also check out `tests/tests.c` to
see example usage from most of the library's API.
## Building
`libflint` requires Cmake to be built. It can then be built using either `cmake` or `make` with the provided build files. The `Makefile` is a wrapper around Cmake for Makefile compatibility.
### Cmake
```cmake
# If libflint is in ./lib/libflint
add_subdirectory(lib/libflint)
# when building target...
target_include_directories(${TARGET} PRIVATE lib/libflint/include)
target_link_libraries(${TARGET} PRIVATE flint )
```
## Requirements
Building on Linux requires `libbsd`. Building on macOS, OpenBSD, or FreeBSD requires no extra dependencies.
## Libraries
`libflint` includes [uthash](https://github.com/troydhanson/uthash) for a hash table implementation. `uthash` is a single header file included in the source code of `libflint`. See the top of `include/uthash.h` for license information
`libflint` includes [uthash](https://github.com/troydhanson/uthash) for a hash table implementation. `uthash` is a single header file included in the source code of `libflint`. See the top of `include/uthash.h` for license information

View File

@ -1,203 +0,0 @@
# binarytree
Binary tree with standard leaf operations
## Usage
Create the tree. The user is responsible for memory management of the `BinTree` struct.
```c
BinTree *tree = malloc(sizeof(BinTree));
```
After the tree is created, init it. The second argument on `bintree_init()` is an optional memory freeing function pointer
with signature `void (*destroy)(void *data)`. Use `free()` from the stdlib if you are creating the data with `malloc()`.
If allocation of your data is more complex, you can pass your own memory deallocation function as long as it fits the
signature.
In this example, we are passing `NULL` because all memory will be stack allocated.
```c
bintree_init(tree, NULL);
int root = 0;
int l1 = 1;
int l2 = 2;
int r1 = 12;
int r2 = 200;
```
Next lets insert our data into the tree. The insert functions signature is `bintree_ins_...(tree, parent, data)`. If you
are inserting data at the root of the tree, you may use either `bintree_ins_left()` or `bintree_ins_right()` as long as
`NULL` is passed as the parent argument.
```c
bintree_ins_left(tree, NULL, &root);
bintree_ins_left(tree, tree->root, &l1);
bintree_ins_left(tree, tree->root->left, &l2);
bintree_ins_right(tree, tree->root->left, &r2);
bintree_ins_right(tree, tree->root, &r1);
bintree_ins_right(tree, tree->root->right, &r2);
bintree_ins_left(tree, tree->root->right, &l1);
```
We can use `bintree_debug_print(tree)` to print a graphical representation of the tree to `stdout`
```plaintext
└──0
├──1
│ ├──2
│ └──200
└──12
├──1
└──200
```
To cleanup the tree, first destroy the nodes. If you passed a deallocation function, it will be called on
the data member of each node before the node itself is freed. `bintree_destroy()` does not free the tree itself, just the
nodes inside of it, hence we must also call `free()` on the tree.
```c
bintree_destroy(tree);
free(tree);
tree = NULL;
```
Here is the entire example:
```c
BinTree *tree = malloc(sizeof(BinTree));
bintree_init(tree, NULL);
int root = 0;
int l1 = 1;
int l2 = 2;
int r1 = 12;
int r2 = 200;
bintree_ins_left(tree, NULL, &root);
bintree_ins_left(tree, tree->root, &l1);
bintree_ins_left(tree, tree->root->left, &l2);
bintree_ins_right(tree, tree->root->left, &r2);
bintree_ins_right(tree, tree->root, &r1);
bintree_ins_right(tree, tree->root->right, &r2);
bintree_ins_left(tree, tree->root->right, &l1);
bintree_debug_print(tree);
bintree_destroy(tree);
free(tree);
tree = NULL;
```
## Structs
### BinTree
Binary tree struct
```c
typedef struct {
int size;
int (*compare)(const void *a, const void *b);
void (*destroy)(void *data);
struct BinTreeNode *root;
} BinTree;
```
Members:
- `size`: How many nodes the tree contains
- `compare`: Comparison function between data in two nodes. Currently not used for anything
- `destroy`: Optional deallocation function for data inside a node. Typical usage is `NULL` for stack allocated data and `free()` for data created with `malloc()`
- `root`: The root node of the tree
### BinTreeNode
Node of the tree
```c
typedef struct BinTreeNode {
void *data;
struct BinTreeNode *left;
struct BinTreeNode *right;
} BinTreeNode;
```
Members:
- `data`: void pointer to data the node contains
- `left`: left facing leaf of the node
- `right`: right facing leaf of the node
## Functions
### bintree_init
Initialize the binary tree. User is responsible for freeing memory with `bintree_destroy()`.
```c
void bintree_init(BinTree *tree, void (*destroy)(void *data))
```
### bintree_destroy
Destroys the nodes inside a tree and calls the deallaction function on the data if one was provided. Does not deallocate
the tree itself, that is left to the user.
```c
void bintree_destroy(BinTree *tree)
```
### bintree_ins_left
Creates a new node containing `data` and inserts it as the left child of `node`.
```c
int bintree_ins_left(BinTree *tree, BinTreeNode *node, void *data)
```
### bintree_ins_right
Creates a new node containing `data` and inserts it as the right child of `node`.
```c
int bintree_ins_right(BinTree *tree, BinTreeNode *node, void *data)
```
### bintree_rem_left
Removes and deallocates the left child node of `node`. Calls the deallocation function on the data if one was provided.
```c
void bintree_rem_left(BinTree *tree, BinTreeNode *node)
```
### bintree_rem_right
Removes and deallocates the right child node of `node`. Calls the deallocation function on the data if one was provided.
```c
void bintree_rem_right(BinTree *tree, BinTreeNode *node)
```
### bintree_debug_print
Prints a representation of the tree to stdout. Gets very messy with large trees.
```c
void bintree_debug_print(BinTree *tree)
```
### bintree_is_eob
Utility macro that checks if the node is the End Of Branch.
```c
#define bintree_is_eob(node) ((node) == NULL)
```
### bintree_is_leaf
Utility macro that checks if a node has children.
```c
#define bintree_is_leaf(node) ((node)->left == NULL && (node)->right == NULL)
```

View File

@ -1,8 +0,0 @@
# bool
Macro representation of truthy values
```c
#define LFTRUE 1
#define LFFALSE 0
```

View File

@ -1,107 +0,0 @@
# crypto
Cryptographic tools
Any functions that return string representations of bytes in hexadecimal format will
always be formatted with no leading `0x` and lower case letters
## Functions
### b64_encode
Encodes an `unsigned char *` into base64. User is responsible for freeing the
`char *` that is returned.
```c
char *b64_encode(const unsigned char *s, size_t sz);
```
### b64_decode
Decodes a base64 encoded set of bytes into an `unsigned char *`. User is responsible
for freeing the `unsigned char *` that is returned. `decode_sz` is an optional argument
in case you need to know the size of the decoded data, otherwise you can just pass `NULL`.
```c
unsigned char *b64_decode(const char *s, size_t sz, size_t *decode_sz);
```
### hex_encode
Encodes an array of bytes into a string in hex representation. For example, converts
`[0xDE, 0xAD, 0xBE, 0xEF]` into `"deadbeef"`. User is responsible for freeing the returned string
```c
const char *hex_encode(const unsigned char *hex, size_t sz);
// Example
unsigned char h[4] = {
0xde, 0xad, 0xbe, 0xef
};
const char *s = hex_encode(h, 4);
assert(strcmp(s, "deadbeef") == 0);
free(s);
```
### hex_decode
Decodes a string of characters representing hexadecimal bytes into an array of `unsigned char`.
Characters can be in upper or lower case, and can start with a leading `0x` or not.
For example, converts `"DEADBEEF"` into `[0xde, 0xad, 0xbe, 0xef]`. User is reponsible for the
freeing of the returned byte array
```c
unsigned char *hex_decode(const char *orig, size_t *sz);
// Example
unsigned char *s = hex_decode("DEADBEEF", &s_sz);
unsigned char h[4] = {
0xDE, 0xAD, 0xBE, 0xEF
};
for (size_t i = 0; i < 4; ++i) {
assert(s[i] == h[i]);
}
free(s);
```
### hex_to_str
Converts an array of `unsigned char` into a string based on the ASCII values of each byte. User is
responsible for freeing the returned string.
```c
const char *hex_to_str(const unsigned char *hex, size_t sz);
```
### repeating_key_xor
Performs a repeating-key XOR encryption on an array of bytes. User is responsible for freeing the returned array
```c
const unsigned char* repeating_key_xor(const unsigned char* s, size_t s_sz, const unsigned char* key, size_t k_sz);
```
### repeating_key_xor_s
Performs a repeating-key XOR encryption on a string. Returns the encrypted string as an array of bytes. User is
responsible for freeing the returned array
```c
const unsigned char *repeating_key_xor_s(const char* s, const char* key);
```
### hamming_distance
Calculates the Hamming Distance (the number of differing bits) between two arrays of unsigned bytes
```c
unsigned int hamming_distance(unsigned char *a, unsigned char *b);
```
### hamming_distance_s
Calculates the Hamming Distance (the number of differing bits) between two strings
```c
unsigned int hamming_distance_s(const char *a, const char *b);
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,25 +0,0 @@
# libflint
`libflint` is a library of common C data structures and algorithms, designed to be as agnostic as possible for its
users. Over time, it has become my personal library of reusable C code.
## Requirements
### Linux
Requires `libbsd`. This should be available on all major Linux distros.
### macOS, OpenBSD, FreeBSD
Requires no extra dependencies
## Memory Management
The parts of this library that create data structures pass all responsibility of memory management to the user. This
is clearly documented in the individual module's documentation.
## Why the name 'libflint'?
`libflint` is named after my dog Flint, who passed away in 2021. I miss you buddy.
![flint](flinty.jpg)

View File

@ -1,120 +0,0 @@
# input
I/O module to assist with consuming data from files
## Functions
### get_binary
Reads a file at `path` and returns the contents as a char* buffer. The `fsz` parameter stores the length of the
returned array. The buffer is allocated inside the function, so the user is responsible for freeing it when finished.
```c
char *get_binary(const char *path, size_t *fsz);
/* Usage */
size_t fsz = 0;
char *buf = get_binary("/home/evan/binfile", &fsz);
free(buf);
```
### get_input
Reads a file at `path` and returns the contents as a single string. The string is allocated inside the function and
the user is responsible for freeing it when finished.
```c
unsigned char *get_input(const char *path);
/* Usage */
char *str = get_input("/home/evan/textfile");
free(str);
```
### get_lines
Reads a file at `path` and returns the contents as an array of strings. The newline character `\n` is used as the
delimiter to determine where the file is split. The user is responsible for cleaning up the memory using `del_lines()`.
`lsz` is set to the number of lines in the array.
```c
char **get_lines(const char *path, size_t *lsz);
/* Usage */
size_t sz = 0;
char **lines = get_lines("/home/evan/textfile", &sz);
for (size_t i = 0; i < sz; i++) {
printf("%s\n", lines[i]);
}
del_lines(lines);
```
### del_lines
Frees all memory used by `get_lines()`
```c
void del_lines(char **lines);
```
### get_ints
Reads a file at `path` and returns the contents as an array of integers. The file is assumed to be a newline seperated
list of integers and nothing else.
The newline character `\n` is used as the delimiter to determine where the file is split. The user is responsible for
cleaning up the memory using `free()`. `lsz` is set to the number of lines in the array.
```c
int *get_ints(const char *path, size_t *lsz);
/* Usage */
int *nums = get_ints("/home/evan/intfile");
for (size_t i = 0; i < sz; i++) {
printf("%d\n", nums[i]);
}
free(nums);
```
### split
Takes a string `s` and splits it into an array of strings based on the delimiter. `s` is left unchanged. The user is
responsible for cleaning up the memory of the split using `del_split()`. `sp_sz` is set to the size of the split.
```c
char **split(char *s, size_t *lsz, const char *delim)
/* Usage */
size_t sp_sz = 0;
char **sp = split("Split on whitespace", &sp_sz, " ");
printf("%s\n", sp[0]); // Prints "Split"
```
### del_split
Frees all memory used by `split()`. Just like `split`, it does not touch the original string.
```c
void del_split(char **sp);
/* Usage */
size_t sp_sz = 0;
char **sp = split("Delete Me!", &sp_sz, " ");
void del_split(sp);
```
### capture_system
Runs a command on the system shell and returns stdout as a string. `buffsize` is the size of
the returned buffer that holds `stdout`. Passing `0` to `buffsize` will use the default buffer size of `1024`.
User is responsible for freeing the returned string.
```c
const char *capture_system(const char *cmd, int buffsize);
/* Usage */
const char *cap = capture_system("ls $HOME", 0);
printf("%s\n", cap);
free(cap);
```

View File

@ -1,230 +0,0 @@
# linkedlist
A dual sided linked list structure. Used as the foundation for many other modules in `libflint`
## Usage
Create the list. The user is responsible for memory management of the `List` struct.
```c
List *list = malloc(sizeof(List));
```
After the tree is created, init it. The second argument on `bintree_init()` is an optional memory freeing function pointer
with signature `void (*destroy)(void *data)`. Use `free()` from the stdlib if you are creating the data with `malloc()`.
If allocation of your data is more complex, you can pass your own memory deallocation function as long as it fits the
signature.
In this example, we are passing `NULL` because all memory will be stack allocated.
```c
ll_init(list, NULL);
int i = 1;
int j = 2;
int k = 4;
```
Next, insert data into the list. Data can be inserted from either side of a node.
```c
ll_ins_next(list, list->head, (void *) &i);
ll_ins_next(list, list->tail, (void *) &j);
ll_ins_next(list, list->tail, (void *) &k);
/* List is now 1 2 4 */
```
Lists can have a node removed by either targeting the node directly or removing a node pointed to by the head or tail of
another node. The user is responsible for the memory management of the data inside the node, which is why a `void*` must
be supplied to hold the data. Since in this example our memory is stack allocated, we don't need to worry about freeing
the `void*` but one must still be supplied for the function to work.
```c
/* List is 1 2 4 */
/* node is the 2nd node in the list with value 2 */
ListNode *node = list->head;
/* void pointer to the data inside of the node */
void *data;
ll_remove(list, node, &data);
/* List is now 1 4 */
printf("Removed: %d\n", *((int *) data));
/* Prints "2" */
```
Here is an alternative example using `ll_remove_next()` instead of `ll_remove()`
```c
/* node is the 2nd node in the list with value 2 */
ListNode *node = list->head;
void *data; /* void pointer to the data inside of the node */
ll_remove_next(list, node, &data);
/* List is now 1 2 */
printf("Removed: %d\n", *((int *) data));
/* Prints "4" */
```
To destroy the list, first call `ll_destroy()` to free the nodes in the list and optionally run the destroy function
against the data stored in the list. Since this example is stack allocated and we passed `NULL` when creating the
list, no destroy function is run against the memory in the nodes. The list itself must be deleted with `free()`
```c
ll_destroy(list);
free(list);
```
Complete example:
```c
List *list = malloc(sizeof(List));
ll_init(list, NULL);
int i = 1;
int j = 2;
int k = 4;
ll_ins_next(list, list->head, (void *) &i);
ll_ins_next(list, list->tail, (void *) &j);
ll_ins_next(list, list->tail, (void *) &k);
printf("List: ");
print_ll(list);
void *data;
ll_remove_next(list, list->head, &data);
printf("List: ");
print_ll(list);
printf("Removed: %d\n", *((int *) data));
ll_destroy(list);
free(list);
```
## Structs
### List
Double ended linked list struct
```c
typedef struct {
size_t size;
void (*destroy)(void *data);
int (*match)(const void *a, const void *b);
struct ListNode *head;
struct ListNode *tail;
} List;
```
Members:
- `size`: How many nodes are in the list
- `destroy`: Optional deallocation function for member data. Use `NULL` if data is stack allocated
- `match`: Comparison function between data inside two nodes. This is not used by `List` itself, but is used in structures built on top of `List`
- `head`: Pointer to the `ListNode` at the head of the list
- `tail`: Pointer to the `ListNode` at the tail of the list
### ListNode
Node of the list
```c
typedef struct ListNode {
void *data;
struct ListNode *next;
struct ListNode *prev;
} ListNode;
```
Members:
- `data`: void pointer to the member data in the node
- `next`: Pointer to the `ListNode` before this node in the list
- `prev`: Pointer to the `ListNode` after this node in the list
## Functions
### ll_init
Initialize the list. User is responsible for creating the initial `List` structure and freeing memory with `ll_destroy()`. `destroy` is a deallocation function for the members of `List`, pass `NULL` if the memory is stack-allocated
```c
void ll_init(List *list, void (*destroy)(void *data));
/* Usage */
List *list = malloc(sizeof(Stack));
// Pass NULL for stack-allocated memory
ll_init(list, NULL);
// Pass free or a custom freeing function for heap allocated memory
ll_init(list, free);
```
### ll_destroy
Destroys the nodes inside a list and calls the deallocation funciton on the data if one was provided. Does not destroy the list itself, that is left up to the user.
```c
void ll_destroy(List *list);
```
### ll_ins_next
Creates a new node containing `data` and inserts it after `node`.
```c
int ll_ins_next(List *list, ListNode *node, const void *data);
```
### ll_ins_prev
Creates a new node containing `data` and inserts it before `node`.
```c
int ll_ins_prev(List *list, ListNode *node, const void *data);
```
### ll_remove
Removes and deallocates the node pointed to by `node`. The user is responsible for managing the contained data's memory,
as such the `destroy` function is **not** run by `ll_remove()`
```c
int ll_remove(List *list, ListNode *node, void **data);
```
### ll_remove_next
Removes and deallocates the node pointed to by `node`'s `tail` pointer. The user is responsible for managing the contained data's memory,
as such the `destroy` function is **not** run by `ll_remove_next()`
```c
int ll_remove_next(List *list, ListNode *node, void **data);
```
### ll_remove_prev
Removes and deallocates the node pointed to by `node`'s `head` pointer. The user is responsible for managing the contained data's memory,
as such the `destroy` function is **not** run by `ll_remove_prev()`
```c
int ll_remove_prev(List *list, ListNode *node, void **data);
```
## Macros
### LL_ITER
A utility macro that helps with iterating over an entire list. A `ListNode` pointer named `node` is created as part of
this macro and can be used to access the current node in the iteration, so be careful your own variable naming if you
intend to use `LL_ITER`.
```c
#define LL_ITER(list) for(ListNode *node = (list)->head; node != NULL; node = node->next)
/* Example with list of strings */
for LL_ITER(list) {
printf("%s\n", (char *)(node->data));
}
```

View File

@ -1,63 +0,0 @@
# macOS
Platform-specific code for macOS. Everything in this module, including the headers, is wrapped in the following
preprocessor macro
```c
#if defined(__APPLE__) || defined(__MACH__)
/*
... code ...
*/
#endif /* defined(__APPLE__) || defined(__MACH__) */
```
## Structs
### ProcessData
ProcessData is a struct that tracks cpu and memory usage of a process. It needs to be regularly updated with calls to
`update_process()` in order to provide accurate information
```c
typedef struct {
double total_user_time;
double total_kernel_time;
double last_total_consumed;
double percent_cpu;
uint64_t virtual_memory;
uint64_t resident_memory;
time_t timestamp;
time_t last_timestamp;
} ProcessData;
```
## Functions
## new_ProcessData
Returns a pointer to a `ProcessData` struct.
```c
ProcessData *new_ProcessData();
```
## update_process
Updates a `ProcessData` struct. This should be called in a loop or at specific intervals to measure proper usage
data. An example is below
```c
int update_process(pid_t pid, ProcessData *proc);
/* Example */
pid_t pid = getpid();
ProcessData *pd = new_ProcessData();
for (int i = 0; i < 10; i++) {
update_process(pid, pd);
printf("CPU: %.2f\n", pd->percent_cpu);
sleep(1);
}
free(pd);
```

View File

@ -1,67 +0,0 @@
# math
General math functions
## Functions
## max_int
Return the maximum integer between `int a` and `int b`
```c
int max_int(int a, int b);
```
## min_int
Return the minimum integer between `int a` and `int b`
```c
int min_int(int a, int b);
```
## clamp_int
Clamps an integer between a high and low value
```c
int clamp_int(int i, int low, int high);
```
## binstr_to_int
Converts a string representing a binary number into an integer. Supports underscores as spacing
```c
int binstr_to_int(const char *s);
/* Usage */
int a = binstr_to_int("10011101");
int b = binstr_to_int("1001_1101_0010_1011");
```
## bresenham
Uses bresenham's line algorithim to generate a line in 2D space.
Returns a pointer to an array of `Point`.
The `sz` parameter holds the size of the array.
```c
Point *bresenham(int x0, int y0, int x1, int y1, size_t *sz);
```
## bresenham_p
Works the same as `bresenham()` but uses the `Point` struct instead of `int`
```c
Point *bresenham_p(Point p1, Point p2, size_t *sz);
```
## is_power_of_two
Returns `1` if `i` is a power of two, otherwise returns `1`.
```c
int is_power_of_two(int i);
```

View File

@ -1,194 +0,0 @@
# memory
Custom allocators and memory functions
## Arena Allocator
A simple arena-style allocator
## Structs
### ArenaAllocator
Represents an arena allocator. `ArenaAllocator` holds its own buffer, but managing its size is left to the user. Like
most structs in `libflint`, it must be malloc'd first before being passed to `arena_init()`.
```c
typedef struct {
unsigned char* buf;
size_t buf_sz;
size_t offset_cur;
size_t offset_prev;
} ArenaAllocator;
```
## Functions
### arena_init
Initializes the `ArenaAllocator`. The struct must first be created by the user using `malloc()`, see the example below.
`buf_sz` is the size of the underlying buffer in bytes.
```c
void arena_init(ArenaAllocator *allocator, size_t buf_sz);
/* Usage */
ArenaAllocator *a = malloc(sizeof(ArenaAllocator));
arena_init(a, 1024);
```
### arena_free
Frees `allocator` and its underlying buffer. Users should set `allocator` to `NULL` after calling `arena_free()`.
```c
void arena_free(ArenaAllocator *allocator);
/* Usage */
arena_free(allocator);
allocator = NULL;
```
### arena_clear
Resets the offset markers of the arena to `0`, but does not wipe the underlying buffer. Technically, any assigned pointers
will still work and
```c
void arena_clear(ArenaAllocator *allocator);
```
### *arena_malloc
Request memory of `size` bytes in length from the arena. Returns `NULL` if the assignment failed.
```c
void *arena_malloc(ArenaAllocator* allocator, size_t size);
```
### arena_resize_buf
Reallocates the underlying buffer in the arena to `new_sz`. You can grow or shrink the arena using this function. Any
pointers allocated out of the arena are invalid after using this function.
```c
void arena_resize_buf(ArenaAllocator *allocator, size_t new_sz);
```
### *arena_resize
Resize an allocated pointer from the arena. See the example below for a simple use case
```c
void *arena_resize(ArenaAllocator *allocator, void *mem, size_t old_sz, size_t new_sz);
/* Usage */
int *i = arena_malloc(a, sizeof(int));
*i = 1;
long *l = arena_resize(a, i1, sizeof(int), sizeof(long));
assert(*l == 1);
```
## Macros
### arena_sz
Convenience macro for getting the size of the arena's buffer
```c
#define arena_sz(a) (a)->buf_sz
```
## Pool Allocator
A pool-based allocator for chunks of the same size. Useful for quickly allocating and using memory of the same size
without worrying about order; most operations are `O(1)`
## Structs
### PoolAllocator
Represents a pool allocator. `PoolAllocator` holds its own buffer, but managing its size is left to the user. Like
most structs in `libflint`, it must be malloc'd first before being passed to `pool_init()`.
```c
typedef struct {
unsigned char *buf;
size_t buf_sz;
size_t chunk_size;
List *free_list;
} PoolAllocator;
```
## Functions
### pool_init
Initializes the `PoolAllocator`. The struct must first be created by the user using `malloc()`, see the example below.
- `buf_sz`: Size of the underlying buffer in bytes
- `chunk_sz`: Size of each chunk in bytes
- `chunk_align`: The alignment of the chunks. The`LF_DEFAULT_ALIGNMENT` macro is available as a good default for basic types
```c
void pool_init(PoolAllocator *allocator, size_t buf_sz, size_t chunk_sz, size_t chunk_align);
/* Usage */
PoolAllocator *pool = malloc(sizeof(PoolAllocator));
pool_init(pool, 64, 16, LF_DEFAULT_ALIGNMENT);
```
### pool_free
Return a single chunk back to the pool. `ptr` is a pointer to the allocated chunk.
```c
void pool_free(PoolAllocator *allocator, void *ptr);
```
### pool_free_all
Returns all chunks back to the pool. Any pointers received before this call are now invalid and must be reasigned with
`pool_alloc` or set to `NULL`.
```c
void pool_free_all(PoolAllocator *allocator);
```
### pool_alloc
Allocate a chunk from the pool. Returns `NULL` on failure.
```c
void *pool_alloc(PoolAllocator *allocator);
```
### pool_destroy
Destroys the underlying buffer and `List` in `allocator`, then frees it. User is responsible for setting `allocator` to
`NULL` afterwards.
```c
void pool_destroy(PoolAllocator *allocator);
```
## Macros
### pool_count_available
Returns the amount of chunks left available in the pool
```c
#define pool_count_available(x) (x)->free_list->size
```
### LF_DEFAULT_ALIGNMENT
The default alignment for allocators. Use this as a simple default (defaults to 16 bytes on amd64 systems) when storing
basic types
```c
#ifndef DEFAULT_ALIGNMENT
#define LF_DEFAULT_ALIGNMENT (2*sizeof(void*))
#endif // DEFAULT_ALIGNMENT
```

View File

@ -1,106 +0,0 @@
# network
This module provides a generic `Server` type that abstracts away the setup and teardown of a socket
## Enums
### ServerType
Types of servers. Currently supports TCP and UDP, will eventually add UNIX sockets.
```c
typedef enum ServerType {
SERVERTYPE_TCP,
SERVERTYPE_UDP
} ServerType;
```
## Structs
### Server
Server is a generic abstraction over sockets. The type of the server is defined by `server_type`.
```c
typedef struct Server {
ServerType server_type;
int fd;
int port;
void (*handler)(struct Server *s);
} Server;
```
## Functions
### new_server
Create a `Server*`. User is responsible for freeing the memory.
```c
Server *new_server(ServerType type, const char *port, void(handler)(Server *s));
```
### delete_server
Frees the memory allocated for `Server*` and sets the pointer to `NULL`.
```c
void delete_server(Server *s);
```
### serve
Starts up the server. `backlog_size` is the size of the backlog buffer for the underlying socket. Use the macro
`DEFAULT_BACKLOG_SIZE` or pass `0` to use a reasonable default.
```c
int serve(Server *s, int backlog_size);
```
### get_in_addr
Convenience method to get an IP address from a `struct sockaddr_storage` of either IPV4 or IPV6.
```c
void *get_in_addr(struct sockaddr *sa);
/* Usage */
struct sockaddr_storage client_addr;
socklen_t client_addr_sz = sizeof(client_addr);
char buf[33];
if (new_fd = accept(s->fd, (struct sockaddr *)&client_addr, &client_addr_sz) == -1) {
/* error handling */
}
inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), buf, 32);
printf("Received connection from %s\n", buf);
```
### handler_tcp_echo
An example handler for a multithreaded tcp echo server.
```c
void handler_tcp_echo(Server *s);
/* Usage */
#include "lfnetwork.h"
int main(int argc, char **argv) {
Server *server = new_server(SERVERTYPE_TCP, "80", handler_tcp_echo);
serve(server, DEFAULT_BACKLOG);
delete_server(server);
}
```
## Macros
### DEFAULT_BACKLOG_SIZE
A default size for the socket's backlog buffer. `5` is a standard default size, providing some backlog but not
enough to make huge buffers for each socket
```c
#define DEFAULT_BACKLOG_SIZE 5
```

View File

@ -1,14 +0,0 @@
# parsing
String parsing tools
## Functions
### simple_english_scoring
Scores a string based on a simple ETAOIN SHRDLU scale. A simple, somewhat accurate way to determine if a string is
English.
```c
int simple_english_scoring(const char *s);
```

View File

@ -1,3 +0,0 @@
# set
Coming soon

View File

@ -1,74 +0,0 @@
# stack
LIFO (last in first out) stack structure
## Structs
`Stack` is a linked list with stack-based operations available
```c
#define Stack List
```
## Functions
### stack_init
Intializes the stack. The user is responsible for creating the initial `Stack` structure and freeing memory with `stack_destroy()`. `destroy` is a deallocation function for the members of `Stack`, pass `NULL` if the memory is stack-allocated
```c
void stack_init(Stack *stack, void (*destroy)(void *data));
/* Usage */
Stack *stack = malloc(sizeof(Stack));
// Pass NULL for stack-allocated memory
stack_init(stack, NULL);
// Pass free or a custom freeing function for heap allocated memory
stack_init(stack, free);
```
### stack_destroy
Destroys the nodes inside a `Stack` and calls the deallocation funciton on the data if one was provided. Does not destroy the list itself, that is left up to the user.
```c
void stack_destroy(Stack *stack);
```
### stack_push
Push a new element onto the top of the stack
```c
int stack_push(Stack *stack, void *data);
```
### stack_peek
Returns a `void *` to the top element of the stack. Does not remove the element
```c
void *stack_peek(Stack *stack);
/* Usage */
// stack: 1 2 3
int *t = (int*)stack_peek(stack);
assert(*t == 3);
// stack: 1 2 3
```
### stack_pop
Returns a `void *` to the top element of the stack and removes the element
```c
int stack_pop(Stack *stack, void **data);
/* Usage */
// stack: 1 2 3
int *t = (int*)stack_peek(stack);
assert(*t == 3);
// stack: 1 2
```

View File

@ -1,46 +0,0 @@
# string
C string helpers
## Functions
### find_substrings
Finds the indicies of all locations of the given needle in the haystack. `substrings` is an array of `size_t` indicies that
the substring is found at. This function allocates the memory for `substrings` and memory cleanup is managed by the user.
`num_substrings` is a pointer to a pre-allocated `size_t` that will be modified to contain the number of found substrings
and subsequently the size of `substrings`.
If no substrings are found, `substrings` will not be allocated and left set to `NULL`, `num_substrings` will be `0`, and
the function will return `0`.
Returns 0 if the function is successful. Returns a non-zero value if there is an error.
```c
int find_substrings(const char* haystack, const char* needle, size_t *num_substrings, size_t **substrings);
/* Usage */
const char* haystack = "One two three two";
const char* needle = "two";
size_t subs_sz = 0;
size_t *subs = NULL;
size_t *subs = find_substrings(haystack, needle, &subs_sz, &subs);
// subs: [ 4, 14 ]
// subs_sz: 2
free(subs);
```
### substr
Extracts a substring at a specific index and length. This function returns a copy of the substring in a heap allocated
buffer that the user is responsible for freeing. Returns `NULL` if there is an error.
```c
const char* substr(const char* str, size_t idx, size_t len);
/* Usage */
const char *s = substr("One two three", 4, 3);
assert(strcmp(s, "two") == 0);
free(s);
```

View File

@ -1,16 +0,0 @@
# utility
Utility code that does not fit anywhere else
## Structs
### Point
Representation of a point on a two dimensional grid
```c
typedef struct {
int x;
int y;
} Point;
```

View File

@ -1,174 +0,0 @@
# vector
Simple type-agnostic dynamic array
## Structs
### Vector
Vector struct
```c
typedef struct Vector {
size_t capacity;
size_t length;
void **elements;
void (*destroy)(void *data);
} Vector;
```
Members:
- `capacity`: The size of `elements` in memory
- `length`: The number of real elements stored in the backing `elements` array
- `elements`: The dynamic array of `void *` that holds the vector's members
- `destroy`: Optional deallocation function for data inside a node. Typical usage is `NULL` for stack allocated data and `free()` for data created with `malloc()`
## Functions
### vec_init
Initialize the vector with a default capacity of 2. User is responsible for freeing elements of the vector with `vec_destroy()`. Returns a non-zero integer if there is an error
```c
int vec_init(Vector *vec, void (*destroy)(void *data));
```
### vec_init_with_capacity
Initialize the vector with a user-specified capacity. User is responsible for freeing elements of the vector with `vec_destroy()`. Returns a non-zero integer if there is an error
```c
int vec_init_with_capacity(Vector *vec, void (*destroy)(void *data), size_t cap);
```
### vec_destroy
Frees the underlying array inside a `Vector`. If `destroy` was provided when creating the vector, then it is called against each element in the array before the array is freed. Does not destroy the vector itself, that is left up to the user
```c
void vec_destroy(Vector *vec);
/* Usage */
vec_destroy(vec);
free(vec);
```
### vec_insert
Insert `data` into the vector at a specified index. Any elements at that array and beyond will be moved up to make room. Returns a non-zero integer if there is an error
```c
int vec_insert(Vector *vec, void *data, size_t index);
/* Usage */
// vec: 1 2 3 4
int i = 99;
vec_insert(vec, &i, 2);
// vec: 1 2 99 3 4
```
### vec_push
Insert `data` at the end of the vector. Returns a non-zero integer if there is an error
```c
int vec_push(Vector *vec, void *data);
/* Usage */
// vec: 1 2 3
int *i = malloc(sizeof(int));
*i = 4;
vec_push(vec, i);
// vec: 1 2 3 4
```
### vec_safe_at
Gets the stored data at a specified index. Uses safety checks to make sure `index` is not out of bounds. Returns `NULL` if there is an error
```c
void *vec_safe_at(Vector *vec, size_t index);
```
### vec_remove
Removes an element from the array and returns the pointer, then moves elements to shrink the array accordingly. Returns `NULL` if the index is not valid
```c
void *vec_remove(Vector *vec, size_t index);
/* Usage */
// vec: 1 2 3 4
int *t = NULL;
t = (int*)vec_remove(vec, 2);
assert(*t == 3);
// vec: 1 2 4
```
### vec_shrink
Shrinks the capacity of the vector down to the current length. Returns a non-zero integer if there is an error
```c
int vec_shrink(Vector *vec);
```
### vec_max
Finds the largest value in the vector and returns a void pointer to the underlying data. Requires a
comparison function to compare the data in the vector. This function must return `1` if `a > b`, `-1` if
`a < b`, or `0` if `a == b`. See the supplied comparison functions below for reference
```c
const void *vec_min(const Vector *vec, int(*cmp)(const void *a, const void *b));
```
### vec_min
Finds the smallest value in the vector and returns a void pointer to the underlying data. Requires a
comparison function to compare the data in the vector. This function must return `1` if `a > b`, `-1` if
`a < b`, or `0` if `a == b`. See the supplied comparison functions below for reference
```c
const void *vec_max(const Vector *vec, int(*cmp)(const void *a, const void *b));
```
## Comparison Functions
Comparison functions to compare data in a vector. These functions must return `1` if `a > b`, `-1` if
`a < b`, or `0` if `a == b`.
```c
int vec_cmp_int(const void *a, const void *b);
int vec_cmp_char(const void *a, const void *b);
```
## Macros
### vec_at
Grabs the element at index `i` without safety checks for better performance. Use with caution
```c
#define vec_at(v, i) (v)->elements[(i)]
```
### vec_len
Returns the length of the vector
```c
#define vec_len(v) (v)->length
```
### vec_cap
Returns the capacity of the vector
```c
#define vec_cap(v) (v)->capacity
```