Skip to content

osvaldoandrade/ova-lib

Repository files navigation

ova-lib

ova-lib is a C11 library of data structures and numeric helpers. The tree on main exposes 14 module headers plus ova.h and types.h, builds 32 library translation units, and runs 22 unit-test executables through CTest. The library keeps payload ownership with the caller and stores user data as void * across the container APIs.

What Ships

The current public surface groups into 8 areas.

Area Headers Notes
Linear containers list.h, queue.h, stack.h, deque.h Array, linked, sorted, FIFO, priority, and double-ended flows
Priority structures heap.h, sort.h Binary heap, Fibonacci heap, and list-based sorting helpers
Keyed storage map.h, set.h, tree.h, trie.h Hash table, ordered trees, sets, and prefix lookup
Numeric helpers matrix.h, solver.h Matrix arithmetic, vectors, and a simplex solver
Graphs graph.h Directed or undirected graphs with pluggable traversal and shortest-path strategies
Probabilistic lookup bloom_filter.h Tunable false-positive membership checks
Umbrella include ova.h Re-exports the main headers
Shared types types.h Comparator and hash typedefs

Documentation

Project documentation now lives in the GitHub wiki.

Build

CMakeLists.txt requires CMake 3.10 or newer and sets C_STANDARD 11. If your CMake build supports presets, the repo ships two configure presets in CMakePresets.json.

cmake --preset dev
cmake --build build/dev

For a release build:

cmake --preset release
cmake --build build/release

The manual path stays short:

mkdir -p build
cmake -S . -B build
cmake --build build

The build produces libova_lib.a and libova_lib.so under the build lib/ directory. cmake --install copies headers into <prefix>/include, libraries into <prefix>/lib, and ova-lib.pc into <prefix>/lib/pkgconfig.

Tests

CTest drives 22 executables listed in CMakeLists.txt.

ctest --test-dir build/dev --output-on-failure

If Valgrind is installed when CMake configures the tree, the memcheck target is available:

cmake --build build/dev --target memcheck

Fuzzing

LibFuzzer harnesses live in fuzz/ for the hash map (fuzz_hash_map), list sorter (fuzz_sort), and matrix module (fuzz_matrix). Enable them with Clang so -fsanitize=fuzzer,address is available:

mkdir -p build/fuzz
cmake -S . -B build/fuzz -DCMAKE_C_COMPILER=clang -DOVA_BUILD_FUZZERS=ON
cmake --build build/fuzz --target fuzz_hash_map fuzz_sort fuzz_matrix

Run any harness directly, for example:

./build/fuzz/bin/fuzz_hash_map -runs=100

The project currently has no parser component, so no parser fuzzer is required.

Examples

This list example uses the array-backed implementation and reads values back by index.

#include "list.h"

int main(void) {
    list *values = create_list(ARRAY_LIST, 4, NULL);
    int a = 3, b = 5;

    values->insert(values, &a, 0);
    values->insert(values, &b, 1);

    int *first = (int *)values->get(values, 0);
    int *second = (int *)values->get(values, 1);

    values->free(values);
    return first && second && *first == 3 && *second == 5 ? 0 : 1;
}

This queue example uses the heap-backed priority variant. The comparator decides what "higher priority" means.

#include "queue.h"

static int int_cmp(const void *a, const void *b) {
    int lhs = *(const int *)a;
    int rhs = *(const int *)b;
    return (lhs > rhs) - (lhs < rhs);
}

int main(void) {
    queue *pq = create_queue(QUEUE_TYPE_PRIORITY, 8, int_cmp);
    int low = 2, high = 9;

    pq->enqueue(pq, &low);
    pq->enqueue(pq, &high);

    int *top = (int *)pq->dequeue(pq);
    pq->free(pq);
    return top && *top == 9 ? 0 : 1;
}

This graph example selects traversal and shortest-path behavior at construction time while keeping the runtime API algorithm-agnostic.

#include "graph.h"

int main(void) {
    graph *g = create_graph(GRAPH_DIRECTED,
                            GRAPH_ADJACENCY_LIST,
                            GRAPH_TRAVERSE_BFS,
                            GRAPH_MIN_PATH_DIJKSTRA);
    vector *dist = NULL;

    g->add_edge(g, 0, 1, 1.0);
    g->add_edge(g, 1, 2, 2.0);
    g->min_path(g, 0, &dist);

    double d = dist ? dist->get(dist, 2) : -1.0;
    if (dist) {
        dist->free(dist);
    }
    g->free(g);
    return d == 3.0 ? 0 : 1;
}

License

ova-lib is licensed under the Apache 2.0 license.

About

This is a compact toolkit offering some data structures in ANSI C for my personal projects. It is designed for simplicity and POSIX portability.

Resources

License

Contributing

Stars

Watchers

Forks

Contributors