# api_types.h ## Overview
Standard types and macros that are always available.
## Index
Types
`struct tm_vec2_t`
`struct tm_vec3_t`
`struct tm_vec4_t`
`struct tm_mat44_t`
`struct tm_transform_t`
`struct tm_rect_t`
`struct tm_str_t`
`tm_str()`
`TM_STR()`
`tm_str_range()`
`struct tm_clock_o`
`struct tm_uuid_t`
`struct tm_color_srgb_t`
`TM_RGB()`
`struct tm_tt_type_t`
`struct tm_tt_id_t`
`tm_tt_type()`
`struct tm_tt_id_t`
`struct tm_tt_undo_scope_t`
`struct tm_version_t`
`TM_VERSION()`
`TM_VERSION_INITIALIZER()`

Build configuration
`TM_OS_WINDOWS`
`TM_OS_MACOSX`
`TM_OS_LINUX`
`TM_OS_POSIX`
`TM_NO_MAIN_FIBER`
`TM_CONFIGURATION_DEBUG`
`TM_CONFIGURATION_RELEASE`

String hashes
`struct tm_strhash_t`
`TM_STRHASH()`
`TM_STRHASH_U64()`
`TM_STRHASH_EQUAL()`
`TM_STATIC_HASH()`

Macros
`TM_LITERAL()`
`TM_DLL_EXPORT`
`TM_ATOMIC`
`TM_STRINGIFY()`
`TM_CONCAT()`
`TM_MACRO_VAR()`
`TM_PAD()`
`TM_DISABLE_PADDING_WARNINGS`
`TM_RESTORE_PADDING_WARNINGS`
`TM_INHERITS()`
## API

Types

