📦 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.