solidc
Robust collection of general-purpose cross-platform C libraries and data structures designed for rapid and safe development in C
Loading...
Searching...
No Matches
Classes | Macros | Typedefs | Functions
cstr.h File Reference

High-performance C string with Small String Optimization (SSO). More...

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "macros.h"
Include dependency graph for cstr.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  cstr
 A dynamically resizable C string with SSO. More...
 

Macros

#define CSTR_MAX_LEN   ((uint32_t)0x7FFFFFFFu)
 
#define CSTR_SSO_CAP   16u /* 15 usable chars + NUL */
 
#define CSTR_HEAP_FLAG   ((uint32_t)0x80000000u)
 
#define CSTR_NPOS   (-1)
 

Typedefs

typedef struct cstr cstr
 A dynamically resizable C string with SSO.
 

Functions

CSTR_INLINE bool cstr_is_heap (const cstr *s) CSTR_PURE
 
CSTR_INLINE uint32_t cstr_heap_cap (const cstr *s) CSTR_PURE
 
CSTR_INLINE size_t cstr_len (const cstr *s) CSTR_PURE
 Length of the string, excluding NUL.
 
CSTR_INLINE size_t cstr_capacity (const cstr *s) CSTR_PURE
 Current storage capacity (bytes available before reallocation). For SSO strings this is CSTR_SSO_CAP - 1 (15 chars + room for NUL).
 
CSTR_INLINE bool cstr_empty (const cstr *s) CSTR_PURE
 
CSTR_INLINE bool cstr_allocated (const cstr *s) CSTR_PURE
 
CSTR_INLINE char * cstr_data (cstr *s) CSTR_PURE
 Mutable pointer to the NUL-terminated string data. Never NULL for a valid cstr.
 
CSTR_INLINE const char * cstr_data_const (const cstr *s) CSTR_PURE
 Const pointer to the NUL-terminated string data.
 
CSTR_INLINE char cstr_at (const cstr *s, size_t index) CSTR_PURE
 Character at index, or NUL if out of range.
 
CSTR_INLINE cstr_view cstr_as_view (const cstr *s)
 Construct a cstr_view from a cstr (zero copy).
 
CSTR_INLINE void cstr_init_inplace (cstr *s)
 Initialize an already-allocated cstr in SSO mode (no heap).
 
cstrcstr_init (size_t initial_capacity) CSTR_WARN_UNUSED
 Create a new heap-allocated cstr with a given initial capacity.
 
cstrcstr_new (const char *input) CSTR_WARN_UNUSED
 Create a new cstr from a C string.
 
cstrcstr_new_len (const char *data, size_t length) CSTR_WARN_UNUSED
 Create a new cstr from a buffer of known length (no strlen needed).
 
void cstr_free (cstr *s)
 Free a heap-allocated cstr and its storage. Safe to call with NULL.
 
void cstr_drop (cstr *s)
 Release only the internal heap buffer of an embedded cstr (one created via cstr_init_inplace). Does NOT free the cstr struct itself.
 
void cstr_debug (const cstr *s)
 Print debug information about a cstr to stderr.
 
bool cstr_reserve (cstr *s, size_t capacity) CSTR_NONNULL(1) CSTR_WARN_UNUSED
 Ensure at least capacity usable bytes are available (NUL extra).
 
CSTR_INLINE bool cstr_resize (cstr *s, size_t capacity) CSTR_NONNULL(1) CSTR_WARN_UNUSED
 
void cstr_shrink_to_fit (cstr *s) CSTR_NONNULL(1)
 Shrink heap allocation to fit the current length (frees wasted memory).
 
CSTR_INLINE void cstr_clear (cstr *s)
 Set length to 0 (data pointer and capacity unchanged).
 
