CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
sarray.h
Go to the documentation of this file.
1#pragma once
7
41
42#include <cx/cx.h>
43#include <cx/debug/assert.h>
44#include <cx/debug/dbgtypes.h>
46
47#define sarrayref(typ) sa_##typ
48#define sarrayhdl(typ) sa_##typ*
49
71
78#define saDeclareType(name, typ) \
79 typedef union sa_##name { \
80 _nv_sarray* _debug; \
81 void* _is_sarray; \
82 void* _is_sarray_##name; \
83 typ* a; \
84 } sa_##name
85
91#define saDeclare(name) saDeclareType(name, name)
92
98#define saDeclarePtr(name) saDeclareType(name, name*)
99
103#define saInitNone { .a = 0 }
104
105// Pre-declared common sarray types
106typedef sa_ref sa_opaque;
107saDeclare(int8);
108saDeclare(int16);
109saDeclare(int32);
110saDeclare(int64);
111saDeclare(intptr);
112saDeclare(uint8);
113saDeclare(uint16);
114saDeclare(uint32);
115saDeclare(uint64);
116saDeclare(uintptr);
117saDeclare(bool);
118saDeclareType(size, size_t);
119saDeclare(float32);
120saDeclare(float64);
121saDeclareType(ptr, void*);
122saDeclare(string);
123// strref doesn't make sense in an sarray
124saDeclareType(object, ObjInst*);
125saDeclareType(suid, SUID);
127saDeclareType(sarray, sa_ref);
128saDeclare(hashtable);
129
130// SArray header structure
131//
132// Internal structure containing array metadata. Access through helper macros.
133typedef struct SArrayHeader {
134 // sarray extended header begins here (only valid if SAINT_Extended is set)
135 STypeOps typeops;
136 // sarray header begins here
137 stype elemtype;
138 int32 count;
139 int32 capacity;
140 uint32 flags; // high 8 bits = growth
141 void* data[1];
142} SArrayHeader;
143
146 SA_Ref = 0x0010,
147 SA_Sorted = 0x0020,
148 SA_AutoShrink = 0x0040,
149
150 SAINT_Extended = 0x8000, // includes extended header
151};
152
153// Growth rate strategies for array expansion
154enum SARRAY_GROW_ENUM {
155 SA_GROW_Auto,
156
157 // Dynamic growth rates (transition from high to lower growth as size increases)
158 SA_GROW_Normal,
159 SA_GROW_Aggressive,
160 SA_GROW_Slow,
161
162 // Fixed growth rates
163 SA_GROW_100,
164 SA_GROW_50,
165 SA_GROW_25,
166
167 SA_GROW_Minimal,
168};
169
174 SA_Unique = 0x00010000,
175
178 SA_Fast = 0x00020000,
179
182 SA_Inexact = 0x00100000,
183
184 // Internal use only - do not use directly
185 SAINT_Consume = 0x10000000,
186};
187
188#define SA_GROW_MASK (0xff000000)
189
230#define SA_Grow(rate) (((uint32)SA_GROW_##rate) << 24)
231
232// Internal macro - extracts growth settings from flags
233#define SA_GET_GROW(flags) ((flags) >> 24)
234
235#define SARRAY_HDRSIZE (offsetof(SArrayHeader, data))
236#define SARRAY_HDR(ref) ((SArrayHeader*)(((uintptr)((ref).a)) - SARRAY_HDRSIZE))
237#define SAREF(r) (unused_noeval(&((r)._is_sarray)), *(sa_ref*)(&(r)))
238#define SAHANDLE(h) ((sahandle)(unused_noeval((h != NULL) && &((h)->_is_sarray)), (h)))
239
240_Ret_notnull_ _meta_inline SArrayHeader* _saHdr(_In_ sa_ref ref)
241{
242 return SARRAY_HDR(ref);
243}
244
251#define saSize(ref) ((ref)._is_sarray ? _saHdr(SAREF(ref))->count : 0)
252
259#define saCapacity(ref) ((ref)._is_sarray ? _saHdr(SAREF(ref))->capacity : 0)
260
267#define saElemSize(ref) ((ref)._is_sarray ? stGetSize(_saHdr(SAREF(ref))->elemtype) : 0)
268
275#define saElemType(ref) ((ref)._is_sarray ? _saHdr(SAREF(ref))->elemtype : 0)
276
283#define saValid(ref) ((ref).a)
284
286
291
292_Success_(!canfail || return)
293_When_(canfail, _Check_return_)
294_At_(out->a, _Post_notnull_) bool _saInit(_Out_ sahandle out, stype elemtype, _In_opt_ STypeOps* ops, int32 capacity,
295 bool canfail, flags_t flags);
296
318#define saInit(out, type, capacity, ...) \
319 _saInit(SAHANDLE(out), stFullType(type), capacity, false, opt_flags(__VA_ARGS__))
320
330#define saTryInit(out, type, capacity, ...) \
331 _saInit(SAHANDLE(out), stFullType(type), capacity, true, opt_flags(__VA_ARGS__))
332
333_At_(handle->a, _Pre_maybenull_ _Post_null_) void _saDestroy(_Inout_ sahandle handle);
334
348#define saDestroy(handle) _saDestroy(SAHANDLE(handle))
349
350_When_(canfail, _Check_return_)
351 _At_(handle->a,
352 _Pre_notnull_
353 _Post_notnull_) bool _saReserve(_Inout_ sahandle handle, int32 capacity, bool canfail);
354
370#define saReserve(handle, capacity) _saReserve(SAHANDLE(handle), capacity, true)
371
372_At_(handle->a,
373 _Pre_notnull_ _Post_notnull_) void _saShrink(_Inout_ sahandle handle, int32 capacity);
374
392#define saShrink(handle, capacity) _saShrink(SAHANDLE(handle), capacity)
393
394_At_(handle->a, _Pre_notnull_ _Post_notnull_) void _saSetSize(_Inout_ sahandle handle, int32 size);
395
410#define saSetSize(handle, size) _saSetSize(SAHANDLE(handle), size)
411
412_At_(handle->a, _Pre_maybenull_) void _saClear(_Inout_ sahandle handle);
413
427#define saClear(handle) _saClear(SAHANDLE(handle))
428
430
435
436#define _sa_Consume_Arg_ \
437 _When_(flags& SAINT_Consume, _Pre_notnull_ _Post_invalid_) \
438 _When_(!(flags & SAINT_Consume), _Inout_)
439_At_(handle->a, _Pre_maybenull_ _Post_notnull_) int32 _saPush(_Inout_ sahandle handle, stype elemtype, _In_ stgeneric elem,
440 flags_t flags);
441_At_(handle->a, _Pre_maybenull_ _Post_notnull_) int32 _saPushPtr(_Inout_ sahandle handle, stype elemtype,
442 _sa_Consume_Arg_ stgeneric* elem, flags_t flags);
443
467#define saPush(handle, type, elem, ...) \
468 _saPush(SAHANDLE(handle), stCheckedArg(type, elem), opt_flags(__VA_ARGS__))
469
493#define saPushC(handle, type, elem, ...) \
494 _saPushPtr(SAHANDLE(handle), \
495 stCheckedPtrArg(type, elem), \
496 opt_flags(__VA_ARGS__) | SAINT_Consume)
497
498_Ret_opt_valid_ _At_(handle->a,
499 _Pre_maybenull_) void* _saPopPtr(_Inout_ sahandle handle, int32 idx);
500
518#define saPopPtr(handle) _saPopPtr(SAHANDLE(handle), -1)
519
535#define saPopPtrI(handle, idx) _saPopPtr(SAHANDLE(handle), idx)
536
537_At_(ref.a, _Pre_notnull_) int32 _saFind(_In_ sa_ref ref, _In_ stgeneric elem, flags_t flags);
538_At_(ref.a, _Pre_maybenull_) _meta_inline int32
539_saFindChecked(_In_ sa_ref ref, stype elemtype, _In_ stgeneric elem, flags_t flags)
540{
541 if (!ref.a)
542 return -1;
543 devAssert(stEq(saElemType(ref), elemtype));
544 return _saFind(ref, elem, flags);
545}
546
569#define saFind(ref, type, elem, ...) \
570 _saFindChecked(SAREF(ref), stCheckedArg(type, elem), opt_flags(__VA_ARGS__))
571
572_At_(
573 handle->a,
574 _Pre_notnull_
575 _Post_notnull_) bool _saFindRemove(_Inout_ sahandle handle, _In_ stgeneric elem, flags_t flags);
576_At_(handle->a, _Pre_maybenull_) _meta_inline bool
577_saFindRemoveChecked(_Inout_ sahandle handle, stype elemtype, _In_ stgeneric elem, flags_t flags)
578{
579 if (!handle->a)
580 return false;
581 devAssert(stEq(saElemType(*handle), elemtype));
582 return _saFindRemove(handle, elem, flags);
583}
584
605#define saFindRemove(handle, type, elem, ...) \
606 _saFindRemoveChecked(SAHANDLE(handle), stCheckedArg(type, elem), opt_flags(__VA_ARGS__))
607
608_At_(handle->a,
609 _Pre_notnull_
610 _Post_notnull_) int32 _saInsert(_Inout_ sahandle handle, int32 idx, _In_ stgeneric elem);
611_At_(handle->a, _Pre_notnull_ _Post_notnull_) _meta_inline int32
612_saInsertChecked(_Inout_ sahandle handle, int32 idx, stype elemtype, _In_ stgeneric elem)
613{
614 devAssert(handle->_is_sarray);
615 devAssert(stEq(saElemType(*handle), elemtype));
616 return _saInsert(handle, idx, elem);
617}
618
641#define saInsert(handle, idx, type, elem) \
642 _saInsertChecked(SAHANDLE(handle), idx, stCheckedArg(type, elem))
643
644_At_(handle->a, _Pre_notnull_ _Post_notnull_) bool _saExtract(_Inout_ sahandle handle, int32 idx, _Inout_opt_ stgeneric* elem,
645 flags_t flags);
646
647_At_(handle->a, _Pre_maybenull_) _meta_inline bool
648_saExtractChecked(_Inout_ sahandle handle, int32 idx, stype elemtype,
649 _stCopyDest_Anno_opt_(elemtype) stgeneric* elem, flags_t flags)
650{
651 if (!handle->a)
652 return false;
653 devAssert(stGetId(elemtype) == stTypeId(none) || stEq(saElemType(*handle), elemtype));
654 return _saExtract(handle, idx, elem, flags);
655}
656
680#define saExtract(handle, idx, type, elem_copy_out, ...) \
681 _saExtractChecked(SAHANDLE(handle), \
682 idx, \
683 stCheckedPtrArg(type, elem_copy_out), \
684 opt_flags(__VA_ARGS__))
685
703#define saRemove(handle, idx, ...) \
704 _saExtractChecked(SAHANDLE(handle), idx, stType(none), NULL, opt_flags(__VA_ARGS__))
705
706_At_(handle->a, _Pre_maybenull_) void _saSort(_Inout_ sahandle handle, bool keep);
707
727#define saSort(handle, keep) _saSort(SAHANDLE(handle), keep)
728
730
734
735_At_(out->a, _When_(ref.a, _Post_notnull_) ) void _saSlice(_Out_ sahandle out, _In_ sa_ref ref, int32 start, int32 end);
736
757#define saSlice(out, src, start, end) _saSlice(SAHANDLE(out), SAREF(src), start, end)
758
776#define saClone(out, src) _saSlice(SAHANDLE(out), SAREF(src), 0, 0)
777
778_At_(out->a,
779 _Post_maybenull_) void _saMerge(_Out_ sahandle out, int n, _In_ sa_ref* refs, flags_t flags);
780
798#define saMerge(out, ...) \
799 _saMerge(SAHANDLE(out), \
800 sizeof((sa_ref[]) { __VA_ARGS__ }) / sizeof(sa_ref), \
801 (sa_ref[]) { __VA_ARGS__ }, \
802 0)
803
821#define saMergeF(out, flags, ...) \
822 _saMerge(SAHANDLE(out), \
823 sizeof((sa_ref[]) { __VA_ARGS__ }) / sizeof(sa_ref), \
824 (sa_ref[]) { __VA_ARGS__ }, \
825 flags)
826
Runtime assertion macros and failure handling.
#define saDeclare(name)
Definition sarray.h:91
#define saElemType(ref)
Definition sarray.h:275
#define saDeclareType(name, typ)
Definition sarray.h:78
SARRAY_CREATE_FLAGS_ENUM
Creation flags for sarray initialization.
Definition sarray.h:145
SARRAY_FUNC_FLAGS_ENUM
Operation flags for sarray functions.
Definition sarray.h:171
@ SA_Ref
Array references data without copying/destroying (pointer types only)
Definition sarray.h:146
@ SA_Sorted
Maintain sorted order with O(log n) search and O(n) insert.
Definition sarray.h:147
@ SA_AutoShrink
Automatically release memory when array shrinks.
Definition sarray.h:148
@ SA_Fast
Definition sarray.h:178
@ SA_Inexact
Definition sarray.h:182
@ SA_Unique
Definition sarray.h:174
#define devAssert(expr)
Definition assert.h:138
#define stvar(typen, val)
Definition stvar.h:153
#define stGetId(st)
Definition stype.h:507
#define stTypeId(name)
Definition stype.h:419
bool stEq(stype sta, stype stb)
Definition stype.h:537
128-bit sortable unique identifier
Definition suid.h:47
Macros for suppressing compiler warnings.