π¦ A modern, modular, and powerful C standard library replacement β inspired by modern languages but built for C.
xstd is a lightweight, flexible, and expressive C standard library focused on developer productivity, safety, and ergonomics. It reimagines the C runtime and standard tooling for 2024 and beyond, introducing idioms and patterns inspired by languages like Rust, Go, and Zig β while remaining fully C-compatible and zero-dependency.
β³οΈ Highlights:
- Result types (
ResultOwnedStr,ResultOwnedBuff,Result<T>) β no moreNULLchecks or magic number errors. - Explicit memory ownership though typedefs (
OwnedStr,ConstStr,String,OwnedBuff,ConstBuff) β ownership is never implicit. - Modular allocators: arena allocators, buffer allocators, tracking/debug allocators, and
c_allocatora thin wrapper around cstd's malloc/free. - Modern tooling: string builders, hashmaps, IO abstractions, file APIs, and more.
- Safer APIs: bounds-checked string functions, typed list operations, and precise error propagation.
- Full introspection support: allocation metrics, file metadata, and crash diagnostics.
- Cross-platform compatibility: completely minimal interface built on top of stdlib.
The C standard library (stdlib) has served faithfully for decades, but:
β Memory management is unsafe and sometimes invisible β allocations are opaque, leaks happen silently.
β Error handling is often unintuitive β fopen() returns NULL and youβre already segfaulting.
β Working with strings is error-prone β strcat, strlen, global buffers...
β Arrays are unsafe β you never know their size.
β Unsafe and deprecated functions are still widely usable.
We think: C deserves better tooling, and we've built xstd to fill that void β a modern, fully C99-compatible library with minimal dependencies and huge ergonomics improvements.
β
Error-Driven Design
β’ Result<T> for allocation, file IO, string manipulation, parsing, hashing, etc.
β’ Clearly defined ErrorCode enum with human-readable messages.
β
Modern Allocator System
β’ Arena allocator β blazing fast, rolling block allocator
β’ Buffer allocator β stack-like allocator with free support
β’ Debug allocator β tracks leaks, counts allocations, checks double frees
β’ Default fallback stdlib allocator (c_allocator)
β’ Clean, pluggable design with full introspection
β
Strings & Buffers Made Safe
β’ Heap strings (owned), const strings, stack strings
β’ Builders for appending strings without unsafe strcat
β’ Fully bounds-checked copies, resizes, and concatenation
β’ File-safe string/bytes APIs
β’ UTF-8 compatible (ASCII-safe) character operations
β
Containers (with Types!)
β’ List<T> β realloc-style resizable vector with type checked push/pop
β’ HashMap<Str, T> β safe, dynamic key:value store with string key support
β’ Safe access macros: ListPushT, HashMapSetStrT, etc.
β
File IO You've Always Wanted
β’ file_readall_str() β read the whole file as a string
β’ file_read_bytes(n) β read n bytes safely
β’ file_write_uint(file, 1234)
β’ Line iterators, flushers, position readers, error checks, etc.
β
Writers = No More snprintf()
β’ Writers to buffered memory, dynamically growing buffers, strings
β’ Writer w; writer_write_uint(&w, 1234);
β
Crash Handling
β’ Setup crash handler with process_setup_crash_handler()
β’ Intercepts SIGSEGV, SIGABRT, SIGFPE, etc.
β
Math & String Parsing
β’ Overflow-checked math operations
β’ Safe string_parse_int, string_from_float, etc.
β’ Standard math ops: power, abs, mul, div, add with overflow detection
β
Fully Modular
β’ Include only what you need: xstd_io.h, xstd_file.h, xstd_list.h, etc.
β’ No global state, allocation decoupled from modules
β’ Platform compatibility via small, replaceable interfaces (xstd_os_int.h)
π Safety: All operations favor bounds-checked, well-defined behavior. Unsafe operations are explicitly marked.
π§ Predictability:
Every function either returns a Result<T> or sets up predictable invariants. No silent NULLs.
π‘ Composability: Allocators plug into lists, writers use buffers, hash maps use allocators β everything connects seamlessly.
π¨ Performance: Header-only, inlined functions. Arena allocators for batch allocations. Avoids unnecessary syscalls.
π₯ Simplicity: Simple, portable, and transparent. Absolutely no macros unless for type safety. No hacks. Always readable.
#include "xstd_core.h"
#include "xstd_string.h"
i32 main() {
Allocator *a = default_allocator();
// Most XSTD functions will either return void, Error, or ResultT
ResultStrBuilder builderRes = strbuilder_init(a); // Any function allocating memory will take a Allocator*
// Check for errors by comparing error code against 0
// Error code of 0 (ERR_OK) means success and a defined value,
// But error code != 0 means failure, and a very likely undefined value.
if (builderRes.error.code != ERR_OK) {
io_printerrln(ErrorToString(builderRes.error.code)) // All standard error codes have string representations
io_printerrln(builderRes.error.msg); // All xstd library errors will also have a descriptive error message!
return 1;
}
StringBuilder builder = builderRes.value; // Extract valid value out of result after error handling
// Push strings to the builder
strbuilder_push_copy(&builder, "Yes! "); // `strbuilder_push_owned` can be used for owned strings you want to push without copy.
strbuilder_push_copy(&builder, "We ");
strbuilder_push_copy(&builder, "Can!");
// Strings the user need to free will be returned through OwnedStr or ResultOwnedStr.
// This way, the intent is clear and explicitly declared through the code.
ResultOwnedStr builtRes = strbuilder_get_string(&builder);
// You do not have to compare the code to ERR_OK for it to achieve the same thing
if (builtRes.error.code) {
io_printerrln(builtRes.error.msg);
return 1;
}
OwnedStr built = builtRes.value;
io_println(built);
// We free the result string, since OwnedStr implies the consumer owns the
// string, it is our responsibility to free it.
// Strings that do not require freeing are passed as either ConstStr or String
a->free(a, built);
// Any call to x_init() should be followed by a call to x_deinit(),
// in order to free the memory.
strbuilder_deinit(&builder);
}- π Want to track leaks? Use the
DebugAllocatorto get peak memory stats and track unfreed blocks. - π₯· Building a DSL? Use
Writerto generate source-like text output. - π₯ Parsing input? Use
string_split_lines,string_parse_float,string_trim_whitespace. - πΎ Need simple caching? Use
HashMapSetStrTand free memory easily withhashmap_deinit.
- A bloated runtime
- A garbage collector
- A pthread-heavy concurrency abstraction
- A C++ STL polyfill
Itβs just modern utilities β nothing intrusive.
#include "xstd_io.h"
#include "xstd_string.h"
i32 main(void)
{
Allocator *a = default_allocator();
io_println("Hello from xstd!");
ResultOwnedStr intStr = string_from_int(a, -42);
if (intStr.error.code) {
io_printerrln(intStr.error.msg);
return 1;
}
io_println(intStr.value);
a->free(a, intStr.value);
return 0;
}| File | Description |
|---|---|
xstd_core.h |
Core types like u8, i64, Bool, Buffer, etc. |
xstd_alloc.h |
Allocator interface (Allocator, alloc) |
xstd_alloc_arena.h |
Arena (stack-like) allocator |
xstd_alloc_buffer.h |
Free-able buffer allocator |
xstd_alloc_debug.h |
Allocation-tracking wrapper |
xstd_io.h |
Terminal IO / assertions / prints |
xstd_file.h |
Cross-platform file reading & writing |
xstd_error.h |
Rich error handling |
xstd_string.h |
Safe strings & builders |
xstd_list.h |
Type-safe dynamic arrays |
xstd_hashmap.h |
Type-safe string-keyed hash maps |
xstd_writer.h |
Writers to buffer & string APIs |
xstd_math.h |
Overflow-safe math utilities |
xstd_result.h |
Result<T> structs |
xstd_vectors.h |
Vec2, Vec3 structs |
xstd_process.h |
Crash signal handlers |
- JSON & text parsing
- Cross-platform filesystem APIs
- More allocator types (slab, fixed-pool)
- Tighter
xstd_stringcodegen/writer integration - Unit tests via
xstd_test.h
Want to help improve C ergonomics? Fork this project and improve one of the modules!
We love:
- Better documentation
- New allocator types
- Performance improvements
- Bug fixes
- Language bindings
Open an issue or PR and join us!
- C developers who love modern patterns
- Embedded engineers who need safety without runtime
- Compiler authors needing tooling
- Systems programmers who want better ergonomics without C++
- You. If you're reading this.
β
Safer
β
Faster
β
Type-safe
β
Debuggable
β
Ergonomic
β
Just C
π MIT licensed | 100% portable | C99+ Contributions welcome.
Projects making use of xstd:
π Built with love for C β€οΈ
I'd like to thank ChatGPT for writing this README, really cool.