A homebrew data structure library for use in personal projects.
Go to file
2018-03-24 17:14:09 -07:00
include Use const where applicable to allow for const data structures. 2018-03-24 17:14:09 -07:00
src Use const where applicable to allow for const data structures. 2018-03-24 17:14:09 -07:00
.clang-format Format code. 2016-12-21 15:07:01 -08:00
.gitignore Initial commit. Add .gitignore file. 2016-12-20 00:30:34 -08:00
CMakeLists.txt Make sure cmake uses C90 for this project. 2018-02-04 00:11:20 -08:00
README.md Add README.md 2017-01-09 18:49:59 -08:00

libds

A homemade data structure library for use in my personal projects.

Rationale

There is very little rationale for programming libds, looking at it from a very general poin of view. I've been rolling my own data structures in my other projects for quite some time now, and I got tired of it. So I wrote this. libds provides a library for three commonly used data structures, linked lists, growable-array-backed vectors and hash tables.

Usage

Because of how small libds is, it's possible to either include it as a subdirectory in a CMake project, or simply copy its header and source files into another project. The code for each data structure is self-contained, but all data structures depend on common libds header and source files that declare and implement "comparison" and "foreach" function types, as well as simple compare_always and compare_pointer comparison functions.

To use a data strcucture, it's only necessary to include the relevant header file, like "ll.h". Most data structures require the call to <data structure name>_init(<data structure pointer>), although they differ in whether memory is allocated or not during these calls.

Error Prone Functions

Some functions may be error prone - for instance, calling malloc inside a function COULD technically fail. Error-prone functions return an enum, LIBDS_RESULT, which is equal to LIBDS_SUCCESS if all goes well, or LIBDS_MALLOC if something went wrong. More erro codes will be implemented as necessary.

Comparison Functions

In order to simplify searching and executing code for every element in the data structure, I've typedef'ed two functions:

typedef int (*compare_func)(void*, void*);
typedef int (*foreach_func)(void*, va_list);

The comparison function is used whenever a search or selection is to be made from a data structure. It should return 1 if the comparison returned true, or 0 if the comparison returned false. Below is a sample implementation of a hypothetical compare_string function.

int compare_string(void*a, void* b){
  return strcmp(a, b) == 0;
}

The first parameter is the data given to whatever function invokes the comparison, and the second parameter is the current element in the data structure being compared with. For instance, in a Linked List containing the strings "A", "B", and "C", when a ll_find is called with the data "D" and a comparison function that always fails, the calls to the comparison function would be as follows:

compare_func("D", "A");
compare_func("D", "B");
compare_func("D", "C");

Comparison functions don't always have to be used on the same datatype - although the last parameter is always an element from the data structure, anything can be passed as the first parameter.

Foreach Functions

Foreach functions are used to execute a piece of code for every element in the list. The functions return an integer, 0 when all went well and a nonzero error code if there was a problem. The functions are passed a va_list together with the element being iterated over, so that any function calling foreach is able to pass any number of additional parameters. Functions that take a foreach function also take a piece of data and a comparison function, so that it is possible to select only certain elements for which the foreach function is to be performed. Example:

/* test_ll is a linked list with the words "if", "else" and "for". 
 * some_foreach_function_a expects no additional parameters and does nothing.
 * some_foreach_function_b prints the element given to it (as a string) as many times as an integer parameter passed to it.
 */

/* Will do nothing, but iterate through every element. */
ll_foreach(&test_ll, NULL, compare_always, some_foreach_function_a);
/* Will print every element 5 times. */
ll_foreach(&test_ll, NULL, compare_always, some_foreach_function_b, 5);
/* Will print only "else" 5 times. */
ll_foreach(&test_ll, "else", compare_string, some_foreach_function_b);

Further Documentation

For further documentation, please consult the headers for each of the data structures!

Tests

The main.c file contains all the tests written for the library, and running the libds executable will perform these tests.