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 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//! Wraps GblInstance_cast() for the given type, implementing a convenient cast operator
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#define GBL_CAST_(cType, self) ((cType*)GblInstance_cast((GblInstance*)self,GBL_TYPEID(cType)))
177#define GBL_AS_(cType, self) ((cType*)GblInstance_as((GblInstance*)self, GBL_TYPEID(cType)))
178#define GBL_CLASSOF_(cType, self) ((GBL_CLASS_STRUCT(cType)*)GblClass_cast(GblInstance_class((GblInstance*)self), GBL_TYPEID(cType)))
179#define GBL_CLASSOF_AS_(cType, self) ((GBL_CLASSOF(cType)*)GblClass_as(GblInstance_class((GblInstance*)self), GBL_TYPEID(cType)))
180
181#define GBL_VCALL_(cType, method, ...)
183 GBL_CLASS_STRUCT(cType)* pClass = GBL_CLASSOF(cType, GBL_TUPLE_FIRST (__VA_ARGS__, 1));
184 GBL_CTX_VERIFY(pClass, GBL_RESULT_ERROR_INVALID_VIRTUAL_CALL);
185 GBL_CTX_VERIFY(pClass->method, GBL_RESULT_ERROR_INVALID_VIRTUAL_CALL);
186 GBL_CTX_CALL(pClass->method(__VA_ARGS__));
188
189#define GBL_VCALL_DEFAULT_(cType, method, ...)
191 GBL_CLASS_STRUCT(cType)* pClass =
192 (GBL_CLASS_STRUCT(cType)*)GblClass_weakRefDefault(GBL_TYPEID(cType));
193 GBL_CTX_VERIFY(pClass, GBL_RESULT_ERROR_INVALID_VIRTUAL_CALL);
194 GBL_CTX_VERIFY(pClass->method, GBL_RESULT_ERROR_INVALID_VIRTUAL_CALL);
195 GBL_CTX_CALL(pClass->method(__VA_ARGS__));
197//! \endcond
198
199/*! \fn GblRefCount GblInstance_destroy(GblInstance* pSelf)
200* Finalizes then deletes an instance that was created on the heap, either unreferencing.
201* its class if using the default or destroying it if using a sunk floating class.
202* \param pSelf heap-callocated instance
203* \returns remaining number of active instances of the associated type
204* \sa GblInstance_destruct
205*/
206
207/*! \fn GblRefCount GblInstance_destruct(GblInstance* pSelf)
208* Equivalent to GblInstance_destroy(), except that the allocation is not deallocated.
209* This is equivalent to a placement delete operation in C++.
210* \param pSelf existing allocation
211* \returns remaining number of active instances of the associated type
212* \sa GblInstance_destroy
213*/
214
215/*! \fn GBL_RESULT GblInstance_swizzleClass(GblInstance* pSelf, GblClass* pClass)
216* Releases ownership of the instance's current class, replacing it with a type-compatible class.
217* This is analogous to Objective-C's "is-a swizzling."
218* \note The instance does not automatically assume ownersip of the new class.
219* \relatesalso GblInstance
220* \param pSelf instance
221* \param pClass replacement GblClass of compatible type
222* \returns result code
223* \sa GblInstance_sinkClass
224*/
225
226/*! \fn GBL_RESULT GblInstance_sinkClass(GblInstance* pSelf)
227* Claims ownership of the previously floating class contained by the instance, binding
228* the lifetime of the two, so that the class will be finalized when the instance is finalized.
229* \attention ONLY a GblClass that has been created or constructed as a floating class can be
230* sunk. Attempting to sink the default class for a given type will result in an erro!
231* \relatesalso GblInstance
232* \param pSelf instance
233* \returns result code
234* \sa GblInstance_floatClass, GblClass_isFloating(), GblClass_createFloating(), GblClass_constructFloating()
235*/
236
237/*! \fn GBL_RESULT GblInstance_floatClass(GblInstance* pSelf)
238* Releases ownership of the owned class contained by the instance. The class will no
239* longer be finalized along with the given instance.
240* \relatesalso GblInstance
241* \param pSelf instance
242* \returns result code
243* \sa GblInstance_sinkClass
244*/
245
246/*! \fn GblBool GblInstance_check(const GblInstance* pSelf, GblType toType)
247* Returns true if the given instance can be casted to an instance of the given type.
248* \relatesalso GblInstance
249* \param pSelf source instance
250* \param toType casted result type
251* \returns true if cast is valid
252* \sa GblInstance_as
253*/
254
255/*! \fn GblInstance* GblInstance_cast(GblInstance* pSelf, GblType toType)
256* Casts the given instance to the given type, erroring-out upon failure.
257* \relatesalso GblInstance
258* \param pSelf source instance
259* \param toType casted result type
260* \returns pointer to casted instance or NULL upon failure
261* \sa GblInstance_check, GblInstance_as
262*/
263
264/*! \fn GblInstance* GblInstance_as(GblInstance* pSelf, GblType toType)
265* Equivalent to GblInstance_cast(), except gracefully returning NULL with no errors upon failure.
266* This is analogous to a dynamic_cast<> operation in C++.
267* \relatesalso GblInstance
268* \param pSelf source instance
269* \param toType casted result type
270* \returns pointer to casted instance or NULL upon failure
271* \sa GblInstance_cast
272*/
273
274
275/*! \fn void* GblInstance_private(const GblInstance* pSelf, GblType base)
276* Returns the private instance data associated with the base or actual type of the given
277* public instance structure.
278* \relatesalso GblInstance
279* \param pSelf source instance
280* \param base type ID to fetch private data for
281* \returns pointer to private data upon success, NULL upon failure
282*/
283
284
285/*! \fn GblInstance* GblInstance_public(const void* pPrivate, GblType base);
286* Returns the public GblInstance structure for the given private data and its associated base
287* or actual type.
288* \relatesalso GblInstance
289* \param pPrivate private data pointer
290* \param base type corresponding to the private data
291* \returns pointer to instance upon success, NULL upon failure
292*/
293
294/*! \fn GblType GblInstance_typeOf(const GblInstance* pSelf)
295* Returns the type ID associated with the given instance.
296* \relatesalso GblInstance
297* \param pSelf instance pointer
298* \returns type ID or NULL if the instance is NULL
299*/
300
301/*! \fn size_t GblInstance_size(const GblInstance* pSelf)
302* Returns the size of the public instance struct for the given instance.
303* \relatesalso GblInstance
304* \param pSelf instance pointer
305* \returns size or 0 if instance is NULL
306* \sa GblInstance_privateSize, GblInstance_totalSize
307*/
308
309/*! \fn size_t GblInstance_privateSize(const GblInstance* pSelf)
310* Returns the size of the private instance struct for the given instance.
311* \relatesalso GblInstance
312* \param pSelf instance pointer
313* \returns size or 0 if instance is NULL
314*/
315
316/*! \fn size_t GblInstance_totalSize(const GblInstance* pSelf)
317* Returns the total size for both public and private instance data for the given instance.
318* \relatesalso GblInstance
319* \param pSelf instance pointer
320* \returns size or 0 if instance is NULL
321*/
322
323/*! \fn GblClcass* GblInstance_class(const GblInstance* pSelf)
324* Returns the public class structure associated with the given instance.
325* \relatesalso GblInstance
326* \param pSelf instance pointer
327* \returns class pointer or NULL if instance is NULL
328*/
329
330#undef GBL_SELF_TYPE
331
332#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:533
#define GBL_CTX_VERIFY(...)
Definition gimbal_ctx.h:97
#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_CLASSOF(cType, self)
#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:51
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.
GblClass * GblInstance_class(const GblInstance *pSelf)
Returns the GblClass associated with the given GblInstance.
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.
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)