CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
stvar.h
Go to the documentation of this file.
1#pragma once
2
5
6#include <cx/cx.h>
7#include <cx/stype/stype.h>
8
9CX_C_BEGIN
10
105
111
132#ifndef __cplusplus
133#define stvarInit(typen, val) { .data = { .st_##typen = val }, ._type = stType(typen) }
134
162#define stvar(typen, val) ((stvar) { .data = stArg(typen, val), ._type = stType(typen) })
163
178#define stvNone ((stvar) { ._type = stType(none) })
179
204#define stvark(key, typen, val) \
205 ((stvar) { .data = stArg(typen, val), ._type = stType(typen), ._key = #key })
206
230#define stvarkn(name, typen, val) \
231 ((stvar) { .data = stArg(typen, val), ._type = stType(typen), ._key = (name) })
232#else
233_meta_inline stvar _stvar(stype st, stgeneric val)
234{
235 stvar ret;
236 ret.data = val;
237 ret._type = st;
238 ret._key = NULL;
239 return ret;
240}
241#define stvar(typen, val) _stvar(stType(typen), stArg(typen, val))
242
243_meta_inline stvar _stvark(const char* nm, stype st, stgeneric val)
244{
245 stvar ret = _stvar(st, val);
246 ret._key = nm;
247 return ret;
248}
249#define stvark(key, typen, val) _stvark(#key, stType(typen), stArg(typen, val))
250#define stvarkn(name, typen, val) _stvark((name), stType(typen), stArg(typen, val))
251
252#define stvNone _stvar(stType(none), _cxStGenZero())
253#endif
254
256
290
293typedef struct stvp {
295 stgeneric* ptr;
296 const char* key;
298
299#ifndef __cplusplus
316#define stvp(typen, pval) ((stvp) { stCheckedPtrArg(typen, pval), NULL })
317
336#define stvpk(key, typen, pval) ((stvp) { stCheckedPtrArg(typen, pval), #key })
337
350#define stvpNone ((stvp) { NULL, NULL, NULL })
351#else
352_meta_inline stvp _stvp(const char* nm, stype st, stgeneric* p)
353{
354 stvp ret;
355 ret.type = st;
356 ret.ptr = p;
357 ret.key = nm;
358 return ret;
359}
360#define stvp(typen, pval) _stvp(NULL, stCheckedPtrArg(typen, pval))
361#define stvpk(key, typen, pval) _stvp(#key, stCheckedPtrArg(typen, pval))
362#define stvpNone _stvp(NULL, NULL, NULL)
363#endif
364
366
372
373// Core lifecycle helpers. These manage storage in a standardized manner so that oversized (PassPtr)
374// values - suid, opaque, struct — are deep-copied into a heap allocation the variant owns, rather
375// than left as dangling pointers to a caller's temporary.
376
377// Initialize *stv (assumed uninitialized) from a type + value. Overwrite/init semantics:
378// does NOT destroy any prior contents. For PassPtr types, allocates and deep-copies.
379// Does not touch the key name.
380void _stvarInit(stvar* stv, stype type, stgeneric val);
381
382// As _stvarInit, but also sets the key name (pointer-copied, never duplicated).
383void _stvarInitK(stvar* stv, stype type, stgeneric val, const char* vk);
384
385// Destroy the contents of *stv, free any owned heap allocation, clear any key name, and
386// reset to none.
387void _stvarClear(stvar* stv, flags_t flags);
388
389// Replace semantics: destroy existing contents, then initialize from type + value.
390// Clears any existing key name.
391void _stvarSet(stvar* stv, stype type, stgeneric val);
392
393// Replace semantics preserving/replacing the key name.
394void _stvarSetK(stvar* stv, stype type, stgeneric val, const char* vk);
395
396// Prepare *stv -- which may hold a live value -- to receive a value of `type` written
397// directly into the returned storage. For PassPtr types the variant allocates and owns the
398// block; otherwise the storage is the variant's own inline `data`. Either way the variant is
399// left holding a zero-filled value of that type, so _stvarClear can always undo it.
400_Ret_notnull_ void* _stvarPrepare(stvar* stv, stype type);
401
422#define stvarSet(stv, type, val) _stvarSet(stv, stCheckedArg(type, val))
423
444#define stvarSetK(stv, key, type, val) _stvarSetK(stv, stCheckedArg(type, val), #key)
445
464_meta_inline void stvarDestroy(stvar* stv)
465{
466 _stvarClear(stv, 0);
467}
468
492_meta_inline void stvarCopy(stvar* dvar, stvar svar)
493{
494 _stvarInitK(dvar, stvarType(&svar), svar.data, svar._key);
495}
496
498
504
523#define stvarIs(svar, type) _stvarIs(svar, stType(type))
524_meta_inline bool _stvarIs(stvar* svar, stype styp)
525{
526 return svar && stEq(stvarType(svar), styp);
527}
528
548_meta_inline string stvarString(stvar* svar)
549{
550 if (stvarIs(svar, string))
551 return svar->data.st_string;
552 return NULL;
553}
554
574_meta_inline string* stvarStringPtr(stvar* svar)
575{
576 if (stvarIs(svar, string))
577 return &svar->data.st_string;
578 return NULL;
579}
580
599_meta_inline ObjInst* stvarObjInst(stvar* svar)
600{
601 if (stvarIs(svar, object))
602 return svar->data.st_object;
603 return NULL;
604}
605
615_meta_inline ObjInst** stvarObjInstPtr(stvar* svar)
616{
617 if (stvarIs(svar, object))
618 return &svar->data.st_object;
619 return NULL;
620}
621
642#define stvarObj(class, svar) (objDynCast(class, stvarObjInst(svar)))
643
645
681
687typedef struct stvlist {
688 int count;
689 int cursor;
692
713void stvlInit(stvlist* list, int count, stvar* vars);
714
737#define stvlInitSA(list, vararray) _stvlInitSA(list, (vararray).a)
738void _stvlInitSA(stvlist* list, stvar* vara);
739
772#define stvlNext(list, type, pvar) _stvlNext(list, stCheckedPtrArg(type, pvar))
773bool _stvlNext(stvlist* list, stype type, stgeneric* out);
774
793#define stvlNextPtr(list) _stvlNextPtr(list, stType(ptr))
794void* _stvlNextPtr(stvlist* list, stype type);
795
815#define stvlNextObj(list, class) objDynCast(class, (ObjInst*)_stvlNextPtr(list, stType(object)))
816
838void stvlRewind(stvlist* list);
839
840stgeneric _stvlAt(_In_ stvlist* list, int idx, stype type);
841
865#define stvlAt(list, idx, type) (_stvlAt((list), (idx), stType(type)).st_##type)
866
874#define stvlAtPtr(list, idx) (_stvlAt((list), (idx), stType(ptr)).st_ptr)
875
885#define stvlAtObj(list, idx, class) \
886 objDynCast(class, (ObjInst*)_stvlAt((list), (idx), stType(object)).st_object)
887
889
936
958#define stvlFind(list, key, type, pvar) _stvlFind(list, #key, stCheckedPtrArg(type, pvar))
959bool _stvlFind(_In_ stvlist* list, const char* key, stype type, stgeneric* out);
960
976#define stvlFindPtr(list, key) _stvlFindPtr(list, #key, stType(ptr))
977void* _stvlFindPtr(_In_ stvlist* list, const char* key, stype type);
978
995#define stvlFindObj(list, key, class) \
996 objDynCast(class, (ObjInst*)_stvlFindPtr(list, #key, stType(object)))
997
998stgeneric _stvlFindVal(_In_ stvlist* list, const char* key, stype type);
999
1017#define stvlFindVal(list, key, type) (_stvlFindVal(list, #key, stType(type)).st_##type)
1018
1031#define stvlHasKey(list, key) _stvlHasKey(list, #key)
1032bool _stvlHasKey(_In_ stvlist* list, const char* key);
1033
1035
1036CX_C_END
#define stvarIs(svar, type)
Definition stvar.h:523
ObjInst * stvarObjInst(stvar *svar)
Definition stvar.h:599
string stvarString(stvar *svar)
Definition stvar.h:548
string * stvarStringPtr(stvar *svar)
Definition stvar.h:574
ObjInst ** stvarObjInstPtr(stvar *svar)
Definition stvar.h:615
#define stvar(typen, val)
Definition stvar.h:162
void stvarDestroy(stvar *stv)
Definition stvar.h:464
void stvarCopy(stvar *dvar, stvar svar)
Definition stvar.h:492
void stvlRewind(stvlist *list)
void stvlInit(stvlist *list, int count, stvar *vars)
#define stvp(typen, pval)
Definition stvar.h:316
bool stEq(stype s1, stype s2)
Definition stype.h:1785
stype stvarType(const stvar *v)
Definition stype.h:457
int cursor
Current position (next variant to examine)
Definition stvar.h:689
stvar * vars
Pointer to variant array.
Definition stvar.h:690
int count
Total number of variants in array.
Definition stvar.h:688
Definition stvar.h:293
stype type
Type of the destination.
Definition stvar.h:294
const char * key
Binding key, or NULL if this destination is positional.
Definition stvar.h:296
stgeneric * ptr
Destination in the caller's own storage.
Definition stvar.h:295
Runtime type system and type descriptor infrastructure.