jenspots / libwheel

Generic data structures for the C programming language with (near) zero overhead.
GNU Affero General Public License v3.0
8 stars 0 forks source link
c generics

CTest

Wheel

This repository provides a "generic datastructures in C" proof-of-concept. Wheel heavily relies on the C preprocessor and resolves at compile time, allowing for generics with (near) zero overhead.

Note that this library is still in a very early stage and should not be trusted. Expect ridiculous bugs and errors!

Example

One of the provided datastructures is optional, which either contains a value or doesn't. The definition in <wheel/optional/impl.h> is as followed.

typedef struct optional {
    bool present;
    LIBWHEEL_TYPE value;
} optional;

Here, the type LIBWHEEL_TYPE is a generic. We can instantiate it to a string, in essence a char* in the C language. When your application uses Wheel, you may define the header file string.h as shown below.

#ifndef STRING_H
#define STRING_H

#define LIBWHEEL_TYPE  char*
#define LIBWHEEL_ALIAS string

#include <wheel.h>

#endif // STRING_H

If you are unfamiliar with the #ifndef STRING_H convention, this simply makes sure this specific header file isn't send to the compiler more than once. It is not in any way specific to the library itself.

We define LIBWHEEL_TYPE, which is what the preprocessor will fill in for every instance of LIBWHEEL_TYPE in <wheel/optional/impl.h>. Here, we want it to be char*.

The name of a struct cannot contain asterisks, so a type definition like struct optional_char* would be invalid. This means will also have to pass a second argument which will dictate the suffix given to every function and struct, since those still have to be unique. This is where LIBWHEEL_ALIAS comes in, here mapped to string. The resulting type will be optional_string.

Since you most likely will use these macros multiple times in your program, we remove their definition using #undef at the bottom of string.h.

Now, the optional type in string.h will take the following form at compile time.

#ifndef STRING_H
#define STRING_H

typedef struct optional_string {
    bool present;
    char* value;
} optional_string;

optional_string optional_empty_string() {
    optional_string result;
    result.present = false;
    return result;
}

// etc

#endif // STRING_H

Creating a generic data structure and its procedures is now as simple as defining some macros and including the <wheel.h> header!