Skip to content

Repository files navigation

zstr.h

zstr.h is a modern, single-header string library for C projects. Designed to mimic the architecture of C++ std::string (specifically Small String Optimization and Views), it offers a safe, convenient API while remaining pure C.

It includes a robust C++17 wrapper for mixed codebases, and optional Lua 5.x bindings for high-performance string manipulation in scripts.

Features

  • Small String Optimization (SSO): Strings shorter than 23 bytes are stored directly on the stack (inside the struct), avoiding heap allocation entirely.
  • View Semantics: Distinct zstr (owning) and zstr_view (non-owning) types allow for zero-copy slicing and parsing.
  • Safe & Auto-Growing: Buffer overflows are handled by automatic reallocation.
  • C++ Support: Includes a full C++ class wrapper (z_str::string) with RAII, move semantics, and std::string_view compatibility.
  • Lua Support: Provides a mutable string buffer for Lua to avoid garbage generation during complex string building.
  • UTF-8 Aware: Includes helpers for UTF-8 validation and rune counting.
  • Zero Dependencies: Only standard C headers used.

Installation

C/C++ (Header Only)

zstr is a concrete type, so setup is straightforward.

  1. Copy zstr.h (and zcommon.h if separated) into your project's include directory.
  2. Include it in your code.

Lua Binding (Shared Library)

To use zstr in Lua, you must compile the binding into a shared library (zstr.so or zstr.dll).

# Compile the module (adjust paths to your Lua headers).
gcc -O3 -shared -fPIC -o zstr.so bindings/lua/zstr_module.c -Iinclude -I/usr/include/lua5.4 -llua5.4

You can also use the Makefile with:

make lua

You will need to change the Makefile to support different versions.

Usage: C

#include<stdio.h>#include"zstr.h"intmain(void)
{
// Initialize (SSO avoids malloc here).zstrs=zstr_lit("Hello");
// Concatenate using printf-style formatting.zstr_fmt(&s, ", %s!", "World");
// Access C-string safely.printf("%s\n", zstr_cstr(&s)); // "Hello, World!"// Create a zero-copy view of the first 5 chars.zstr_viewv=zstr_sub(zstr_as_view(&s), 0, 5);
// Cleanup.zstr_free(&s);
return0;
}

Usage: C++

The library detects C++ compilers automatically. To avoid naming collisions with the C struct zstr, the C++ classes live in the z_str namespace.

#include<iostream>
#include"zstr.h"intmain()
{
// RAII handles memory automatically (Constructor/Destructor).
z_str::string s = "Hello";
// Operator overloads.
s += " World!";
// Modern C++17 string_view support.
z_str::view v = s; // Static formatting helper (Safety Warning: Only pass POD types!).
z_str::string log = z_str::string::fmt("ID: %d", 42);
std::cout << s << std::endl; // "Hello World!"return0;
}

Usage: Lua

zstr acts as a high-performance mutable string buffer for Lua. It avoids the garbage collection overhead of repeated string concatenation.

