|
CX Framework
Cross-platform C utility framework
|
Macros | |
| #define | stvarInit(typen, val) { .data = { .st_##typen = val }, ._type = stType(typen) } |
| #define | stvar(typen, val) ((stvar) { .data = stArg(typen, val), ._type = stType(typen) }) |
| #define | stvNone ((stvar) { ._type = stType(none) }) |
| #define | stvark(key, typen, val) ((stvar) { .data = stArg(typen, val), ._type = stType(typen), ._key = #key }) |
| #define | stvarkn(name, typen, val) ((stvar) { .data = stArg(typen, val), ._type = stType(typen), ._key = (name) }) |
Macros for creating and initializing variant containers.
stvar stvar(type, value)
Create a temporary variant containing a typed value.
Uses C99 compound literals to create a stack-allocated temporary with automatic storage duration. The temporary is valid until the end of the enclosing block scope. This is the primary mechanism for passing typed arguments to variadic functions.
IMPORTANT: The variant's lifetime is limited to the current function scope. Do not return these from functions or store pointers to them beyond the current scope.
| typen | Type name (e.g., int32, string, object) |
| val | Value of the specified type |
Example:
| #define stvarInit | ( | typen, | |
| val | |||
| ) | { .data = { .st_##typen = val }, ._type = stType(typen) } |
stvar stvarInit(type, value)
Static initializer for variant structures (C only).
Creates a compile-time initializer suitable for static/automatic variable initialization. This is primarily used when declaring persistent variant variables, not for temporary expressions.
| typen | Type name (e.g., int32, string) |
| val | Value of the specified type |
Example:
| #define stvark | ( | key, | |
| typen, | |||
| val | |||
| ) | ((stvar) { .data = stArg(typen, val), ._type = stType(typen), ._key = #key }) |
stvar stvark(key, type, value)
Create a temporary variant tagged with a key name.
Identical to stvar() except that the variant also carries a name, letting the receiver locate it with stvlFind() by key rather than by type and position. Keyed and unkeyed arguments mix freely in the same call.
The key is written as a bare token and stringized, so it costs nothing at runtime on any compiler and cannot be handed a pointer that dangles. Any comma-free token sequence works, including dotted names (stvark(http.status, int32, code)).
The name is metadata: preserved by copy, ignored by compare and hash.
| key | Key name as a bare token (not a string literal) |
| typen | Type name (e.g., int32, string, object) |
| val | Value of the specified type |
Example:
| #define stvarkn | ( | name, | |
| typen, | |||
| val | |||
| ) | ((stvar) { .data = stArg(typen, val), ._type = stType(typen), ._key = (name) }) |
stvar stvarkn(name, type, value)
Create a temporary keyed variant from a runtime name pointer.
The escape hatch for argument lists built at runtime rather than at a call site – deserialization, script bindings, forwarded log records. Prefer stvark() everywhere else: it stringizes a token and so enforces the lifetime rule structurally.
The name is pointer-copied, never duplicated. It must remain valid for as long as any copy of the variant does, which in practice means program lifetime. Passing a stack buffer, or a heap buffer that is later freed, leaves a dangling pointer that will not surface until something formats or serializes the variant.
| name | const char* with program lifetime (or NULL) |
| typen | Type name (e.g., int32, string, object) |
| val | Value of the specified type |
Example:
stvar stvNone
Empty variant constant representing no value.
Used to represent the absence of a value or as a sentinel/terminator in variant arrays. The type field is set to stType(none).
Example: