https://github.com/bamless/extlib
c extended library
https://github.com/bamless/extlib
array c c11 c99 dynamic dynamic-array dynamic-arrays hashmap hashmap-c hashtable single-header string string-buffer string-builder vector
Last synced: 16 days ago
JSON representation
c extended library
- Host: GitHub
- URL: https://github.com/bamless/extlib
- Owner: bamless
- License: mit
- Created: 2021-02-13T16:29:06.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2026-04-06T08:55:32.000Z (21 days ago)
- Last Synced: 2026-04-06T10:29:24.247Z (21 days ago)
- Topics: array, c, c11, c99, dynamic, dynamic-array, dynamic-arrays, hashmap, hashmap-c, hashtable, single-header, string, string-buffer, string-builder, vector
- Language: C
- Homepage:
- Size: 465 KB
- Stars: 10
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# extlib: c extended library
[](https://github.com/bamless/extlib/actions/workflows/build.yml)
extlib is a header-only library that implements common data structures and algorithms that are not
provided by the c standard library.
Features:
- Context abstraction to easily modify the application's allocation and logging behaviour
- Custom Allocators that easily integrate with the context and datastructures
- Generic, type-safe dynamic arrays and hash maps
- StringBuffer for easily working with dynamic buffers of bytes
- StringSlice for easy manipulation of immutable 'views' over byte buffers
- Cross-platform IO functions for working with processes, files and more generally
interacting with the operating system
- Configurable logging
- Misc utility macros
- No-std and wasm support
## Quickstart
To use the library do this in *exactly one* c file:
```c
#define EXTLIB_IMPL
// Optional configuration options
#include "extlib.h"
```
> NOTE: The library by default exports all symbols without any prefix. If you find any conflicts
> when using in your project, you can define `EXTLIB_NO_SHORTHANDS` before including any of the
> library headers to disable names without prefixes.
Configuration options:
```c
#define EXTLIB_NO_SHORTHANDS // Disable shorthands names, only prefixed one will be defined
#define EXTLIB_NO_STD // Do not use libc functions
#define EXTLIB_WASM // Enable when compiling for wasm target. Implies EXTLIB_NO_STD
#define EXTLIB_THREADSAFE // Thread safe Context
#define EXTLIB_SHARED_EXPORT // Mark all public API symbols for shared library use (see below)
#define NDEBUG // Strips runtime assertions and replaces unreachables with compiler
// intrinsics
```
### Building as a shared library
Define `EXTLIB_SHARED_EXPORT` to enable the `EXT_API` visibility attribute on all public symbols,
making it possible to compile extlib as a DLL or shared object.
The macro behaves differently depending on whether the translation unit is building the
implementation or consuming it:
- **Implementation TU** (`EXTLIB_IMPL` defined): symbols are *exported*.
- **Consumer TUs** (`EXTLIB_IMPL` not defined): symbols are *imported*.
On **Windows** this maps to `__declspec(dllexport)` / `__declspec(dllimport)`.
On **GCC / Clang** both use `__attribute__((visibility("default")))`.
On unrecognized compilers/platforms the attribute expands to nothing.
On GCC / Clang it is strongly recommended to compile the shared library with
`-fvisibility=hidden`. Without it all symbols are public by default, defeating the purpose of
`EXT_API` and leaking internal symbols into the DSO's export table. `EXT_API` then selectively
restores visibility only for the symbols that are meant to be public.
A typical CMake setup looks like:
```cmake
# Shared library target — EXTLIB_IMPL builds the implementation and exports symbols.
# -fvisibility=hidden ensures only EXT_API-marked symbols are exported on GCC/Clang.
add_library(extlib SHARED extlib_impl.c)
target_compile_definitions(extlib PRIVATE EXTLIB_IMPL EXTLIB_SHARED_EXPORT)
target_compile_options(extlib PRIVATE $<$:-fvisibility=hidden>)
# Consumer target — only EXTLIB_SHARED_EXPORT is defined so symbols are imported
target_compile_definitions(my_app PRIVATE EXTLIB_SHARED_EXPORT)
target_link_libraries(my_app extlib)
```
Where `extlib_impl.c` contains exactly:
```c
#define EXTLIB_IMPL
#include "extlib.h"
```
## Examples
You can find a bunch of examples showcasing library features in `examples/`
### Minimal example
```c
#include
#include
#define EXTLIB_IMPL
#include "extlib.h"
typedef struct {
StringSlice key;
int value;
} WordFreq;
// Could also create this typedef with `HashMap` utility macro:
// typedef HashMap(StringSlice, int) WordMap;
typedef struct {
WordFreq* entries;
size_t* hashes;
size_t size, capacity;
Allocator* allocator;
} WordMap;
// Could also create this typedef with `Array` utility macro:
// typedef Array(StringSlice) Words;
typedef struct {
StringSlice* items;
size_t size, capacity;
Allocator* allocator;
} Words;
int main(int argc, char** argv) {
// Push context with temp allocator so that we don't need to free
Context ctx = *ext_context;
ctx.alloc = &temp_allocator.base;
push_context(&ctx);
Words words = {0};
// Could also specify allocators on a per-datastructure level
// words.allocator = &default_allocator.base
int i;
for(i = 1; i < argc; i++) {
StringSlice line = ss_from_cstr(argv[i]);
while(line.size) {
StringSlice word = ss_split_once_ws(&line);
array_push(&words, word);
}
}
ext_log(INFO, "Processed %d lines", i-1);
printf("Words:\n");
array_foreach(StringSlice, it, &words) {
printf(" " SS_Fmt "\n", SS_Arg(*it));
}
WordMap word_freqs = {0};
array_foreach(StringSlice, it, &words) {
WordFreq* e = hmap_get_default_ss(&word_freqs, *it, 0);
e->value++;
}
printf("Frequency:\n");
hmap_foreach(WordFreq, it, &word_freqs) {
printf(" " SS_Fmt ": %d\n", SS_Arg(it->key), it->value);
}
pop_context();
}
```
## Tests
You can find tests in `test/test.c`. To run them:
```sh
make test
```