localzstr=require("zstr")
-- Create a buffer (allocates once).localbuf=zstr.new("Start: ")
-- Append efficiently (no new Lua objects created).buf:append("User: ")
:append("Alice")
:append(" [Admin]")
-- Modify in-place.buf:upper() -- "START: USER: ALICE [ADMIN]"buf:trim()
-- Convert back to Lua string only when needed.print(tostring(buf)) print("Length: " ..#buf)

API Reference (C)

Initialization & Creation

FunctionDescription
zstr_init()Returns an empty string {0}.
zstr_from(const char *s)Creates a new zstr from a standard C-string.
zstr_from_len(const char *p, size_t len)Creates a zstr from a buffer and explicit length.
zstr_lit("literal")Optimized macro for string literals (calculates length at compile time).
zstr_dup(const zstr *s)Creates a deep copy of an existing zstr.
zstr_with_capacity(size_t cap)Creates an empty string with pre-allocated heap capacity.
zstr_read_file(path)Reads an entire file into a new zstr. Returns empty on failure.
zstr_own(ptr, len, cap)Takes ownership of a raw malloc'd buffer.

Memory Management

FunctionDescription
zstr_free(s)Frees the string if it is on the heap and resets it to empty.
zstr_clear(s)Sets length to 0 but preserves capacity.
zstr_reserve(s, cap)Ensures the string has space for at least cap bytes.
zstr_shrink_to_fit(s)Reduces heap usage to fit the length (or moves back to SSO).
zstr_take(s)Returns the raw malloc'd pointer and resets the zstr (caller must free).

Modification

FunctionDescription
zstr_cat(s, str)Appends a C-string to the end.
zstr_cat_len(s, ptr, len)Appends a raw buffer of known length.
zstr_push(s, char)Appends a single character (alias for zstr_push_char).
zstr_pop_char(s)Removes and returns the last character.
zstr_fmt(s, fmt, ...)Appends a formatted string (printf-style).
zstr_join(arr, n, delim)Joins an array of strings into a new zstr.
zstr_trim(s)Removes leading and trailing whitespace in-place.
zstr_to_lower(s)Converts to lowercase in-place (ASCII only).
zstr_to_upper(s)Converts to uppercase in-place (ASCII only).
zstr_replace(s, old, new)Replaces all occurrences of old with new.

Accessors & Helpers

FunctionDescription
zstr_len(s)Returns the current length (excluding null terminator).
zstr_data(s)Returns a pointer to the mutable data buffer.
zstr_cstr(s)Returns a const char* safe for C APIs.
zstr_is_empty(s)Returns true if the string length is 0.
zstr_is_long(s)Returns true if the string is currently heap-allocated.

Comparison & Search

FunctionDescription
zstr_eq(a, b)Returns true if strings are equal (faster than strcmp).
zstr_eq_ignore_case(a, b)Returns true if strings are equal (case-insensitive, ASCII only).
zstr_cmp(a, b)Standard strcmp behavior for zstr objects.
zstr_find(s, needle)Returns index of first occurrence or -1 if not found.
zstr_contains(s, needle)Returns true if the string contains the substring.
zstr_starts_with(s, pre)Checks if string starts with prefix.
zstr_ends_with(s, suf)Checks if string ends with suffix.

Views & Slices (Zero-Copy)

FunctionDescription
ZSV("lit")Macro to create a zstr_view from a literal.
zstr_as_view(s)Returns a zstr_view covering the whole string.
zstr_view_from(cstr)Creates a view from a C-string.
zstr_from_view(v)Converts a view back into an owning zstr (allocates).
zstr_sub(v, start, len)Returns a view slice (substring) without copying memory.
zstr_view_eq(v, cstr)Checks if view equals a C-string.
zstr_view_eq_view(a, b)Checks if two views are equal.
zstr_view_starts_with(v, pre)Checks if view starts with prefix.
zstr_view_ends_with(v, suf)Checks if view ends with suffix.
zstr_view_lstrip(v)Returns view with leading whitespace removed.
zstr_view_rstrip(v)Returns view with trailing whitespace removed.
zstr_view_trim(v)Returns view with both ends trimmed.
zstr_view_to_int(v, out)Parses an integer from a view (like atoi).

UTF-8 Support

FunctionDescription
zstr_is_valid_utf8(s)Validates string is strict UTF-8 (rejects overlongs/surrogates).
zstr_count_runes(s)Counts the number of actual UTF-8 Runes (not bytes).
zstr_next_rune(ptr)Decodes next rune and advances pointer. Returns 0xFFFD on error.

Iteration (Splitting)

FunctionDescription
zstr_split_init(src, delim)Initializes a split iterator (zstr_split_iter).
zstr_split_next(it, out)Advances iterator and populates out (view) with the next part.

Extensions (Experimental)

If you are using a compiler that supports __attribute__((cleanup)) (like GCC or Clang), you can use the Auto-Cleanup extension.

MacroDescription
zstr_autofreeDeclares a variable that automatically calls zstr_free when it leaves scope.

Example:

voidlog_status()
{
zstr_autofreemsg=zstr_from("Status: ");
zstr_cat(&msg, "OK");
// msg is freed automatically here.
}

API Reference (C++)

The C++ wrapper is defined in the z_str namespace to avoid collisions with the C struct. It strictly adheres to RAII principles and is designed to drop into existing C++11/17 projects.

class z_str::string

An owning string class that internally manages a zstr struct.

Constructors & Management

MethodDescription
string()Default constructor (empty).
string(const char*)Construct from C-string.
string(std::string_view)Construct from C++17 string view.
own(ptr, len, cap)Static. Wraps an existing malloc'd buffer without copying.
from_file(path)Static. Reads entire file into a string.
release()Returns the raw char* and empties the object. Caller must free().

Access & Iterators

MethodDescription
c_str(), data()Returns const char*.
size(), length()Returns length in bytes.
capacity()Returns current allocated capacity.
is_empty()Returns true if length is 0.
operator[]Mutable/Const access to character at index.
front(), back()Access first/last character.
begin(), end()Standard iterators (pointers) compatible with STL algorithms.

Modification

MethodDescription
append(s) / +=Appends C-string, character, or other z_str::string.
push_back(c)Appends a single char.
pop_back()Removes and returns the last char.
replace(old, new)Replaces all occurrences of string old with new.
to_lower(), to_upper()In-place case conversion (ASCII).
trim()In-place whitespace removal.
clear()Sets length to 0 (capacity remains).
fmt(fmt, ...)Static. Creates a string via printf formatting.
Warning: Pass only POD types (int, char*), not C++ objects.

Search & Utilities

MethodDescription
find(needle)Returns index of substring or -1.
contains(needle)Returns true if substring exists.
starts_with(s)Returns true if string starts with s.
ends_with(s)Returns true if string ends with s.
split(delim)Returns a split_iterable for use in range-based for loops.
Safety: Deleted for r-values (temporaries) to prevent dangling views.
rune_count()Returns the number of UTF-8 code points.
is_valid_utf8()Returns true if the string contains valid UTF-8.

class z_str::view

A lightweight, non-owning wrapper around zstr_view. Compatible with std::string_view (C++17).

MethodDescription
view(string&)Implicit conversion from z_str::string.
sub(start, len)Returns a new view slice.
lstrip(), rstrip(), trim()Returns a new view with whitespace removed.
to_int(out)Parses view to integer. Returns true on success.
starts_with, ends_withPredicate checks.
operator==Compares with view, string, or const char*.

API Reference (Lua)

The Lua module exports a zstr table with constructors. Instances are userdata objects with methods.

Constructors

FunctionDescription
zstr.new([str])Creates a new buffer, optionally initialized with str.
zstr.from_file(path)Reads an entire file into a buffer.

Buffer Methods

MethodDescription
s:append(str...)Appends one or more strings to the buffer. Returns self.
s:reserve(n)Pre-allocates capacity for n bytes.
s:clear()Empties the buffer (length 0).
s:clone()Returns a deep copy of the buffer.
s:capacity()Returns the current allocated capacity.

Transformations (In-Place)

MethodDescription
s:trim()Removes leading/trailing whitespace.
s:upper()Converts to uppercase (ASCII).
s:lower()Converts to lowercase (ASCII).
s:replace(old, new)Replaces all occurrences of old with new.

Queries

MethodDescription
s:contains(sub)Returns true if sub is found.
s:starts_with(sub)Returns true if buffer starts with sub.
s:ends_with(sub)Returns true if buffer ends with sub.
s:is_valid_utf8()Returns true if content is valid UTF-8.
s:rune_count()Returns the number of UTF-8 characters.

Utilities

MethodDescription
s:split(delim)Returns a Lua table (array) of strings split by delim.
#s (Len operator)Returns the length in bytes.
tostring(s)Converts the buffer to a standard Lua string.

Memory Management

By default, zstr.h uses the standard C library functions (malloc, realloc, free).

However, you can override these to use your own memory subsystem (e.g., Memory Arenas, Pools, or Debug Allocators).

First Option: Global Override (Recommended)

To use a custom allocator globally across all z-libs, define the Z_ macros before including zstr.h.

// my_config.h#defineZ_MALLOC(sz) my_malloc(sz)
#defineZ_CALLOC(n, sz) my_calloc(n, sz)
#defineZ_REALLOC(p, sz) my_realloc(p, sz)
#defineZ_FREE(p) my_free(p)
#include"zstr.h"

Second Option: Library-Specific Override (Advanced)

If you need a specific allocator just for strings, use the library-specific macros.

// Example: Strings use a specific heap, other z-libs use default.#defineZ_STR_MALLOC(sz) custom_alloc(sz)
#defineZ_STR_REALLOC(p, sz) custom_realloc(p, sz)
#defineZ_STR_FREE(p) custom_free(p)
#include"zstr.h"

Note for C++: If you override these macros manually, ensure your MALLOC and REALLOC macros cast their result to (char*) to satisfy C++ strict typing, though zstr.h handles this internally for standard headers (just a gentle reminder).

Notes

Small String Optimization (SSO)

zstr structs are 32 bytes (on 64-bit systems).

  • Long Mode: 8 bytes pointer, 8 bytes length, 8 bytes capacity, 1 byte flag, 7 bytes padding.
  • Short Mode: 23 bytes buffer, 1 byte length.

This means strings of length 0-22 are stored entirely within the struct definition. Creating them or modifying them requires zero heap interaction.

About

A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views.

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - z-libs/zstr.h: A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views. · GitHub
Skip to content

Repository files navigation

zstr.h

zstr.h is a modern, single-header string library for C projects. Designed to mimic the architecture of C++ std::string (specifically Small String Optimization and Views), it offers a safe, convenient API while remaining pure C.

It includes a robust C++17 wrapper for mixed codebases, and optional Lua 5.x bindings for high-performance string manipulation in scripts.

Features

  • Small String Optimization (SSO): Strings shorter than 23 bytes are stored directly on the stack (inside the struct), avoiding heap allocation entirely.
  • View Semantics: Distinct zstr (owning) and zstr_view (non-owning) types allow for zero-copy slicing and parsing.
  • Safe & Auto-Growing: Buffer overflows are handled by automatic reallocation.
  • C++ Support: Includes a full C++ class wrapper (z_str::string) with RAII, move semantics, and std::string_view compatibility.
  • Lua Support: Provides a mutable string buffer for Lua to avoid garbage generation during complex string building.
  • UTF-8 Aware: Includes helpers for UTF-8 validation and rune counting.
  • Zero Dependencies: Only standard C headers used.

Installation

C/C++ (Header Only)

zstr is a concrete type, so setup is straightforward.

  1. Copy zstr.h (and zcommon.h if separated) into your project's include directory.
  2. Include it in your code.

Lua Binding (Shared Library)

To use zstr in Lua, you must compile the binding into a shared library (zstr.so or zstr.dll).

# Compile the module (adjust paths to your Lua headers).
gcc -O3 -shared -fPIC -o zstr.so bindings/lua/zstr_module.c -Iinclude -I/usr/include/lua5.4 -llua5.4

You can also use the Makefile with:

make lua

You will need to change the Makefile to support different versions.

Usage: C

#include<stdio.h>#include"zstr.h"intmain(void)
{
// Initialize (SSO avoids malloc here).zstrs=zstr_lit("Hello");
// Concatenate using printf-style formatting.zstr_fmt(&s, ", %s!", "World");
// Access C-string safely.printf("%s\n", zstr_cstr(&s)); // "Hello, World!"// Create a zero-copy view of the first 5 chars.zstr_viewv=zstr_sub(zstr_as_view(&s), 0, 5);
// Cleanup.zstr_free(&s);
return0;
}

Usage: C++

The library detects C++ compilers automatically. To avoid naming collisions with the C struct zstr, the C++ classes live in the z_str namespace.

#include<iostream>
#include"zstr.h"intmain()
{
// RAII handles memory automatically (Constructor/Destructor).
z_str::string s = "Hello";
// Operator overloads.
s += " World!";
// Modern C++17 string_view support.
z_str::view v = s; // Static formatting helper (Safety Warning: Only pass POD types!).
z_str::string log = z_str::string::fmt("ID: %d", 42);
std::cout << s << std::endl; // "Hello World!"return0;
}

Usage: Lua

zstr acts as a high-performance mutable string buffer for Lua. It avoids the garbage collection overhead of repeated string concatenation.

localzstr=require("zstr")
-- Create a buffer (allocates once).localbuf=zstr.new("Start: ")
-- Append efficiently (no new Lua objects created).buf:append("User: ")
:append("Alice")
:append(" [Admin]")
-- Modify in-place.buf:upper() -- "START: USER: ALICE [ADMIN]"buf:trim()
-- Convert back to Lua string only when needed.print(tostring(buf)) print("Length: " ..#buf)

API Reference (C)

Initialization & Creation

FunctionDescription
zstr_init()Returns an empty string {0}.
zstr_from(const char *s)Creates a new zstr from a standard C-string.
zstr_from_len(const char *p, size_t len)Creates a zstr from a buffer and explicit length.
zstr_lit("literal")Optimized macro for string literals (calculates length at compile time).
zstr_dup(const zstr *s)Creates a deep copy of an existing zstr.
zstr_with_capacity(size_t cap)Creates an empty string with pre-allocated heap capacity.
zstr_read_file(path)Reads an entire file into a new zstr. Returns empty on failure.
zstr_own(ptr, len, cap)Takes ownership of a raw malloc'd buffer.

Memory Management

FunctionDescription
zstr_free(s)Frees the string if it is on the heap and resets it to empty.
zstr_clear(s)Sets length to 0 but preserves capacity.
zstr_reserve(s, cap)Ensures the string has space for at least cap bytes.
zstr_shrink_to_fit(s)Reduces heap usage to fit the length (or moves back to SSO).
zstr_take(s)Returns the raw malloc'd pointer and resets the zstr (caller must free).

Modification

FunctionDescription
zstr_cat(s, str)Appends a C-string to the end.
zstr_cat_len(s, ptr, len)Appends a raw buffer of known length.
zstr_push(s, char)Appends a single character (alias for zstr_push_char).
zstr_pop_char(s)Removes and returns the last character.
zstr_fmt(s, fmt, ...)Appends a formatted string (printf-style).
zstr_join(arr, n, delim)Joins an array of strings into a new zstr.
zstr_trim(s)Removes leading and trailing whitespace in-place.
zstr_to_lower(s)Converts to lowercase in-place (ASCII only).
zstr_to_upper(s)Converts to uppercase in-place (ASCII only).
zstr_replace(s, old, new)Replaces all occurrences of old with new.

Accessors & Helpers

FunctionDescription
zstr_len(s)Returns the current length (excluding null terminator).
zstr_data(s)Returns a pointer to the mutable data buffer.
zstr_cstr(s)Returns a const char* safe for C APIs.
zstr_is_empty(s)Returns true if the string length is 0.
zstr_is_long(s)Returns true if the string is currently heap-allocated.

Comparison & Search

FunctionDescription
zstr_eq(a, b)Returns true if strings are equal (faster than strcmp).
zstr_eq_ignore_case(a, b)Returns true if strings are equal (case-insensitive, ASCII only).
zstr_cmp(a, b)Standard strcmp behavior for zstr objects.
zstr_find(s, needle)Returns index of first occurrence or -1 if not found.
zstr_contains(s, needle)Returns true if the string contains the substring.
zstr_starts_with(s, pre)Checks if string starts with prefix.
zstr_ends_with(s, suf)Checks if string ends with suffix.

Views & Slices (Zero-Copy)

FunctionDescription
ZSV("lit")Macro to create a zstr_view from a literal.
zstr_as_view(s)Returns a zstr_view covering the whole string.
zstr_view_from(cstr)Creates a view from a C-string.
zstr_from_view(v)Converts a view back into an owning zstr (allocates).
zstr_sub(v, start, len)Returns a view slice (substring) without copying memory.
zstr_view_eq(v, cstr)Checks if view equals a C-string.
zstr_view_eq_view(a, b)Checks if two views are equal.
zstr_view_starts_with(v, pre)Checks if view starts with prefix.
zstr_view_ends_with(v, suf)Checks if view ends with suffix.
zstr_view_lstrip(v)Returns view with leading whitespace removed.
zstr_view_rstrip(v)Returns view with trailing whitespace removed.
zstr_view_trim(v)Returns view with both ends trimmed.
zstr_view_to_int(v, out)Parses an integer from a view (like atoi).

UTF-8 Support

FunctionDescription
zstr_is_valid_utf8(s)Validates string is strict UTF-8 (rejects overlongs/surrogates).
zstr_count_runes(s)Counts the number of actual UTF-8 Runes (not bytes).
zstr_next_rune(ptr)Decodes next rune and advances pointer. Returns 0xFFFD on error.

Iteration (Splitting)

FunctionDescription
zstr_split_init(src, delim)Initializes a split iterator (zstr_split_iter).
zstr_split_next(it, out)Advances iterator and populates out (view) with the next part.

Extensions (Experimental)

If you are using a compiler that supports __attribute__((cleanup)) (like GCC or Clang), you can use the Auto-Cleanup extension.

MacroDescription
zstr_autofreeDeclares a variable that automatically calls zstr_free when it leaves scope.

Example:

voidlog_status()
{
zstr_autofreemsg=zstr_from("Status: ");
zstr_cat(&msg, "OK");
// msg is freed automatically here.
}

API Reference (C++)

The C++ wrapper is defined in the z_str namespace to avoid collisions with the C struct. It strictly adheres to RAII principles and is designed to drop into existing C++11/17 projects.

class z_str::string

An owning string class that internally manages a zstr struct.

Constructors & Management

MethodDescription
string()Default constructor (empty).
string(const char*)Construct from C-string.
string(std::string_view)Construct from C++17 string view.
own(ptr, len, cap)Static. Wraps an existing malloc'd buffer without copying.
from_file(path)Static. Reads entire file into a string.
release()Returns the raw char* and empties the object. Caller must free().

Access & Iterators

MethodDescription
c_str(), data()Returns const char*.
size(), length()Returns length in bytes.
capacity()Returns current allocated capacity.
is_empty()Returns true if length is 0.
operator[]Mutable/Const access to character at index.
front(), back()Access first/last character.
begin(), end()Standard iterators (pointers) compatible with STL algorithms.

Modification

MethodDescription
append(s) / +=Appends C-string, character, or other z_str::string.
push_back(c)Appends a single char.
pop_back()Removes and returns the last char.
replace(old, new)Replaces all occurrences of string old with new.
to_lower(), to_upper()In-place case conversion (ASCII).
trim()In-place whitespace removal.
clear()Sets length to 0 (capacity remains).
fmt(fmt, ...)Static. Creates a string via printf formatting.
Warning: Pass only POD types (int, char*), not C++ objects.

Search & Utilities

MethodDescription
find(needle)Returns index of substring or -1.
contains(needle)Returns true if substring exists.
starts_with(s)Returns true if string starts with s.
ends_with(s)Returns true if string ends with s.
split(delim)Returns a split_iterable for use in range-based for loops.
Safety: Deleted for r-values (temporaries) to prevent dangling views.
rune_count()Returns the number of UTF-8 code points.
is_valid_utf8()Returns true if the string contains valid UTF-8.

class z_str::view

A lightweight, non-owning wrapper around zstr_view. Compatible with std::string_view (C++17).

MethodDescription
view(string&)Implicit conversion from z_str::string.
sub(start, len)Returns a new view slice.
lstrip(), rstrip(), trim()Returns a new view with whitespace removed.
to_int(out)Parses view to integer. Returns true on success.
starts_with, ends_withPredicate checks.
operator==Compares with view, string, or const char*.

API Reference (Lua)

The Lua module exports a zstr table with constructors. Instances are userdata objects with methods.

Constructors

FunctionDescription
zstr.new([str])Creates a new buffer, optionally initialized with str.
zstr.from_file(path)Reads an entire file into a buffer.

Buffer Methods

MethodDescription
s:append(str...)Appends one or more strings to the buffer. Returns self.
s:reserve(n)Pre-allocates capacity for n bytes.
s:clear()Empties the buffer (length 0).
s:clone()Returns a deep copy of the buffer.
s:capacity()Returns the current allocated capacity.

Transformations (In-Place)

MethodDescription
s:trim()Removes leading/trailing whitespace.
s:upper()Converts to uppercase (ASCII).
s:lower()Converts to lowercase (ASCII).
s:replace(old, new)Replaces all occurrences of old with new.

Queries

MethodDescription
s:contains(sub)Returns true if sub is found.
s:starts_with(sub)Returns true if buffer starts with sub.
s:ends_with(sub)Returns true if buffer ends with sub.
s:is_valid_utf8()Returns true if content is valid UTF-8.
s:rune_count()Returns the number of UTF-8 characters.

Utilities

MethodDescription
s:split(delim)Returns a Lua table (array) of strings split by delim.
#s (Len operator)Returns the length in bytes.
tostring(s)Converts the buffer to a standard Lua string.

Memory Management

By default, zstr.h uses the standard C library functions (malloc, realloc, free).

However, you can override these to use your own memory subsystem (e.g., Memory Arenas, Pools, or Debug Allocators).

First Option: Global Override (Recommended)

To use a custom allocator globally across all z-libs, define the Z_ macros before including zstr.h.

// my_config.h#defineZ_MALLOC(sz) my_malloc(sz)
#defineZ_CALLOC(n, sz) my_calloc(n, sz)
#defineZ_REALLOC(p, sz) my_realloc(p, sz)
#defineZ_FREE(p) my_free(p)
#include"zstr.h"

Second Option: Library-Specific Override (Advanced)

If you need a specific allocator just for strings, use the library-specific macros.

// Example: Strings use a specific heap, other z-libs use default.#defineZ_STR_MALLOC(sz) custom_alloc(sz)
#defineZ_STR_REALLOC(p, sz) custom_realloc(p, sz)
#defineZ_STR_FREE(p) custom_free(p)
#include"zstr.h"

Note for C++: If you override these macros manually, ensure your MALLOC and REALLOC macros cast their result to (char*) to satisfy C++ strict typing, though zstr.h handles this internally for standard headers (just a gentle reminder).

Notes

Small String Optimization (SSO)

zstr structs are 32 bytes (on 64-bit systems).

  • Long Mode: 8 bytes pointer, 8 bytes length, 8 bytes capacity, 1 byte flag, 7 bytes padding.
  • Short Mode: 23 bytes buffer, 1 byte length.

This means strings of length 0-22 are stored entirely within the struct definition. Creating them or modifying them requires zero heap interaction.

About

A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views.

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - z-libs/zstr.h: A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views. · GitHub
Skip to content

Repository files navigation

zstr.h

zstr.h is a modern, single-header string library for C projects. Designed to mimic the architecture of C++ std::string (specifically Small String Optimization and Views), it offers a safe, convenient API while remaining pure C.

It includes a robust C++17 wrapper for mixed codebases, and optional Lua 5.x bindings for high-performance string manipulation in scripts.

Features

  • Small String Optimization (SSO): Strings shorter than 23 bytes are stored directly on the stack (inside the struct), avoiding heap allocation entirely.
  • View Semantics: Distinct zstr (owning) and zstr_view (non-owning) types allow for zero-copy slicing and parsing.
  • Safe & Auto-Growing: Buffer overflows are handled by automatic reallocation.
  • C++ Support: Includes a full C++ class wrapper (z_str::string) with RAII, move semantics, and std::string_view compatibility.
  • Lua Support: Provides a mutable string buffer for Lua to avoid garbage generation during complex string building.
  • UTF-8 Aware: Includes helpers for UTF-8 validation and rune counting.
  • Zero Dependencies: Only standard C headers used.

Installation

C/C++ (Header Only)

zstr is a concrete type, so setup is straightforward.

  1. Copy zstr.h (and zcommon.h if separated) into your project's include directory.
  2. Include it in your code.

Lua Binding (Shared Library)

To use zstr in Lua, you must compile the binding into a shared library (zstr.so or zstr.dll).

# Compile the module (adjust paths to your Lua headers).
gcc -O3 -shared -fPIC -o zstr.so bindings/lua/zstr_module.c -Iinclude -I/usr/include/lua5.4 -llua5.4

You can also use the Makefile with:

make lua

You will need to change the Makefile to support different versions.

Usage: C

#include<stdio.h>#include"zstr.h"intmain(void)
{
// Initialize (SSO avoids malloc here).zstrs=zstr_lit("Hello");
// Concatenate using printf-style formatting.zstr_fmt(&s, ", %s!", "World");
// Access C-string safely.printf("%s\n", zstr_cstr(&s)); // "Hello, World!"// Create a zero-copy view of the first 5 chars.zstr_viewv=zstr_sub(zstr_as_view(&s), 0, 5);
// Cleanup.zstr_free(&s);
return0;
}

Usage: C++

The library detects C++ compilers automatically. To avoid naming collisions with the C struct zstr, the C++ classes live in the z_str namespace.

#include<iostream>
#include"zstr.h"intmain()
{
// RAII handles memory automatically (Constructor/Destructor).
z_str::string s = "Hello";
// Operator overloads.
s += " World!";
// Modern C++17 string_view support.
z_str::view v = s; // Static formatting helper (Safety Warning: Only pass POD types!).
z_str::string log = z_str::string::fmt("ID: %d", 42);
std::cout << s << std::endl; // "Hello World!"return0;
}

Usage: Lua

zstr acts as a high-performance mutable string buffer for Lua. It avoids the garbage collection overhead of repeated string concatenation.

localzstr=require("zstr")
-- Create a buffer (allocates once).localbuf=zstr.new("Start: ")
-- Append efficiently (no new Lua objects created).buf:append("User: ")
:append("Alice")
:append(" [Admin]")
-- Modify in-place.buf:upper() -- "START: USER: ALICE [ADMIN]"buf:trim()
-- Convert back to Lua string only when needed.print(tostring(buf)) print("Length: " ..#buf)

API Reference (C)

Initialization & Creation

FunctionDescription
zstr_init()Returns an empty string {0}.
zstr_from(const char *s)Creates a new zstr from a standard C-string.
zstr_from_len(const char *p, size_t len)Creates a zstr from a buffer and explicit length.
zstr_lit("literal")Optimized macro for string literals (calculates length at compile time).
zstr_dup(const zstr *s)Creates a deep copy of an existing zstr.
zstr_with_capacity(size_t cap)Creates an empty string with pre-allocated heap capacity.
zstr_read_file(path)Reads an entire file into a new zstr. Returns empty on failure.
zstr_own(ptr, len, cap)Takes ownership of a raw malloc'd buffer.

Memory Management

FunctionDescription
zstr_free(s)Frees the string if it is on the heap and resets it to empty.
zstr_clear(s)Sets length to 0 but preserves capacity.
zstr_reserve(s, cap)Ensures the string has space for at least cap bytes.
zstr_shrink_to_fit(s)Reduces heap usage to fit the length (or moves back to SSO).
zstr_take(s)Returns the raw malloc'd pointer and resets the zstr (caller must free).

Modification

FunctionDescription
zstr_cat(s, str)Appends a C-string to the end.
zstr_cat_len(s, ptr, len)Appends a raw buffer of known length.
zstr_push(s, char)Appends a single character (alias for zstr_push_char).
zstr_pop_char(s)Removes and returns the last character.
zstr_fmt(s, fmt, ...)Appends a formatted string (printf-style).
zstr_join(arr, n, delim)Joins an array of strings into a new zstr.
zstr_trim(s)Removes leading and trailing whitespace in-place.
zstr_to_lower(s)Converts to lowercase in-place (ASCII only).
zstr_to_upper(s)Converts to uppercase in-place (ASCII only).
zstr_replace(s, old, new)Replaces all occurrences of old with new.

Accessors & Helpers

FunctionDescription
zstr_len(s)Returns the current length (excluding null terminator).
zstr_data(s)Returns a pointer to the mutable data buffer.
zstr_cstr(s)Returns a const char* safe for C APIs.
zstr_is_empty(s)Returns true if the string length is 0.
zstr_is_long(s)Returns true if the string is currently heap-allocated.

Comparison & Search

FunctionDescription
zstr_eq(a, b)Returns true if strings are equal (faster than strcmp).
zstr_eq_ignore_case(a, b)Returns true if strings are equal (case-insensitive, ASCII only).
zstr_cmp(a, b)Standard strcmp behavior for zstr objects.
zstr_find(s, needle)Returns index of first occurrence or -1 if not found.
zstr_contains(s, needle)Returns true if the string contains the substring.
zstr_starts_with(s, pre)Checks if string starts with prefix.
zstr_ends_with(s, suf)Checks if string ends with suffix.

Views & Slices (Zero-Copy)

FunctionDescription
ZSV("lit")Macro to create a zstr_view from a literal.
zstr_as_view(s)Returns a zstr_view covering the whole string.
zstr_view_from(cstr)Creates a view from a C-string.
zstr_from_view(v)Converts a view back into an owning zstr (allocates).
zstr_sub(v, start, len)Returns a view slice (substring) without copying memory.
zstr_view_eq(v, cstr)Checks if view equals a C-string.
zstr_view_eq_view(a, b)Checks if two views are equal.
zstr_view_starts_with(v, pre)Checks if view starts with prefix.
zstr_view_ends_with(v, suf)Checks if view ends with suffix.
zstr_view_lstrip(v)Returns view with leading whitespace removed.
zstr_view_rstrip(v)Returns view with trailing whitespace removed.
zstr_view_trim(v)Returns view with both ends trimmed.
zstr_view_to_int(v, out)Parses an integer from a view (like atoi).

UTF-8 Support

FunctionDescription
zstr_is_valid_utf8(s)Validates string is strict UTF-8 (rejects overlongs/surrogates).
zstr_count_runes(s)Counts the number of actual UTF-8 Runes (not bytes).
zstr_next_rune(ptr)Decodes next rune and advances pointer. Returns 0xFFFD on error.

Iteration (Splitting)

FunctionDescription
zstr_split_init(src, delim)Initializes a split iterator (zstr_split_iter).
zstr_split_next(it, out)Advances iterator and populates out (view) with the next part.

Extensions (Experimental)

If you are using a compiler that supports __attribute__((cleanup)) (like GCC or Clang), you can use the Auto-Cleanup extension.

MacroDescription
zstr_autofreeDeclares a variable that automatically calls zstr_free when it leaves scope.

Example:

voidlog_status()
{
zstr_autofreemsg=zstr_from("Status: ");
zstr_cat(&msg, "OK");
// msg is freed automatically here.
}

API Reference (C++)

The C++ wrapper is defined in the z_str namespace to avoid collisions with the C struct. It strictly adheres to RAII principles and is designed to drop into existing C++11/17 projects.

class z_str::string

An owning string class that internally manages a zstr struct.

Constructors & Management

MethodDescription
string()Default constructor (empty).
string(const char*)Construct from C-string.
string(std::string_view)Construct from C++17 string view.
own(ptr, len, cap)Static. Wraps an existing malloc'd buffer without copying.
from_file(path)Static. Reads entire file into a string.
release()Returns the raw char* and empties the object. Caller must free().

Access & Iterators

MethodDescription
c_str(), data()Returns const char*.
size(), length()Returns length in bytes.
capacity()Returns current allocated capacity.
is_empty()Returns true if length is 0.
operator[]Mutable/Const access to character at index.
front(), back()Access first/last character.
begin(), end()Standard iterators (pointers) compatible with STL algorithms.

Modification

MethodDescription
append(s) / +=Appends C-string, character, or other z_str::string.
push_back(c)Appends a single char.
pop_back()Removes and returns the last char.
replace(old, new)Replaces all occurrences of string old with new.
to_lower(), to_upper()In-place case conversion (ASCII).
trim()In-place whitespace removal.
clear()Sets length to 0 (capacity remains).
fmt(fmt, ...)Static. Creates a string via printf formatting.
Warning: Pass only POD types (int, char*), not C++ objects.

Search & Utilities

MethodDescription
find(needle)Returns index of substring or -1.
contains(needle)Returns true if substring exists.
starts_with(s)Returns true if string starts with s.
ends_with(s)Returns true if string ends with s.
split(delim)Returns a split_iterable for use in range-based for loops.
Safety: Deleted for r-values (temporaries) to prevent dangling views.
rune_count()Returns the number of UTF-8 code points.
is_valid_utf8()Returns true if the string contains valid UTF-8.

class z_str::view

A lightweight, non-owning wrapper around zstr_view. Compatible with std::string_view (C++17).

MethodDescription
view(string&)Implicit conversion from z_str::string.
sub(start, len)Returns a new view slice.
lstrip(), rstrip(), trim()Returns a new view with whitespace removed.
to_int(out)Parses view to integer. Returns true on success.
starts_with, ends_withPredicate checks.
operator==Compares with view, string, or const char*.

API Reference (Lua)

The Lua module exports a zstr table with constructors. Instances are userdata objects with methods.

Constructors

FunctionDescription
zstr.new([str])Creates a new buffer, optionally initialized with str.
zstr.from_file(path)Reads an entire file into a buffer.

Buffer Methods

MethodDescription
s:append(str...)Appends one or more strings to the buffer. Returns self.
s:reserve(n)Pre-allocates capacity for n bytes.
s:clear()Empties the buffer (length 0).
s:clone()Returns a deep copy of the buffer.
s:capacity()Returns the current allocated capacity.

Transformations (In-Place)

MethodDescription
s:trim()Removes leading/trailing whitespace.
s:upper()Converts to uppercase (ASCII).
s:lower()Converts to lowercase (ASCII).
s:replace(old, new)Replaces all occurrences of old with new.

Queries

MethodDescription
s:contains(sub)Returns true if sub is found.
s:starts_with(sub)Returns true if buffer starts with sub.
s:ends_with(sub)Returns true if buffer ends with sub.
s:is_valid_utf8()Returns true if content is valid UTF-8.
s:rune_count()Returns the number of UTF-8 characters.

Utilities

MethodDescription
s:split(delim)Returns a Lua table (array) of strings split by delim.
#s (Len operator)Returns the length in bytes.
tostring(s)Converts the buffer to a standard Lua string.

Memory Management

By default, zstr.h uses the standard C library functions (malloc, realloc, free).

However, you can override these to use your own memory subsystem (e.g., Memory Arenas, Pools, or Debug Allocators).

First Option: Global Override (Recommended)

To use a custom allocator globally across all z-libs, define the Z_ macros before including zstr.h.

// my_config.h#defineZ_MALLOC(sz) my_malloc(sz)
#defineZ_CALLOC(n, sz) my_calloc(n, sz)
#defineZ_REALLOC(p, sz) my_realloc(p, sz)
#defineZ_FREE(p) my_free(p)
#include"zstr.h"

Second Option: Library-Specific Override (Advanced)

If you need a specific allocator just for strings, use the library-specific macros.

// Example: Strings use a specific heap, other z-libs use default.#defineZ_STR_MALLOC(sz) custom_alloc(sz)
#defineZ_STR_REALLOC(p, sz) custom_realloc(p, sz)
#defineZ_STR_FREE(p) custom_free(p)
#include"zstr.h"

Note for C++: If you override these macros manually, ensure your MALLOC and REALLOC macros cast their result to (char*) to satisfy C++ strict typing, though zstr.h handles this internally for standard headers (just a gentle reminder).

Notes

Small String Optimization (SSO)

zstr structs are 32 bytes (on 64-bit systems).

  • Long Mode: 8 bytes pointer, 8 bytes length, 8 bytes capacity, 1 byte flag, 7 bytes padding.
  • Short Mode: 23 bytes buffer, 1 byte length.

This means strings of length 0-22 are stored entirely within the struct definition. Creating them or modifying them requires zero heap interaction.

About

A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views.

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - z-libs/zstr.h: A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views. · GitHub
Skip to content

Repository files navigation

zstr.h

zstr.h is a modern, single-header string library for C projects. Designed to mimic the architecture of C++ std::string (specifically Small String Optimization and Views), it offers a safe, convenient API while remaining pure C.

It includes a robust C++17 wrapper for mixed codebases, and optional Lua 5.x bindings for high-performance string manipulation in scripts.

Features

  • Small String Optimization (SSO): Strings shorter than 23 bytes are stored directly on the stack (inside the struct), avoiding heap allocation entirely.
  • View Semantics: Distinct zstr (owning) and zstr_view (non-owning) types allow for zero-copy slicing and parsing.
  • Safe & Auto-Growing: Buffer overflows are handled by automatic reallocation.
  • C++ Support: Includes a full C++ class wrapper (z_str::string) with RAII, move semantics, and std::string_view compatibility.
  • Lua Support: Provides a mutable string buffer for Lua to avoid garbage generation during complex string building.
  • UTF-8 Aware: Includes helpers for UTF-8 validation and rune counting.
  • Zero Dependencies: Only standard C headers used.

Installation

C/C++ (Header Only)

zstr is a concrete type, so setup is straightforward.

  1. Copy zstr.h (and zcommon.h if separated) into your project's include directory.
  2. Include it in your code.

Lua Binding (Shared Library)

To use zstr in Lua, you must compile the binding into a shared library (zstr.so or zstr.dll).

# Compile the module (adjust paths to your Lua headers).
gcc -O3 -shared -fPIC -o zstr.so bindings/lua/zstr_module.c -Iinclude -I/usr/include/lua5.4 -llua5.4

You can also use the Makefile with:

make lua

You will need to change the Makefile to support different versions.

Usage: C

#include<stdio.h>#include"zstr.h"intmain(void)
{
// Initialize (SSO avoids malloc here).zstrs=zstr_lit("Hello");
// Concatenate using printf-style formatting.zstr_fmt(&s, ", %s!", "World");
// Access C-string safely.printf("%s\n", zstr_cstr(&s)); // "Hello, World!"// Create a zero-copy view of the first 5 chars.zstr_viewv=zstr_sub(zstr_as_view(&s), 0, 5);
// Cleanup.zstr_free(&s);
return0;
}

Usage: C++

The library detects C++ compilers automatically. To avoid naming collisions with the C struct zstr, the C++ classes live in the z_str namespace.

#include<iostream>
#include"zstr.h"intmain()
{
// RAII handles memory automatically (Constructor/Destructor).
z_str::string s = "Hello";
// Operator overloads.
s += " World!";
// Modern C++17 string_view support.
z_str::view v = s; // Static formatting helper (Safety Warning: Only pass POD types!).
z_str::string log = z_str::string::fmt("ID: %d", 42);
std::cout << s << std::endl; // "Hello World!"return0;
}

Usage: Lua

zstr acts as a high-performance mutable string buffer for Lua. It avoids the garbage collection overhead of repeated string concatenation.

localzstr=require("zstr")
-- Create a buffer (allocates once).localbuf=zstr.new("Start: ")
-- Append efficiently (no new Lua objects created).buf:append("User: ")
:append("Alice")
:append(" [Admin]")
-- Modify in-place.buf:upper() -- "START: USER: ALICE [ADMIN]"buf:trim()
-- Convert back to Lua string only when needed.print(tostring(buf)) print("Length: " ..#buf)

API Reference (C)

Initialization & Creation

FunctionDescription
zstr_init()Returns an empty string {0}.
zstr_from(const char *s)Creates a new zstr from a standard C-string.
zstr_from_len(const char *p, size_t len)Creates a zstr from a buffer and explicit length.
zstr_lit("literal")Optimized macro for string literals (calculates length at compile time).
zstr_dup(const zstr *s)Creates a deep copy of an existing zstr.
zstr_with_capacity(size_t cap)Creates an empty string with pre-allocated heap capacity.
zstr_read_file(path)Reads an entire file into a new zstr. Returns empty on failure.
zstr_own(ptr, len, cap)Takes ownership of a raw malloc'd buffer.

Memory Management

FunctionDescription
zstr_free(s)Frees the string if it is on the heap and resets it to empty.
zstr_clear(s)Sets length to 0 but preserves capacity.
zstr_reserve(s, cap)Ensures the string has space for at least cap bytes.
zstr_shrink_to_fit(s)Reduces heap usage to fit the length (or moves back to SSO).
zstr_take(s)Returns the raw malloc'd pointer and resets the zstr (caller must free).

Modification

FunctionDescription
zstr_cat(s, str)Appends a C-string to the end.
zstr_cat_len(s, ptr, len)Appends a raw buffer of known length.
zstr_push(s, char)Appends a single character (alias for zstr_push_char).
zstr_pop_char(s)Removes and returns the last character.
zstr_fmt(s, fmt, ...)Appends a formatted string (printf-style).
zstr_join(arr, n, delim)Joins an array of strings into a new zstr.
zstr_trim(s)Removes leading and trailing whitespace in-place.
zstr_to_lower(s)Converts to lowercase in-place (ASCII only).
zstr_to_upper(s)Converts to uppercase in-place (ASCII only).
zstr_replace(s, old, new)Replaces all occurrences of old with new.

Accessors & Helpers

FunctionDescription
zstr_len(s)Returns the current length (excluding null terminator).
zstr_data(s)Returns a pointer to the mutable data buffer.
zstr_cstr(s)Returns a const char* safe for C APIs.
zstr_is_empty(s)Returns true if the string length is 0.
zstr_is_long(s)Returns true if the string is currently heap-allocated.

Comparison & Search

FunctionDescription
zstr_eq(a, b)Returns true if strings are equal (faster than strcmp).
zstr_eq_ignore_case(a, b)Returns true if strings are equal (case-insensitive, ASCII only).
zstr_cmp(a, b)Standard strcmp behavior for zstr objects.
zstr_find(s, needle)Returns index of first occurrence or -1 if not found.
zstr_contains(s, needle)Returns true if the string contains the substring.
zstr_starts_with(s, pre)Checks if string starts with prefix.
zstr_ends_with(s, suf)Checks if string ends with suffix.

Views & Slices (Zero-Copy)

FunctionDescription
ZSV("lit")Macro to create a zstr_view from a literal.
zstr_as_view(s)Returns a zstr_view covering the whole string.
zstr_view_from(cstr)Creates a view from a C-string.
zstr_from_view(v)Converts a view back into an owning zstr (allocates).
zstr_sub(v, start, len)Returns a view slice (substring) without copying memory.
zstr_view_eq(v, cstr)Checks if view equals a C-string.
zstr_view_eq_view(a, b)Checks if two views are equal.
zstr_view_starts_with(v, pre)Checks if view starts with prefix.
zstr_view_ends_with(v, suf)Checks if view ends with suffix.
zstr_view_lstrip(v)Returns view with leading whitespace removed.
zstr_view_rstrip(v)Returns view with trailing whitespace removed.
zstr_view_trim(v)Returns view with both ends trimmed.
zstr_view_to_int(v, out)Parses an integer from a view (like atoi).

UTF-8 Support

FunctionDescription
zstr_is_valid_utf8(s)Validates string is strict UTF-8 (rejects overlongs/surrogates).
zstr_count_runes(s)Counts the number of actual UTF-8 Runes (not bytes).
zstr_next_rune(ptr)Decodes next rune and advances pointer. Returns 0xFFFD on error.

Iteration (Splitting)

FunctionDescription
zstr_split_init(src, delim)Initializes a split iterator (zstr_split_iter).
zstr_split_next(it, out)Advances iterator and populates out (view) with the next part.

Extensions (Experimental)

If you are using a compiler that supports __attribute__((cleanup)) (like GCC or Clang), you can use the Auto-Cleanup extension.

MacroDescription
zstr_autofreeDeclares a variable that automatically calls zstr_free when it leaves scope.

Example:

voidlog_status()
{
zstr_autofreemsg=zstr_from("Status: ");
zstr_cat(&msg, "OK");
// msg is freed automatically here.
}

API Reference (C++)

The C++ wrapper is defined in the z_str namespace to avoid collisions with the C struct. It strictly adheres to RAII principles and is designed to drop into existing C++11/17 projects.

class z_str::string

An owning string class that internally manages a zstr struct.

Constructors & Management

MethodDescription
string()Default constructor (empty).
string(const char*)Construct from C-string.
string(std::string_view)Construct from C++17 string view.
own(ptr, len, cap)Static. Wraps an existing malloc'd buffer without copying.
from_file(path)Static. Reads entire file into a string.
release()Returns the raw char* and empties the object. Caller must free().

Access & Iterators

MethodDescription
c_str(), data()Returns const char*.
size(), length()Returns length in bytes.
capacity()Returns current allocated capacity.
is_empty()Returns true if length is 0.
operator[]Mutable/Const access to character at index.
front(), back()Access first/last character.
begin(), end()Standard iterators (pointers) compatible with STL algorithms.

Modification

MethodDescription
append(s) / +=Appends C-string, character, or other z_str::string.
push_back(c)Appends a single char.
pop_back()Removes and returns the last char.
replace(old, new)Replaces all occurrences of string old with new.
to_lower(), to_upper()In-place case conversion (ASCII).
trim()In-place whitespace removal.
clear()Sets length to 0 (capacity remains).
fmt(fmt, ...)Static. Creates a string via printf formatting.
Warning: Pass only POD types (int, char*), not C++ objects.

Search & Utilities

MethodDescription
find(needle)Returns index of substring or -1.
contains(needle)Returns true if substring exists.
starts_with(s)Returns true if string starts with s.
ends_with(s)Returns true if string ends with s.
split(delim)Returns a split_iterable for use in range-based for loops.
Safety: Deleted for r-values (temporaries) to prevent dangling views.
rune_count()Returns the number of UTF-8 code points.
is_valid_utf8()Returns true if the string contains valid UTF-8.

class z_str::view

A lightweight, non-owning wrapper around zstr_view. Compatible with std::string_view (C++17).

MethodDescription
view(string&)Implicit conversion from z_str::string.
sub(start, len)Returns a new view slice.
lstrip(), rstrip(), trim()Returns a new view with whitespace removed.
to_int(out)Parses view to integer. Returns true on success.
starts_with, ends_withPredicate checks.
operator==Compares with view, string, or const char*.

API Reference (Lua)

The Lua module exports a zstr table with constructors. Instances are userdata objects with methods.

Constructors

FunctionDescription
zstr.new([str])Creates a new buffer, optionally initialized with str.
zstr.from_file(path)Reads an entire file into a buffer.

Buffer Methods

MethodDescription
s:append(str...)Appends one or more strings to the buffer. Returns self.
s:reserve(n)Pre-allocates capacity for n bytes.
s:clear()Empties the buffer (length 0).
s:clone()Returns a deep copy of the buffer.
s:capacity()Returns the current allocated capacity.

Transformations (In-Place)

MethodDescription
s:trim()Removes leading/trailing whitespace.
s:upper()Converts to uppercase (ASCII).
s:lower()Converts to lowercase (ASCII).
s:replace(old, new)Replaces all occurrences of old with new.

Queries

MethodDescription
s:contains(sub)Returns true if sub is found.
s:starts_with(sub)Returns true if buffer starts with sub.
s:ends_with(sub)Returns true if buffer ends with sub.
s:is_valid_utf8()Returns true if content is valid UTF-8.
s:rune_count()Returns the number of UTF-8 characters.

Utilities

MethodDescription
s:split(delim)Returns a Lua table (array) of strings split by delim.
#s (Len operator)Returns the length in bytes.
tostring(s)Converts the buffer to a standard Lua string.

Memory Management

By default, zstr.h uses the standard C library functions (malloc, realloc, free).

However, you can override these to use your own memory subsystem (e.g., Memory Arenas, Pools, or Debug Allocators).

First Option: Global Override (Recommended)

To use a custom allocator globally across all z-libs, define the Z_ macros before including zstr.h.

// my_config.h#defineZ_MALLOC(sz) my_malloc(sz)
#defineZ_CALLOC(n, sz) my_calloc(n, sz)
#defineZ_REALLOC(p, sz) my_realloc(p, sz)
#defineZ_FREE(p) my_free(p)
#include"zstr.h"

Second Option: Library-Specific Override (Advanced)

If you need a specific allocator just for strings, use the library-specific macros.

// Example: Strings use a specific heap, other z-libs use default.#defineZ_STR_MALLOC(sz) custom_alloc(sz)
#defineZ_STR_REALLOC(p, sz) custom_realloc(p, sz)
#defineZ_STR_FREE(p) custom_free(p)
#include"zstr.h"

Note for C++: If you override these macros manually, ensure your MALLOC and REALLOC macros cast their result to (char*) to satisfy C++ strict typing, though zstr.h handles this internally for standard headers (just a gentle reminder).

Notes

Small String Optimization (SSO)

zstr structs are 32 bytes (on 64-bit systems).

  • Long Mode: 8 bytes pointer, 8 bytes length, 8 bytes capacity, 1 byte flag, 7 bytes padding.
  • Short Mode: 23 bytes buffer, 1 byte length.

This means strings of length 0-22 are stored entirely within the struct definition. Creating them or modifying them requires zero heap interaction.

About

A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views.

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - z-libs/zstr.h: A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views. · GitHub
Skip to content

Repository files navigation

zstr.h

zstr.h is a modern, single-header string library for C projects. Designed to mimic the architecture of C++ std::string (specifically Small String Optimization and Views), it offers a safe, convenient API while remaining pure C.

It includes a robust C++17 wrapper for mixed codebases, and optional Lua 5.x bindings for high-performance string manipulation in scripts.

Features

  • Small String Optimization (SSO): Strings shorter than 23 bytes are stored directly on the stack (inside the struct), avoiding heap allocation entirely.
  • View Semantics: Distinct zstr (owning) and zstr_view (non-owning) types allow for zero-copy slicing and parsing.
  • Safe & Auto-Growing: Buffer overflows are handled by automatic reallocation.
  • C++ Support: Includes a full C++ class wrapper (z_str::string) with RAII, move semantics, and std::string_view compatibility.
  • Lua Support: Provides a mutable string buffer for Lua to avoid garbage generation during complex string building.
  • UTF-8 Aware: Includes helpers for UTF-8 validation and rune counting.
  • Zero Dependencies: Only standard C headers used.

Installation

C/C++ (Header Only)

zstr is a concrete type, so setup is straightforward.

  1. Copy zstr.h (and zcommon.h if separated) into your project's include directory.
  2. Include it in your code.

Lua Binding (Shared Library)

To use zstr in Lua, you must compile the binding into a shared library (zstr.so or zstr.dll).

# Compile the module (adjust paths to your Lua headers).
gcc -O3 -shared -fPIC -o zstr.so bindings/lua/zstr_module.c -Iinclude -I/usr/include/lua5.4 -llua5.4

You can also use the Makefile with:

make lua

You will need to change the Makefile to support different versions.

Usage: C

#include<stdio.h>#include"zstr.h"intmain(void)
{
// Initialize (SSO avoids malloc here).zstrs=zstr_lit("Hello");
// Concatenate using printf-style formatting.zstr_fmt(&s, ", %s!", "World");
// Access C-string safely.printf("%s\n", zstr_cstr(&s)); // "Hello, World!"// Create a zero-copy view of the first 5 chars.zstr_viewv=zstr_sub(zstr_as_view(&s), 0, 5);
// Cleanup.zstr_free(&s);
return0;
}

Usage: C++

The library detects C++ compilers automatically. To avoid naming collisions with the C struct zstr, the C++ classes live in the z_str namespace.

#include<iostream>
#include"zstr.h"intmain()
{
// RAII handles memory automatically (Constructor/Destructor).
z_str::string s = "Hello";
// Operator overloads.
s += " World!";
// Modern C++17 string_view support.
z_str::view v = s; // Static formatting helper (Safety Warning: Only pass POD types!).
z_str::string log = z_str::string::fmt("ID: %d", 42);
std::cout << s << std::endl; // "Hello World!"return0;
}

Usage: Lua

zstr acts as a high-performance mutable string buffer for Lua. It avoids the garbage collection overhead of repeated string concatenation.

localzstr=require("zstr")
-- Create a buffer (allocates once).localbuf=zstr.new("Start: ")
-- Append efficiently (no new Lua objects created).buf:append("User: ")
:append("Alice")
:append(" [Admin]")
-- Modify in-place.buf:upper() -- "START: USER: ALICE [ADMIN]"buf:trim()
-- Convert back to Lua string only when needed.print(tostring(buf)) print("Length: " ..#buf)

API Reference (C)

Initialization & Creation

FunctionDescription
zstr_init()Returns an empty string {0}.
zstr_from(const char *s)Creates a new zstr from a standard C-string.
zstr_from_len(const char *p, size_t len)Creates a zstr from a buffer and explicit length.
zstr_lit("literal")Optimized macro for string literals (calculates length at compile time).
zstr_dup(const zstr *s)Creates a deep copy of an existing zstr.
zstr_with_capacity(size_t cap)Creates an empty string with pre-allocated heap capacity.
zstr_read_file(path)Reads an entire file into a new zstr. Returns empty on failure.
zstr_own(ptr, len, cap)Takes ownership of a raw malloc'd buffer.

Memory Management

FunctionDescription
zstr_free(s)Frees the string if it is on the heap and resets it to empty.
zstr_clear(s)Sets length to 0 but preserves capacity.
zstr_reserve(s, cap)Ensures the string has space for at least cap bytes.
zstr_shrink_to_fit(s)Reduces heap usage to fit the length (or moves back to SSO).
zstr_take(s)Returns the raw malloc'd pointer and resets the zstr (caller must free).

Modification

FunctionDescription
zstr_cat(s, str)Appends a C-string to the end.
zstr_cat_len(s, ptr, len)Appends a raw buffer of known length.
zstr_push(s, char)Appends a single character (alias for zstr_push_char).
zstr_pop_char(s)Removes and returns the last character.
zstr_fmt(s, fmt, ...)Appends a formatted string (printf-style).
zstr_join(arr, n, delim)Joins an array of strings into a new zstr.
zstr_trim(s)Removes leading and trailing whitespace in-place.
zstr_to_lower(s)Converts to lowercase in-place (ASCII only).
zstr_to_upper(s)Converts to uppercase in-place (ASCII only).
zstr_replace(s, old, new)Replaces all occurrences of old with new.

Accessors & Helpers

FunctionDescription
zstr_len(s)Returns the current length (excluding null terminator).
zstr_data(s)Returns a pointer to the mutable data buffer.
zstr_cstr(s)Returns a const char* safe for C APIs.
zstr_is_empty(s)Returns true if the string length is 0.
zstr_is_long(s)Returns true if the string is currently heap-allocated.

Comparison & Search

FunctionDescription
zstr_eq(a, b)Returns true if strings are equal (faster than strcmp).
zstr_eq_ignore_case(a, b)Returns true if strings are equal (case-insensitive, ASCII only).
zstr_cmp(a, b)Standard strcmp behavior for zstr objects.
zstr_find(s, needle)Returns index of first occurrence or -1 if not found.
zstr_contains(s, needle)Returns true if the string contains the substring.
zstr_starts_with(s, pre)Checks if string starts with prefix.
zstr_ends_with(s, suf)Checks if string ends with suffix.

Views & Slices (Zero-Copy)

FunctionDescription
ZSV("lit")Macro to create a zstr_view from a literal.
zstr_as_view(s)Returns a zstr_view covering the whole string.
zstr_view_from(cstr)Creates a view from a C-string.
zstr_from_view(v)Converts a view back into an owning zstr (allocates).
zstr_sub(v, start, len)Returns a view slice (substring) without copying memory.
zstr_view_eq(v, cstr)Checks if view equals a C-string.
zstr_view_eq_view(a, b)Checks if two views are equal.
zstr_view_starts_with(v, pre)Checks if view starts with prefix.
zstr_view_ends_with(v, suf)Checks if view ends with suffix.
zstr_view_lstrip(v)Returns view with leading whitespace removed.
zstr_view_rstrip(v)Returns view with trailing whitespace removed.
zstr_view_trim(v)Returns view with both ends trimmed.
zstr_view_to_int(v, out)Parses an integer from a view (like atoi).

UTF-8 Support

FunctionDescription
zstr_is_valid_utf8(s)Validates string is strict UTF-8 (rejects overlongs/surrogates).
zstr_count_runes(s)Counts the number of actual UTF-8 Runes (not bytes).
zstr_next_rune(ptr)Decodes next rune and advances pointer. Returns 0xFFFD on error.

Iteration (Splitting)

FunctionDescription
zstr_split_init(src, delim)Initializes a split iterator (zstr_split_iter).
zstr_split_next(it, out)Advances iterator and populates out (view) with the next part.

Extensions (Experimental)

If you are using a compiler that supports __attribute__((cleanup)) (like GCC or Clang), you can use the Auto-Cleanup extension.

MacroDescription
zstr_autofreeDeclares a variable that automatically calls zstr_free when it leaves scope.

Example:

voidlog_status()
{
zstr_autofreemsg=zstr_from("Status: ");
zstr_cat(&msg, "OK");
// msg is freed automatically here.
}

API Reference (C++)

The C++ wrapper is defined in the z_str namespace to avoid collisions with the C struct. It strictly adheres to RAII principles and is designed to drop into existing C++11/17 projects.

class z_str::string

An owning string class that internally manages a zstr struct.

Constructors & Management

MethodDescription
string()Default constructor (empty).
string(const char*)Construct from C-string.
string(std::string_view)Construct from C++17 string view.
own(ptr, len, cap)Static. Wraps an existing malloc'd buffer without copying.
from_file(path)Static. Reads entire file into a string.
release()Returns the raw char* and empties the object. Caller must free().

Access & Iterators

MethodDescription
c_str(), data()Returns const char*.
size(), length()Returns length in bytes.
capacity()Returns current allocated capacity.
is_empty()Returns true if length is 0.
operator[]Mutable/Const access to character at index.
front(), back()Access first/last character.
begin(), end()Standard iterators (pointers) compatible with STL algorithms.

Modification

MethodDescription
append(s) / +=Appends C-string, character, or other z_str::string.
push_back(c)Appends a single char.
pop_back()Removes and returns the last char.
replace(old, new)Replaces all occurrences of string old with new.
to_lower(), to_upper()In-place case conversion (ASCII).
trim()In-place whitespace removal.
clear()Sets length to 0 (capacity remains).
fmt(fmt, ...)Static. Creates a string via printf formatting.
Warning: Pass only POD types (int, char*), not C++ objects.

Search & Utilities

MethodDescription
find(needle)Returns index of substring or -1.
contains(needle)Returns true if substring exists.
starts_with(s)Returns true if string starts with s.
ends_with(s)Returns true if string ends with s.
split(delim)Returns a split_iterable for use in range-based for loops.
Safety: Deleted for r-values (temporaries) to prevent dangling views.
rune_count()Returns the number of UTF-8 code points.
is_valid_utf8()Returns true if the string contains valid UTF-8.

class z_str::view

A lightweight, non-owning wrapper around zstr_view. Compatible with std::string_view (C++17).

MethodDescription
view(string&)Implicit conversion from z_str::string.
sub(start, len)Returns a new view slice.
lstrip(), rstrip(), trim()Returns a new view with whitespace removed.
to_int(out)Parses view to integer. Returns true on success.
starts_with, ends_withPredicate checks.
operator==Compares with view, string, or const char*.

API Reference (Lua)

The Lua module exports a zstr table with constructors. Instances are userdata objects with methods.

Constructors

FunctionDescription
zstr.new([str])Creates a new buffer, optionally initialized with str.
zstr.from_file(path)Reads an entire file into a buffer.

Buffer Methods

MethodDescription
s:append(str...)Appends one or more strings to the buffer. Returns self.
s:reserve(n)Pre-allocates capacity for n bytes.
s:clear()Empties the buffer (length 0).
s:clone()Returns a deep copy of the buffer.
s:capacity()Returns the current allocated capacity.

Transformations (In-Place)

MethodDescription
s:trim()Removes leading/trailing whitespace.
s:upper()Converts to uppercase (ASCII).
s:lower()Converts to lowercase (ASCII).
s:replace(old, new)Replaces all occurrences of old with new.

Queries

MethodDescription
s:contains(sub)Returns true if sub is found.
s:starts_with(sub)Returns true if buffer starts with sub.
s:ends_with(sub)Returns true if buffer ends with sub.
s:is_valid_utf8()Returns true if content is valid UTF-8.
s:rune_count()Returns the number of UTF-8 characters.

Utilities

MethodDescription
s:split(delim)Returns a Lua table (array) of strings split by delim.
#s (Len operator)Returns the length in bytes.
tostring(s)Converts the buffer to a standard Lua string.

Memory Management

By default, zstr.h uses the standard C library functions (malloc, realloc, free).

However, you can override these to use your own memory subsystem (e.g., Memory Arenas, Pools, or Debug Allocators).

First Option: Global Override (Recommended)

To use a custom allocator globally across all z-libs, define the Z_ macros before including zstr.h.

// my_config.h#defineZ_MALLOC(sz) my_malloc(sz)
#defineZ_CALLOC(n, sz) my_calloc(n, sz)
#defineZ_REALLOC(p, sz) my_realloc(p, sz)
#defineZ_FREE(p) my_free(p)
#include"zstr.h"

Second Option: Library-Specific Override (Advanced)

If you need a specific allocator just for strings, use the library-specific macros.

// Example: Strings use a specific heap, other z-libs use default.#defineZ_STR_MALLOC(sz) custom_alloc(sz)
#defineZ_STR_REALLOC(p, sz) custom_realloc(p, sz)
#defineZ_STR_FREE(p) custom_free(p)
#include"zstr.h"

Note for C++: If you override these macros manually, ensure your MALLOC and REALLOC macros cast their result to (char*) to satisfy C++ strict typing, though zstr.h handles this internally for standard headers (just a gentle reminder).

Notes

Small String Optimization (SSO)

zstr structs are 32 bytes (on 64-bit systems).

  • Long Mode: 8 bytes pointer, 8 bytes length, 8 bytes capacity, 1 byte flag, 7 bytes padding.
  • Short Mode: 23 bytes buffer, 1 byte length.

This means strings of length 0-22 are stored entirely within the struct definition. Creating them or modifying them requires zero heap interaction.

About

A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views.

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - z-libs/zstr.h: A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views. · GitHub
Skip to content

Repository files navigation

zstr.h

zstr.h is a modern, single-header string library for C projects. Designed to mimic the architecture of C++ std::string (specifically Small String Optimization and Views), it offers a safe, convenient API while remaining pure C.

It includes a robust C++17 wrapper for mixed codebases, and optional Lua 5.x bindings for high-performance string manipulation in scripts.

Features

  • Small String Optimization (SSO): Strings shorter than 23 bytes are stored directly on the stack (inside the struct), avoiding heap allocation entirely.
  • View Semantics: Distinct zstr (owning) and zstr_view (non-owning) types allow for zero-copy slicing and parsing.
  • Safe & Auto-Growing: Buffer overflows are handled by automatic reallocation.
  • C++ Support: Includes a full C++ class wrapper (z_str::string) with RAII, move semantics, and std::string_view compatibility.
  • Lua Support: Provides a mutable string buffer for Lua to avoid garbage generation during complex string building.
  • UTF-8 Aware: Includes helpers for UTF-8 validation and rune counting.
  • Zero Dependencies: Only standard C headers used.

Installation

C/C++ (Header Only)

zstr is a concrete type, so setup is straightforward.

  1. Copy zstr.h (and zcommon.h if separated) into your project's include directory.
  2. Include it in your code.

Lua Binding (Shared Library)

To use zstr in Lua, you must compile the binding into a shared library (zstr.so or zstr.dll).

# Compile the module (adjust paths to your Lua headers).
gcc -O3 -shared -fPIC -o zstr.so bindings/lua/zstr_module.c -Iinclude -I/usr/include/lua5.4 -llua5.4

You can also use the Makefile with:

make lua

You will need to change the Makefile to support different versions.

Usage: C

#include<stdio.h>#include"zstr.h"intmain(void)
{
// Initialize (SSO avoids malloc here).zstrs=zstr_lit("Hello");
// Concatenate using printf-style formatting.zstr_fmt(&s, ", %s!", "World");
// Access C-string safely.printf("%s\n", zstr_cstr(&s)); // "Hello, World!"// Create a zero-copy view of the first 5 chars.zstr_viewv=zstr_sub(zstr_as_view(&s), 0, 5);
// Cleanup.zstr_free(&s);
return0;
}

Usage: C++

The library detects C++ compilers automatically. To avoid naming collisions with the C struct zstr, the C++ classes live in the z_str namespace.

#include<iostream>
#include"zstr.h"intmain()
{
// RAII handles memory automatically (Constructor/Destructor).
z_str::string s = "Hello";
// Operator overloads.
s += " World!";
// Modern C++17 string_view support.
z_str::view v = s; // Static formatting helper (Safety Warning: Only pass POD types!).
z_str::string log = z_str::string::fmt("ID: %d", 42);
std::cout << s << std::endl; // "Hello World!"return0;
}

Usage: Lua

zstr acts as a high-performance mutable string buffer for Lua. It avoids the garbage collection overhead of repeated string concatenation.

localzstr=require("zstr")
-- Create a buffer (allocates once).localbuf=zstr.new("Start: ")
-- Append efficiently (no new Lua objects created).buf:append("User: ")
:append("Alice")
:append(" [Admin]")
-- Modify in-place.buf:upper() -- "START: USER: ALICE [ADMIN]"buf:trim()
-- Convert back to Lua string only when needed.print(tostring(buf)) print("Length: " ..#buf)

API Reference (C)

Initialization & Creation

FunctionDescription
zstr_init()Returns an empty string {0}.
zstr_from(const char *s)Creates a new zstr from a standard C-string.
zstr_from_len(const char *p, size_t len)Creates a zstr from a buffer and explicit length.
zstr_lit("literal")Optimized macro for string literals (calculates length at compile time).
zstr_dup(const zstr *s)Creates a deep copy of an existing zstr.
zstr_with_capacity(size_t cap)Creates an empty string with pre-allocated heap capacity.
zstr_read_file(path)Reads an entire file into a new zstr. Returns empty on failure.
zstr_own(ptr, len, cap)Takes ownership of a raw malloc'd buffer.

Memory Management

FunctionDescription
zstr_free(s)Frees the string if it is on the heap and resets it to empty.
zstr_clear(s)Sets length to 0 but preserves capacity.
zstr_reserve(s, cap)Ensures the string has space for at least cap bytes.
zstr_shrink_to_fit(s)Reduces heap usage to fit the length (or moves back to SSO).
zstr_take(s)Returns the raw malloc'd pointer and resets the zstr (caller must free).

Modification

FunctionDescription
zstr_cat(s, str)Appends a C-string to the end.
zstr_cat_len(s, ptr, len)Appends a raw buffer of known length.
zstr_push(s, char)Appends a single character (alias for zstr_push_char).
zstr_pop_char(s)Removes and returns the last character.
zstr_fmt(s, fmt, ...)Appends a formatted string (printf-style).
zstr_join(arr, n, delim)Joins an array of strings into a new zstr.
zstr_trim(s)Removes leading and trailing whitespace in-place.
zstr_to_lower(s)Converts to lowercase in-place (ASCII only).
zstr_to_upper(s)Converts to uppercase in-place (ASCII only).
zstr_replace(s, old, new)Replaces all occurrences of old with new.

Accessors & Helpers

FunctionDescription
zstr_len(s)Returns the current length (excluding null terminator).
zstr_data(s)Returns a pointer to the mutable data buffer.
zstr_cstr(s)Returns a const char* safe for C APIs.
zstr_is_empty(s)Returns true if the string length is 0.
zstr_is_long(s)Returns true if the string is currently heap-allocated.

Comparison & Search

FunctionDescription
zstr_eq(a, b)Returns true if strings are equal (faster than strcmp).
zstr_eq_ignore_case(a, b)Returns true if strings are equal (case-insensitive, ASCII only).
zstr_cmp(a, b)Standard strcmp behavior for zstr objects.
zstr_find(s, needle)Returns index of first occurrence or -1 if not found.
zstr_contains(s, needle)Returns true if the string contains the substring.
zstr_starts_with(s, pre)Checks if string starts with prefix.
zstr_ends_with(s, suf)Checks if string ends with suffix.

Views & Slices (Zero-Copy)

FunctionDescription
ZSV("lit")Macro to create a zstr_view from a literal.
zstr_as_view(s)Returns a zstr_view covering the whole string.
zstr_view_from(cstr)Creates a view from a C-string.
zstr_from_view(v)Converts a view back into an owning zstr (allocates).
zstr_sub(v, start, len)Returns a view slice (substring) without copying memory.
zstr_view_eq(v, cstr)Checks if view equals a C-string.
zstr_view_eq_view(a, b)Checks if two views are equal.
zstr_view_starts_with(v, pre)Checks if view starts with prefix.
zstr_view_ends_with(v, suf)Checks if view ends with suffix.
zstr_view_lstrip(v)Returns view with leading whitespace removed.
zstr_view_rstrip(v)Returns view with trailing whitespace removed.
zstr_view_trim(v)Returns view with both ends trimmed.
zstr_view_to_int(v, out)Parses an integer from a view (like atoi).

UTF-8 Support

FunctionDescription
zstr_is_valid_utf8(s)Validates string is strict UTF-8 (rejects overlongs/surrogates).
zstr_count_runes(s)Counts the number of actual UTF-8 Runes (not bytes).
zstr_next_rune(ptr)Decodes next rune and advances pointer. Returns 0xFFFD on error.

Iteration (Splitting)

FunctionDescription
zstr_split_init(src, delim)Initializes a split iterator (zstr_split_iter).
zstr_split_next(it, out)Advances iterator and populates out (view) with the next part.

Extensions (Experimental)

If you are using a compiler that supports __attribute__((cleanup)) (like GCC or Clang), you can use the Auto-Cleanup extension.

MacroDescription
zstr_autofreeDeclares a variable that automatically calls zstr_free when it leaves scope.

Example:

voidlog_status()
{
zstr_autofreemsg=zstr_from("Status: ");
zstr_cat(&msg, "OK");
// msg is freed automatically here.
}

API Reference (C++)

The C++ wrapper is defined in the z_str namespace to avoid collisions with the C struct. It strictly adheres to RAII principles and is designed to drop into existing C++11/17 projects.

class z_str::string

An owning string class that internally manages a zstr struct.

Constructors & Management

MethodDescription
string()Default constructor (empty).
string(const char*)Construct from C-string.
string(std::string_view)Construct from C++17 string view.
own(ptr, len, cap)Static. Wraps an existing malloc'd buffer without copying.
from_file(path)Static. Reads entire file into a string.
release()Returns the raw char* and empties the object. Caller must free().

Access & Iterators

MethodDescription
c_str(), data()Returns const char*.
size(), length()Returns length in bytes.
capacity()Returns current allocated capacity.
is_empty()Returns true if length is 0.
operator[]Mutable/Const access to character at index.
front(), back()Access first/last character.
begin(), end()Standard iterators (pointers) compatible with STL algorithms.

Modification

MethodDescription
append(s) / +=Appends C-string, character, or other z_str::string.
push_back(c)Appends a single char.
pop_back()Removes and returns the last char.
replace(old, new)Replaces all occurrences of string old with new.
to_lower(), to_upper()In-place case conversion (ASCII).
trim()In-place whitespace removal.
clear()Sets length to 0 (capacity remains).
fmt(fmt, ...)Static. Creates a string via printf formatting.
Warning: Pass only POD types (int, char*), not C++ objects.

Search & Utilities

MethodDescription
find(needle)Returns index of substring or -1.
contains(needle)Returns true if substring exists.
starts_with(s)Returns true if string starts with s.
ends_with(s)Returns true if string ends with s.
split(delim)Returns a split_iterable for use in range-based for loops.
Safety: Deleted for r-values (temporaries) to prevent dangling views.
rune_count()Returns the number of UTF-8 code points.
is_valid_utf8()Returns true if the string contains valid UTF-8.

class z_str::view

A lightweight, non-owning wrapper around zstr_view. Compatible with std::string_view (C++17).

MethodDescription
view(string&)Implicit conversion from z_str::string.
sub(start, len)Returns a new view slice.
lstrip(), rstrip(), trim()Returns a new view with whitespace removed.
to_int(out)Parses view to integer. Returns true on success.
starts_with, ends_withPredicate checks.
operator==Compares with view, string, or const char*.

API Reference (Lua)

The Lua module exports a zstr table with constructors. Instances are userdata objects with methods.

Constructors

FunctionDescription
zstr.new([str])Creates a new buffer, optionally initialized with str.
zstr.from_file(path)Reads an entire file into a buffer.

Buffer Methods

MethodDescription
s:append(str...)Appends one or more strings to the buffer. Returns self.
s:reserve(n)Pre-allocates capacity for n bytes.
s:clear()Empties the buffer (length 0).
s:clone()Returns a deep copy of the buffer.
s:capacity()Returns the current allocated capacity.

Transformations (In-Place)

MethodDescription
s:trim()Removes leading/trailing whitespace.
s:upper()Converts to uppercase (ASCII).
s:lower()Converts to lowercase (ASCII).
s:replace(old, new)Replaces all occurrences of old with new.

Queries

MethodDescription
s:contains(sub)Returns true if sub is found.
s:starts_with(sub)Returns true if buffer starts with sub.
s:ends_with(sub)Returns true if buffer ends with sub.
s:is_valid_utf8()Returns true if content is valid UTF-8.
s:rune_count()Returns the number of UTF-8 characters.

Utilities

MethodDescription
s:split(delim)Returns a Lua table (array) of strings split by delim.
#s (Len operator)Returns the length in bytes.
tostring(s)Converts the buffer to a standard Lua string.

Memory Management

By default, zstr.h uses the standard C library functions (malloc, realloc, free).

However, you can override these to use your own memory subsystem (e.g., Memory Arenas, Pools, or Debug Allocators).

First Option: Global Override (Recommended)

To use a custom allocator globally across all z-libs, define the Z_ macros before including zstr.h.

// my_config.h#defineZ_MALLOC(sz) my_malloc(sz)
#defineZ_CALLOC(n, sz) my_calloc(n, sz)
#defineZ_REALLOC(p, sz) my_realloc(p, sz)
#defineZ_FREE(p) my_free(p)
#include"zstr.h"

Second Option: Library-Specific Override (Advanced)

If you need a specific allocator just for strings, use the library-specific macros.

// Example: Strings use a specific heap, other z-libs use default.#defineZ_STR_MALLOC(sz) custom_alloc(sz)
#defineZ_STR_REALLOC(p, sz) custom_realloc(p, sz)
#defineZ_STR_FREE(p) custom_free(p)
#include"zstr.h"

Note for C++: If you override these macros manually, ensure your MALLOC and REALLOC macros cast their result to (char*) to satisfy C++ strict typing, though zstr.h handles this internally for standard headers (just a gentle reminder).

Notes

Small String Optimization (SSO)

zstr structs are 32 bytes (on 64-bit systems).

  • Long Mode: 8 bytes pointer, 8 bytes length, 8 bytes capacity, 1 byte flag, 7 bytes padding.
  • Short Mode: 23 bytes buffer, 1 byte length.

This means strings of length 0-22 are stored entirely within the struct definition. Creating them or modifying them requires zero heap interaction.

About

A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views.

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - z-libs/zstr.h: A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views. · GitHub
Skip to content

Repository files navigation

zstr.h

zstr.h is a modern, single-header string library for C projects. Designed to mimic the architecture of C++ std::string (specifically Small String Optimization and Views), it offers a safe, convenient API while remaining pure C.

It includes a robust C++17 wrapper for mixed codebases, and optional Lua 5.x bindings for high-performance string manipulation in scripts.

Features

  • Small String Optimization (SSO): Strings shorter than 23 bytes are stored directly on the stack (inside the struct), avoiding heap allocation entirely.
  • View Semantics: Distinct zstr (owning) and zstr_view (non-owning) types allow for zero-copy slicing and parsing.
  • Safe & Auto-Growing: Buffer overflows are handled by automatic reallocation.
  • C++ Support: Includes a full C++ class wrapper (z_str::string) with RAII, move semantics, and std::string_view compatibility.
  • Lua Support: Provides a mutable string buffer for Lua to avoid garbage generation during complex string building.
  • UTF-8 Aware: Includes helpers for UTF-8 validation and rune counting.
  • Zero Dependencies: Only standard C headers used.

Installation

C/C++ (Header Only)

zstr is a concrete type, so setup is straightforward.

  1. Copy zstr.h (and zcommon.h if separated) into your project's include directory.
  2. Include it in your code.

Lua Binding (Shared Library)

To use zstr in Lua, you must compile the binding into a shared library (zstr.so or zstr.dll).

# Compile the module (adjust paths to your Lua headers).
gcc -O3 -shared -fPIC -o zstr.so bindings/lua/zstr_module.c -Iinclude -I/usr/include/lua5.4 -llua5.4

You can also use the Makefile with:

make lua

You will need to change the Makefile to support different versions.

Usage: C

#include<stdio.h>#include"zstr.h"intmain(void)
{
// Initialize (SSO avoids malloc here).zstrs=zstr_lit("Hello");
// Concatenate using printf-style formatting.zstr_fmt(&s, ", %s!", "World");
// Access C-string safely.printf("%s\n", zstr_cstr(&s)); // "Hello, World!"// Create a zero-copy view of the first 5 chars.zstr_viewv=zstr_sub(zstr_as_view(&s), 0, 5);
// Cleanup.zstr_free(&s);
return0;
}

Usage: C++

The library detects C++ compilers automatically. To avoid naming collisions with the C struct zstr, the C++ classes live in the z_str namespace.

#include<iostream>
#include"zstr.h"intmain()
{
// RAII handles memory automatically (Constructor/Destructor).
z_str::string s = "Hello";
// Operator overloads.
s += " World!";
// Modern C++17 string_view support.
z_str::view v = s; // Static formatting helper (Safety Warning: Only pass POD types!).
z_str::string log = z_str::string::fmt("ID: %d", 42);
std::cout << s << std::endl; // "Hello World!"return0;
}

Usage: Lua

zstr acts as a high-performance mutable string buffer for Lua. It avoids the garbage collection overhead of repeated string concatenation.

localzstr=require("zstr")
-- Create a buffer (allocates once).localbuf=zstr.new("Start: ")
-- Append efficiently (no new Lua objects created).buf:append("User: ")
:append("Alice")
:append(" [Admin]")
-- Modify in-place.buf:upper() -- "START: USER: ALICE [ADMIN]"buf:trim()
-- Convert back to Lua string only when needed.print(tostring(buf)) print("Length: " ..#buf)

API Reference (C)

Initialization & Creation

FunctionDescription
zstr_init()Returns an empty string {0}.
zstr_from(const char *s)Creates a new zstr from a standard C-string.
zstr_from_len(const char *p, size_t len)Creates a zstr from a buffer and explicit length.
zstr_lit("literal")Optimized macro for string literals (calculates length at compile time).
zstr_dup(const zstr *s)Creates a deep copy of an existing zstr.
zstr_with_capacity(size_t cap)Creates an empty string with pre-allocated heap capacity.
zstr_read_file(path)Reads an entire file into a new zstr. Returns empty on failure.
zstr_own(ptr, len, cap)Takes ownership of a raw malloc'd buffer.

Memory Management

FunctionDescription
zstr_free(s)Frees the string if it is on the heap and resets it to empty.
zstr_clear(s)Sets length to 0 but preserves capacity.
zstr_reserve(s, cap)Ensures the string has space for at least cap bytes.
zstr_shrink_to_fit(s)Reduces heap usage to fit the length (or moves back to SSO).
zstr_take(s)Returns the raw malloc'd pointer and resets the zstr (caller must free).

Modification

FunctionDescription
zstr_cat(s, str)Appends a C-string to the end.
zstr_cat_len(s, ptr, len)Appends a raw buffer of known length.
zstr_push(s, char)Appends a single character (alias for zstr_push_char).
zstr_pop_char(s)Removes and returns the last character.
zstr_fmt(s, fmt, ...)Appends a formatted string (printf-style).
zstr_join(arr, n, delim)Joins an array of strings into a new zstr.
zstr_trim(s)Removes leading and trailing whitespace in-place.
zstr_to_lower(s)Converts to lowercase in-place (ASCII only).
zstr_to_upper(s)Converts to uppercase in-place (ASCII only).
zstr_replace(s, old, new)Replaces all occurrences of old with new.

Accessors & Helpers

FunctionDescription
zstr_len(s)Returns the current length (excluding null terminator).
zstr_data(s)Returns a pointer to the mutable data buffer.
zstr_cstr(s)Returns a const char* safe for C APIs.
zstr_is_empty(s)Returns true if the string length is 0.
zstr_is_long(s)Returns true if the string is currently heap-allocated.

Comparison & Search

FunctionDescription
zstr_eq(a, b)Returns true if strings are equal (faster than strcmp).
zstr_eq_ignore_case(a, b)Returns true if strings are equal (case-insensitive, ASCII only).
zstr_cmp(a, b)Standard strcmp behavior for zstr objects.
zstr_find(s, needle)Returns index of first occurrence or -1 if not found.
zstr_contains(s, needle)Returns true if the string contains the substring.
zstr_starts_with(s, pre)Checks if string starts with prefix.
zstr_ends_with(s, suf)Checks if string ends with suffix.

Views & Slices (Zero-Copy)

FunctionDescription
ZSV("lit")Macro to create a zstr_view from a literal.
zstr_as_view(s)Returns a zstr_view covering the whole string.
zstr_view_from(cstr)Creates a view from a C-string.
zstr_from_view(v)Converts a view back into an owning zstr (allocates).
zstr_sub(v, start, len)Returns a view slice (substring) without copying memory.
zstr_view_eq(v, cstr)Checks if view equals a C-string.
zstr_view_eq_view(a, b)Checks if two views are equal.
zstr_view_starts_with(v, pre)Checks if view starts with prefix.
zstr_view_ends_with(v, suf)Checks if view ends with suffix.
zstr_view_lstrip(v)Returns view with leading whitespace removed.
zstr_view_rstrip(v)Returns view with trailing whitespace removed.
zstr_view_trim(v)Returns view with both ends trimmed.
zstr_view_to_int(v, out)Parses an integer from a view (like atoi).

UTF-8 Support

FunctionDescription
zstr_is_valid_utf8(s)Validates string is strict UTF-8 (rejects overlongs/surrogates).
zstr_count_runes(s)Counts the number of actual UTF-8 Runes (not bytes).
zstr_next_rune(ptr)Decodes next rune and advances pointer. Returns 0xFFFD on error.

Iteration (Splitting)

FunctionDescription
zstr_split_init(src, delim)Initializes a split iterator (zstr_split_iter).
zstr_split_next(it, out)Advances iterator and populates out (view) with the next part.

Extensions (Experimental)

If you are using a compiler that supports __attribute__((cleanup)) (like GCC or Clang), you can use the Auto-Cleanup extension.

MacroDescription
zstr_autofreeDeclares a variable that automatically calls zstr_free when it leaves scope.

Example:

voidlog_status()
{
zstr_autofreemsg=zstr_from("Status: ");
zstr_cat(&msg, "OK");
// msg is freed automatically here.
}

API Reference (C++)

The C++ wrapper is defined in the z_str namespace to avoid collisions with the C struct. It strictly adheres to RAII principles and is designed to drop into existing C++11/17 projects.

class z_str::string

An owning string class that internally manages a zstr struct.

Constructors & Management

MethodDescription
string()Default constructor (empty).
string(const char*)Construct from C-string.
string(std::string_view)Construct from C++17 string view.
own(ptr, len, cap)Static. Wraps an existing malloc'd buffer without copying.
from_file(path)Static. Reads entire file into a string.
release()Returns the raw char* and empties the object. Caller must free().

Access & Iterators

MethodDescription
c_str(), data()Returns const char*.
size(), length()Returns length in bytes.
capacity()Returns current allocated capacity.
is_empty()Returns true if length is 0.
operator[]Mutable/Const access to character at index.
front(), back()Access first/last character.
begin(), end()Standard iterators (pointers) compatible with STL algorithms.

Modification

MethodDescription
append(s) / +=Appends C-string, character, or other z_str::string.
push_back(c)Appends a single char.
pop_back()Removes and returns the last char.
replace(old, new)Replaces all occurrences of string old with new.
to_lower(), to_upper()In-place case conversion (ASCII).
trim()In-place whitespace removal.
clear()Sets length to 0 (capacity remains).
fmt(fmt, ...)Static. Creates a string via printf formatting.
Warning: Pass only POD types (int, char*), not C++ objects.

Search & Utilities

MethodDescription
find(needle)Returns index of substring or -1.
contains(needle)Returns true if substring exists.
starts_with(s)Returns true if string starts with s.
ends_with(s)Returns true if string ends with s.
split(delim)Returns a split_iterable for use in range-based for loops.
Safety: Deleted for r-values (temporaries) to prevent dangling views.
rune_count()Returns the number of UTF-8 code points.
is_valid_utf8()Returns true if the string contains valid UTF-8.

class z_str::view

A lightweight, non-owning wrapper around zstr_view. Compatible with std::string_view (C++17).

MethodDescription
view(string&)Implicit conversion from z_str::string.
sub(start, len)Returns a new view slice.
lstrip(), rstrip(), trim()Returns a new view with whitespace removed.
to_int(out)Parses view to integer. Returns true on success.
starts_with, ends_withPredicate checks.
operator==Compares with view, string, or const char*.

API Reference (Lua)

The Lua module exports a zstr table with constructors. Instances are userdata objects with methods.

Constructors

FunctionDescription
zstr.new([str])Creates a new buffer, optionally initialized with str.
zstr.from_file(path)Reads an entire file into a buffer.

Buffer Methods

MethodDescription
s:append(str...)Appends one or more strings to the buffer. Returns self.
s:reserve(n)Pre-allocates capacity for n bytes.
s:clear()Empties the buffer (length 0).
s:clone()Returns a deep copy of the buffer.
s:capacity()Returns the current allocated capacity.

Transformations (In-Place)

MethodDescription
s:trim()Removes leading/trailing whitespace.
s:upper()Converts to uppercase (ASCII).
s:lower()Converts to lowercase (ASCII).
s:replace(old, new)Replaces all occurrences of old with new.

Queries

MethodDescription
s:contains(sub)Returns true if sub is found.
s:starts_with(sub)Returns true if buffer starts with sub.
s:ends_with(sub)Returns true if buffer ends with sub.
s:is_valid_utf8()Returns true if content is valid UTF-8.
s:rune_count()Returns the number of UTF-8 characters.

Utilities

MethodDescription
s:split(delim)Returns a Lua table (array) of strings split by delim.
#s (Len operator)Returns the length in bytes.
tostring(s)Converts the buffer to a standard Lua string.

Memory Management

By default, zstr.h uses the standard C library functions (malloc, realloc, free).

However, you can override these to use your own memory subsystem (e.g., Memory Arenas, Pools, or Debug Allocators).

First Option: Global Override (Recommended)

To use a custom allocator globally across all z-libs, define the Z_ macros before including zstr.h.

// my_config.h#defineZ_MALLOC(sz) my_malloc(sz)
#defineZ_CALLOC(n, sz) my_calloc(n, sz)
#defineZ_REALLOC(p, sz) my_realloc(p, sz)
#defineZ_FREE(p) my_free(p)
#include"zstr.h"

Second Option: Library-Specific Override (Advanced)

If you need a specific allocator just for strings, use the library-specific macros.

// Example: Strings use a specific heap, other z-libs use default.#defineZ_STR_MALLOC(sz) custom_alloc(sz)
#defineZ_STR_REALLOC(p, sz) custom_realloc(p, sz)
#defineZ_STR_FREE(p) custom_free(p)
#include"zstr.h"

Note for C++: If you override these macros manually, ensure your MALLOC and REALLOC macros cast their result to (char*) to satisfy C++ strict typing, though zstr.h handles this internally for standard headers (just a gentle reminder).

Notes

Small String Optimization (SSO)

zstr structs are 32 bytes (on 64-bit systems).

  • Long Mode: 8 bytes pointer, 8 bytes length, 8 bytes capacity, 1 byte flag, 7 bytes padding.
  • Short Mode: 23 bytes buffer, 1 byte length.

This means strings of length 0-22 are stored entirely within the struct definition. Creating them or modifying them requires zero heap interaction.

About

A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views.

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - z-libs/zstr.h: A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views. · GitHub
Skip to content

Repository files navigation

zstr.h

zstr.h is a modern, single-header string library for C projects. Designed to mimic the architecture of C++ std::string (specifically Small String Optimization and Views), it offers a safe, convenient API while remaining pure C.

It includes a robust C++17 wrapper for mixed codebases, and optional Lua 5.x bindings for high-performance string manipulation in scripts.

Features

  • Small String Optimization (SSO): Strings shorter than 23 bytes are stored directly on the stack (inside the struct), avoiding heap allocation entirely.
  • View Semantics: Distinct zstr (owning) and zstr_view (non-owning) types allow for zero-copy slicing and parsing.
  • Safe & Auto-Growing: Buffer overflows are handled by automatic reallocation.
  • C++ Support: Includes a full C++ class wrapper (z_str::string) with RAII, move semantics, and std::string_view compatibility.
  • Lua Support: Provides a mutable string buffer for Lua to avoid garbage generation during complex string building.
  • UTF-8 Aware: Includes helpers for UTF-8 validation and rune counting.
  • Zero Dependencies: Only standard C headers used.

Installation

C/C++ (Header Only)

zstr is a concrete type, so setup is straightforward.

  1. Copy zstr.h (and zcommon.h if separated) into your project's include directory.
  2. Include it in your code.

Lua Binding (Shared Library)

To use zstr in Lua, you must compile the binding into a shared library (zstr.so or zstr.dll).

# Compile the module (adjust paths to your Lua headers).
gcc -O3 -shared -fPIC -o zstr.so bindings/lua/zstr_module.c -Iinclude -I/usr/include/lua5.4 -llua5.4

You can also use the Makefile with:

make lua

You will need to change the Makefile to support different versions.

Usage: C

#include<stdio.h>#include"zstr.h"intmain(void)
{
// Initialize (SSO avoids malloc here).zstrs=zstr_lit("Hello");
// Concatenate using printf-style formatting.zstr_fmt(&s, ", %s!", "World");
// Access C-string safely.printf("%s\n", zstr_cstr(&s)); // "Hello, World!"// Create a zero-copy view of the first 5 chars.zstr_viewv=zstr_sub(zstr_as_view(&s), 0, 5);
// Cleanup.zstr_free(&s);
return0;
}

Usage: C++

The library detects C++ compilers automatically. To avoid naming collisions with the C struct zstr, the C++ classes live in the z_str namespace.

#include<iostream>
#include"zstr.h"intmain()
{
// RAII handles memory automatically (Constructor/Destructor).
z_str::string s = "Hello";
// Operator overloads.
s += " World!";
// Modern C++17 string_view support.
z_str::view v = s; // Static formatting helper (Safety Warning: Only pass POD types!).
z_str::string log = z_str::string::fmt("ID: %d", 42);
std::cout << s << std::endl; // "Hello World!"return0;
}

Usage: Lua

zstr acts as a high-performance mutable string buffer for Lua. It avoids the garbage collection overhead of repeated string concatenation.

localzstr=require("zstr")
-- Create a buffer (allocates once).localbuf=zstr.new("Start: ")
-- Append efficiently (no new Lua objects created).buf:append("User: ")
:append("Alice")
:append(" [Admin]")
-- Modify in-place.buf:upper() -- "START: USER: ALICE [ADMIN]"buf:trim()
-- Convert back to Lua string only when needed.print(tostring(buf)) print("Length: " ..#buf)

API Reference (C)

Initialization & Creation

FunctionDescription
zstr_init()Returns an empty string {0}.
zstr_from(const char *s)Creates a new zstr from a standard C-string.
zstr_from_len(const char *p, size_t len)Creates a zstr from a buffer and explicit length.
zstr_lit("literal")Optimized macro for string literals (calculates length at compile time).
zstr_dup(const zstr *s)Creates a deep copy of an existing zstr.
zstr_with_capacity(size_t cap)Creates an empty string with pre-allocated heap capacity.
zstr_read_file(path)Reads an entire file into a new zstr. Returns empty on failure.
zstr_own(ptr, len, cap)Takes ownership of a raw malloc'd buffer.

Memory Management

FunctionDescription
zstr_free(s)Frees the string if it is on the heap and resets it to empty.
zstr_clear(s)Sets length to 0 but preserves capacity.
zstr_reserve(s, cap)Ensures the string has space for at least cap bytes.
zstr_shrink_to_fit(s)Reduces heap usage to fit the length (or moves back to SSO).
zstr_take(s)Returns the raw malloc'd pointer and resets the zstr (caller must free).

Modification

FunctionDescription
zstr_cat(s, str)Appends a C-string to the end.
zstr_cat_len(s, ptr, len)Appends a raw buffer of known length.
zstr_push(s, char)Appends a single character (alias for zstr_push_char).
zstr_pop_char(s)Removes and returns the last character.
zstr_fmt(s, fmt, ...)Appends a formatted string (printf-style).
zstr_join(arr, n, delim)Joins an array of strings into a new zstr.
zstr_trim(s)Removes leading and trailing whitespace in-place.
zstr_to_lower(s)Converts to lowercase in-place (ASCII only).
zstr_to_upper(s)Converts to uppercase in-place (ASCII only).
zstr_replace(s, old, new)Replaces all occurrences of old with new.

Accessors & Helpers

FunctionDescription
zstr_len(s)Returns the current length (excluding null terminator).
zstr_data(s)Returns a pointer to the mutable data buffer.
zstr_cstr(s)Returns a const char* safe for C APIs.
zstr_is_empty(s)Returns true if the string length is 0.
zstr_is_long(s)Returns true if the string is currently heap-allocated.

Comparison & Search

FunctionDescription
zstr_eq(a, b)Returns true if strings are equal (faster than strcmp).
zstr_eq_ignore_case(a, b)Returns true if strings are equal (case-insensitive, ASCII only).
zstr_cmp(a, b)Standard strcmp behavior for zstr objects.
zstr_find(s, needle)Returns index of first occurrence or -1 if not found.
zstr_contains(s, needle)Returns true if the string contains the substring.
zstr_starts_with(s, pre)Checks if string starts with prefix.
zstr_ends_with(s, suf)Checks if string ends with suffix.

Views & Slices (Zero-Copy)

FunctionDescription
ZSV("lit")Macro to create a zstr_view from a literal.
zstr_as_view(s)Returns a zstr_view covering the whole string.
zstr_view_from(cstr)Creates a view from a C-string.
zstr_from_view(v)Converts a view back into an owning zstr (allocates).
zstr_sub(v, start, len)Returns a view slice (substring) without copying memory.
zstr_view_eq(v, cstr)Checks if view equals a C-string.
zstr_view_eq_view(a, b)Checks if two views are equal.
zstr_view_starts_with(v, pre)Checks if view starts with prefix.
zstr_view_ends_with(v, suf)Checks if view ends with suffix.
zstr_view_lstrip(v)Returns view with leading whitespace removed.
zstr_view_rstrip(v)Returns view with trailing whitespace removed.
zstr_view_trim(v)Returns view with both ends trimmed.
zstr_view_to_int(v, out)Parses an integer from a view (like atoi).

UTF-8 Support

FunctionDescription
zstr_is_valid_utf8(s)Validates string is strict UTF-8 (rejects overlongs/surrogates).
zstr_count_runes(s)Counts the number of actual UTF-8 Runes (not bytes).
zstr_next_rune(ptr)Decodes next rune and advances pointer. Returns 0xFFFD on error.

Iteration (Splitting)

FunctionDescription
zstr_split_init(src, delim)Initializes a split iterator (zstr_split_iter).
zstr_split_next(it, out)Advances iterator and populates out (view) with the next part.

Extensions (Experimental)

If you are using a compiler that supports __attribute__((cleanup)) (like GCC or Clang), you can use the Auto-Cleanup extension.

MacroDescription
zstr_autofreeDeclares a variable that automatically calls zstr_free when it leaves scope.

Example:

voidlog_status()
{
zstr_autofreemsg=zstr_from("Status: ");
zstr_cat(&msg, "OK");
// msg is freed automatically here.
}

API Reference (C++)

The C++ wrapper is defined in the z_str namespace to avoid collisions with the C struct. It strictly adheres to RAII principles and is designed to drop into existing C++11/17 projects.

class z_str::string

An owning string class that internally manages a zstr struct.

Constructors & Management

MethodDescription
string()Default constructor (empty).
string(const char*)Construct from C-string.
string(std::string_view)Construct from C++17 string view.
own(ptr, len, cap)Static. Wraps an existing malloc'd buffer without copying.
from_file(path)Static. Reads entire file into a string.
release()Returns the raw char* and empties the object. Caller must free().

Access & Iterators

MethodDescription
c_str(), data()Returns const char*.
size(), length()Returns length in bytes.
capacity()Returns current allocated capacity.
is_empty()Returns true if length is 0.
operator[]Mutable/Const access to character at index.
front(), back()Access first/last character.
begin(), end()Standard iterators (pointers) compatible with STL algorithms.

Modification

MethodDescription
append(s) / +=Appends C-string, character, or other z_str::string.
push_back(c)Appends a single char.
pop_back()Removes and returns the last char.
replace(old, new)Replaces all occurrences of string old with new.
to_lower(), to_upper()In-place case conversion (ASCII).
trim()In-place whitespace removal.
clear()Sets length to 0 (capacity remains).
fmt(fmt, ...)Static. Creates a string via printf formatting.
Warning: Pass only POD types (int, char*), not C++ objects.

Search & Utilities

MethodDescription
find(needle)Returns index of substring or -1.
contains(needle)Returns true if substring exists.
starts_with(s)Returns true if string starts with s.
ends_with(s)Returns true if string ends with s.
split(delim)Returns a split_iterable for use in range-based for loops.
Safety: Deleted for r-values (temporaries) to prevent dangling views.
rune_count()Returns the number of UTF-8 code points.
is_valid_utf8()Returns true if the string contains valid UTF-8.

class z_str::view

A lightweight, non-owning wrapper around zstr_view. Compatible with std::string_view (C++17).

MethodDescription
view(string&)Implicit conversion from z_str::string.
sub(start, len)Returns a new view slice.
lstrip(), rstrip(), trim()Returns a new view with whitespace removed.
to_int(out)Parses view to integer. Returns true on success.
starts_with, ends_withPredicate checks.
operator==Compares with view, string, or const char*.

API Reference (Lua)

The Lua module exports a zstr table with constructors. Instances are userdata objects with methods.

Constructors

FunctionDescription
zstr.new([str])Creates a new buffer, optionally initialized with str.
zstr.from_file(path)Reads an entire file into a buffer.

Buffer Methods

MethodDescription
s:append(str...)Appends one or more strings to the buffer. Returns self.
s:reserve(n)Pre-allocates capacity for n bytes.
s:clear()Empties the buffer (length 0).
s:clone()Returns a deep copy of the buffer.
s:capacity()Returns the current allocated capacity.

Transformations (In-Place)

MethodDescription
s:trim()Removes leading/trailing whitespace.
s:upper()Converts to uppercase (ASCII).
s:lower()Converts to lowercase (ASCII).
s:replace(old, new)Replaces all occurrences of old with new.

Queries

MethodDescription
s:contains(sub)Returns true if sub is found.
s:starts_with(sub)Returns true if buffer starts with sub.
s:ends_with(sub)Returns true if buffer ends with sub.
s:is_valid_utf8()Returns true if content is valid UTF-8.
s:rune_count()Returns the number of UTF-8 characters.

Utilities

MethodDescription
s:split(delim)Returns a Lua table (array) of strings split by delim.
#s (Len operator)Returns the length in bytes.
tostring(s)Converts the buffer to a standard Lua string.

Memory Management

By default, zstr.h uses the standard C library functions (malloc, realloc, free).

However, you can override these to use your own memory subsystem (e.g., Memory Arenas, Pools, or Debug Allocators).

First Option: Global Override (Recommended)

To use a custom allocator globally across all z-libs, define the Z_ macros before including zstr.h.

// my_config.h#defineZ_MALLOC(sz) my_malloc(sz)
#defineZ_CALLOC(n, sz) my_calloc(n, sz)
#defineZ_REALLOC(p, sz) my_realloc(p, sz)
#defineZ_FREE(p) my_free(p)
#include"zstr.h"

Second Option: Library-Specific Override (Advanced)

If you need a specific allocator just for strings, use the library-specific macros.

// Example: Strings use a specific heap, other z-libs use default.#defineZ_STR_MALLOC(sz) custom_alloc(sz)
#defineZ_STR_REALLOC(p, sz) custom_realloc(p, sz)
#defineZ_STR_FREE(p) custom_free(p)
#include"zstr.h"

Note for C++: If you override these macros manually, ensure your MALLOC and REALLOC macros cast their result to (char*) to satisfy C++ strict typing, though zstr.h handles this internally for standard headers (just a gentle reminder).

Notes

Small String Optimization (SSO)

zstr structs are 32 bytes (on 64-bit systems).

  • Long Mode: 8 bytes pointer, 8 bytes length, 8 bytes capacity, 1 byte flag, 7 bytes padding.
  • Short Mode: 23 bytes buffer, 1 byte length.

This means strings of length 0-22 are stored entirely within the struct definition. Creating them or modifying them requires zero heap interaction.

About

A modern, header-only string library for C/C++ using Small String Optimization (SSO) and Views.

Resources

Stars

34 stars

Watchers

1 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages