MCPcopy Index your code
hub / github.com/KaisenAmin/c_std

github.com/KaisenAmin/c_std @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
2,789 symbols 5,648 edges 110 files 2,428 documented · 87%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

C STL — C++ Standard Library & Python-style utilities, reimplemented in C

c_std — C++ STL & Python-style utilities, reimplemented in pure C17

This project reimplements a large slice of the C++ Standard Library (containers, algorithms, smart pointers, …) together with many Python-style conveniences (statistics, random, secrets, json, regex, …) in pure C17. The goal is to give C developers familiar, well-documented building blocks — dynamic arrays, maps, strings, JSON, networking, big integers, and much more — without leaving the C ecosystem.

Highlights

  • Zero memory leaks. Every module, test suite, and README example is verified under Valgrind (--leak-check=full) — 0 leaks, 0 errors. Network/socket code is additionally checked for descriptor leaks (--track-fds=yes).

  • Cross-platform. Builds and runs on Windows (MSVC and MinGW-w64) and Linux (GCC/Clang), with POSIX/Win32 backends behind one API. Compiles cleanly under -Wall -Wextra.

  • Pure C17. No C++ — just portable standard C with thin platform shims.

  • 40+ modules. Containers, algorithms, smart pointers, strings, JSON/XML/CSV/INI, networking (TCP/UDP/HTTP), crypto & JWT, arbitrary-precision math, graphics, and more.

  • Familiar APIs. Modeled on the C++ STL (vector, map, unique_ptr, …) and the Python standard library (random, statistics, json, regex, turtle, …).

  • Heavily tested with true results. Deep per-module test suites, plus runnable examples in every README whose shown output is captured from a real run.

  • Fast & predictable. Efficient data structures (geometric vector growth with inlined push_back/at, O(1) average hashmap, O(log n) map), clear ownership rules and deallocators.

  • CMake build. Build the whole library, a single module, or one example at a time, with GCC, Clang, or MSVC.

Benchmarks vs the C++ STL

The library aims to be fast where it counts. The table below pits each C container against its C++ <stl> counterpart on the same workload, the same data, and the same compiler family at -O2. Both programs walk an identical deterministic key stream and compute identical checksums, so they do exactly the same work — only the container implementation differs.

Environment: Windows 10, MinGW-w64 GCC / G++ 14.2.0, -O2, single thread, best of three runs (lower is better). Absolute numbers vary by machine; the ratio is what carries over.

C container ↔ C++ STL Workload (N) C STL C++ STL C ÷ C++
vectorstd::vector<int> push_back + sum, 10,000,000 0.041 s 0.031 s 1.3×
mapstd::map<int,int> (ordered / RB-tree) insert + lookup, 1,000,000 1.00 s 1.20 s 0.83×
hashmapstd::unordered_map<int,int> insert + lookup, 1,000,000 0.231 s 0.364 s 0.63×
setstd::set<int> (ordered / RB-tree) insert + lookup, 1,000,000 1.17 s 1.05 s 1.1×
priority_queuestd::priority_queue<int> push + pop (heap-sort), 1,000,000 0.156 s 0.108 s 1.4×
dequestd::deque<int> push_back + iterate + pop_front, 1,000,000 0.009 s 0.004 s 2.2×
liststd::list<int> push_back + iterate + teardown, 1,000,000 0.093 s 0.075 s 1.2×
forward_liststd::forward_list<int> push_front + iterate + teardown, 1,000,000 0.080 s 0.076 s 1.05×
queuestd::queue<int> enqueue + dequeue (FIFO), 1,000,000 0.006 s 0.003 s 2.0×
stackstd::stack<int> push + pop (LIFO), 1,000,000 0.005 s 0.003 s 1.7×

