|
CX Framework
Cross-platform C utility framework
|
The library uses three related types:
Most functions take strref for input (read-only) and strhandle for output. This pattern prevents accidental modification and makes ownership clear.
While the implementation uses copy-on-write optimization, the API is designed to behave as if strings were immutable values. Think of string variables like you would in Python, Java, or other languages with immutable strings:
After the append, s1 and s2 appear to be independent strings, even though they initially shared the same buffer. The copy-on-write mechanism is transparent - you program as if each variable owns its own immutable string value, but the library optimizes away unnecessary copies behind the scenes.
This mental model makes it easy to reason about string operations:
A string variable set to NULL (or 0) is treated as an empty string throughout the entire API. This is an intentional design decision for convenience:
This eliminates the need for null checks in most code and allows operations to work naturally with uninitialized or empty strings. Functions that return strings via output parameters will properly destroy any existing string first, so you can always safely initialize to NULL and let the functions manage it.
The library uses atomic reference counting to track how many variables reference the same underlying string buffer. When you use strDup(), both variables point to the same buffer with an incremented reference count. When a modification operation is performed (strAppend, strBuffer, etc.), the library automatically checks the reference count and creates a private copy if the buffer is shared.
String literals created with the _S macro have static storage and don't need reference counting - they're truly immutable and exist for the program's lifetime.
String literals:
Building strings dynamically:
All strings created dynamically (not static literals) MUST be destroyed:
Strings initialized to NULL/0 are safe to destroy without allocation.
Reference counting uses atomic operations for thread safety. Multiple threads can safely call strDup() on the same source string concurrently. However, modifying a string is not thread-safe - if multiple threads need to modify the same logical string, external synchronization is required.
The library automatically optimizes for different use cases: