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