C ÷ C++ is the C time divided by the C++ time — below 1.0 means the C library is faster.

  • Where C wins — map and hashmap. Both allocate their tree nodes / buckets from a pooled slab allocator, so a million inserts cost a handful of big mallocs instead of a million tiny ones, beating the STL's per-node new.
  • About set — near parity. Same pooled-slab, inline-element RB-tree as map. Lookups are actually a hair faster than std::set; inserts are a little slower, so it nets ~1.1×. Unlike map (which stores caller-owned pointers and skips the copy), set has value semantics and deep-copies each element exactly like std::set, so it can't win the copy back — and its node carries the publicly-inspectable key/left/right/parent/color fields (the test suite walks them to check the red-black invariants), which a templated std::set node doesn't expose. A large RB-tree is cache-miss-bound, so that slightly larger node is the whole gap.
  • Where C++ wins — vector and priority_queue. Both are tight loops over raw ints. The C vector now inlines push_back/at at the call site just like std::vector and closes most of the gap (~1.3×); the small residual is the type-erased ABI — a runtime itemSize stride and a size-dispatched element copy where C++ has a compile-time sizeof(int), plus the bounds check in vector_at that operator[] skips. The C priority_queue size-dispatches its heap moves the same way (~1.4×); its residual is the comparator — one indirect call through a function pointer per comparison, which std::priority_queue inlines from its template argument. Either way it's a small fixed per-element cost — the price of a uniform C API — not a worse complexity.
  • About deque. The C deque stores elements inline in byte-budgeted block buffers (one allocation per block, not one malloc per element) and inlines front / back / at with shift-indexed block math like std::deque, so it lands at ~2.2×; the residual is the out-of-line push_back / pop_front calls that std::deque inlines from templates.
  • About list. Each node stores its element inline in the same allocation (one malloc per node, like std::list) instead of a second heap block per element, which roughly halves the allocation/teardown cost and lands it at ~1.2×. The residual is a slightly larger node — the type-erased API keeps a value pointer and aligns the inline element for any type — plus the out-of-line per-node call std::list inlines.
  • About forward_list — at parity. It already uses the same single-node- allocation, inline-element design as std::forward_list, so push_front / iterate / teardown match it within measurement noise (≈1.05×). No type-erasure penalty survives here because the per-node malloc dominates and both pay it once per element.
  • About queue. The C queue is a contiguous vector used as a ring: enqueue appends and dequeue advances a front index (an O(1) bump, not a buffer shift), with the dead front prefix reclaimed in bulk when the buffer fills — so both ends are amortized O(1), like std::queue. The hot ops are inlined; the ~2× residual is the per-element copy into the contiguous buffer vs std::queue's deque node writes. (Previously dequeue shifted the whole buffer — O(n), an O(n²) drain; that's fixed.)
  • About stack. LIFO at the back of a contiguous vector, so push and pop are already O(1). push / top / pop / empty are now inlined in the header (the way std::stack inlines through its container), which cut it from ~3.3× to ~1.7×; the residual is the vector's amortized realloc-copy on growth vs std::stack's default deque adding blocks — in exchange the C stack keeps its elements fully contiguous.

Reproduce it yourself — a C and a C++ program over the identical key stream:

# C  (link the containers used + algorithm, which queue depends on):
gcc -O2 bench.c vector/vector.c queue/queue.c priority_queue/priority_queue.c \
    hashmap/hashmap.c map/map.c algorithm/algorithm.c -I. -o bench_c && ./bench_c
# C++:
g++ -O2 -std=c++17 bench.cpp -o bench_cpp && ./bench_cpp

A personal note

I undertake this project out of a deep affection for the C programming language. C remains an essential tool for any computer engineer, providing the foundation needed to build efficient and robust software. This effort aims to enrich the language with the conveniences found in higher-level standard libraries.


Table of contents


Modules

Every module lives in its own directory with a .c source, a .h header, and a README.md containing a full API reference and runnable examples.

Containers

Module Analogous to Description
array std::array Fixed-size array wrapper with bounds-checked access.
vector std::vector Dynamic, automatically resizing array with memory pooling.
string std::string Growable string with a rich manipulation API (string/std_string.h).
list std::list Doubly linked list.
forward_list std::forward_list Singly linked list.
deque std::deque Double-ended queue with fast insertion/removal at both ends.
queue std::queue FIFO queue.
stack std::stack LIFO stack.
priority_queue std::priority_queue Heap-backed priority queue with a custom comparator.
span std::span Non-owning view over a contiguous sequence.
bitset std::bitset Fixed-size sequence of bits with bitwise operations.
map std::map Ordered associative container (Red-Black tree, O(log n)).
hashmap std::unordered_map Hash table with O(1) average insert/lookup and automatic rehashing.
set std::set Ordered, unique associative container (Red-Black tree, O(log n));
tuple std::tuple Fixed-size heterogeneous collection.
variant std::variant Type-safe tagged union with a visitor interface.
uniqueptr std::unique_ptr RAII smart pointer with automatic, scope-based cleanup.