### `struct tm_vec2_t`
Represents a 2D vector. ~~~c typedef struct tm_vec2_t { float x, y; } tm_vec2_t; ~~~
### `struct tm_vec3_t`
Represents a 3D vector. ~~~c typedef struct tm_vec3_t { float x, y, z; } tm_vec3_t; ~~~
### `struct tm_vec4_t`
Represents a 4D vector. ~~~c typedef struct tm_vec4_t { float x, y, z, w; } tm_vec4_t; ~~~
### `struct tm_mat44_t`
Represents a 4x4 matrix. ~~~c typedef struct tm_mat44_t { float xx, xy, xz, xw; float yx, yy, yz, yw; float zx, zy, zz, zw; float wx, wy, wz, ww; } tm_mat44_t; ~~~
### `struct tm_transform_t`
Represents a transform in TRS form. ~~~c typedef struct tm_transform_t { tm_vec3_t pos; tm_vec4_t rot; tm_vec3_t scl; } tm_transform_t; ~~~
### `struct tm_rect_t`
Represents a rectangle. ~~~c typedef struct tm_rect_t { float x, y, w, h; } tm_rect_t; ~~~
### `struct tm_str_t`
Used to represent a string slice with pointer and length. This lets you reason about parts of a string, which you are not able to do with standard NULL-terminated strings. ~~~c typedef struct tm_str_t { // Pointer to string bytes. const char *data; // Length of the string. uint32_t size; // If set to *true*, indicates that there is an allocated NULL-byte after the string data. I.e. // `data[size] == 0`. This means that `data` can be used immediately as a C string without // needing to copy it to a separate memory area. // // If *false*, there may or may not be a NULL-byte at the end of the string and accessing // `data[size]` may cause an access violation, so if you want to use it as a C-string you have // to copy it to a new memory area and append a NULL byte. // // Note that the NULL-byte is never included in the `size`. uint32_t null_terminated; } tm_str_t; ~~~
### `tm_str()`
~~~c #define tm_str(s) ~~~ Creates a `tm_str_t` from a `char *` `s`.
### `TM_STR()`
~~~c #define TM_STR(s) ~~~ Creates a `tm_str_t` from a static string `s`. As `tm_str()`, but uses `sizeof()` instead of `strlen()` to determine the length of the string. This means it avoids the `strlen()` overhead and can be used to initialize static data, but it can only be used with static strings.
### `tm_str_range()`
~~~c #define tm_str_range(s, e) ~~~ Creates a `tm_str_t` from a start pointer `s` and end pointer `e`.
### `struct tm_clock_o`
Represents a time from the system clock. You can assume the clock to be monotonically increasing, i.e. a larger `opaque` value represents a later time, but you shouldn't assume anything else about what the `opaque` value represents or the resolution of the timer. Instead, use `tm_os_time_api->delta()` to convert elapsed time to seconds. ~~~c typedef struct tm_clock_o { uint64_t opaque; } tm_clock_o; ~~~
### `struct tm_uuid_t`
Represents a unique 128-bit identifier. ~~~c typedef struct tm_uuid_t { uint64_t a; uint64_t b; } tm_uuid_t; ~~~
### `struct tm_color_srgb_t`
Represents an 8-bit per channel RGBA color in sRGB color space (Note: alpha is always linear.) ~~~c typedef struct tm_color_srgb_t { uint8_t r, g, b, a; } tm_color_srgb_t; ~~~
### `TM_RGB()`
~~~c #define TM_RGB(c) ~~~ Converts an `uint32_t` to an `tm_color_srgb_t` color. The nibbles in the `uint32_t` hex representation specify TRGB, where T is transparancy (0x00 means fully opaque and 0xff fully transparent, i.e. it is the invert of alpha). This lets you leave the highest nibble out for an opaque color (the most common case), but specify it if you want transparency. Hex | Color ---------- | ------------------- 0x00 | Black 0xff0000 | Red 0xff000000 | Transparent black 0x80ffff00 | 50 % transparent yellow
### `struct tm_tt_type_t`
Type representing a type in The Truth. ~~~c typedef struct tm_tt_type_t { uint64_t u64; } tm_tt_type_t; ~~~
### `struct tm_tt_id_t`
ID representing an object in The Truth. ~~~c typedef struct tm_tt_id_t { union { // Used for comparing objects or storing them in hash tables. uint64_t u64; struct { // Type of the object. uint64_t type : 10; // Generation of the object, used to distinguish objects created at the same index. uint64_t generation : 22; // Index of the object. uint64_t index : 32; }; }; } tm_tt_id_t; ~~~
### `tm_tt_type()`
~~~c static inline tm_tt_type_t tm_tt_type(tm_tt_id_t id) ~~~ Returns the type of `id`.
### `struct tm_tt_id_t`
~~~c typedef struct tm_tt_id_t { uint64_t u64; } tm_tt_id_t; ~~~
### `struct tm_tt_undo_scope_t`
Type representing an undo scope in The Truth. ~~~c typedef struct tm_tt_undo_scope_t { uint64_t u64; } tm_tt_undo_scope_t; ~~~
### `struct tm_version_t`
Used to represent API versions. Version numbers follow the SemVer 2.0.0 specification: * The major version is bumped for breaking API changes. * The minor version is bumped when new functionality is added in a backwards-compatible manner. * The patch version is bumped for backwards-compatible bug fixes. * If the major version is 0, the API is considered unstable and under development. In this case, nothing should be assumed about backwards compatibility. See: https://semver.org/spec/v2.0.0.html !!! WARNING: Be careful about backwards compatibility The default action should be to bump the major version whenever you change something in the API. If you are considering just bumping the minor or patch version, you must make 100 % sure that your changes are backwards compatible, since otherwise you will break existing plugins without any warning. ~~~c typedef struct tm_version_t { // Bumped when breaking changes are made to the API. For example: // // * Adding functions in the middle of the API. // * Changing the number of parameters to a function or their types. // * Changing the return type of a function. // * Changing the fields of a struct. uint32_t major; // Bumped when new functionality is added to the API in a backwards-compatible manner. // Changes are backwards compatible if a caller using an old version of the header file can // still call into the new version of the ABI without errors. Examples of backwards-compatible // changes are: // // * Adding new functions to the end of the API. // * Repurposing unused bits in structs. // // If you want to change an API and only bump the minor version you should make sure to take // special care that your changes are really backwards compatible. uint32_t minor; // Bumped for backwards-compatible bug fixes. uint32_t patch; } tm_version_t; ~~~
### `TM_VERSION()`
~~~c #define TM_VERSION(major, minor, patch) ~~~ Creates a `tm_version_t` literal.
### `TM_VERSION_INITIALIZER()`
~~~c #define TM_VERSION_INITIALIZER(major, minor, patch) ~~~ The `TM_VERSION()` macro cannot be used to initialize constant objects in Visual Studio. (It will give the error "initializer not constant".) This macro can be used as an alternative for constant initializations. !!! TODO: TODO Having two separate macros for this is not very elegant. See if we can find a better solution.

Build configuration

These macros are defined in the build file `premake5.lua`, but listed here for documentation purposes. ### `TM_OS_WINDOWS`
~~~c #define TM_OS_WINDOWS ~~~ Defined for Windows builds.
### `TM_OS_MACOSX`
~~~c #define TM_OS_MACOSX ~~~ Defined for OS X builds.
### `TM_OS_LINUX`
~~~c #define TM_OS_LINUX ~~~ Defined for Linux builds.
### `TM_OS_POSIX`
~~~c #define TM_OS_POSIX ~~~ Defined for POSIX builds (OS X or Linux).
### `TM_NO_MAIN_FIBER`
~~~c #define TM_NO_MAIN_FIBER ~~~ If defined, the main job runs on a thread, not a fiber.
### `TM_CONFIGURATION_DEBUG`
~~~c #define TM_CONFIGURATION_DEBUG ~~~ Defined for debug builds.
### `TM_CONFIGURATION_RELEASE`
~~~c #define TM_CONFIGURATION_RELEASE ~~~ Defined for release builds.

String hashes

`#define TM_USE_STRHASH_TYPE` controls whether we should use a custom type `tm_strhash_t` for string hashes, or if they should just be `uint64_t`. Currently, it is set to `0` when compiling using MSVC and `1` otherwise. We cannot use the `tm_strhash_t` type with the Visual Studio compiler, because it doesn't see our `TM_STATIC_HASH()` macro as a constant, and thus will generate [C2099](https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2099?view=msvc-160) compiler error. errors whenever it is used to initialize a global variable. This is unfortunate, because it means we can't get type safe string hashes in Visual Studio. Hopefully, this will be fixed in a future Visual Studio release and we can transition fully to the `tm_strhash_t` type. ### `struct tm_strhash_t`
Type-safe representation of a hashed string. !!! WARNING: WARNING In Visual Studio, string hashes won't use this string type, instead `tm_strhash_t` will be typedefed to `uint64_t`. The reason for this is that the `TM_STATIC_HASH()` macro is not seen as a constant by the MSVC compiler and thus using it to initialize global variables yields the [C2099](https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/compiler-error-c2099?view=msvc-160) compiler error. This means that the type safety of string hashes won't be checked when compiling with MSVC. Make sure you build your code under clang too, with `tmbuild --clang` to check the type safety of string hashes. Also, always use the macros `TM_STRHASH()` and `TM_STRHASH_U64()` to convert between `tm_strhash_t` and `uint64_t`. This ensures that the conversions work on all platforms. ~~~c typedef struct tm_strhash_t { uint64_t u64; } tm_strhash_t; ~~~
### `TM_STRHASH()`
~~~c #define TM_STRHASH(x) ~~~ Converts a `uint64_t` to a `tm_strhash_t`.
### `TM_STRHASH_U64()`
~~~c #define TM_STRHASH_U64(x) ~~~ Extracts the `uint64_t` of a `tm_strhash_t` value `x`.
### `TM_STRHASH_EQUAL()`
~~~c #define TM_STRHASH_EQUAL(a, b) ~~~ Returns true if the the two `tm_strhash_t` are equal.
### `TM_STATIC_HASH()`
~~~c #define TM_STATIC_HASH(s, v) ~~~ Used for static string hashes. The `hash.exe` utility checks the entire source code and makes sure that wherever you use `TM_STATIC_HASH()`, the numeric value `v` matches the actual hash of the string `s` (if not, the code is updated). When you create a new static hash, don't enter the numeric value, just the string: `TM_STATIC_HASH<!-- -->("bla")`. This ensures that the macro fails to compile until you run `hash.exe` to generate a numeric value. `TM_STATIC_HASH()` returns a constant value of type `tm_strhash_t`. <!-- `(sizeof("" s "") ? v : v)` is a trick to get an expression that evaluates to `v` but produces a compile error if `s` is anything other than a static string. -->

Macros

### `TM_LITERAL()`
~~~c #define TM_LITERAL(T) ~~~ Macro for creating a struct literal of type `T` that works both in C and C++. Use as: ~~~c x = TM_LITERAL(tm_vec2_t) {x, y} ~~~ In C, this turns into `(tm_vec2_t){0, 0}` and in C++ to `tm_vec2_t{0, 0}`. Note that use of `TM_LITERAL()` is only needed in .h and .inl files that might be included from both C and C++. In .c and .cpp file you should just use the native literal format instead of relying on `TM_LITERAL()`.
### `TM_DLL_EXPORT`
~~~c #define TM_DLL_EXPORT ~~~ Marks a function to be exported to DLLs.
### `TM_ATOMIC`
~~~c #define TM_ATOMIC ~~~ Mark struct fields in header files as atomic.
### `TM_STRINGIFY()`
~~~c #define TM_STRINGIFY(name) ~~~ Returns the `name` as a string.
### `TM_CONCAT()`
~~~c #define TM_CONCAT(a, b) ~~~ Concatenates `a` and `b` , allowing you to expand macros before doing the concatenation. This is useful when used with builtin macros like `__LINE__` or `__COUNTER__`. `x##__COUNTER__` doesn't expand to `x1` since a macro is not expanded if preceded by `#` or `##`, but `TM_CONCAT(x, __COUNTER__)` works.
### `TM_MACRO_VAR()`
~~~c #define TM_MACRO_VAR(name) ~~~ Generates a unique name for a macro variable, based on `name`.
### `TM_PAD()`
~~~c #define TM_PAD(n) ~~~ Declares a field that pads a struct with the specified number of bytes. To ensure that structs are completely zero-initialized by designated initializers, we require all struct padding to be explicitly declared using this macro. (We enable warnings that trigger if there is undeclared padding in a struct.) Example: ~~~c struct x { uint32_t a; // This padding is needed since `b` needs to be aligned to a 64-bit boundary. TM_PAD(4); uint64_t b; }; ~~~ Note that in situations where types have different sizes on different platforms you may need to pad with different amounts: ~~~c TM_PAD(8 - sizeof(x)); ~~~
### `TM_DISABLE_PADDING_WARNINGS`
~~~c #define TM_DISABLE_PADDING_WARNINGS ~~~ Disable warnings about padding inserted into structs. Use this before including external headers that do not explicitly declare padding. Restore the padding warning afterwards with `TM_RESTORE_PADDING_WARNINGS`.
### `TM_RESTORE_PADDING_WARNINGS`
~~~c #define TM_RESTORE_PADDING_WARNINGS ~~~ Restore padding warnings disabled by `TM_DISABLE_PADDING_WARNINGS`.
### `TM_INHERITS()`
~~~c #define TM_INHERITS(TYPE) ~~~ Used to implement "inheritance" -- inserting the members of one struct into another, with a construct like: ~~~c struct tm_class_t { TM_INHERITS(struct tm_super_t); ... } ~~~ In a compiler that supports anonymous structs, (`-Wno-microsoft-anon-tag`, `-fms-extensions`), this will be expanded to just `struct tm_super_t;`, otherwise to `struct tm_super_t super;`. !!! note A struct should never have more than one `TM_INHERITS()` and it should always be placed at the top of the struct.