bool cstr_append (cstr *s, const char *CSTR_RESTRICT append) CSTR_NONNULL(1
 Append a NUL-terminated C string.
 
bool bool cstr_append_cstr (cstr *s, const cstr *append) CSTR_NONNULL(1
 Append another cstr.
 
bool bool bool cstr_ncat (cstr *dest, const cstr *src, size_t n) CSTR_NONNULL(1
 Append at most n chars from src.
 
bool bool bool CSTR_INLINE bool cstr_cat (cstr *dest, const cstr *src) CSTR_NONNULL(1
 
CSTR_INLINE bool cstr_append_fast (cstr *s, const char *CSTR_RESTRICT append) CSTR_NONNULL(1
 Append without capacity check — caller guarantees space. ~20% faster for bulk building when capacity is pre-reserved.
 
bool cstr_append_char (cstr *s, char c) CSTR_NONNULL(1)
 Append a single character.
 
 PRINTF_FORMAT (1, 2) cstr *cstr_format(const char *format
 Create a new cstr from a printf-style format string.
 
 PRINTF_FORMAT (2, 3) bool cstr_append_fmt(cstr *s
 Append a printf-style formatted string.
 
bool cstr_prepend (cstr *s, const char *prepend) CSTR_NONNULL(1
 Prepend a NUL-terminated C string.
 
bool bool cstr_prepend_cstr (cstr *s, const cstr *prepend) CSTR_NONNULL(1
 Prepend another cstr.
 
bool bool bool cstr_prepend_fast (cstr *s, const char *prepend) CSTR_NONNULL(1
 Prepend without capacity check — caller guarantees space.
 
bool bool bool bool cstr_insert (cstr *s, size_t index, const char *insert) CSTR_NONNULL(1
 Insert a C string at byte offset index.
 
bool bool bool bool bool cstr_insert_cstr (cstr *s, size_t index, const cstr *insert) CSTR_NONNULL(1
 Insert a cstr at byte offset index.
 
bool bool bool bool bool bool cstr_remove (cstr *s, size_t index, size_t count) CSTR_NONNULL(1)
 Remove count characters starting at index.
 
size_t cstr_remove_all (cstr *s, const char *substr) CSTR_NONNULL(1
 Remove all occurrences of substr (in-place, single pass).
 
size_t size_t void cstr_remove_char (cstr *s, char c) CSTR_NONNULL(1)
 Remove a specific character from every position.
 
void cstr_remove_substr (cstr *str, size_t start, size_t substr_length) CSTR_NONNULL(1)
 Remove a run of substr_length bytes starting at start.
 
bool cstr_copy (cstr *dest, const cstr *src) CSTR_NONNULL(1
 Deep copy src into dest (dest is overwritten).
 
bool CSTR_INLINE bool cstr_assign (cstr *dest, const cstr *src) CSTR_NONNULL(1
 
void int cstr_cmp (const cstr *s1, const cstr *s2) CSTR_PURE
 Lexicographic compare. NULL < non-NULL; two NULLs are equal.
 
CSTR_INLINE bool cstr_equals (const cstr *s1, const cstr *s2) CSTR_PURE
 Equality check (length-first — very fast for non-equal strings).
 
int cstr_find (const cstr *s, const char *substr) CSTR_NONNULL(1
 Find first occurrence of substr. Uses optimised search (no memmem).
 
int cstr_rfind (const cstr *s, const char *substr) CSTR_NONNULL(1
 
size_t cstr_count_substr (const cstr *s, const char *substr) CSTR_NONNULL(1
 
cstr ** cstr_split (const cstr *s, const char *delim, size_t *count_out) CSTR_NONNULL(1
 Split on delimiter. Returns array of cstr* (each must be freed), terminated by setting *count_out. Caller must free each element and the array itself.
 
cstrcstr_join (const cstr **strings, size_t count, const char *delim) CSTR_WARN_UNUSED
 Join an array of cstr pointers with a delimiter.
 

Detailed Description

High-performance C string with Small String Optimization (SSO).

Key design decisions vs. the convential implementation:

  1. Self-referential SSO pointer data always points to the live bytes — either into buf[] (stack) or a heap allocation. Every read/write goes through one pointer with zero branching; the "is-heap?" test is only needed for free/resize paths.
  2. Flat length and capacity in the struct root (uint32_t) No union-of-structs, no masked flag bits in length. The heap-flag lives in the MSB of capacity only. Reading length is always s->length.
  3. uint32_t sizes — 4 GB cap is plenty for a string type Halves the size of the length/capacity fields vs. size_t on 64-bit. Struct fits in 32 bytes (one cache line on most CPUs).
  4. Inline SSO buffer sized to fill the struct to exactly 32 bytes On 64-bit: ptr(8) + len(4) + cap(4) + buf(16) = 32 bytes. SSO holds strings up to 15 chars (+ NUL).
  5. No memmem — replaced with a fast Rabin-Karp or Sunday's algorithm variant that avoids glibc's dynamic dispatch overhead for short needles.

Struct layout (64-bit, little-endian): offset 0 : char* data (8 bytes) — always valid pointer offset 8 : uint32_t length (4 bytes) offset 12 : uint32_t capacity (4 bytes) — MSB = heap flag offset 16 : char buf[16] (16 bytes) — inline storage Total: 32 bytes

Warning
Do NOT access struct fields directly — use the API.

Definition in file cstr.h.

Macro Definition Documentation

◆ CSTR_HEAP_FLAG

#define CSTR_HEAP_FLAG   ((uint32_t)0x80000000u)

Bit flag stored in capacity to indicate heap allocation.

Definition at line 83 of file cstr.h.

◆ CSTR_MAX_LEN

#define CSTR_MAX_LEN   ((uint32_t)0x7FFFFFFFu)

Maximum string length / capacity (4 GB - 1, MSB reserved for heap flag).

Definition at line 77 of file cstr.h.

◆ CSTR_NPOS

#define CSTR_NPOS   (-1)

Sentinel returned by find functions when no match is found.

Definition at line 86 of file cstr.h.

◆ CSTR_SSO_CAP

#define CSTR_SSO_CAP   16u /* 15 usable chars + NUL */

Size of the inline (SSO) buffer. Strings shorter than this need no heap.

Definition at line 80 of file cstr.h.

Typedef Documentation

◆ cstr

typedef struct cstr cstr

A dynamically resizable C string with SSO.

data is ALWAYS a valid, NUL-terminated pointer:

  • When heap flag is clear: data == &buf[0] (SSO path)
  • When heap flag is set: data points to malloc'd memory

This eliminates the branch in every read — callers just dereference data.

Function Documentation

◆ cstr_allocated()

CSTR_INLINE bool cstr_allocated ( const cstr s)

True if the string is heap-allocated (i.e. not in SSO mode).

Definition at line 171 of file cstr.h.

References cstr_is_heap().

Here is the call graph for this function:

◆ cstr_append_fast()

CSTR_INLINE bool CSTR_INLINE bool cstr_append_fast ( cstr s,
const char *CSTR_RESTRICT  append 
)

Append without capacity check — caller guarantees space. ~20% faster for bulk building when capacity is pre-reserved.

Precondition
s->length + strlen(append) < effective_capacity(s)

Definition at line 333 of file cstr.h.

References cstr::data, and cstr::length.

◆ cstr_assign()

bool CSTR_INLINE bool CSTR_INLINE bool cstr_assign ( cstr dest,
const cstr src 
)

Alias for cstr_copy.

Definition at line 410 of file cstr.h.

References cstr_copy().

Here is the call graph for this function:

◆ cstr_cat()

bool bool bool CSTR_INLINE bool CSTR_INLINE bool cstr_cat ( cstr dest,
const cstr src 
)

Alias: concatenate two cstrs.

Definition at line 325 of file cstr.h.

References cstr_append_cstr().

Here is the call graph for this function:

◆ cstr_count_substr()

size_t cstr_count_substr ( const cstr s,
const char *  substr 
)

Count occurrences (non-overlapping).

◆ cstr_empty()

CSTR_INLINE bool cstr_empty ( const cstr s)

True if the string is empty or NULL.

Definition at line 167 of file cstr.h.

References cstr::length.

◆ cstr_find()

int cstr_find ( const cstr s,
const char *  substr 
)

Find first occurrence of substr. Uses optimised search (no memmem).

Returns
Byte offset, or CSTR_NPOS if not found.

Referenced by cstr_rfind().

Here is the caller graph for this function:

◆ cstr_heap_cap()

CSTR_INLINE uint32_t cstr_heap_cap ( const cstr s)

Extract actual heap capacity (strip flag bit).

Definition at line 143 of file cstr.h.

References cstr::capacity.

Referenced by cstr_capacity(), cstr_debug(), and cstr_shrink_to_fit().

Here is the caller graph for this function:

◆ cstr_init()

cstr * cstr_init ( size_t  initial_capacity)

Create a new heap-allocated cstr with a given initial capacity.

Parameters
initial_capacityDesired usable capacity (NUL not counted).
Returns
New cstr, or NULL on OOM.
Note
Caller must call cstr_free().

Definition at line 127 of file cstr.c.

References cstr_init_inplace(), and CSTR_SSO_CAP.

Referenced by cstr_join().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cstr_init_inplace()

CSTR_INLINE void cstr_init_inplace ( cstr s)

Initialize an already-allocated cstr in SSO mode (no heap).

Use this to embed a cstr inside another struct without a separate alloc. The cstr must be freed with cstr_drop() (not cstr_free()) when done.

Parameters
sPointer to uninitialised cstr storage.

Definition at line 225 of file cstr.h.

References cstr::buf, cstr::capacity, cstr::data, and cstr::length.

Referenced by cstr_drop(), cstr_init(), and cstr_new_len().

Here is the caller graph for this function:

◆ cstr_is_heap()

CSTR_INLINE bool cstr_is_heap ( const cstr s)

True when string data lives on the heap.

Definition at line 139 of file cstr.h.

References cstr::capacity, and CSTR_HEAP_FLAG.

Referenced by cstr_allocated(), cstr_capacity(), cstr_debug(), cstr_drop(), cstr_free(), and cstr_shrink_to_fit().

Here is the caller graph for this function:

◆ cstr_new()

cstr * cstr_new ( const char *  input)

Create a new cstr from a C string.

Parameters
inputNUL-terminated source. Must not be NULL.
Returns
New cstr, or NULL on OOM.
Note
Caller must call cstr_free().

Definition at line 146 of file cstr.c.

References cstr_new_len().

Here is the call graph for this function:

◆ cstr_new_len()

cstr * cstr_new_len ( const char *  data,
size_t  length 
)

Create a new cstr from a buffer of known length (no strlen needed).

Parameters
dataPointer to characters (need not be NUL-terminated).
lengthNumber of bytes to copy.
Returns
New cstr, or NULL on OOM.

Definition at line 151 of file cstr.c.

References cstr_init_inplace(), cstr::data, and cstr::length.

Referenced by cstr_join(), and cstr_new().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ cstr_remove_all()

size_t cstr_remove_all ( cstr s,
const char *  substr 
)

Remove all occurrences of substr (in-place, single pass).

Returns
Number of occurrences removed.

◆ cstr_reserve()

bool cstr_reserve ( cstr s,
size_t  capacity 
)

Ensure at least capacity usable bytes are available (NUL extra).

Returns
true on success, false on OOM or overflow.

Definition at line 205 of file cstr.c.

Referenced by cstr_resize().

Here is the caller graph for this function:

◆ cstr_resize()

CSTR_INLINE bool cstr_resize ( cstr s,
size_t  capacity 
)

Alias kept for compatibility.

Definition at line 286 of file cstr.h.

References cstr_reserve().

Here is the call graph for this function:

◆ cstr_rfind()

int cstr_rfind ( const cstr s,
const char *  substr 
)

Find last occurrence.

References cstr_find(), and CSTR_NPOS.

Here is the call graph for this function: