libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_instance.h
Go to the documentation of this file.
1/*! \file
2 * \ingroup meta
3 * \brief GblInstance structure and related functions.
4 *
5 * This file contains the API for the GblInstance type,
6 * which is the most low-level, minimalistic primitive
7 * instantiable type within the type-system. It's the
8 * root of all other instantiables and contains nothing
9 * other than a pointer to its GblClass.
10 *
11 * \sa gimbal_type.h, gimbal_class.h
12 *
13 * \author 2023, 2025 Falco Girgis
14 * \copyright MIT License
15 */
16#ifndef GIMBAL_INSTANCE_H
17#define GIMBAL_INSTANCE_H
18
19#include "../../core/gimbal_ctx.h"
20#include "../classes/gimbal_class.h"
21
22/*! \name Instance Root Type
23 * \brief UUID and cast operators
24 * @{
25 */
26#define GBL_INSTANCE_TYPE (GBL_BUILTIN_TYPE(INSTANCE)) //!< Type UUID for GblInstance
27#define GBL_INSTANCE(self) ((GblInstance*)self) //!< Casts GblInstance-compatible to GblInstance
28#define GBL_INSTANCE_GET_CLASS(self) (GblInstance_class(GBL_INSTANCE(self))) //!< Extracts the class from a GblInstance
29//! @}
30
31/*! \name Instance Operators
32 * \brief Builtin operations for Instance-derived types
33 * \relatesalso GblInstance
34 * @{
35 */
36//! Returns the type UUID for a GblInstance
37#define GBL_TYPEOF(self) GBL_TYPEOF_(self)
38//! Wraps GblInstance_private(), passing the given type and returning its private structure
39#define GBL_PRIVATE(cType, self) GBL_PRIVATE_(cType, self)
40//! Wraps GblInstance_public(), passing the given type, and returning its public struct
41#define GBL_PUBLIC(cType, selfPriv) GBL_PUBLIC_(cType, selfPriv)
42//! Returns GBL_TRUE if the instance can be casted to the given type safely
43#define GBL_TYPECHECK(cType, self) GBL_TYPECHECK_(cType, self)
44//! Dynamically validated, error throwing cast in `DEBUG` builds, 0 overhead C-style cast in `RELEASE` builds (with `NDEBUG` defined).
45#define GBL_CAST(cType, self) GBL_CAST_(cType, self)
46//! Wraps GblInstance_as() for the given type, providing a gracefully-failing case
47#define GBL_AS(cType, self) GBL_AS_(cType, self)
48//! Casts to the given instance type, then returns its class, returning NULL and raising an error upon failure
49#define GBL_CLASSOF(cType, self) GBL_CLASSOF_(cType, self)
50//! Uses GblInstance_as(), then gets its class (if successful) or returns NULL without raising an error
51#define GBL_CLASSOF_AS(cType, self) GBL_CLASSOF_AS_(cType, self)
52//! Invokes a virtual method on the given type's class, passing the variadic arguments directly through to it as method arguments
53#define GBL_VCALL(cType, method, ...) GBL_VCALL_(cType, method, __VA_ARGS__)
54//! Invokes a virtual method on the default class for a given type, used for calling into parent or default methods
55#define GBL_VCALL_DEFAULT(cType, method, ...) GBL_VCALL_DEFAULT_(cType, method, __VA_ARGS__)
56//! @}
57
58#define GBL_SELF_TYPE GblInstance
59
61
62/*! \brief Base struct for all instantiable meta types.
63 * \ingroup meta
64 *
65 * An Instance simply represents an object that can be created from a given
66 * GblType which shares some data with other instances of the same type,
67 * located within their class.
68 *
69 * GblInstance is the base structure which is to be inherited by instances of all
70 * instantiable types. This means placing it or a type inheriting from it as the
71 * first member of an instance struct.
72 *
73 * \note
74 * As the root instantiable type, an instance contains nothing but a
75 * pointer to its corresponding class. Its as lightweight as possible.
76 *
77 * \sa GblClass, GblType, GblBox, GblObject
78 */
79typedef struct GblInstance {
80 GblClass* pClass; //!< READ-ONLY Pointer to Instance's Class, do not modify directly
81} GblInstance;
82
83/*! \name Lifetime Management
84 * \brief Constructors and Destructors
85 * @{
86 */
87//! Creates and returns an instance, optionally with an extended size and/or non-default class
89 size_t publicSize/*=DEFAULT*/,
90 GblClass* pClass /*=NULL*/) GBL_NOEXCEPT;
91//! Constructs an instance, optionally with a non-default class, returning a result code
93 GblType type,
94 GblClass* pClass/*=NULL*/) GBL_NOEXCEPT;
95//! Destructs and deallocates an instance. It must have been created with GblInstance_create().
97//! Destructs but doesn't deallocate an instance. It must have been created with GblInstance_construct().
99//! @}
100
101/*! \name Type Conversions
102 * \brief Methods for type casting and checking
103 * \relatesalso GblInstance
104 * @{
105 */
106//! Returns GBL_TRUE if the given instance's type is compatible with \p toType
108//! Attempts to cast the given instance to \p toType, raising an error and returning NULL upon failure
110//! Attempts to cast the given instance to \p toType, gracefully returning NULL upon failure
112//! @}
113
114/*! \name Public and Private Data
115 * \brief Methods for accessing public and private segments
116 * \relatesalso GblInstance
117 * @{
118 */
119//! Returns the private structure associated with the given \p base type of the instance
121//! Casts back to the instance type from a base type's private data segment structure
122GBL_EXPORT GblInstance* GblInstance_public (const void* pPriv, GblType base) GBL_NOEXCEPT;
123//! @}
124
125/*! \name Type Info
126 * \brief Methods for getting instance information
127 * \relatesalso GblInstance
128 * @{
129 */
130//! Returns the GblType associated with the given GblInstance
132//! Returns the size of the given GblInstance's public data segment
134//! Returns the size of the given GblInstance's private data segment
136//! Returns the instance's combined DEFAULT size (not extended allocation size)
138//! @}
139
140/*! \name Classes
141 * \brief Methods for managing classes
142 * \relatesalso GblInstance
143 * @{
144 */
145//! Returns the GblClass associated with the given GblInstance
147//! Swaps out the class associated with the instance, without taking ownership of it
149//! Takes ownership of the class associated with the instance, deallocating it with the instance
151//! Relinquishes ownership of the class assosciated with the instance, but maintaining their association
153//! @}
154
156
157//! \cond
158#define GblInstance_create(...)
159 GblInstance_createDefault_(__VA_ARGS__)
160#define GblInstance_createDefault_(...)
161 GblInstance_createDefault__(__VA_ARGS__, 0, GBL_NULL)
162#define GblInstance_createDefault__(type, size, klass, ...)
163 (GblInstance_create)(type, size, klass)
164
165#define GblInstance_construct(...)
166 GblInstance_constructDefault_(__VA_ARGS__)
167#define GblInstance_constructDefault_(...)
168 GblInstance_constructDefault__(__VA_ARGS__, GBL_NULL)
169#define GblInstance_constructDefault__(self, type, klass, ...)
170 (GblInstance_construct)(self, type, klass)
171
172#define GBL_TYPEOF_(self) (GblInstance_typeOf(GBL_INSTANCE(self)))
173#define GBL_PRIVATE_(cType, self) ((GBL_INSTANCE_PRIVATE_STRUCT(cType)*) GblInstance_private(GBL_INSTANCE(self), GBL_TYPEID(cType)))
174#define GBL_PUBLIC_(cType, selfPriv) ((cType*)GblInstance_public((const void*)selfPriv, GBL_TYPEID(cType)))
175#define GBL_TYPECHECK_(cType, self) (GblInstance_check(GBL_INSTANCE(self), GBL_TYPEID(cType)))
176#ifndef NDEBUG
177# define GBL_CAST_(cType, self) ((cType*)GblInstance_cast((GblInstance*)self, GBL_TYPEID(cType)))
178#else
179# define GBL_CAST_(cType, self) ((cType*)self)
180#endif
181#define GBL_AS_(cType, self) ((cType*)GblInstance_as((GblInstance*)self, GBL_TYPEID(cType)))
182#define GBL_CLASSOF_(cType, self) ((GBL_CLASS_STRUCT(cType)*)GblClass_cast(GblInstance_class((GblInstance*)self), GBL_TYPEID(cType)))
183#define GBL_CLASSOF_AS_(cType, self) ((GBL_CLASSOF(cType)*)GblClass_as(GblInstance_class((GblInstance*)self), GBL_TYPEID(cType)))
184
185#define GBL_VCALL_(cType, method, ...)
187 GBL_CLASS_STRUCT(cType)* pClass = GBL_CLASSOF(cType, GBL_TUPLE_FIRST (__VA_ARGS__, 1));
188 GBL_CTX_VERIFY(pClass, GBL_RESULT_ERROR_INVALID_VIRTUAL_CALL);
189 GBL_CTX_VERIFY(pClass->method, GBL_RESULT_ERROR_INVALID_VIRTUAL_CALL);
190 GBL_CTX_CALL(pClass->method(__VA_ARGS__));
192
193#define GBL_VCALL_DEFAULT_(cType, method, ...)
195 GBL_CLASS_STRUCT(cType)* pClass =
196 (GBL_CLASS_STRUCT(cType)*)GblClass_weakRefDefault(GBL_TYPEID(cType));
197 GBL_CTX_VERIFY(pClass, GBL_RESULT_ERROR_INVALID_VIRTUAL_CALL);
198 GBL_CTX_VERIFY(pClass->method, GBL_RESULT_ERROR_INVALID_VIRTUAL_CALL);
199 GBL_CTX_CALL(pClass->method(__VA_ARGS__));
201//! \endcond
202
203/*! \fn GblRefCount GblInstance_destroy(GblInstance* pSelf)
204* Finalizes then deletes an instance that was created on the heap, either unreferencing.
205* its class if using the default or destroying it if using a sunk floating class.
206* \param pSelf heap-callocated instance
207* \returns remaining number of active instances of the associated type
208* \sa GblInstance_destruct
209*/
210
211/*! \fn GblRefCount GblInstance_destruct(GblInstance* pSelf)
212* Equivalent to GblInstance_destroy(), except that the allocation is not deallocated.
213* This is equivalent to a placement delete operation in C++.
214* \param pSelf existing allocation
215* \returns remaining number of active instances of the associated type
216* \sa GblInstance_destroy
217*/
218
219/*! \fn GBL_RESULT GblInstance_swizzleClass(GblInstance* pSelf, GblClass* pClass)
220* Releases ownership of the instance's current class, replacing it with a type-compatible class.
221* This is analogous to Objective-C's "is-a swizzling."
222* \note The instance does not automatically assume ownersip of the new class.
223* \relatesalso GblInstance
224* \param pSelf instance
225* \param pClass replacement GblClass of compatible type
226* \returns result code
227* \sa GblInstance_sinkClass
228*/
229
230/*! \fn GBL_RESULT GblInstance_sinkClass(GblInstance* pSelf)
231* Claims ownership of the previously floating class contained by the instance, binding
232* the lifetime of the two, so that the class will be finalized when the instance is finalized.
233* \attention ONLY a GblClass that has been created or constructed as a floating class can be
234* sunk. Attempting to sink the default class for a given type will result in an erro!
235* \relatesalso GblInstance
236* \param pSelf instance
237* \returns result code
238* \sa GblInstance_floatClass, GblClass_isFloating(), GblClass_createFloating(), GblClass_constructFloating()
239*/
240
241/*! \fn GBL_RESULT GblInstance_floatClass(GblInstance* pSelf)
242* Releases ownership of the owned class contained by the instance. The class will no
243* longer be finalized along with the given instance.
244* \relatesalso GblInstance
245* \param pSelf instance
246* \returns result code
247* \sa GblInstance_sinkClass
248*/
249
250/*! \fn GblBool GblInstance_check(const GblInstance* pSelf, GblType toType)
251* Returns true if the given instance can be casted to an instance of the given type.
252* \relatesalso GblInstance
253* \param pSelf source instance
254* \param toType casted result type
255* \returns true if cast is valid
256* \sa GblInstance_as
257*/
258
259/*! \fn GblInstance* GblInstance_cast(GblInstance* pSelf, GblType toType)
260* Casts the given instance to the given type, erroring-out upon failure.
261* \relatesalso GblInstance
262* \param pSelf source instance
263* \param toType casted result type
264* \returns pointer to casted instance or NULL upon failure
265* \sa GblInstance_check, GblInstance_as
266*/
267
268/*! \fn GblInstance* GblInstance_as(GblInstance* pSelf, GblType toType)
269* Equivalent to GblInstance_cast(), except gracefully returning NULL with no errors upon failure.
270* This is analogous to a dynamic_cast<> operation in C++.
271* \relatesalso GblInstance
272* \param pSelf source instance
273* \param toType casted result type
274* \returns pointer to casted instance or NULL upon failure
275* \sa GblInstance_cast
276*/
277
278
279/*! \fn void* GblInstance_private(const GblInstance* pSelf, GblType base)
280* Returns the private instance data associated with the base or actual type of the given
281* public instance structure.
282* \relatesalso GblInstance
283* \param pSelf source instance
284* \param base type ID to fetch private data for
285* \returns pointer to private data upon success, NULL upon failure
286*/
287
288
289/*! \fn GblInstance* GblInstance_public(const void* pPrivate, GblType base);
290* Returns the public GblInstance structure for the given private data and its associated base
291* or actual type.
292* \relatesalso GblInstance
293* \param pPrivate private data pointer
294* \param base type corresponding to the private data
295* \returns pointer to instance upon success, NULL upon failure
296*/
297
298/*! \fn GblType GblInstance_typeOf(const GblInstance* pSelf)
299* Returns the type ID associated with the given instance.
300* \relatesalso GblInstance
301* \param pSelf instance pointer
302* \returns type ID or NULL if the instance is NULL
303*/
304
305/*! \fn size_t GblInstance_size(const GblInstance* pSelf)
306* Returns the size of the public instance struct for the given instance.
307* \relatesalso GblInstance
308* \param pSelf instance pointer
309* \returns size or 0 if instance is NULL
310* \sa GblInstance_privateSize, GblInstance_totalSize
311*/
312
313/*! \fn size_t GblInstance_privateSize(const GblInstance* pSelf)
314* Returns the size of the private instance struct for the given instance.
315* \relatesalso GblInstance
316* \param pSelf instance pointer
317* \returns size or 0 if instance is NULL
318*/
319
320/*! \fn size_t GblInstance_totalSize(const GblInstance* pSelf)
321* Returns the total size for both public and private instance data for the given instance.
322* \relatesalso GblInstance
323* \param pSelf instance pointer
324* \returns size or 0 if instance is NULL
325*/
326
327/*! \fn GblClcass* GblInstance_class(const GblInstance* pSelf)
328* Returns the public class structure associated with the given instance.
329* \relatesalso GblInstance
330* \param pSelf instance pointer
331* \returns class pointer or NULL if instance is NULL
332*/
333
334#undef GBL_SELF_TYPE
335
336#endif // GIMBAL_INSTANCE_H
#define GBL_BUILTIN_TYPE(prefix)
Returns a type from the macro prefix of a builtin type.
#define GBL_STMT_START
#define GBL_NULL
#define GBL_NOEXCEPT
#define GBL_STMT_END
#define GBL_CTX_CALL(...)
Definition gimbal_ctx.h:535
#define GBL_CTX_VERIFY(...)
Definition gimbal_ctx.h:99
#define GBL_DECLS_BEGIN
#define GBL_TYPEID(instanceStruct)
#define GBL_INSTANCE_PRIVATE_STRUCT(instanceStruct)
#define GBL_CLASS_STRUCT(cType)
#define GBL_EXPORT
GblInstance * GblInstance_create(GblType type, size_t publicSize, GblClass *pClass)
Creates and returns an instance, optionally with an extended size and/or non-default class.
GblRefCount GblInstance_destruct(GblInstance *pSelf)
Destructs but doesn't deallocate an instance. It must have been created with GblInstance_construct().
GblRefCount GblInstance_destroy(GblInstance *pSelf)
Destructs and deallocates an instance. It must have been created with GblInstance_create().
#define GBL_INSTANCE(self)
Casts GblInstance-compatible to GblInstance.
GBL_RESULT GblInstance_construct(GblInstance *pSelf, GblType type, GblClass *pClass)
Constructs an instance, optionally with a non-default class, returning a result code.
#define GBL_TUPLE_FIRST(...)
uint8_t GblBool
Basic boolean type, standardized to sizeof(char)
uint16_t GblRefCount
Type able to hold a reference counter across the codebase.
uintptr_t GblType
Meta Type UUID.
Definition gimbal_type.h:52
Base struct for all instantiable meta types.
GblBool GblInstance_check(const GblInstance *pSelf, GblType toType)
Returns GBL_TRUE if the given instance's type is compatible with toType.
void * GblInstance_private(const GblInstance *pSelf, GblType base)
Returns the private structure associated with the given base type of the instance.
GblClass * pClass
READ-ONLY Pointer to Instance's Class, do not modify directly.
GBL_RESULT GblInstance_swizzleClass(GblInstance *pSelf, GblClass *pClass)
Swaps out the class associated with the instance, without taking ownership of it.
GblType GblInstance_typeOf(const GblInstance *pSelf)
Returns the GblType associated with the given GblInstance.
size_t GblInstance_size(const GblInstance *pSelf)
Returns the size of the given GblInstance's public data segment.
GblClass * GblInstance_class(const GblInstance *pSelf)
Returns the GblClass associated with the given GblInstance.
GblInstance * GblInstance_public(const void *pPriv, GblType base)
Casts back to the instance type from a base type's private data segment structure.
GblInstance * GblInstance_as(GblInstance *pSelf, GblType toType)
Attempts to cast the given instance to toType, gracefully returning NULL upon failure.
GBL_RESULT GblInstance_sinkClass(GblInstance *pSelf)
Takes ownership of the class associated with the instance, deallocating it with the instance.
GBL_RESULT GblInstance_floatClass(GblInstance *pSelf)
Relinquishes ownership of the class assosciated with the instance, but maintaining their association.
GblInstance * GblInstance_cast(GblInstance *pSelf, GblType toType)
Attempts to cast the given instance to toType, raising an error and returning NULL upon failure.
size_t GblInstance_privateSize(const GblInstance *pSelf)
Returns the size of the given GblInstance's private data segment.
size_t GblInstance_totalSize(const GblInstance *pSelf)
Returns the instance's combined DEFAULT size (not extended allocation size)