13 changed files with 373 additions and 2 deletions
@ -1,3 +1,11 @@
@@ -1,3 +1,11 @@
|
||||
# libflint |
||||
|
||||
My personal library of common C data structures and algorithms. |
||||
My personal library of common C data structures and algorithms. Supports Linux, OpenBSD, and FreeBSD. |
||||
|
||||
## Documentation |
||||
|
||||
Extensive documentation can be found [here](https://docs.fputs.com/libflint/index.html) |
||||
|
||||
## Requirements |
||||
|
||||
Building on Linux requires `libbsd`. |
@ -1,8 +1,10 @@
@@ -1,8 +1,10 @@
|
||||
#!/bin/sh -e |
||||
|
||||
# For building outside of CLion |
||||
|
||||
mkdir -p build |
||||
cd build |
||||
cmake .. |
||||
make |
||||
cp compile_commands.json .. |
||||
cd |
||||
cd |
||||
|
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
# libflint |
||||
|
||||
`libflint` is a library of common C data structures and algorithms, designed to be as agnostic as possible for its |
||||
users. |
||||
|
||||
## Requirements |
||||
|
||||
The only requirement is `libbsd`. This should be available on all major Linux distros. If building on a bsd, then |
||||
|
||||
## 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 'libflint'? |
||||
|
||||
`libflint` is named after my dog Flint, who passed away in 2021. I miss you, buddy. |
||||
|
||||
 |
@ -0,0 +1,202 @@
@@ -0,0 +1,202 @@
|
||||
# lfbinarytree |
||||
|
||||
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) |
||||
``` |
@ -0,0 +1,8 @@
@@ -0,0 +1,8 @@
|
||||
# lfbool |
||||
|
||||
Macro representation of truthy values |
||||
|
||||
```c |
||||
#define LFTRUE 1 |
||||
#define LFFALSE 0 |
||||
``` |
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
# lfinput |
||||
|
||||
I/O module to assist with consuming data from files |
||||
|
||||
## Functions |
||||
|
||||
### 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 |
||||
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(char **sp); |
||||
``` |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
# lfutility |
||||
|
||||
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; |
||||
``` |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
site_name: libflint |
||||
site_url: https://example.com |
||||
theme: |
||||
name: readthedocs |
||||
nav: |
||||
- 'index.md' |
||||
- 'Modules': |
||||
- 'Boolean': 'lfbool.md' |
||||
- 'Input': 'lfinput.md' |
||||
- 'Math': 'lfmath.md' |
||||
- 'Utility': 'lfutility.md' |
||||
- 'Data Structures': |
||||
- 'Binary Tree': 'lfbinarytree.md' |
||||
- 'Linked List': 'lflinkedlist.md' |
||||
- 'Set': 'lfset.md' |
||||
- 'Stack': 'lfstack.md' |
Loading…
Reference in new issue