libGimbal 0.1.0
C17-Based Extended Standard Library and Cross-Language Runtime Framework
Loading...
Searching...
No Matches
gimbal_class.h
Go to the documentation of this file.
1/*! \file
2 * \brief GblClass virtual-table structure and APIE
3 * \ingroup meta
4 *
5 * This file contains the GblClass structure,
6 * which is the inherited base type and first
7 * data member of all derievd class structures.
8 *
9 * While GblClass itself is empty other than its
10 * basic type info, a derived class typically
11 * contains data which is shared by all instances
12 * of a type, for deduplication and efficiency.
13 *
14 * This data is typically in the form of:
15 * - Overridable virtual methods (in the form of function pointers)
16 * - Static class data
17 *
18 * \sa gimbal_instance.h, gimbal_type.h
19 *
20 * \author 2023 Falco Girgis
21 * \copyright MIT License
22 */
23#ifndef GIMBAL_CLASS_H
24#define GIMBAL_CLASS_H
25
26#include "../types/gimbal_type.h"
27
28/*! \name Class Operators
29 * \brief Builtin operations for class structures
30 * \relatesalso GblClass
31 * @{
32 */
33//! Function-style cast to GblClass*: will always pass, here for consistence with other operators
34#define GBL_CLASS(klass) ((GblClass*)klass)
35//! Wraps GblClass_typeOf(), returning the type associated with the given class
36#define GBL_CLASS_TYPEOF(klass) GBL_CLASS_TYPEOF_(klass)
37//! Wraps GblClass_private(), returning the private structure on the class associated with the given type
38#define GBL_CLASS_PRIVATE(cType, klass) GBL_CLASS_PRIVATE_(cType, klass)
39//! Wraps GblClass_public(), returning the public class structure from the given type's private structure
40#define GBL_CLASS_PUBLIC(cType, priv) GBL_CLASS_PUBLIC_(cType, privKlass)
41//! Returns GBL_TRUE if the given class is type-compatible with and can be safely casted to the given type
42#define GBL_CLASS_TYPECHECK(cType, klass) GBL_CLASS_TYPECHECK_(type, klass)
43//! Wraps GblClass_cast(), casting the given class to another type, returning NULL and raising an error upon failure
44#define GBL_CLASS_CAST(cType, klass) GBL_CLASS_CAST_(cType, klass)
45//! Wraps GblClass_as(), returning the given class as another type or gracefully returning NULL upon failure
46#define GBL_CLASS_AS(cType, klass) GBL_CLASS_AS_(cType, klass)
47//! @}
48
49/*! \name Static Class Type UUID and cast operators
50 * \brief UUID and cast operators for builtin static root class type
51 * @{
52 */
53#define GBL_STATIC_CLASS_TYPE (GBL_BUILTIN_TYPE(STATIC_CLASS)) //!< GblType UUID for builtin static class primitive
54#define GBL_STATIC_CLASS(klass) GBL_STATIC_CLASS_(klass) //!< Casts a class to a static class
55//! @}
56
57#define GBL_SELF_TYPE GblClass
58
60
61/*! \brief Base struct for all type classes.
62 * \ingroup meta
63 *
64 * A class represents a collection of data that is shared among
65 * all instances of a given type. This data is typically in the
66 * form of function pointers for modeling overridable methods
67 * or regular data for modeling static member variables.
68 *
69 * GblClass is the base structure which is to be inherited by all
70 * class structures within the meta type system. This means placing
71 * it or a type "inheriting" from it as the first member of a
72 * class struct, when using C.
73
74 * \sa GblInstance, GblType
75 */
76typedef struct GblClass {
78 uintptr_t metaClassInfo; //!< PRIVATE: Pointer-sized opaque member
80} GblClass;
81
82/*! \name Default Class Management
83 * \brief Methods for managing references to internally-managed default class instances
84 * @{
85 */
86//! Returns a reference to the default class for \p type, instantiating it if necessary
88//! Releases a reference to the default version of the given class, possibly freeing it
90//! Returns a reference to the default class for \p type or NULL if it hasn't been created
92//! @}
93
94/*! \name Floating Class Mangement
95 * \brief Methods for managing lifetime of dynamic override class instances
96 * @{
97 */
98//! Creates a standalone, unowned, "floating" class for the given type, which can override defaults
100 size_t size/*=DEFAULT*/) GBL_NOEXCEPT;
101//! Constructs a standalone, unowned, overridable, "floating" class for the given type in-place
103//! Destroys the standalone, "floating" class, releasing its memory allocation
105//! Destructs the standalone, "floating" class, without releasing any allocated resources
107//! @}
108
109/*! \name Type Conversions
110 * \brief Methods for type casting and checking
111 * \relatesalso GblClass
112 * @{
113 */
114//! Returns GBL_TRUE if the given class can be casted to \p toType
116//! Casts the given class to a \p toType class, or returns NULL and emits an error if unsuccessful
118//! Casts the given class to a \p toType class, or gracefully returns NULL without erroring
120//! @}
121
122/*! \name Public and Private Data
123 * \brief Methods for accessing public and private segments
124 * \relatesalso GblClass
125 * @{
126 */
127//! Returns the private structure associated with the given \p base type of the class
129//! Casts back to the class structure from a base type's private data segment structure
130GBL_EXPORT GblClass* GblClass_public (const void* pPrivate, GblType base) GBL_NOEXCEPT;
131//! @}
132
133/*! \name Static Type Info
134 * \brief Methods for getting static class information
135 * \relatesalso GblClass
136 * @{
137 */
138//! Returns the GblType UUID associated with the given class
140//! Returns the size of the given class's public class structrue
142//! Returns the combined size of the class's private data segments
144//! Returns the class's combined DEFAULT size (not extended allocation size)
146//! @}
147
148/*! \name Dynamic Flags
149 * \brief Methods for checking dyanmic runtime flags
150 * \relatesalso GblClass
151 */
152//! Returns GBL_TRUE if the class is the internally-managed default for its type
154//! Returns GBL_TRUE if the class differs from the default class for its type
156//! Returns GBL_TRUE if the class is an interfaced type
158//! Returns GBL_TRUE if the class is another class's implementation of an interface
160//! Returns GBL_TRUE if the class is a non-default floating class and is unowned by an instance
162//! Returns GBL_TRUE if the class is a non-default floating class is uowned by an instance
164//! Returns GBL_TRUE if the class was constructed in-place with an existing allocation
166//! @}
167
168/*! \name Related Classes
169 * \brief Methods for fetching associated classes
170 * \relatesalso GblClass
171 */
172//! Returns the default class of the class's parent type or NULL if it's a root class
174//! Returns the default implementation of the given class
176//! @}
177
179
180//! \cond
181#define GblClass_createFloating(...)
182 GblClass_createFloatingDefault_(__VA_ARGS__)
183#define GblClass_createFloatingDefault_(...)
184 GblClass_createFloatingDefault__(__VA_ARGS__, 0)
185#define GblClass_createFloatingDefault__(type, size, ...)
186 (GblClass_createFloating)(type, size)
187
188#define GBL_CLASS_TYPEOF_(klass) (GblClass_typeOf(GBL_CLASS(klass)))
189#define GBL_CLASS_PRIVATE_(cType, klass) ((GBL_CLASS_PRIVATE_STRUCT(cType)*)GblClass_private(GBL_CLASS(klass), GBL_TYPEID(cType)))
190#define GBL_CLASS_PUBLIC_(cType, priv) ((GBL_CLASS_STRUCT(cType)*)GblClass_public(klassPriv, GBL_TYPEID(cType))
191#define GBL_CLASS_TYPECHECK_(cType, klass) (GblClass_check((GblClass*)klass, GBL_TYPEID(cType)))
192#define GBL_CLASS_CAST_(cType, klass) ((GBL_CLASS_STRUCT(cType)*)GblClass_cast((GblClass*)klass, GBL_TYPEID(cType)))
193#define GBL_CLASS_AS_(cType, klass) ((GBL_CLASS_STRUCT(cType)*)GblClass_as((GblClass*)klass, GBL_TYPEID(cType)))
194#define GBL_STATIC_CLASS_(klass) ) (GblClass_cast((GblClass*)klass, GBL_STATIC_CLASS_TYPE))
195//! \endcond
196
197/*! \def GBL_STATIC_CLASS_TYPE
198 * Builtin type ID for a class-only types
199 * \ingroup metaBuiltinTypes
200 */
201
202/*! \fn GBL_CLASS(klass)
203 * \param klass pointer to a GblClass-compatible
204 * \returns klass C-style casted to GblClass*
205 * \relatesalso GblClass
206 * Convenience function-style casting macro.
207 */
208
209/*! \fn GBL_CLASS_TYPEOF(klass)
210 * \param klass pointer to a GblClass-compatible
211 * \returns type associated with the class, or GBL_INVALID_TYPE if NULL
212 * \relatesalso GblClass
213 * \sa GblClass_typeOf()
214 * Convenience wrapper around GblClass_typeOf() which automatically casts.
215 */
216
217/*! \fn GBL_CLASS_SUPER(klass)
218 * \param klass pointer to a GblClass-compatible
219 * \returns parent class of the given class, or GBL_INVALID_TYPE if NULL
220 * \relatesalso GblClass
221 * \sa GblClass_super()
222 * Convenience wrapper around GblClass_super() which automatically casts.
223 */
224
225/*! \fn GBL_CLASS_DEFAULT(klass)
226 * \param klass pointer to a GblClass-compatible
227 * \returns default class of the given class, or GBL_INVALID_TYPE if NULL
228 * \relatesalso GblClass
229 * \sa GblClass_default()
230 * Convenience wrapper around GblClass_default() which automatically casts.
231 */
232
233/*! \fn GBL_CLASS_PRIVATE(klass, type)
234 * \param klass pointer to a GblClass-compatible
235 * \param type supertype owning the private data
236 * \returns private data owned by the given superType or NULL if type there is
237 * none or type is not a parent, or type is invalid
238 * \relatesalso GblClass
239 * \sa GblClass_private()
240 * Convenience wrapper around GblClass_private() which automatically casts.
241 */
242
243/*! \fn GBL_CLASS_PUBLIC(klassPrivate, type)
244 * \param klassPrivate void* pointer to private class data
245 * \param type supertype owning the private data
246 * \returns public GblClass* pointer or NULL if none could be found
247 * \relatesalso GblClass
248 * \sa GblClass_public()
249 * Convenience wrapper around GblClass_public().
250 */
251
252/*! \fn GBL_CLASS_TYPECHECK(klass, toType)
253 * \param klass pointer to a GblClass-compatible
254 * \param toType the desired destination type
255 * \returns true if the given class can be casted to a calss of toType
256 * \relatesalso GblClass
257 *
258 * \sa GblClass_check(), GBL_CLASS_TYPECHECK_REFIX()
259 * Convenience wrapper around GblClass_check() which automatically casts.
260 */
261/*! \fn GBL_CLASS_TYPECHECK_PREFIX(klass, typePrefix)
262 * \param klass pointer to a GblClass-compatible
263 * \param typePrefix prefix of the given type (type name macro identifier minus _TYPE postfix)
264 * \returns true if the given class can be casted to a calss of toType
265 * \relatesalso GblClass
266 * \sa GBL_CLASS_TYPECHECK_PREFIX(), GblClass_check()
267 *
268 * Convenience wrapper around GBL_CLASS_TYPECHECK() which automatically appends _TYPE suffix.
269 * \note
270 * This macro is typically used for definining convenience function-style casting utilities
271 * for derived types.
272 */
273
274/*! \fn GBL_CLASS_CAST(klass, toType, cType)
275 * \param klass pointer to a GblClass-compatible
276 * \param toType desination type for resulting class
277 * \param cType C structure for the given type's class
278 * \returns klass casted to cType if the cast was successful, otherwise NULL
279 * \relatesalso GblClass
280 * \sa GBL_CLASS_CAST_PREFIX(), GblClass_cast(
281 *
282 * Convenience wrapper around GblClass_cast() which automatically performs casting.
283 */
284
285/*! \fn GBL_CLASS_CAST_PREFIX(klass, typePrefix)
286 * \param klass pointer to a GblClass-compatible
287 * \param typePrefix prefix of destination type (NAME macro minus the _TYPE suffix)
288 * \note This macro also requires a macro be defined that is the given typePrefix
289 * appended with _CLASS_STRUCT, which it uses as the destination class type for casting.
290 * \returns klass casted to the formed type identifier upon success, NULL otherwise
291 * \relatesalso GblClass
292 * \sa GBL_CLASS_CAST(), GblClass_cast()
293 *
294 * Convenience wrapper around GBL_CLASS_CAST() which automatically deduces class structure
295 * and type identifier.
296 * \note
297 * This macro is typically used for definining convenience function-style casting utilities
298 * for derived types.
299 */
300
301/*! \fn GBL_CLASS_TRY(klass, toType, cType)
302 * \param klass pointer to a GblClass-compatible
303 * \param toType desination type for resulting class
304 * \param cType C structure for the given type's class
305 * \returns klass casted to cType if the cast was successful, otherwise NULL
306 * \relatesalso GblClass
307 * \sa GBL_CLASS_TRY_PREFIX(), GblClass_as(
308 *
309 * Convenience wrapper around GblClass_as() which automatically performs casting.
310 */
311
312/*! \fn GBL_CLASS_TRY_PREFIX(klass, typePrefix)
313 * \param klass pointer to a GblClass-compatible
314 * \param typePrefix prefix of destination type (NAME macro minus the _TYPE suffix)
315 * \note This macro also requires a macro be defined that is the given typePrefix
316 * appended with _CLASS_STRUCT, which it uses as the destination class type for casting.
317 * \returns klass casted to the formed type identifier upon success, NULL otherwise
318 * \relatesalso GblClass
319 * \sa GBL_CLASS_TRY(), GblClass_as()
320 *
321 * Convenience wrapper around GBL_CLASS_TRY() which automatically deduces class structure
322 * and type identifier.
323 * \note
324 * This macro is typically used for defining convenience function-style casting utilities
325 * for derived types.
326 *
327 */
328
329/*!
330 * \fn GblClass* GblClass_refDefault(GblType type)
331 * Returns a new reference to the existing internally managed default class for the given type or
332 * lazily allocates a new one with an initial refCount of 1.
333 * \note
334 * When you're done using the reference, it must be released using GblClass_unrefDefault() in order to avoid
335 * memory leaks!
336 * \relatesalso GblClass
337 * \param type classed type ID
338 * \returns reference to internally managed class
339 * \sa GblClass_weakRefDefault, GblClass_unrefDefault
340 */
341
342/*!
343 * \fn GblRefCount GblClass_unrefDefault(GblClass* pSelf)
344 * Release a reference to the default class associated with pSelf,
345 * destroying the class if it's reference count hits 0.
346 * \note
347 * This should not be called to release a previously floating
348 * class, as it is not reference-counted. See GblClass_destructFloating
349 * and GblClass_destroyFloating
350 * \note
351 * It is safe to call this function with a NULL class, as
352 * libGimbal tries to be consistent with free() semantics.
353 * \note Types may be flagged as "persisting", despite
354 * their reference counts hitting zero. This is used for
355 * builtin types. See GBL_TYPE_FLAG_CLASS_PINNED.
356 * \param pSelf reference to class
357 * \returns remaining reference count
358 * \relatesalso GblClass
359 * \sa GblClass_refDefault
360 */
361
362/*!
363 * \fn GblClass* GblClass_weakRefDefault(GblType type)
364 * Returns a pointer to the default class for the given type without incrementing refCount.
365 * \note
366 * If there has not yet been a class created, or one is no longer active, this call will
367 * raise an error followed by returning NULL. Since no references are being created, only
368 * use this within contexts where you know a class reference already exists.
369 * \relatesalso GblClass
370 * \param type type of desired class
371 * \returns pointer to a GblClss or NULL upon failure
372 * \sa GblClass_refDefault
373 */
374
375/*!
376 * \fn GblClass* GblClass_createFloating(GblType type)
377 * Creates a new, unowned class for the given type on the heap.
378 * \relatesalso GblClass
379 * \param type classed type ID
380 * \returns dynamically allocated unowned class
381 * \sa GblClass_constructFloating, GblClass_destroyFloating, floatingClasses
382 */
383
384/*!
385 * \fn GBL_RESULT GblClass_destroyFloating(GblClass* pSelf)
386 * \relatesalso GblClass
387* Destructs then frees the given heap-allocated, floating
388* class.
389* \note
390* It is safe to call this function with a NULL class, as
391* libGimbal tries to be consistent with free() semantics.
392* \attention
393* Do not call this with a stack-constructed in-place floating class
394* constructed with GblClass_constructFloating()
395* Luckily libGyro will catch it for you and return an error.
396* \param pSelf GblClass pointer
397* \returns destructor result code or GBL_RESULT_ERROR_INVALID_OPERATION
398* \sa GblClass_destructFloating, GblClass_createFloating
399 */
400
401/*!
402 * \fn GBL_RESULT GblClass_constructFloating(GblClass* pSelf, GblType type)
403 * Placement constructs an unowned class for the given type using an existing
404 * user-provided allocation.
405 * \relatesalso GblClass
406 * \param pSelf pointer to instance allocation
407 * \param type type of instance to construct
408 * \returns result code
409 * \sa GblClass_createFloating, GblClass_destructFloating
410 */
411
412/*!
413 * \fn GBL_RESULT GblClass_destructFloating(GblClass* pSelf)
414 * Calls placement delete on the given floating class which was
415 * constructed in-place, using GblClass_constructFloating.
416 * It is safe to call this function with a NULL class, as
417 * libGimbal tries to be consistent with free() semantics.
418 * \attention
419 * Do not call this with a heap-allocated floating class,
420 * created with GblClass_createFloating().
421 * Luckily libGyro will catch it for you and return an error.
422 * \param pSelf class pointer
423 * \return destructor result code or GBL_RESULT_ERROR_INVALID_OPERATION
424 * \relatesalso GblClass
425 * \sa GblClass_destroyFloating, GblClass_constructFloating
426*/
427
428/*!
429 * \fn GblBool GblClass_check(const GblClass* pSelf, GblType toType)
430 * Returns true if the given class can be casted to the given class type.
431 * \note Also returns true if pClass is NULL AND toType is GBL_TYPE_INVALID,
432 * since that would semantically be a valid cast to the invalid type.
433 * \param pSelf class pointer
434 * \param toType desired destination type
435 * \returns true upon success
436 * \relatesalso GblClass
437 * \sa GblClass_cast, GblClass_as
438*/
439
440/*!
441 * \fn GblClass* GblClass_cast(GblClass* pSelf, GblType toType)
442 * Casts the given class to a class of the given type, raising errors and
443 * returning NULL upon failure.
444 * \param pSelf source class pointer
445 * \param toType desired destination type
446 * \returns pointer to GblClass upon success, NULL upon failure
447 * \relatesalso GblClass
448 * \sa GBL_CLASS_CAST(), GblClass_check, GblClass_as
449*/
450
451/*!
452 * \fn GblClass* GblClass_as(GblClass* pSelf, GblType toType)
453 * Equivalent to GblClass_cast(), except gracefully returning NULL
454 * with no errors getting raised if the given class could not be
455 * casted to toType.
456 * \note This is equivalent to a C++ dynamic cast.
457 * \param pSelf source class
458 * \param toType desired destination type
459 * \returns pointer to GblClass or NULL upon failure
460 * \relatesalso GblClass
461 * \sa GBL_CLASS_TRY(), GblClass_cast(), GblClass_check()
462*/
463
464/*!
465 * \fn void* GblClass_private(const GblClass* pSelf, GblType type)
466 * Retrieves the private data pointer associated with the given base type or
467 * NULL if there isn't one.
468 * \param pSelf class pointer
469 * \param type type owning the private data
470 * \returns pointer to private data or NULL upon failure
471 * \relatesalso GblClass
472 * \sa GblClass_public()
473*/
474
475/*!
476 * \fn GblClass* GblClass_public(const void* pPrivate, GblType base)
477 * Retrieves the public GblClass corresponding to the given private data
478 * pointer for the given type or base type or NULL upon failure.
479 * \param pPrivate pointer to private data
480 * \param base type or base type that registered the private data
481 * \returns pointer to public GblClass* or NULL upon failure
482 * \relatesalso GblClass
483*/
484
485/*!
486 * \fn GblType GblClass_typeOf(const GblClass* pSelf)
487 * Returns the type associated with the given GblClass pointer,
488 * or GBL_INVALID_TYPE if the pointer is NULL.
489 * \param pSelf pointer to a GblClass
490 * \returns type ID of the class or GBL_INVALID_TYPE if NULL
491 * \relatesalso GblClass
492*/
493
494/*!
495 * \fn size_t GblClass_size(const GblClass* pSelf)
496 * Returns the size of the public class structure for the
497 * given GblClass pointer or 0 if NULL
498 * \param pSelf pointer to a GblClass
499 * \returns size or 0 if class is NULL
500 * \relatesalso GblClass
501 * \sa GblClass_privateSize(), GblClass_totalSize()
502*/
503
504/*!
505 * \fn size_t GblClass_privateSize(const GblClass* pSelf)
506 * Returns the TOTAL size of the private data structure
507 * associated with the type of the given class and all
508 * of its base types.
509 * \param pSelf pointer to a GblClass
510 * \returns size or 0 if class is NULL
511 * \relatesalso GblClass
512 * \sa GblClass_size(), GblClass_totalSize()
513*/
514
515/*!
516 * \fn size_t GblClass_totalSize(const GblClass* pSelf)
517 * Returns the total combined size of the public and private
518 * class structures for the class type and all of its inherited
519 * bases.
520 * \param pSelf pointer to a GblClass
521 * \returns size or 0 if class is NULL
522 * \relatesalso GblClass
523 * \sa GblClass_size(), GblClass_privateSize()
524*/
525
526/*!
527 * \fn GblClass* GblClass_super(const GblClass* pSelf)
528 * Returns the default class for the parent type of
529 * the given class type. This is typically used in the implementation of
530 * overridden methods to allow you to call into the base class's
531 * implementations.
532 * \note The returned class is a weak reference and does not impact
533 * the reference count for the parent's default class.
534 * \param pSelf pointer to a GblClass
535 * \returns pointer to parent GblClass or NULL if the given class is
536 * NULL or has no parent
537 * \relatesalso GblClass
538 * \sa GblClass_default()
539*/
540
541/*!
542 * \fn GblClass* GblClass_default(const GblClass* pSelf)
543 * Returns a weak reference to the internally-managed default class
544 * corresonding to the given class's type. This will only be different
545 * than the given argument if the class has been created either as a
546 * floating class, or if it is a pointer to the implementation of an
547 * interface. In the case of an interface, this is how you access the
548 * interface's default implementation as well.
549 * \note The returned class is a weak reference and does not impact
550 * the reference count for the default class.
551 * \param pSelf pointer to a GblClass
552 * \returns pointer to default GblClass or NULL if the given class is
553 * NULL
554 * \relatesalso GblClass
555 * \sa GblClass_isDefault()
556*/
557
558/*!
559 * \fn GblBool GblClass_isDefault(const GblClass* pSelf)
560 * Returns true if the given GblClass pointer points to the
561 * internally-managed default class for its type or false if it
562 * not the default.
563 * \note Note: The class will not be the default if it was created
564 * as separate floating class, or if it's the implementation of a
565 * GblInterface on another GblClass.
566 * \param pSelf pointer to a GblClass
567 * \returns true if default, false if not or if pSelf is NULL
568 * \relatesalso GblClass
569 * \sa GblClass_default()
570*/
571
572/*!
573 * \fn GblBool GblClass_isOverridden(const GblClass* pSelf)
574 * Inspects the internal memory of the given GblClass pointer
575 * and compares it to that of the internally managed default
576 * class, returning true if they differ or false if they are the
577 * same.
578 * \note Note: Just because a class is a floating class or an
579 * interface implementation doesn't necessarily mean it has
580 * actually been overridden to have non-default values!
581 * \param pSelf pointer to a GblClass
582 * \returns true if overridden, false if not or if pSelf is NULL
583 * \relatesalso GblClass
584*/
585
586/*!
587 * \fn GblBool GblClass_isFloating(const GblClass* pSelf)
588 * Returns true if the given GblClass is an unowned, floating
589 * class which must be manually managed, or false if it is
590 * either the default class or has been sunk by a GblInstance.
591 * \param pSelf pointer to a GblClass
592 * \returns true if floating, false if not or if pSelf is NULL
593 * \sa GblClass_createFloating(), GblClass_constructFloating(),
594 * GblInstance_sinkClass(),
595 * GblInstance_floatClass()
596 * \relatesalso GblClass
597*/
598
599/*!
600 * \fn GblBool GblClass_isFloating(const GblClass* pSelf)
601 * Returns true if the given GblClass is an unowned, floating
602 * class which must be manually managed, or false if it is
603 * either the default class or has been sunk by a GblInstance.
604 * \param pSelf pointer to a GblClass
605 * \returns true if floating, false if not or if pSelf is NULL
606 * \sa GblClass_createFloating(), GblClass_constructFloating(),
607 * GblInstance_sinkClass(),
608 * GblInstance_floatClass()
609 * \relatesalso GblClass
610*/
611
612/*!
613 * \fn GblBool GblClass_isInterface(const GblClass* pSelf)
614 * Returns true if the given GblClass is actually of or
615 * derived from GBL_INTERFACE_TYPE, false otherwise.
616 * \param pSelf pointer to a GblClass
617 * \returns true if pSelf is a GblInterface, false if not or if pSelf is NULL
618 * \sa GblClass_isInterfaceImpl
619 * \relatesalso GblClass
620*/
621
622/*!
623 * \fn GblBool GblClass_isInterfaceImpl(const GblClass* pSelf)
624 * Returns true if the given GblClass an interface *implementation*
625 * wihch has been mapped onto another GblClass, false otherwise.
626 * \param pSelf pointer to a GblClass
627 * \returns true if pSelf is a mapped GblInterface, false if not or if pSelf is NULL
628 * \sa GblClass_isInterface
629 * \relatesalso GblClass
630*/
631
632/*!
633 * \fn GblBool GblClass_isOwned(const GblClass* pSelf)
634 * Returns true if the given GblClass is a previously floating, nondefault
635 * class which has been sunk and is now owned by a GblInstance.
636 * \note This means that its lifetime has been bound to that of the instance,
637 * and it will be destructed (and deleted if necessary) with the instance.
638 * \param pSelf pointer to a GblClass
639 * \returns true if pSelf is a owned by a GblInstance, false if not or if pSelf is NULL
640 * \sa GblInstance_sinkClass(), GblInstance_floatClass()
641 * \relatesalso GblClass
642*/
643
644/*!
645 * \fn GblBool GblClass_isInPlace(const GblClass* pSelf)
646 * Returns true if the given GblClass was constructed from an existing,
647 * user-managed allocation, using GblClass_constructFloating().
648 * \note If a GblClass is both floating and in-place, it means that you are
649 * responsible for uninitializing it manually via GblClass_destructFloating()
650 * \param pSelf pointer to a GblClass
651 * \returns true if pSelf was constructed in-place, false if not or if pSelf is NULL
652 * \sa GblClass_constructFloating(), GblClass_destructFloating()
653 * \relatesalso GblClass
654*/
655
656/*! \page Classes Classes
657 * \brief Overview of classed types
658 * \tableofcontents
659 *
660 * ## GblClass
661 * \copydoc GblClass
662 *
663 * ## Floating Classes
664 *
665 * Typically, when you wish to override virtual methods on a class to provide
666 * custom functionality, you would need to register a new, derived static type
667 * inheriting from the existing type and overriding the desired methods within
668 * the class constructor.
669 *
670 * This is good for when you need to implement lots of custom state and logic or
671 * for when this logic is to be applied to all instances of a class... However,
672 * this can be extremely inconvenient and cumbersome when you simply wish to
673 * quickly override one or two methods on a single instance.
674 *
675 * This is where libGimbal's floating classes come into play. Lets say you
676 * wish to quickly create a new GblObject with a custom event handler:
677 *
678 * \code{.c}
679 * GblObject* pMyObj = GblInstance_create(GBL_OBJECT_TYPE);
680 * GblIEventHandler* pHandler = GBL_EVENT_HANDLER(pMyObj);
681 *
682 * // I want to override this, but don't want to register a new type!
683 * GblIEventHandler_eventNotify(pHandler, NULL);
684 * \endcode
685 * By creating a separate "floating" class, we are able to perform ad-hoc
686 * method overriding for a single instance:
687 * \code{.c}
688 * // We have a brand-new, unowned class just for us!
689 * GblObjectClass* pClass = GBL_OBJECT_CLASS(GblClass_createFloating(GBL_OBJECT_TYPE));
690 *
691 * // override a virtual method on the event handler interface to do our own thing
692 * pClass->iEventHandlerIFace.pFnEventNotify = my_event_notifier_function_;
693 *
694 * // now create an instance *using our floating class* instead of the default class:
695 * GblObject* pObj = GBL_OBJECT(GblInstance_createWithClass(pClass));
696 *
697 * // Tell the class to assume ownership of our "floating" class by "sinking" it.
698 * // If you don't sink the class, it's assumed you are maintaining its lifetime manually,
699 * // which can be useful if you want to share among multiple instances.
700 * GblInstance_sinkClass(GBL_INSTANCE(pObj));
701 *
702 * // now it calls into our method when the interface is used!
703 * GblIEventHandler_eventNotify(GBL_IEVENT_HANDLER(pObj), NULL);
704 *
705 * // Destroys the sunk class with it
706 * GblInstance_destroy(GBL_INSTANCE(pObj));
707 * \endcode
708 * \note
709 * If we do not "sink" the floating class, then we have to destory it manually,
710 * because its lifetime will not yet be bound to the instance. This can actually
711 * be useful for allowing you to manually manage the class's lifetime as it's
712 * shared among multiple instances.
713 *
714 * For extra credit, we can do the same trick with stack-allocated types as well:
715 * \code{.c}
716 * // call placement constructor on existing memory
717 * GblObjectClass klass;
718 * GblClass_constructFloating(GBL_CLASS(&klass), GBL_OBJECT_TYPE);
719 *
720 * pClass->iEventHandlerIFace.pFnEventNotify = my_event_notifier_function_;
721 *
722 * // call placement constructor on existing memory
723 * GblObject object;
724 * GblInstance_constructWithClass(GBL_INSTANCE(&object), &klass);
725 *
726 * GblInstance_sinkClass(GBL_INSTANCE(&object));
727 *
728 * // now it calls into our shit when the interface is used!
729 * GblIEventHandler_eventNotify(GBL_IEVENT_HANDLER(&object), NULL);
730 *
731 * // Call placement destructor which doesn't deallocate
732 * GblInstance_destruct(GBL_INSTANCE(&object));
733 * \endcode
734 * ## Class Swizzling
735 *
736 * Sometimes you would like to do something similar to the previous example,
737 * with ad-hoc virtual method overriding, but the creation of the object is
738 * not actually under your control. This is a time for libGimbal's class
739 * swizzling, inspired by Objective-C's "is-a" swizzling:
740 * \code{.c}
741 * GblObject* pObject = GblObject_create(GBL_OBJECT_TYPE,
742 * "name", "MyObject",
743 * "userdata", (void*)0xdeadbabe,
744 * NULL);
745 *
746 * GblObjectClass* pClass = GBL_OBJECT_GET_CLASS(pObject);
747 *
748 * //nothing fancy, regular-ass reference counted internally managed, instance-shared class...
749 * assert(GblClass_isDefault(GBL_CLASS(pClass));
750 * assert(!GblClass_isOverridden(GBL_CLASS(pClass));
751 * assert(!GblClass_isFloating(GBL_CLASS(pClass));
752 *
753 * // k, now lets make a new class and do some C++'y shit upon events...
754 * GblObjectClass* pClass2 = GBL_OBJECT_CLASS(GblClass_createFloating(GBL_OBJECT));
755 *
756 * // a lambda is nice for being all ad-hoc
757 * pClass2->iEventHandlerIFace.pFnEvent = [](GblIEventHandler* pSelf, GblEvent* pEvent) {
758 * GBL_CTX_BEGIN(NULL);
759 * GBL_CTX_VERBOSE("So %s just sent a %s to a C++ lambda...",
760 * GblType_name(GBL_CLASS_TYPEOF(pSelf)),
761 * GblType_name(GblEvent_typeof(pEvent)));
762 * GblEvent_accept(pEvent);
763 * GBL_CTX_END();
764 * };
765 *
766 * // k, this class is now officially interesting
767 * assert(!GblClass_isDefault(pClass2));
768 * assert(GblClass_isOverridden(pClass2));
769 * assert(!GblClass_isOwned(pClass2));
770 *
771 * // K NOW LETS JUST SWAP THE FUCKER OUT RANDOMLY EVEN THOUGH ITS ALREADY INSTANTIATED LULUL
772 * // releases reference to default class and gets our override
773 * GblInstance_swizzleClass(GBL_INSTANCE(pObj), GBL_CLASS(pClass2));
774 *
775 * // tell the instance to take exclusive ownership:
776 * GblInstance_classClassSink(GBL_INSTANCE(pObj));
777 *
778 * GblEvent event;
779 * GblInstance_construct(&event, GBL_EVENT_TYPE);
780 * GblIEventHandler_eventNotify(GBL_IEVENT_HANDLER(pObj), pSomeEventObject);
781 *
782 * // K clean up our fuckery
783 * GblInstance_destroy(GBL_INSTANCE(pObj);
784 * \endcode
785 */
786/*! \page TypeTemplate Type Templates
787 * \brief Boilerplate macros for type operations
788 *
789 * At the top of the file for most libGimbal derived types, along with the type identifier,
790 * you will find a collection of convenience utility macros implementing function-style
791 * casts for the given type.
792 * \code{.c}
793 * // type UUID macro (expands to GblObject_type() registration function)
794 * #define GBL_OBJECT_TYPE (GBL_TYPEID(GblObject))
795 *
796 * // instance function-style cast macro
797 * #define GBL_OBJECT(instance) (GBL_CAST(instance, GblObject))
798 *
799 * // class cast function-style cast macro
800 * #define GBL_OBJECT_CLASS(klass) (GBL_CLASS_CAST(klass, GblObject))
801 *
802 * // instance-to-class cast macro
803 * #define GBL_OBJECT_GET_CLASS(instance) (GBL_CLASSOF(instance, GblObject))
804 * \endcode
805 * While these macros are obviously optional, they do add a lot to the codebase in terms of readability
806 * and convenience as well as uniform styling. With these sorts of macros defined, we then gain access to
807 * lots of convenience:
808 * \code{.c}
809 * // create a floating object class
810 * // - easy cast to particular class
811 * GblObjectClass* pClass = GBL_OBJECT_CLASS(GblClass_createFloating(GBL_OBJECT_TYPE));
812 *
813 * // lets override just its implementation of the GblIEventHandlerClass interface
814 * // - easy cast to particular interface
815 * GblIEventHandlerClass* pIEvent = GBL_IEVENT_HANDLER_CLASS(pClass);
816 * // override virtual method
817 * pIEvent->pFnEvent = [&](GblIEventHandler* pSelf, GblEvent* pEvent) {
818 * // easy cast to particular instance type
819 * GblObject* pSelfObj = GBL_OBJECT(pSelf);
820 *
821 * printf("%s received an Event!", GblObject_name(pSelfObj));
822 *
823 *
824 * if(GBL_TYPECHECK(pEvent, MyEventType)) {
825 * // easy cast to particular event instance
826 * MyCustomEvent* pEvent = MY_CUSTOM_EVENT(pEvent);
827 *
828 * // do something
829 * } else if(GBL_TYPECHECK(pEvent, MyOtherEventType)) {
830 * // easy cast to particular event instance
831 * SomeOtherEvent* pEvent = SOME_OTHER_EVENT(pEvent);
832 *
833 * // do something
834 * }
835 * }
836 *
837 * GblObject* pObject = GblObject_createWithClass(pClass);
838 * // easy cast from object to GblInstance base
839 * GblInstance_sinkClass(GBL_INSTANCE(pObject));
840 * // easy cast from object to GblBox base
841 * GblBox_unref(GBL_BOX(pObject));
842 * \endcode
843 */
844
845#undef GBL_SELF_TYPE
846
847#endif // GIMBAL_CLASS_H
#define GBL_BUILTIN_TYPE(prefix)
Returns a type from the macro prefix of a builtin type.
GBL_RESULT GblClass_destructFloating(GblClass *pSelf)
Destructs the standalone, "floating" class, without releasing any allocated resources.
GblRefCount GblClass_unrefDefault(GblClass *pSelf)
Releases a reference to the default version of the given class, possibly freeing it.
GblClass * GblClass_createFloating(GblType type, size_t size)
Creates a standalone, unowned, "floating" class for the given type, which can override defaults.
GBL_RESULT GblClass_constructFloating(GblClass *pSelf, GblType type)
Constructs a standalone, unowned, overridable, "floating" class for the given type in-place.
GBL_RESULT GblClass_destroyFloating(GblClass *pSelf)
Destroys the standalone, "floating" class, releasing its memory allocation.
#define GBL_CLASS(klass)
GblClass * GblClass_weakRefDefault(GblType type)
Returns a reference to the default class for type or NULL if it hasn't been created.
GblClass * GblClass_refDefault(GblType type)
Returns a reference to the default class for type, instantiating it if necessary.
#define GBL_NOEXCEPT
#define GBL_DECLS_BEGIN
#define GBL_CLASS_PRIVATE_STRUCT(instanceStruct)
#define GBL_TYPEID(instanceStruct)
#define GBL_PRIVATE_BEGIN
#define GBL_CLASS_STRUCT(cType)
#define GBL_EXPORT
#define GBL_PRIVATE_END
Private data structure.
uint8_t GblBool
Basic boolean type, standardized to sizeof(char)
uint16_t GblRefCount
Type able to hold a reference counter across the codebase.
#define GBL_STATIC_CLASS_TYPE
uintptr_t GblType
Meta Type UUID.
Definition gimbal_type.h:51
Base struct for all type classes.
size_t GblClass_size(const GblClass *pSelf)
Returns the size of the given class's public class structrue.
GblBool GblClass_isOverridden(const GblClass *pSelf)
Returns GBL_TRUE if the class differs from the default class for its type.
void * GblClass_private(const GblClass *pSelf, GblType base)
Returns the private structure associated with the given base type of the class.
GblClass * GblClass_cast(GblClass *pSelf, GblType toType)
Casts the given class to a toType class, or returns NULL and emits an error if unsuccessful.
GblClass * GblClass_public(const void *pPrivate, GblType base)
Casts back to the class structure from a base type's private data segment structure.
GblType GblClass_typeOf(const GblClass *pSelf)
Returns the GblType UUID associated with the given class.
GblBool GblClass_isInterface(const GblClass *pSelf)
Returns GBL_TRUE if the class is an interfaced type.
GblBool GblClass_check(const GblClass *pSelf, GblType toType)
Returns GBL_TRUE if the given class can be casted to toType.
GblClass * GblClass_super(const GblClass *pSelf)
Returns the default class of the class's parent type or NULL if it's a root class.
size_t GblClass_privateSize(const GblClass *pSelf)
Returns the combined size of the class's private data segments.
GblBool GblClass_isInPlace(const GblClass *pSelf)
Returns GBL_TRUE if the class was constructed in-place with an existing allocation.
GblBool GblClass_isOwned(const GblClass *pSelf)
Returns GBL_TRUE if the class is a non-default floating class is uowned by an instance.
GblBool GblClass_isFloating(const GblClass *pSelf)
Returns GBL_TRUE if the class is a non-default floating class and is unowned by an instance.
uintptr_t metaClassInfo
PRIVATE: Pointer-sized opaque member.
GblBool GblClass_isDefault(const GblClass *pSelf)
Returns GBL_TRUE if the class is the internally-managed default for its type.
GblClass * GblClass_as(GblClass *pSelf, GblType toType)
Casts the given class to a toType class, or gracefully returns NULL without erroring.
GblBool GblClass_isInterfaceImpl(const GblClass *pSelf)
Returns GBL_TRUE if the class is another class's implementation of an interface.
GblClass * GblClass_default(const GblClass *pSelf)
Returns the default implementation of the given class.
size_t GblClass_totalSize(const GblClass *pSelf)
Returns the class's combined DEFAULT size (not extended allocation size)