49#define INITIAL_REGISTRY_BUCKETS 61
76 hash = ((hash << 5) + hash) + c;
93 if (current->hash == hash && strcmp(current->name, name) == 0)
124 size_t new_index = entry->
hash % new_num_buckets;
127 entry->
next = new_buckets[new_index];
128 new_buckets[new_index] = entry;
167 size_t name_len = strlen(name) + 1;
174 new_entry->
name = name_copy;
175 new_entry->
hash = hash;
176 new_entry->
type =
nullptr;
270 for (
size_t i = 0; i <
src->num_buckets; ++i) {
287 if (!new_entry->
type) {
347 if (node->src == type)
356 memo_node->
src = type;
357 memo_node->
next = *memo_head;
358 *memo_head = memo_node;
366 if (!entry || !entry->
type) {
370 *type_ptr = entry->
type;
460 while (isspace((
unsigned char)*state->
p))
462 if (*state->
p ==
'#')
463 while (*state->
p !=
'\n' && *state->
p !=
'\0')
479 const char * name_start = state->
p;
480 if (!isalpha((
unsigned char)*name_start) && *name_start !=
'_')
482 while (isalnum((
unsigned char)*state->
p) || *state->
p ==
'_' || *state->
p ==
':') {
483 if (*state->
p ==
':' && state->
p[1] !=
':')
485 if (*state->
p ==
':')
489 size_t len = state->
p - name_start;
534 const char * def_body_start;
537 size_t defs_capacity = 64;
538 struct def_info * defs_found =
infix_malloc(
sizeof(
struct def_info) * defs_capacity);
543 size_t num_defs_found = 0;
547 while (*state.
p !=
'\0') {
549 if (*state.
p ==
'\0')
551 if (*state.
p !=
'@') {
557 char name_buffer[256];
565 if (*state.
p ==
'=') {
581 if (num_defs_found >= defs_capacity) {
582 size_t new_capacity = defs_capacity * 2;
583 struct def_info * new_defs =
infix_realloc(defs_found,
sizeof(
struct def_info) * new_capacity);
589 defs_found = new_defs;
590 defs_capacity = new_capacity;
593 defs_found[num_defs_found].entry = entry;
594 defs_found[num_defs_found].def_body_start = state.
p;
596 const char * body_end = state.
p;
597 while (*body_end !=
'\0' &&
598 !(*body_end ==
';' &&
600 if (*body_end ==
'-' && body_end[1] ==
'>') {
604 if (*body_end ==
'{' || *body_end ==
'<' || *body_end ==
'(' || *body_end ==
'[')
606 if (*body_end ==
'}' || *body_end ==
'>' || *body_end ==
')' || *body_end ==
']')
610 defs_found[num_defs_found].def_body_len = body_end - state.
p;
614 else if (*state.
p ==
';') {
667 for (
size_t i = 0; i < num_defs_found; ++i) {
673 char body_buffer[64];
674 if (defs_found[i].def_body_len > 0 && defs_found[i].def_body_len <
sizeof(body_buffer)) {
675 infix_memcpy(body_buffer, defs_found[i].def_body_start, defs_found[i].def_body_len);
676 body_buffer[defs_found[i].def_body_len] =
'\0';
679 parser_state fast_state = {.
p = body_buffer, .start = body_buffer, .arena = parser_arena, .depth = 0};
683 if (fast_primitive) {
685 if (*fast_state.
p !=
'\0')
686 fast_primitive =
nullptr;
691 if (fast_primitive) {
692 raw_type = fast_primitive;
697 char * body_copy =
infix_malloc(defs_found[i].def_body_len + 1);
704 infix_memcpy(body_copy, defs_found[i].def_body_start, defs_found[i].def_body_len);
705 body_copy[defs_found[i].def_body_len] =
'\0';
707 parser_state state = {.
p = body_copy, .start = body_copy, .arena = parser_arena, .depth = 0};
712 if (*state.
p !=
'\0') {
734 if (existing_entry && existing_entry->
type)
735 type_to_alias = existing_entry->
type;
740 (
size_t)(defs_found[i].def_body_start -
definitions) + relative_pos);
754 *new_def = *type_to_alias;
773 *entry->
type = *new_def;
780 entry->
type = new_def;
792 for (
size_t i = 0; i < num_defs_found; ++i) {
800 size_t body_offset = defs_found[i].def_body_start -
definitions;
infix_arena_t * arena
Definition 005_layouts.c:62
const char * definitions
Definition 008_registry_introspection.c:36
infix_registry_t * registry
Definition 008_registry_introspection.c:33
infix_status status
Definition 103_unions.c:61
size_t buf_size
Definition 904_registry_benchmark.c:23
#define c23_nodiscard
Internal alias for the public INFIX_NODISCARD macro.
Definition compat_c23.h:92
#define INFIX_TLS
Definition error.c:68
INFIX_API infix_error_details_t infix_get_last_error(void)
Retrieves detailed information about the last error that occurred on the current thread.
Definition error.c:281
@ INFIX_CODE_UNRESOLVED_NAMED_TYPE
Definition infix.h:1387
@ INFIX_CODE_UNEXPECTED_TOKEN
Definition infix.h:1375
@ INFIX_CODE_NULL_POINTER
Definition infix.h:1364
@ INFIX_CODE_OUT_OF_MEMORY
Definition infix.h:1369
@ INFIX_CATEGORY_ALLOCATION
Definition infix.h:1353
@ INFIX_CATEGORY_GENERAL
Definition infix.h:1352
@ INFIX_CATEGORY_PARSER
Definition infix.h:1354
size_t source_offset
Definition infix.h:282
void * _current_entry
Definition infix.h:520
struct infix_type_t::@0::@1 pointer_info
Metadata for INFIX_TYPE_POINTER.
size_t position
Definition infix.h:1403
union infix_type_t::@0 meta
A union containing metadata specific to the type's category.
struct infix_type_t::@0::@7 vector_info
Metadata for INFIX_TYPE_VECTOR.
infix_error_category_t category
Definition infix.h:1401
const infix_registry_t * registry
Definition infix.h:518
bool is_incomplete
Definition infix.h:280
infix_type * type
Definition infix.h:348
struct infix_type_t::@0::@4 func_ptr_info
Metadata for INFIX_TYPE_REVERSE_TRAMPOLINE.
infix_arena_t * arena
Definition infix.h:281
size_t size
Definition infix.h:277
size_t alignment
Definition infix.h:278
infix_struct_member * members
Definition infix.h:293
struct infix_type_t::@0::@6 complex_info
Metadata for INFIX_TYPE_COMPLEX.
const char * name
Definition infix.h:275
infix_function_argument * args
Definition infix.h:306
infix_status
Enumerates the possible status codes returned by infix API functions.
Definition infix.h:434
infix_type_category category
Definition infix.h:276
size_t _bucket_index
Definition infix.h:519
struct infix_type_t::@0::@2 aggregate_info
Metadata for INFIX_TYPE_STRUCT and INFIX_TYPE_UNION.
struct infix_type_t::@0::@3 array_info
Metadata for INFIX_TYPE_ARRAY.
struct infix_type_t * pointee_type
Definition infix.h:289
infix_type * type
Definition infix.h:336
struct infix_type_t * element_type
Definition infix.h:299
struct infix_type_t * return_type
Definition infix.h:305
struct infix_type_t::@0::@5 enum_info
Metadata for INFIX_TYPE_ENUM.
struct infix_type_t * base_type
Definition infix.h:316
infix_error_code_t code
Definition infix.h:1402
size_t num_members
Definition infix.h:294
struct infix_type_t * underlying_type
Definition infix.h:312
struct infix_type_t::@0::@8 named_reference
Metadata for INFIX_TYPE_NAMED_REFERENCE.
size_t num_args
Definition infix.h:307
bool is_arena_allocated
Definition infix.h:279
@ INFIX_ERROR_ALLOCATION_FAILED
Definition infix.h:436
@ INFIX_SUCCESS
Definition infix.h:435
@ INFIX_ERROR_INVALID_ARGUMENT
Definition infix.h:437
#define infix_free
A macro that can be defined to override the default free function.
Definition infix.h:383
INFIX_API INFIX_NODISCARD void * infix_arena_alloc(infix_arena_t *, size_t, size_t)
Allocates a block of memory from an arena.
Definition arena.c:117
#define infix_memcpy
A macro that can be defined to override the default memcpy function.
Definition infix.h:387
#define infix_calloc
A macro that can be defined to override the default calloc function.
Definition infix.h:375
#define infix_realloc
A macro that can be defined to override the default realloc function.
Definition infix.h:379
INFIX_API INFIX_NODISCARD infix_arena_t * infix_arena_create(size_t)
Creates a new memory arena.
Definition arena.c:52
INFIX_API INFIX_NODISCARD void * infix_arena_calloc(infix_arena_t *, size_t, size_t, size_t)
Allocates and zero-initializes a block of memory from an arena.
Definition arena.c:188
#define infix_malloc
A macro that can be defined to override the default malloc function.
Definition infix.h:371
INFIX_API void infix_arena_destroy(infix_arena_t *)
Destroys an arena and frees all memory allocated from it.
Definition arena.c:83
INFIX_API void infix_registry_destroy(infix_registry_t *registry)
Destroys a type registry and frees all associated memory.
Definition type_registry.c:307
INFIX_API c23_nodiscard infix_status infix_register_types(infix_registry_t *registry, const char *definitions)
Parses a string of type definitions and adds them to a registry.
Definition type_registry.c:523
INFIX_API c23_nodiscard infix_registry_t * infix_registry_create(void)
Creates a new, empty named type registry.
Definition type_registry.c:196
INFIX_API c23_nodiscard infix_registry_t * infix_registry_clone(const infix_registry_t *src)
Creates a deep copy of an existing registry.
Definition type_registry.c:261
INFIX_API c23_nodiscard const infix_type * infix_registry_lookup_type(const infix_registry_t *registry, const char *name)
Retrieves the canonical infix_type object for a given name from the registry.
Definition type_registry.c:938
INFIX_API c23_nodiscard infix_registry_t * infix_registry_create_in_arena(infix_arena_t *arena)
Creates a new, empty named type registry that allocates from a user-provided arena.
Definition type_registry.c:233
INFIX_API c23_nodiscard bool infix_registry_iterator_next(infix_registry_iterator_t *iter)
Advances the iterator to the next defined type in the registry.
Definition type_registry.c:849
INFIX_API c23_nodiscard infix_registry_iterator_t infix_registry_iterator_begin(const infix_registry_t *registry)
Initializes an iterator for traversing the types in a registry.
Definition type_registry.c:832
INFIX_API c23_nodiscard const infix_type * infix_registry_iterator_get_type(const infix_registry_iterator_t *iter)
Gets the infix_type object of the type at the iterator's current position.
Definition type_registry.c:906
INFIX_API c23_nodiscard bool infix_registry_is_defined(const infix_registry_t *registry, const char *name)
Checks if a type with the given name is fully defined in the registry.
Definition type_registry.c:922
INFIX_API c23_nodiscard const char * infix_registry_iterator_get_name(const infix_registry_iterator_t *iter)
Gets the name of the type at the iterator's current position.
Definition type_registry.c:892
@ INFIX_TYPE_UNION
Definition infix.h:231
@ INFIX_TYPE_COMPLEX
Definition infix.h:235
@ INFIX_TYPE_ARRAY
Definition infix.h:232
@ INFIX_TYPE_VECTOR
Definition infix.h:236
@ INFIX_TYPE_POINTER
Definition infix.h:229
@ INFIX_TYPE_NAMED_REFERENCE
Definition infix.h:237
@ INFIX_TYPE_REVERSE_TRAMPOLINE
Definition infix.h:233
@ INFIX_TYPE_ENUM
Definition infix.h:234
@ INFIX_TYPE_STRUCT
Definition infix.h:230
#define INFIX_API
Symbol visibility macro.
Definition infix.h:114
Internal data structures, function prototypes, and constants.
INFIX_INTERNAL infix_type * parse_primitive(parser_state *state)
Definition signature.c:463
INFIX_INTERNAL void skip_whitespace(parser_state *state)
Definition signature.c:70
INFIX_INTERNAL infix_type * _copy_type_graph_to_arena(infix_arena_t *, const infix_type *)
Performs a deep copy of a type graph into a destination arena.
Definition types.c:1112
INFIX_INTERNAL void _infix_set_parser_error(parser_state *state, infix_error_code_t code)
Definition signature.c:60
INFIX_INTERNAL void _infix_type_recalculate_layout(infix_type *type)
Recalculates the layout of a fully resolved type graph.
Definition types.c:924
INFIX_INTERNAL void _infix_clear_error(void)
Clears the thread-local error state.
Definition error.c:268
INFIX_INTERNAL void _infix_set_error(infix_error_category_t category, infix_error_code_t code, size_t position)
Sets the thread-local error state with detailed information.
Definition error.c:175
INFIX_INTERNAL infix_type * parse_type(parser_state *state)
Definition signature.c:592
A single entry in the registry's hash table.
Definition infix_internals.h:174
bool is_forward_declaration
Definition infix_internals.h:178
const char * name
Definition infix_internals.h:175
uint64_t hash
Definition infix_internals.h:176
infix_type * type
Definition infix_internals.h:177
struct _infix_registry_entry_t * next
Definition infix_internals.h:179
Definition type_registry.c:449
const char * start
Definition type_registry.c:451
const char * p
Definition type_registry.c:450
Internal definition of a memory arena.
Definition infix_internals.h:143
Provides detailed, thread-local information about the last error that occurred.
Definition infix.h:1400
An iterator for traversing a type registry.
Definition infix.h:517
Internal definition of a named type registry.
Definition infix_internals.h:188
size_t num_items
Definition infix_internals.h:192
bool is_external_arena
Definition infix_internals.h:190
infix_arena_t * arena
Definition infix_internals.h:189
_infix_registry_entry_t ** buckets
Definition infix_internals.h:193
size_t num_buckets
Definition infix_internals.h:191
A semi-opaque structure that describes a C type.
Definition infix.h:274
Holds the complete state of the recursive descent parser during a single parse operation.
Definition infix_internals.h:199
const char * p
Definition infix_internals.h:200
Definition type_registry.c:60
struct resolve_memo_node_t * next
Definition type_registry.c:62
infix_type * src
Definition type_registry.c:61
static uint64_t _registry_hash_string(const char *str)
Definition type_registry.c:72
#define INITIAL_REGISTRY_BUCKETS
Definition type_registry.c:49
c23_nodiscard infix_status _infix_resolve_type_graph_inplace(infix_type **type_ptr, infix_registry_t *registry)
Resolves all named type references in a type graph in-place.
Definition type_registry.c:428
static void _registry_rehash(infix_registry_t *registry)
Definition type_registry.c:104
static _infix_registry_entry_t * _registry_lookup(infix_registry_t *registry, const char *name)
Definition type_registry.c:86
static _infix_registry_entry_t * _registry_insert(infix_registry_t *registry, const char *name)
Definition type_registry.c:153
static char * _registry_parser_parse_name(_registry_parser_state_t *state, char *buffer, size_t buf_size)
Definition type_registry.c:477
static void _registry_parser_skip_whitespace(_registry_parser_state_t *state)
Definition type_registry.c:458
static infix_status _resolve_type_graph_inplace_recursive(infix_arena_t *temp_arena, infix_type **type_ptr, infix_registry_t *registry, resolve_memo_node_t **memo_head)
Definition type_registry.c:337
INFIX_TLS const char * g_infix_last_signature_context
A thread-local pointer to the full signature string being parsed.
Definition error.c:99