Algorithms & numerics

Module Description
algorithm Generic algorithms inspired by <algorithm>: sort, search, transform, accumulate, …
sort Stand-alone sorting library: 8+ algorithms, benchmarking and search helpers.
statistics Mean, median, variance, … (mirrors Python's statistics).
random Pseudo-random numbers and sequence helpers (mirrors Python's random).
secrets Cryptographically secure random numbers/tokens and constant-time comparison.
uuid RFC 9562 Universally Unique Identifiers (v4/v7/v3/v5, Nil/Max), mirroring Python's uuid.
numbers Mathematical constants (header-only, like C++20 <numbers>).
matrix Matrix creation, manipulation and linear-algebra operations.
bigint Arbitrary-precision integers (backed by GMP).
bigfloat Arbitrary-precision floating point (backed by MPFR).
evalexpr Runtime arithmetic-expression evaluator.

Text, data & I/O

Module Description
fmt Formatting / I/O library inspired by Go's fmt, with Unicode support.
encoding Base64 / Base32 / Base16 / URL encoding and decoding.
json Parse, generate and manipulate JSON.
xml Parse, create, modify and traverse XML documents.
csv Read, write and manipulate CSV files.
config Read/modify/save INI-style configuration files.
regex Regular-expression compile/match/search (PCRE on Windows, POSIX on Linux).
cli Command-line argument/option/sub-command parser.
log Leveled logging (DEBUG…FATAL) to console and/or file.
file_io FileReader / FileWriter with text and binary (UTF-8/UTF-16) modes.
dir Directory and filesystem manipulation.

Time & date

Module Description
time Time measurement and manipulation (time/std_time.h).
date Gregorian and Persian calendar dates, conversions and arithmetic.

System & concurrency

Module Description
sysinfo OS / hardware information (Windows & Linux).
concurrent Threads, mutexes, condition variables, semaphore and a thread pool.
serial_port Serial-port (RS-232) communication.

Security

Module Description
crypto Hashing, encryption/decryption and other primitives (backed by OpenSSL).
jwt JSON Web Token creation/verification (HS/RS/ES/PS families).

Networking & databases

Module Description
network TCP and UDP sockets plus a small HTTP server/client.
database PostgreSQL client built on libpq (optional — only built when libpq is present).

Graphics

Module Description
plot 2-D plotting (line/scatter/bar) built on raylib.
turtle Turtle graphics, inspired by Python's turtle (built on raylib).

Testing

Module Description
unittest Lightweight unit-testing framework (assertions, suites, fixtures).

Dependencies

To build the whole project you need:

Build tools - CMake ≥ 3.15 - A C17 compiler — GCC, Clang, or MSVC - A generator — Ninja (reco

Core symbols most depended-on inside this repo

matrix_create
called by 236
matrix/matrix.c
matrix_deallocate
called by 114
matrix/matrix.c
string_strdup
called by 105
string/std_string.c
mutex_unlock
called by 88
concurrent/concurrent.c
udp_set_last_error
called by 58
network/udp.c
json_deallocate
called by 54
json/json.c
encoding_utf8_to_wchar
called by 53
encoding/encoding.c
vector_size
called by 45
vector/vector.c

Shape

Function 2,651
Class 137
Enum 1

Languages

C96%
C++4%

Modules by API surface

matrix/matrix.c306 symbols
string/std_string.c120 symbols
sysinfo/sysinfo.c103 symbols
variant/variant.c98 symbols
jwt/jwt.c97 symbols
algorithm/algorithm.c89 symbols
database/postgres.c88 symbols
xml/xml.c74 symbols
network/http.c74 symbols
turtle/turtle.c71 symbols
json/json.c70 symbols
network/tcp.c67 symbols

Datastores touched

appDatabase · 1 repos

For agents

$ claude mcp add c_std \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact