CX Framework
Cross-platform C utility framework
Loading...
Searching...
No Matches
stype.h
Go to the documentation of this file.
1#pragma once
2
5
10
185
186#include <cx/debug/assert.h>
187#include <cx/platform/base.h>
188#include <cx/platform/cpp.h>
189#include <cx/string/strliteral.h>
191#include <cx/utils/macros/salieri.h>
193#include <stdbool.h>
194#include <stddef.h>
195#include <stdint.h>
196#include <string.h>
197
198// extra files that can be included for specific functions
199#define STYPE_FOREACH_ALL <cx/stype/alltypes.inc>
200
201CX_C_BEGIN
202
203// do this as a typedef instead of a #define
204#ifdef bool
205#undef bool
206#endif
207
208// IMPORTANT NOTE!
209// Always initialize string to NULL or 0 first!
210typedef struct str_ref* _Nullable string;
211typedef const struct str_ref* _Nullable strref;
212typedef struct hashtable_ref* hashtable;
213typedef struct closure_ref* closure;
214typedef struct cchain_ref* cchain;
215typedef struct BufferHeader* Buffer;
216typedef struct ObjInst ObjInst;
217typedef struct ObjInst_WeakRef ObjInst_WeakRef;
218typedef struct StructBase StructBase;
219typedef struct SUID SUID;
220typedef struct stvar stvar;
221typedef struct SerWriter SerWriter;
222typedef struct SerReader SerReader;
223
224enum STYPE_ID_CONSTANTS {
225 STCLASS_BASIC = 0x00000000, // basic discrete types
226 STCLASS_CX = 0x00010000, // "CX framework" types (strings, objects, containers)
227 STCLASS_DYNAMIC = 0x00020000, // dynamically defined types created at runtime
228 STCLASS_USER = 0x00100000, // start of user-defined static type range
229
230 // subtypes for STCLASS_BASIC types
231 STST_INT = 0x0100,
232 STST_UINT = 0x0200,
233 STST_FLOAT = 0x0300,
234 STST_PTR = 0x0400,
235
236 // subtypes for STCLASS_CX types
237 // these intentionally don't overlap with the basic subtypes, to allow for easier checks
238 STST_OPAQUE = 0x1000, // opaque byte blocks, often with custom ops
239 STST_MISC = 0x1100, // miscallenous CX-related types like SUIDs
240 STST_OBJ = 0x1200, // object-like types that use pointer handles
241 STST_CONTAINER = 0x1300, // container types
242};
243
244#define STYPE_CLASS_MASK 0xffff0000
245#define STYPE_CLASS(v) ((v) & STYPE_CLASS_MASK)
246
247// subtypes are only valid for STCLASS_BASIC and STCLASS_CX
248#define STYPE_HAS_SUBTYPE(v) (STYPE_CLASS(v) == STCLASS_BASIC || STYPE_CLASS(v) == STCLASS_CX)
249#define STYPE_SUBTYPE_MASK 0x0000ff00
250#define STYPE_SUBTYPE(v) ((v) & STYPE_SUBTYPE_MASK)
251
252typedef signed char int8;
253typedef unsigned char uint8;
254typedef short int16;
255typedef unsigned short uint16;
256typedef int int32;
257typedef unsigned int uint32;
258typedef long long int64;
259typedef unsigned long long uint64;
260typedef intptr_t intptr;
261typedef uintptr_t uintptr;
262#ifndef __cplusplus
263#if __STDC_VERSION__ < 202311L
264// C23 made bool a keyword, so the typedef is both unnecessary and illegal there.
265typedef _Bool bool;
266#endif
267#elif !defined(_Bool)
268// Some C++ standard library / compiler configurations (e.g. GNU-extension stdbool.h
269// under C++) already #define _Bool as a macro expanding to the built-in bool type.
270// Only add the typedef when that hasn't happened, otherwise it becomes a
271// self-referential "typedef bool bool;"
272typedef bool _Bool;
273#endif
274
275// limits for integer types
276
277#define MIN_INT8 (-0x7f - 1)
278#define MAX_INT8 0x7f
279#define MAX_UINT8 0xff
280#define MIN_INT16 (-0x7fff - 1)
281#define MAX_INT16 0x7fff
282#define MAX_UINT16 0xffff
283#define MIN_INT32 (-0x7fffffffL - 1)
284#define MAX_INT32 0x7fffffffL
285#define MAX_UINT32 0xffffffffUL
286#define MAX_INT64 0x7fffffffffffffffLL
287#define MIN_INT64 (-0x7fffffffffffffffLL - 1)
288#define MAX_UINT64 0xffffffffffffffffULL
289
290#if defined(_64BIT)
291#define MIN_INTPTR MIN_INT64
292#define MAX_INTPTR MAX_INT64
293#define MAX_UINTPTR MAX_UINT64
294#elif defined(_32BIT)
295#define MIN_INTPTR MIN_INT32
296#define MAX_INTPTR MAX_INT32
297#define MAX_UINTPTR MAX_UINT32
298#endif
299
300typedef float float32;
301typedef double float64;
302
303typedef struct STypeOps STypeOps;
304// stype is a pointer to the canonical STypeInfo structure for the type
305typedef struct STypeInfo STypeInfo;
306typedef const STypeInfo* stype;
308
309// standardize on uint32 for function call flags
310typedef uint32 flags_t;
311
312// sarrays are special because of the pointer union
313typedef union sa_ref {
314 void* _is_sarray;
315 void* a;
316} sa_ref;
317typedef union sa_ref* sahandle;
318
319// This is the type that is used for passing as a parameter by-value, as well as variants. Should be
320// no larger than 64 bits wide, but can be smaller.
321#define SType_none void*
322#define SType_opaque void*
323#define SType_int8 int8
324#define SType_int16 int16
325#define SType_int32 int32
326#define SType_int64 int64
327#define SType_uint8 uint8
328#define SType_uint16 uint16
329#define SType_uint32 uint32
330#define SType_uint64 uint64
331#define SType_intptr intptr
332#define SType_uintptr uintptr
333#define SType_bool _Bool
334#define SType_size size_t
335#define SType_float32 float32
336#define SType_float64 float64
337#define SType_ptr void*
338#define SType_string string
339#define SType_strref strref
340#define SType_object ObjInst*
341#define SType_weakref ObjInst_WeakRef*
342#define SType_suid SUID*
343#define SType_stvar stvar*
344#define SType_sarray sa_ref
345#define SType_hashtable hashtable
346#define SType_closure closure
347#define SType_cchain cchain
348#define SType_buffer Buffer
349#define SType_struct StructBase*
350#define SType_structp StructBase*
351#define stTypeDef(name) SType_##name
352
358
372#define stTypeCast(name, v) ((SType_##name)(v))
373
387#define stPtrCast(name, v) ((SType_##name*)(v))
388
389// container that can be aliased for any type
390#define CONTAINER_TYPE(type) stTypeDef(type) st_##type
391typedef union stgeneric {
392 uint64 st_generic;
393 CONTAINER_TYPE(none);
394 CONTAINER_TYPE(opaque);
395 CONTAINER_TYPE(int8);
396 CONTAINER_TYPE(int16);
397 CONTAINER_TYPE(int32);
398 CONTAINER_TYPE(int64);
399 CONTAINER_TYPE(uint8);
400 CONTAINER_TYPE(uint16);
401 CONTAINER_TYPE(uint32);
402 CONTAINER_TYPE(uint64);
403 CONTAINER_TYPE(intptr);
404 CONTAINER_TYPE(uintptr);
405 CONTAINER_TYPE(bool);
406 CONTAINER_TYPE(size);
407 CONTAINER_TYPE(float32);
408 CONTAINER_TYPE(float64);
409 CONTAINER_TYPE(ptr);
410 CONTAINER_TYPE(string);
411 CONTAINER_TYPE(strref);
412 CONTAINER_TYPE(object);
413 CONTAINER_TYPE(weakref);
414 CONTAINER_TYPE(suid);
415 CONTAINER_TYPE(stvar);
416 CONTAINER_TYPE(sarray);
417 CONTAINER_TYPE(hashtable);
418 CONTAINER_TYPE(closure);
419 CONTAINER_TYPE(cchain);
420 CONTAINER_TYPE(buffer);
421 CONTAINER_TYPE(struct);
422 CONTAINER_TYPE(structp);
423} stgeneric;
424
425_Static_assert(sizeof(stgeneric) == sizeof(uint64), "stype container too large");
426
427#ifndef __cplusplus
428#define stgeneric(type, val) ((stgeneric) { .st_##type = stCheck(type, val) })
429#define stgeneric_unchecked(type, val) ((stgeneric) { .st_##type = (val) })
430#define stgensarray(val) stgeneric(ptr, (val)._is_sarray)
431#else
432// C++ definitions of stgeneric / stgeneric_unchecked / stgensarray live in
433// stype_cxx.hpp
434#endif
435
436// Compact variant structure. This is most often used for passing arrays of values that
437// the type is not known at compile time, as part of the type-safe varargs replacement
438// mechanism.
439
440typedef struct stvar {
441 stgeneric data;
442 stype _type; // low bit: STVAR_OwnsData; use stvarType()/setters below
443 const char* _key; // optional key; NULL or program-lifetime. Use stvarKey().
444} stvar;
445
446// Low-bit tag stashed in the _type pointer. stype is a pointer to a canonical STypeInfo
447// descriptor which is always at least pointer-aligned, so bit 0 is free to record whether
448// this stvar owns a heap allocation holding an oversized (PassPtr) value.
449enum { STVAR_OwnsData = 1 };
450
457_meta_inline stype stvarType(const stvar* v)
458{
459 return (stype)((uintptr)v->_type & ~(uintptr)STVAR_OwnsData);
460}
461
479#define stvarTypeId(v) (stvarType(v)->id)
480
481// True if this variant owns a heap allocation backing a PassPtr value.
482_meta_inline bool _stvarOwns(const stvar* v)
483{
484 return ((uintptr)v->_type & STVAR_OwnsData) != 0;
485}
486
487// Set the type descriptor and ownership tag together. t must be a clean (untagged) stype.
488_meta_inline void _stvarSetType(stvar* v, stype t, bool owns)
489{
490 dbgAssert(((uintptr)t & STVAR_OwnsData) == 0); // alignment sanity
491 v->_type = (stype)((uintptr)t | (owns ? STVAR_OwnsData : 0));
492}
493
514_meta_inline const char* stvarKey(const stvar* v)
515{
516 return v->_key;
517}
518
519// Attach a key name to a variant. nm must be NULL or have program lifetime -- it is
520// pointer-copied, never duplicated. Prefer the stvark() macro, which stringizes a token
521// and so cannot be handed a pointer that dangles.
522_meta_inline void _stvarSetKey(stvar* v, const char* nm)
523{
524 v->_key = nm;
525}
526
527// The type that's actually used for storage in containers, etc.
528#define STStorageType_none void
529#define STStorageType_opaque void
530#define STStorageType_int8 int8
531#define STStorageType_int16 int16
532#define STStorageType_int32 int32
533#define STStorageType_int64 int64
534#define STStorageType_uint8 uint8
535#define STStorageType_uint16 uint16
536#define STStorageType_uint32 uint32
537#define STStorageType_uint64 uint64
538#define STStorageType_intptr intptr
539#define STStorageType_uintptr uintptr
540#define STStorageType_bool _Bool
541#define STStorageType_size size_t
542#define STStorageType_float32 float32
543#define STStorageType_float64 float64
544#define STStorageType_ptr void*
545#define STStorageType_string string
546#define STStorageType_strref string
547#define STStorageType_object ObjInst*
548#define STStorageType_weakref ObjInst_WeakRef*
549#define STStorageType_suid SUID
550#define STStorageType_stvar stvar
551#define STStorageType_sarray sa_ref
552#define STStorageType_hashtable hashtable
553#define STStorageType_closure closure
554#define STStorageType_cchain cchain
555#define STStorageType_buffer Buffer
556#define STStorageType_struct StructBase
557#define STStorageType_structp StructBase*
558#define stStorageType(name) STStorageType_##name
559
560enum STYPE_ID {
561 // none is a special type for empty argument lists, variants, etc
562 STypeId_none = STCLASS_BASIC | 0,
563 // opaque is a magic catch-all type for custom structures and such
564 STypeId_opaque = STCLASS_CX | STST_OPAQUE | 1,
565 // generic scalar types
566 STypeId_int8 = STCLASS_BASIC | STST_INT | 1,
567 STypeId_int16 = STCLASS_BASIC | STST_INT | 2,
568 STypeId_int32 = STCLASS_BASIC | STST_INT | 4,
569 STypeId_int64 = STCLASS_BASIC | STST_INT | 8,
570 STypeId_intptr = STCLASS_BASIC | STST_INT |
571 sizeof(intptr), // alias for one of the other int types
572 STypeId_uint8 = STCLASS_BASIC | STST_UINT | 1,
573 STypeId_uint16 = STCLASS_BASIC | STST_UINT | 2,
574 STypeId_uint32 = STCLASS_BASIC | STST_UINT | 4,
575 STypeId_uint64 = STCLASS_BASIC | STST_UINT | 8,
576 STypeId_uintptr = STCLASS_BASIC | STST_UINT | sizeof(intptr),
577 STypeId_bool = STCLASS_BASIC | STST_UINT | 3, // fill in a gap in the ID sequence
578 STypeId_size = STCLASS_BASIC | STST_UINT | sizeof(size_t), // alias for one of the uint types
579 STypeId_float32 = STCLASS_BASIC | STST_FLOAT | 4,
580 STypeId_float64 = STCLASS_BASIC | STST_FLOAT | 8,
581 STypeId_ptr = STCLASS_BASIC | STST_PTR | sizeof(void*),
582 // most of the CX class are "object-like" types and use pointers as handles
583 STypeId_suid = STCLASS_CX | STST_MISC | 0, // notable exception
584 STypeId_string = STCLASS_CX | STST_OBJ | 0,
585 STypeId_strref = STCLASS_CX | STST_OBJ | 0,
586 STypeId_object = STCLASS_CX | STST_OBJ | 1,
587 STypeId_weakref = STCLASS_CX | STST_OBJ | 2,
588 STypeId_stvar = STCLASS_CX | STST_OBJ | 3,
589 STypeId_closure = STCLASS_CX | STST_OBJ | 4,
590 STypeId_buffer = STCLASS_CX | STST_OBJ | 5,
591 STypeId_struct = STCLASS_CX | STST_OBJ | 6,
592 STypeId_structp = STCLASS_CX | STST_OBJ | 7,
593 STypeId_sarray = STCLASS_CX | STST_CONTAINER | 0,
594 STypeId_hashtable = STCLASS_CX | STST_CONTAINER | 1,
595 STypeId_cchain = STCLASS_CX | STST_CONTAINER | 2,
596};
597
610#define stTypeId(name) STypeId_##name
611
612// The actual storage size of the type
613enum STYPE_SIZE {
614 STypeSize_none = 0,
615 // opaque is not really size 0, but filled by by macros later
616 STypeSize_opaque = 0,
617 STypeSize_int8 = sizeof(int8),
618 STypeSize_int16 = sizeof(int16),
619 STypeSize_int32 = sizeof(int32),
620 STypeSize_int64 = sizeof(int64),
621 STypeSize_intptr = sizeof(intptr),
622 STypeSize_uint8 = sizeof(int8),
623 STypeSize_uint16 = sizeof(int16),
624 STypeSize_uint32 = sizeof(int32),
625 STypeSize_uint64 = sizeof(int64),
626 STypeSize_uintptr = sizeof(uintptr),
627 STypeSize_bool = sizeof(_Bool),
628 STypeSize_size = sizeof(size_t),
629 STypeSize_float32 = sizeof(float32),
630 STypeSize_float64 = sizeof(float64),
631 STypeSize_ptr = sizeof(void*),
632 STypeSize_string = sizeof(void*),
633 STypeSize_strref = sizeof(void*),
634 STypeSize_object = sizeof(ObjInst*),
635 STypeSize_weakref = sizeof(ObjInst_WeakRef*),
636 // SUID is special because it's always passed by reference, but stored as the full 16 bytes
637 STypeSize_suid = 16,
638 STypeSize_stvar = sizeof(stvar),
639 STypeSize_sarray = sizeof(sa_ref),
640 STypeSize_hashtable = sizeof(hashtable),
641 STypeSize_closure = sizeof(closure),
642 STypeSize_cchain = sizeof(cchain),
643 STypeSize_buffer = sizeof(Buffer),
644 // similar to opaque, not known at compile time
645 STypeSize_struct = 0,
646 STypeSize_structp = sizeof(StructBase*),
647};
648
660#define stTypeSize(name) STypeSize_##name
661
662enum STYPE_FLAGS {
663 STypeFlag_Object = (1 << 0), // "object-like" type -- pointer to managed object
664 STypeFlag_PassPtr = (1 << 1), // type is passed by pointer rather than by value,
665 // does not apply to 'handle' style objects
666 STypeFlag_Temporary = (1 << 2), // type info is temporary, i.e. constructed as a compound
667 // literal or otherwise dynamic. must be registered into the
668 // global type registry before use
669};
670#define stFlag(name) STypeFlag_##name
671
686#define stHasFlag(st, fname) (((st)->flags & stFlag(fname)) != 0)
687
694#define stGetSize(st) ((st)->size)
695
696// Static type checks
697// These types all include the marker as either the first member, or as part of
698// a union that coincides with the first member. Therefore we can take their address
699// and get the address of the parent structure that we already had (essentially a no-op)
700// while checking that they exist, thus verifying the type is correct.
701// Note the magic of the comma operator -- these prevent compilation if something is wrong,
702// but get optimized away entirely and do not emit any code.
703// The use of unused_noeval further improves this by hiding it in a conditional branch that
704// is guaranteed to not be evaluated, preventing any side effects such as function calls or
705// postfix operators.
706// The seemingly redundant (h) && portions of the expression are there solely to suppress
707// warnings from stupid compilers that don't understand it can never actually be dereferenced.
708#define saCheckType(name, h) ((sa_##name*)(unused_noeval((h) && &((h)->is_sarray_##name)), (h)))
709#define saCheck(s) (unused_noeval(&((s)._is_sarray)), (s.a))
710#define saCheckPtr(h) (unused_noeval((h != NULL) && &((h)->_is_sarray)), (h))
711#define htCheck(h) (unused_noeval((h) && &((h)->_is_hashtable)), (h))
712#define htCheckPtr(h) (unused_noeval((h) && (*h) && &((*h)->_is_hashtable)), (h))
713#define objInstCheck(o) (unused_noeval((o) && &((o)->_is_ObjInst)), (o))
714#define objInstCheckPtr(o) (unused_noeval((o != NULL) && (*o) && &((*o)->_is_ObjInst)), (o))
715#define objInstCheckClass(cls, o) (unused_noeval((o) && &((o)->_is_##cls)), (cls*)(o))
716#define objInstCheckClassPtr(cls, o) \
717 (unused_noeval((o != NULL) && (*o) && &((*o)->_is_##cls)), (cls**)(o))
718#define objWeakRefCheck(o) (unused_noeval((o) && &((o)->_is_ObjInst_WeakRef)), (o))
719#define objWeakRefCheckPtr(o) (unused_noeval((o) && (*o) && &((*o)->_is_ObjInst_WeakRef)), (o))
720#define objWeakRefCheckClass(cls, o) \
721 (unused_noeval((o) && &((o)->_is_##cls##_WeakRef)), (cls##_WeakRef*)(o))
722#define objWeakRefCheckClassPtr(cls, o) \
723 (unused_noeval((o) && (*o) && &((*o)->_is_##cls##_WeakRef)), (cls##_WeakRef**)(o))
724#define strCheck(s) (unused_noeval((s) && &((s)->_is_string)), (s))
725#define strCheckPtr(s) (unused_noeval((s != NULL) && (*s) && &((*s)->_is_string)), (s))
726#define closureCheck(c) (unused_noeval((c) && &((c)->_is_closure)), (c))
727#define closureCheckPtr(c) (unused_noeval((c != NULL) && (*c) && &((*c)->_is_closure)), (c))
728#define cchainCheck(c) (unused_noeval((c) && &((c)->_is_closure_chain)), (c))
729#define cchainCheckPtr(c) (unused_noeval((c != NULL) && (*c) && &((*c)->_is_closure_chain)), (c))
730#define bufferCheck(c) (unused_noeval((c) && &((c)->_is_buffer)), (c))
731#define bufferCheckPtr(c) (unused_noeval((c != NULL) && (*c) && &((*c)->_is_buffer)), (c))
732#define structCheckPtr(s) (unused_noeval((s != NULL) && &((s)->_is_struct)), (s))
733#define structCheckPtrPtr(s) (unused_noeval((s != NULL) && (*s) && &((*s)->_is_struct)), (s))
734
735// most of these are no-ops, but some can do extra type checking
736#define STypeCheck_opaque(type, val) (val)
737#define STypeCheck_int8(type, val) (val)
738#define STypeCheck_int16(type, val) (val)
739#define STypeCheck_int32(type, val) (val)
740#define STypeCheck_int64(type, val) (val)
741#define STypeCheck_intptr(type, val) (val)
742#define STypeCheck_uint8(type, val) (val)
743#define STypeCheck_uint16(type, val) (val)
744#define STypeCheck_uint32(type, val) (val)
745#define STypeCheck_uint64(type, val) (val)
746#define STypeCheck_uintptr(type, val) (val)
747#define STypeCheck_bool(type, val) (val)
748#define STypeCheck_size(type, val) (val)
749#define STypeCheck_float32(type, val) (val)
750#define STypeCheck_float64(type, val) (val)
751#define STypeCheck_ptr(type, val) (val)
752#define STypeCheck_string(type, val) strCheck(val)
753#define STypeCheck_strref(type, val) strCheck(val)
754#define STypeCheck_object(type, val) objInstCheck(val)
755#define STypeCheck_weakref(type, val) objWeakRefCheck(val)
756#define STypeCheck_suid(type, val) (unused_noeval((((val).low), ((val).high))), (val))
757#define STypeCheck_stvar(type, val) (unused_noeval((((val).data), ((val)._type))), (val))
758#define STypeCheck_sarray(type, val) saCheck(val)
759#define STypeCheck_hashtable(type, val) htCheck(val)
760#define STypeCheck_closure(type, val) closureCheck(val)
761#define STypeCheck_cchain(type, val) cchainCheck(val)
762#define STypeCheck_buffer(type, val) bufferCheck(val)
763// We get the pointer for bare structs, similar to opaque, but we can type check the structure
764#define STypeCheck_struct(type, val) structCheckPtr(val)
765#define STypeCheck_structp(type, val) structCheckPtr(val)
766
787#define stCheck(type, val) STypeCheck_##type(type, val)
788
789#define STypeCheckPtr_gen(type, ptr) (unused_noeval((stTypeDef(type)*)(ptr)), ptr)
790#define STypeCheckPtr_opaque(type, ptr) (ptr)
791#define STypeCheckPtr_int8(type, ptr) (ptr)
792#define STypeCheckPtr_int16(type, ptr) (ptr)
793#define STypeCheckPtr_int32(type, ptr) (ptr)
794#define STypeCheckPtr_int64(type, ptr) (ptr)
795#define STypeCheckPtr_intptr(type, ptr) (ptr)
796#define STypeCheckPtr_uint8(type, ptr) (ptr)
797#define STypeCheckPtr_uint16(type, ptr) (ptr)
798#define STypeCheckPtr_uint32(type, ptr) (ptr)
799#define STypeCheckPtr_uint64(type, ptr) (ptr)
800#define STypeCheckPtr_uintptr(type, ptr) (ptr)
801#define STypeCheckPtr_bool(type, ptr) (ptr)
802#define STypeCheckPtr_size(type, ptr) (ptr)
803#define STypeCheckPtr_float32(type, ptr) (ptr)
804#define STypeCheckPtr_float64(type, ptr) (ptr)
805#define STypeCheckPtr_ptr(type, ptr) (ptr)
806#define STypeCheckPtr_string(type, ptr) strCheckPtr(ptr)
807#define STypeCheckPtr_strref(type, ptr) strCheckPtr(ptr)
808#define STypeCheckPtr_object(type, ptr) objInstCheckPtr(ptr)
809#define STypeCheckPtr_weakref(type, ptr) objWeakRefCheckPtr(ptr)
810#define STypeCheckPtr_suid(type, ptr) (unused_noeval((((ptr)->low), ((ptr)->high))), (ptr))
811#define STypeCheckPtr_stvar(type, ptr) (unused_noeval((((ptr)->data), ((ptr)->_type))), (ptr))
812#define STypeCheckPtr_sarray(type, ptr) saCheckPtr(ptr)
813#define STypeCheckPtr_hashtable(type, ptr) htCheckPtr(ptr)
814#define STypeCheckPtr_closure(type, ptr) closureCheckPtr(ptr)
815#define STypeCheckPtr_cchain(type, ptr) cchainCheckPtr(ptr)
816#define STypeCheckPtr_buffer(type, ptr) bufferCheckPtr(ptr)
817#define STypeCheckPtr_struct(type, ptr) structCheckPtr(ptr)
818#define STypeCheckPtr_structp(type, ptr) structCheckPtrPtr(ptr)
819
830#define stCheckPtr(type, ptr) STypeCheckPtr_##type(type, ptr)
831
850// C99 compound literals are lvalues and can force the compiler to create a temporary
851// on the stack if necessary, so that we can pass pointers to arbitrary expressions
852#define stRvalAddr(type, rval) ((stStorageType(type)[1]) { rval })
853
855
856// Canonical type information for builtin types
857extern const STypeInfo _sti_none;
858extern const STypeInfo _sti_int8;
859extern const STypeInfo _sti_int16;
860extern const STypeInfo _sti_int32;
861extern const STypeInfo _sti_int64;
862extern const STypeInfo _sti_uint8;
863extern const STypeInfo _sti_uint16;
864extern const STypeInfo _sti_uint32;
865extern const STypeInfo _sti_uint64;
866extern const STypeInfo _sti_bool;
867extern const STypeInfo _sti_float32;
868extern const STypeInfo _sti_float64;
869extern const STypeInfo _sti_ptr;
870extern const STypeInfo _sti_string;
871extern const STypeInfo _sti_object;
872extern const STypeInfo _sti_weakref;
873extern const STypeInfo _sti_suid;
874extern const STypeInfo _sti_stvar;
875extern const STypeInfo _sti_sarray;
876extern const STypeInfo _sti_hashtable;
877extern const STypeInfo _sti_closure;
878extern const STypeInfo _sti_cchain;
879extern const STypeInfo _sti_buffer;
880extern const STypeInfo _sti_structp;
881
882extern const STypeOps _stops_opaque;
883extern const STypeOps _stops_struct;
884
885// canonical type info name for static types
886#define stTypeInfo(name) _sti_##name
887
888// MEGA PREPROCESSOR HACKS INCOMING
889// this enables the use of opaque(realtype) as type name in functions like saCreate
890#ifndef __cplusplus
891#define _sti_opaque(realtype) \
892 ((const STypeInfo) { .id = stTypeId(opaque), \
893 .flags = stFlag(PassPtr) | stFlag(Temporary), \
894 .size = (uint16)sizeof(realtype), \
895 .ops = _stops_opaque })
896#define _sti_struct(realtype) \
897 ((const STypeInfo) { .id = stTypeId(struct), \
898 .flags = stFlag(PassPtr) | stFlag(Object) | stFlag(Temporary), \
899 .size = (uint16)sizeof(realtype), \
900 .ops = _stops_struct })
901#else
902// C++ versions of _sti_opaque / _sti_struct are defined in stype_cxx.hpp
903#endif
904
905// aliases for types that don't have their own info
906
907#define _sti_strref _sti_string
908
909// these are architecture-dependant alises
910#if defined(_64BIT)
911#define _sti_intptr _sti_int64
912#define _sti_uintptr _sti_uint64
913#define _sti_size _sti_uint64
914#else
915#define _sti_intptr _sti_int32
916#define _sti_uintptr _sti_uint32
917#define _sti_size _sti_uint32
918#endif
919
957
972#define stType(name) (&stTypeInfo(name))
973
974// Macros for passing arguments by value
975
976// none ignores the value
977#define STypeArg_none(type, val) ((stgeneric) { 0 })
978// opqaue is a special case that must always be passed by pointer, and
979// the caller must supply an lvalue
980#define STypeArg_opaque(type, val) stgeneric(type, &(val))
981// but everything else gets put into a container
982#define STypeArg_int8(type, val) stgeneric(type, val)
983#define STypeArg_int16(type, val) stgeneric(type, val)
984#define STypeArg_int32(type, val) stgeneric(type, val)
985#define STypeArg_int64(type, val) stgeneric(type, val)
986#define STypeArg_intptr(type, val) stgeneric(type, val)
987#define STypeArg_uint8(type, val) stgeneric(type, val)
988#define STypeArg_uint16(type, val) stgeneric(type, val)
989#define STypeArg_uint32(type, val) stgeneric(type, val)
990#define STypeArg_uint64(type, val) stgeneric(type, val)
991#define STypeArg_uintptr(type, val) stgeneric(type, val)
992#define STypeArg_bool(type, val) stgeneric(type, val)
993#define STypeArg_size(type, val) stgeneric(type, val)
994#define STypeArg_float32(type, val) stgeneric(type, val)
995#define STypeArg_float64(type, val) stgeneric(type, val)
996#define STypeArg_ptr(type, val) stgeneric(type, val)
997#define STypeArg_string(type, val) stgeneric(type, val)
998#define STypeArg_strref(type, val) stgeneric(type, val)
999#define STypeArg_object(type, val) stgeneric(type, objInstBase(val))
1000#define STypeArg_weakref(type, val) stgeneric(type, objWeakRefBase(val))
1001// SUID and stvar are too big, so make a copy and pass a pointer
1002#define STypeArg_suid(type, val) stgeneric_unchecked(type, stRvalAddr(type, stCheck(type, val)))
1003#define STypeArg_stvar(type, val) stgeneric_unchecked(type, stRvalAddr(type, stCheck(type, val)))
1004#define STypeArg_sarray(type, val) stgensarray(val)
1005#define STypeArg_hashtable(type, val) stgeneric(type, val)
1006#define STypeArg_closure(type, val) stgeneric(type, val)
1007#define STypeArg_cchain(type, val) stgeneric(type, val)
1008#define STypeArg_buffer(type, val) stgeneric(type, val)
1009// struct works like opaque
1010#define STypeArg_struct(type, val) stgeneric(type, &(val))
1011#define STypeArg_structp(type, val) stgeneric(type, val)
1012
1036#define stArg(type, val) STypeArg_##type(type, val)
1037
1038// And for passing a pointer-to-pointer, mostly for functions that want to
1039// consume or reallocate the object
1040
1041#define STypeArgPtr_none(type, val) NULL
1042// opaque is already passed in as a pointer
1043#define STypeArgPtr_opaque(type, val) &stgeneric(type, val)
1044#define STypeArgPtr_int8(type, val) (stgeneric*)stCheckPtr(type, val)
1045#define STypeArgPtr_int16(type, val) (stgeneric*)stCheckPtr(type, val)
1046#define STypeArgPtr_int32(type, val) (stgeneric*)stCheckPtr(type, val)
1047#define STypeArgPtr_int64(type, val) (stgeneric*)stCheckPtr(type, val)
1048#define STypeArgPtr_intptr(type, val) (stgeneric*)stCheckPtr(type, val)
1049#define STypeArgPtr_uint8(type, val) (stgeneric*)stCheckPtr(type, val)
1050#define STypeArgPtr_uint16(type, val) (stgeneric*)stCheckPtr(type, val)
1051#define STypeArgPtr_uint32(type, val) (stgeneric*)stCheckPtr(type, val)
1052#define STypeArgPtr_uint64(type, val) (stgeneric*)stCheckPtr(type, val)
1053#define STypeArgPtr_uintptr(type, val) (stgeneric*)stCheckPtr(type, val)
1054#define STypeArgPtr_bool(type, val) (stgeneric*)stCheckPtr(type, val)
1055#define STypeArgPtr_size(type, val) (stgeneric*)stCheckPtr(type, val)
1056#define STypeArgPtr_float32(type, val) (stgeneric*)stCheckPtr(type, val)
1057#define STypeArgPtr_float64(type, val) (stgeneric*)stCheckPtr(type, val)
1058#define STypeArgPtr_ptr(type, val) (stgeneric*)stCheckPtr(type, (void**)(val))
1059#define STypeArgPtr_string(type, val) (stgeneric*)stCheckPtr(type, val)
1060#define STypeArgPtr_strref(type, val) (stgeneric*)stCheckPtr(type, val)
1061#define STypeArgPtr_object(type, val) (stgeneric*)stCheckPtr(type, val)
1062#define STypeArgPtr_weakref(type, val) (stgeneric*)stCheckPtr(type, val)
1063// same for the other pass-by-pointer cases (SUID, stvar)
1064#define STypeArgPtr_suid(type, val) &stgeneric_unchecked(type, stCheckPtr(type, val))
1065#define STypeArgPtr_stvar(type, val) &stgeneric_unchecked(type, stCheckPtr(type, val))
1066#define STypeArgPtr_sarray(type, val) (stgeneric*)stCheckPtr(type, val)
1067#define STypeArgPtr_hashtable(type, val) (stgeneric*)stCheckPtr(type, val)
1068#define STypeArgPtr_closure(type, val) (stgeneric*)stCheckPtr(type, val)
1069#define STypeArgPtr_cchain(type, val) (stgeneric*)stCheckPtr(type, val)
1070#define STypeArgPtr_buffer(type, val) (stgeneric*)stCheckPtr(type, val)
1071#define STypeArgPtr_struct(type, val) &stgeneric(type, val)
1072#define STypeArgPtr_structp(type, val) (stgeneric*)stCheckPtr(type, val)
1073
1091#define stArgPtr(type, val) STypeArgPtr_##type(type, val)
1092
1093// Macros for type-checked inline metafunctions.
1094// These expand to a pair of parameters for type, followed by a pointer.
1095
1096#define STypeCheckedArg_none(type, val) stType(type), stArg(type, val)
1097#define STypeCheckedArg_opaque(type, val) (&_sti_opaque(val)), stArg(type, val)
1098#define STypeCheckedArg_int8(type, val) stType(type), stArg(type, val)
1099#define STypeCheckedArg_int16(type, val) stType(type), stArg(type, val)
1100#define STypeCheckedArg_int32(type, val) stType(type), stArg(type, val)
1101#define STypeCheckedArg_int64(type, val) stType(type), stArg(type, val)
1102#define STypeCheckedArg_intptr(type, val) stType(type), stArg(type, val)
1103#define STypeCheckedArg_uint8(type, val) stType(type), stArg(type, val)
1104#define STypeCheckedArg_uint16(type, val) stType(type), stArg(type, val)
1105#define STypeCheckedArg_uint32(type, val) stType(type), stArg(type, val)
1106#define STypeCheckedArg_uint64(type, val) stType(type), stArg(type, val)
1107#define STypeCheckedArg_uintptr(type, val) stType(type), stArg(type, val)
1108#define STypeCheckedArg_bool(type, val) stType(type), stArg(type, val)
1109#define STypeCheckedArg_size(type, val) stType(type), stArg(type, val)
1110#define STypeCheckedArg_float32(type, val) stType(type), stArg(type, val)
1111#define STypeCheckedArg_float64(type, val) stType(type), stArg(type, val)
1112#define STypeCheckedArg_ptr(type, val) stType(type), stArg(type, val)
1113#define STypeCheckedArg_string(type, val) stType(type), stArg(type, val)
1114#define STypeCheckedArg_strref(type, val) stType(type), stArg(type, val)
1115#define STypeCheckedArg_object(type, val) stType(type), stArg(type, val)
1116#define STypeCheckedArg_weakref(type, val) stType(type), stArg(type, val)
1117#define STypeCheckedArg_suid(type, val) stType(type), stArg(type, val)
1118#define STypeCheckedArg_stvar(type, val) stType(type), stArg(type, val)
1119#define STypeCheckedArg_sarray(type, val) stType(type), stArg(type, val)
1120#define STypeCheckedArg_hashtable(type, val) stType(type), stArg(type, val)
1121#define STypeCheckedArg_closure(type, val) stType(type), stArg(type, val)
1122#define STypeCheckedArg_cchain(type, val) stType(type), stArg(type, val)
1123#define STypeCheckedArg_buffer(type, val) stType(type), stArg(type, val)
1124#define STypeCheckedArg_struct(type, val) (&_sti_struct(val)), stArg(type, val)
1125#define STypeCheckedArg_structp(type, val) stType(type), stArg(type, val)
1126
1147#define stCheckedArg(type, val) STypeCheckedArg_##type(type, val)
1148
1149// Type checking of pointers to types, mostly for functions that want to
1150// consume object-like variables and destroy them
1151
1152#define STypeCheckedPtrArg_none(type, val) stType(type), stArgPtr(type, val)
1153// go the opposite direction for opaque since it's already passed in as a pointer
1154#define STypeCheckedPtrArg_opaque(type, val) (&_sti_opaque(*val)), stArgPtr(type, val)
1155#define STypeCheckedPtrArg_int8(type, val) stType(type), stArgPtr(type, val)
1156#define STypeCheckedPtrArg_int16(type, val) stType(type), stArgPtr(type, val)
1157#define STypeCheckedPtrArg_int32(type, val) stType(type), stArgPtr(type, val)
1158#define STypeCheckedPtrArg_int64(type, val) stType(type), stArgPtr(type, val)
1159#define STypeCheckedPtrArg_intptr(type, val) stType(type), stArgPtr(type, val)
1160#define STypeCheckedPtrArg_uint8(type, val) stType(type), stArgPtr(type, val)
1161#define STypeCheckedPtrArg_uint16(type, val) stType(type), stArgPtr(type, val)
1162#define STypeCheckedPtrArg_uint32(type, val) stType(type), stArgPtr(type, val)
1163#define STypeCheckedPtrArg_uint64(type, val) stType(type), stArgPtr(type, val)
1164#define STypeCheckedPtrArg_uintptr(type, val) stType(type), stArgPtr(type, val)
1165#define STypeCheckedPtrArg_bool(type, val) stType(type), stArgPtr(type, val)
1166#define STypeCheckedPtrArg_size(type, val) stType(type), stArgPtr(type, val)
1167#define STypeCheckedPtrArg_float32(type, val) stType(type), stArgPtr(type, val)
1168#define STypeCheckedPtrArg_float64(type, val) stType(type), stArgPtr(type, val)
1169#define STypeCheckedPtrArg_ptr(type, val) stType(type), stArgPtr(type, val)
1170#define STypeCheckedPtrArg_string(type, val) stType(type), stArgPtr(type, val)
1171#define STypeCheckedPtrArg_strref(type, val) stType(type), stArgPtr(type, val)
1172#define STypeCheckedPtrArg_object(type, val) stType(type), stArgPtr(type, val)
1173#define STypeCheckedPtrArg_weakref(type, val) stType(type), stArgPtr(type, val)
1174#define STypeCheckedPtrArg_suid(type, val) stType(type), stArgPtr(type, val)
1175#define STypeCheckedPtrArg_stvar(type, val) stType(type), stArgPtr(type, val)
1176#define STypeCheckedPtrArg_sarray(type, val) stType(type), stArgPtr(type, val)
1177#define STypeCheckedPtrArg_hashtable(type, val) stType(type), stArgPtr(type, val)
1178#define STypeCheckedPtrArg_closure(type, val) stType(type), stArgPtr(type, val)
1179#define STypeCheckedPtrArg_cchain(type, val) stType(type), stArgPtr(type, val)
1180#define STypeCheckedPtrArg_buffer(type, val) stType(type), stArgPtr(type, val)
1181#define STypeCheckedPtrArg_struct(type, val) (&_sti_struct(*val)), stArgPtr(type, val)
1182#define STypeCheckedPtrArg_structp(type, val) stType(type), stArgPtr(type, val)
1183
1205#define stCheckedPtrArg(type, val) STypeCheckedPtrArg_##type(type, val)
1206
1208
1212
1222
1230 ST_Equality = 0x00000002,
1231
1238 ST_Overflow = 0x00000004,
1239
1247 ST_Lossless = 0x00000008,
1248};
1249
1251
1277
1278#define _stCopyDest_Anno_(typvar) _Post_valid_ _When_(stHasFlag(typvar, PassPtr), _Pre_valid_)
1279#define _stCopyDest_Anno_opt_(typvar) _Out_opt_ _When_(stHasFlag(typvar, PassPtr), _Pre_opt_valid_)
1280
1292typedef void (*stDtorFunc)(stype st, _Pre_notnull_ _Post_invalid_ stgeneric* gen, flags_t flags);
1293
1305typedef intptr (*stCmpFunc)(stype st, _In_ stgeneric gen1, _In_ stgeneric gen2, flags_t flags);
1306
1318typedef uint32 (*stHashFunc)(stype st, _In_ stgeneric gen, flags_t flags);
1319
1335typedef void (*stCopyFunc)(stype st, _stCopyDest_Anno_(st) stgeneric* dest, _In_ stgeneric src,
1336 flags_t flags);
1337
1356typedef _Success_(return)
1357_Check_return_ bool (*stConvertFunc)(stype destst, _stCopyDest_Anno_(destst) stgeneric* dest,
1358 stype srcst, _In_ stgeneric src, flags_t flags);
1359
1375typedef bool (*stSerializeFunc)(stype st, stgeneric val, _Inout_ SerWriter* w);
1376
1387typedef bool (*stDeserializeFunc)(stype st, _Inout_ stgeneric* val, _Inout_ SerReader* r);
1388
1389typedef struct STypeOps {
1390 stDtorFunc dtor;
1391 stCmpFunc cmp;
1392 stHashFunc hash;
1393 stCopyFunc copy;
1394 stConvertFunc convert;
1395 stSerializeFunc serialize;
1396 stDeserializeFunc deserialize;
1397} STypeOps;
1398
1409typedef struct STypeInfo {
1410 uint32 id;
1411 uint16 size;
1412 uint16 flags;
1413
1414 STypeOps ops;
1415} STypeInfo;
1416
1418
1436
1444
1454typedef struct STypeInfoExt {
1456 uint32 flags;
1457
1461 strref name;
1462
1465 const void* detail;
1466
1468} STypeInfoExt;
1469
1475extern const STypeInfoExt _stie_none;
1476extern const STypeInfoExt _stie_bool;
1477extern const STypeInfoExt _stie_int8;
1478extern const STypeInfoExt _stie_int16;
1479extern const STypeInfoExt _stie_int32;
1480extern const STypeInfoExt _stie_int64;
1481extern const STypeInfoExt _stie_uint8;
1482extern const STypeInfoExt _stie_uint16;
1483extern const STypeInfoExt _stie_uint32;
1484extern const STypeInfoExt _stie_uint64;
1485extern const STypeInfoExt _stie_float32;
1486extern const STypeInfoExt _stie_float64;
1487extern const STypeInfoExt _stie_string;
1488extern const STypeInfoExt _stie_suid;
1489extern const STypeInfoExt _stie_object;
1490extern const STypeInfoExt _stie_buffer;
1491extern const STypeInfoExt _stie_stvar;
1492extern const STypeInfoExt _stie_sarray;
1493extern const STypeInfoExt _stie_hashtable;
1494
1507#define stExt(name) (&_stie_##name)
1508
1510
1518
1519_meta_inline stgeneric _stStoredVal(stype st, _In_ const void* storage)
1520{
1521 stgeneric ret;
1522 switch (st->size) {
1523 case 1:
1524 ret.st_uint8 = *(uint8*)storage;
1525 break;
1526 case 2:
1527 ret.st_uint16 = *(uint16*)storage;
1528 break;
1529 case 4:
1530 ret.st_uint32 = *(uint32*)storage;
1531 break;
1532 case 8:
1533 ret.st_uint64 = *(uint64*)storage;
1534 break;
1535 default:
1536 devFatalError("Invalid small stype size");
1537 ret.st_uint64 = 0;
1538 }
1539 return ret;
1540}
1541
1559#define stStored(st, storage) \
1560 (stHasFlag(st, PassPtr) ? stgeneric(ptr, (void*)(storage)) : _stStoredVal(st, storage))
1561
1572#define stStoredPtr(st, storage) \
1573 (stHasFlag(st, PassPtr) ? &stgeneric(ptr, ((void*)(storage))) : (stgeneric*)((void*)(storage)))
1574
1585#define stGenPtr(st, gen) (stHasFlag(st, PassPtr) ? (gen).st_ptr : &(gen))
1586
1588
1596
1597// inlining these lets most of it get optimized out and specialized if the type is known at
1598// compile-time
1599
1617#define stDestroy(type, pobj, ...) \
1618 _stDestroy(stType(type), stArgPtr(type, pobj), opt_flags(__VA_ARGS__))
1619_meta_inline void _stDestroy(stype st, _Pre_notnull_ _Post_invalid_ stgeneric* gen, flags_t flags)
1620{
1621 if (!st)
1622 return;
1623
1624 if (st->ops.dtor)
1625 st->ops.dtor(st, gen, flags);
1626}
1627
1628#ifdef _COMPILER_GCC
1629// GCC incorrectly emits an array bounds warning on the second memcpy in _stCopy; and we use -Werror
1630// which turns it into an error. The warning is provably a false positive because it's triggering on
1631// the int8 case where the size is 1, but the branch that accesses st_ptr is never reached because
1632// int8 does not have the PassPtr flag.
1633// The same line also triggers a maybe-uninitialized warning.
1634// This section also suppresses an incorrect nonnull warning in _stCmp that follows the same pattern
1635// of the compiler thinking we're accessing the pointer version when we are not.
1636#pragma GCC diagnostic push
1637#pragma GCC diagnostic ignored "-Wpragmas"
1638#pragma GCC diagnostic ignored "-Wunknown-warning-option"
1639#pragma GCC diagnostic ignored "-Warray-bounds"
1640#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1641#pragma GCC diagnostic ignored "-Wnonnull"
1642#endif
1643
1662#define stCmp(type, obj1, obj2, ...) \
1663 _stCmp(stType(type), stArg(type, obj1), stArg(type, obj2), opt_flags(__VA_ARGS__))
1664_meta_inline intptr _stCmp(stype st, _In_ stgeneric gen1, _In_ stgeneric gen2, flags_t flags)
1665{
1666 if (!st)
1667 return 1; // treat null type as always greater (sorts last), mirrors stCmp_none
1668
1669 if (st->ops.cmp)
1670 return st->ops.cmp(st, gen1, gen2, flags);
1671
1672 if (!stHasFlag(st, PassPtr))
1673 return memcmp(&gen1, &gen2, st->size);
1674 else
1675 return memcmp(gen1.st_ptr, gen2.st_ptr, st->size);
1676}
1677
1695#define stCopy(type, pdest, src, ...) \
1696 _stCopy(stType(type), stArgPtr(type, pdest), stArg(type, src), opt_flags(__VA_ARGS__))
1697_meta_inline void _stCopy(stype st, _stCopyDest_Anno_(st) stgeneric* dest, _In_ stgeneric src,
1698 flags_t flags)
1699{
1700 if (!st)
1701 return;
1702
1703 if (st->ops.copy)
1704 st->ops.copy(st, dest, src, flags);
1705 else if (!stHasFlag(st, PassPtr))
1706 memcpy(dest, &src, st->size);
1707 else
1708 memcpy(dest->st_ptr, src.st_ptr, st->size);
1709}
1710
1711#ifdef _COMPILER_GCC
1712#pragma GCC diagnostic pop
1713#endif
1714
1715uint32 stHash_gen(stype st, _In_ stgeneric stgen, flags_t flags);
1716
1731#define stHash(type, obj, ...) _stHash(stType(type), stArg(type, obj), opt_flags(__VA_ARGS__))
1732_meta_inline uint32 _stHash(stype st, _In_ stgeneric gen, flags_t flags)
1733{
1734 if (!st)
1735 return 0;
1736
1737 if (st->ops.hash)
1738 return st->ops.hash(st, gen, flags);
1739 else
1740 return stHash_gen(st, gen, flags);
1741}
1742
1743// Internal: look up or insert a Temporary descriptor in the global type registry.
1744// Recursively canonicalizes param[0]/param[1] before keying. Thread-safe via RWLock.
1745// Always returns a non-Temporary canonical pointer.
1746stype _stGetCanonical(stype st);
1747
1763_meta_inline stype stCanonical(stype st)
1764{
1765 if (!st)
1766 return stType(none);
1767
1768 if (!stHasFlag(st, Temporary))
1769 return st;
1770
1771 return _stGetCanonical(st);
1772}
1773
1785_meta_inline bool stEq(stype s1, stype s2)
1786{
1787 return stCanonical(s1) == stCanonical(s2);
1788}
1789
1812#define stConvert(desttype, pdest, srctype, src, ...) \
1813 _stConvert(stType(desttype), \
1814 stArgPtr(desttype, pdest), \
1815 stType(srctype), \
1816 stArg(srctype, src), \
1817 opt_flags(__VA_ARGS__))
1818_Success_(return) _Check_return_ _meta_inline bool
1819_stConvert(stype destst, _stCopyDest_Anno_(destst) stgeneric* dest, stype srcst, _In_ stgeneric src,
1820 flags_t flags)
1821{
1822 if (!srcst || !destst)
1823 return false;
1824
1825 // The *source* stype is responsible for handling conversions to other types.
1826 // Compare with stEq rather than by pointer: generated compound descriptors are
1827 // Temporary, so the same logical type can arrive as two different pointers.
1828 if (stEq(srcst, destst))
1829 return _stCopy(destst, dest, src, flags), true;
1830 if (srcst->ops.convert)
1831 return srcst->ops.convert(destst, dest, srcst, src, flags);
1832
1833 return false; // can't convert it if we don't know how!
1834}
1835
1898
1908#define stDeclare(name) extern const STypeInfo _sti_##name
1909
1928#define stDefine(name) const STypeInfo _sti_##name =
1929
1931
1933
1935
1936CX_C_END
1937
1938#ifdef __cplusplus
1939#include <cx/stype/stype_cxx.hpp>
1940#endif
Runtime assertion macros and failure handling.
Compiler and platform detection macros.
struct closure_ref * closure
Opaque handle to a closure.
Definition closure.h:111
#define devFatalError(msg)
Definition assert.h:189
#define dbgAssert(expr)
Definition assert.h:85
struct hashtable_ref * hashtable
Definition hashtable.h:28
struct str_ref * string
Opaque handle to a string object.
Definition strbase.h:42
const struct str_ref * strref
Borrowed reference to a string.
Definition strbase.h:58
#define stvar(typen, val)
Definition stvar.h:162
bool stEq(stype s1, stype s2)
Definition stype.h:1785
stype stCanonical(stype st)
Definition stype.h:1763
#define stType(name)
Definition stype.h:972
const STypeInfoExt _stie_stvar
const STypeInfoExt _stie_uint64
STypeInfoExtFlagsEnum
Flags for STypeInfoExt::flags.
Definition stype.h:1438
const STypeInfoExt _stie_uint8
const STypeInfoExt _stie_buffer
const STypeInfoExt _stie_uint16
const STypeInfoExt _stie_sarray
const STypeInfoExt _stie_hashtable
const STypeInfoExt _stie_int8
const STypeInfoExt _stie_object
const STypeInfoExt _stie_int64
const STypeInfoExt _stie_int32
const STypeInfoExt _stie_bool
const STypeInfoExt _stie_float32
const STypeInfoExt _stie_suid
const STypeInfoExt _stie_uint32
const STypeInfoExt _stie_string
const STypeInfoExt _stie_float64
const STypeInfoExt _stie_none
const STypeInfoExt _stie_int16
@ STIE_TypeSet
Definition stype.h:1442
STYPE_OPS_FLAGS
Definition stype.h:1215
@ ST_Overflow
Definition stype.h:1238
@ ST_CaseInsensitive
Definition stype.h:1221
@ ST_Equality
Definition stype.h:1230
@ ST_Lossless
Definition stype.h:1247
bool(* stDeserializeFunc)(stype st, stgeneric *val, SerReader *r)
Definition stype.h:1387
void(* stDtorFunc)(stype st, stgeneric *gen, flags_t flags)
Definition stype.h:1292
intptr(* stCmpFunc)(stype st, stgeneric gen1, stgeneric gen2, flags_t flags)
Definition stype.h:1305
bool(* stConvertFunc)(stype destst, _stCopyDest_Anno_(destst) stgeneric *dest, stype srcst, stgeneric src, flags_t flags)
Definition stype.h:1357
bool(* stSerializeFunc)(stype st, stgeneric val, SerWriter *w)
Definition stype.h:1375
uint32(* stHashFunc)(stype st, stgeneric gen, flags_t flags)
Definition stype.h:1318
void(* stCopyFunc)(stype st, _stCopyDest_Anno_(st) stgeneric *dest, stgeneric src, flags_t flags)
Definition stype.h:1335
#define stHasFlag(st, fname)
Definition stype.h:686
const char * stvarKey(const stvar *v)
Definition stype.h:514
stype stvarType(const stvar *v)
Definition stype.h:457
Optional macro argument handling.
Copy-on-write strings with automatic memory management and rope optimization.
String literal prefix macros and compile-time constant declarations.
const STypeInfoExt * param[2]
Element type, or key type + value type.
Definition stype.h:1467
uint32 flags
See STypeInfoExtFlagsEnum.
Definition stype.h:1456
const void * detail
Definition stype.h:1465
strref name
Definition stype.h:1461
stype type
The stype this extends; always a valid, canonical stype.
Definition stype.h:1455
STypeOps ops
operations embedded directly - no separate allocation
Definition stype.h:1414
uint16 size
storage size in bytes
Definition stype.h:1411
uint16 flags
STypeFlag_Object, STypeFlag_PassPtr, STypeFlag_Temporary.
Definition stype.h:1412
uint32 id
hierarchical type ID: STCLASS | STST_subtype | discriminant
Definition stype.h:1410
128-bit sortable unique identifier
Definition suid.h:47
Macros for suppressing compiler warnings.