Generates type-safe wrappers for the SHT API. More...
#include "sht.h"Go to the source code of this file.
Macros | |
| #define | SHT_TABLE_TYPE(ttspec, ktype, etype, hfspec, efspec, ...) |
| Generate types and functions for a type-safe hash table type. | |
Generates type-safe wrappers for the SHT API.
The SHT_TABLE_TYPE() macro generates a strongly typed front-end to the generic SHT hash table implementation. The underlying library (sht.h) operates on void pointers, but the type-safe layer ensures that each instance of a table is associated with specific key and entry types, eliminating unsafe casts, mismatched callback signatures, and logic errors. All errors related to type mismatch are detected at compile time, not runtime.
A type-safe table instance is parameterized by the following.
The table type spec (ttspec). This is a 1- or 2-member tuple that contains an optional storage class modifier and a required prefix.
The tuple must be parenthesized if a storage class modified is specified; otherwise, parentheses are optional, so the following formats are all valid — prefix, (prefix), and (storage_class, prefix).
The hash function spec (hfspec). This is a 1- or 2-member tuple that that contains a required type-safe hash function name and an optional context type.
Note that unlike the key and entry types, context types are not const-qualified by default. This allows application-supplied hash, equality, and free functions to modify their contexts, if needed. If the supplied function does expect a const-qualified pointer as its context argument, then const should be included in the context type — e.g., const uint32_t.
The tuple must be parenthesized if a context type is specified; otherwise, parentheses are optional, so the following formats are all valid — hash_function, (hash_function), and (hash_function, context_type).
Based on these parameters, SHT_TABLE_TYPE() generates:
This example shows a simple set of integers. No values are stored, so no entry structure or free function is required. XXH3_64bits() is used as a hash function, and it does not require a seed, so no context is needed by either the hash or equality functions.
NOTE
The type-safe hash, equality, and (if needed) free functions should almost always be static, so that they can be inlined within the generated callback wrappers.
A simplified subset of the code generated by this SHT_TABLE_TYPE() invocation is shown below for illustrative purposes. See the next example for a complete SHT_TABLE_TYPE() expansion.
These wrapper functions conform to the SHT API for hash and equality functions.
These incomplete types will be used in the type-safe wrapper functions.
Note the compile-time check of the entry size (int in this case). Because of this check, the only possible failure mode of int_new() is a memory allocation failure (SHT_ERR_ALLOC), so there is no need to pass an error code output pointer to sht_new_().
This function simply calls sht_new_() and casts its return value to the generated table type. Like all of the generated wrappers (except the callback wrappers), it will almost always be "optimized away," and generate no actual code.
The macro generates setters for the load factor threshold (LFT) and the probe sequence length (PSL) limit, but it doesn't generate any context setters, because no context types were specified.
These wrappers accept and return pointers to the key and entry types (both int), rather than the void pointers used by the underlying API. (Conversions between void pointers and other object pointer types do not require explicit casts.)
This wrapper returns the incomplete type-safe iterator type that was declared earlier.
These wrappers operate on the type-safe iterator (struct int_iter *) and entry (int) types.
This example shows a map that uses C strings as both its key and value types.
This example is constructed to show as many options as possible.
The complete expansion of this SHT_TABLE_TYPE() invocation is shown below. It was produced by running the following command. (The .clang-format file used can be found in the root directory of this repository.)
The macro expansion is found at the end of the generated file.
Definition in file sht-ts.h.
| #define SHT_TABLE_TYPE | ( | ttspec, | |
| ktype, | |||
| etype, | |||
| hfspec, | |||
| efspec, | |||
| ... ) |
Generate types and functions for a type-safe hash table type.
| ttspec | Table type spec — a 1- or 2-member tuple that contains an optional storage class (e.g., static) followed by a required name prefix. If a storage class is specified, the tuple must be enclosed in parentheses. Thus, the following formats are allowed.
|
| ktype | The type of the table's keys. For example, if the type-safe hash and equality functions accept a const char * as their key argument, then ktype should be char. |
| etype | The type of the table's entries. If the type-safe equality and free functions (if any) accept a const struct foo_entry *, then etype should be struct foo_entry. |
| hfspec | Hash function spec — a 1- or 2-member tuple that contains a required type-safe hash function name followed by an optional hash function context type. For example, if the type-safe hash function accepts a const uint32_t * as its context argument, then the context type should be const uint32_t. (Context pointers may be either const-qualified or non-const, depending on the needs of the application.) If a context type is specified, the tuple must be enclosed in parentheses. Thus, the following formats are allowed.
|
| efspec | Equality function spec — a 1- or 2-member tuple that contains a required type-safe equality function name followed by an optional context type. (See hfspec for the allowed formats.) |
| ... | Optional free function spec — a 1- or 2-member tuple that contains a required (if the spec if present) type-safe free function name followed by an optional context type. (See hfspec for the allowed formats.) |