ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
core.c File Reference

Internal helper functions for registry implementation. More...

Go to the source code of this file.

Functions

void registry_init_from_builders (void)
 Initialize registry from category builders Populates g_options_registry by concatenating all category arrays.
 
asciichat_error_t registry_validate_unique_options (void)
 Validate that no short or long options appear more than once in the registry.
 
void registry_init_size (void)
 Initialize registry size and metadata.
 
const registry_entry_t * registry_find_entry_by_name (const char *long_name)
 Get a registry entry by long name.
 
const registry_entry_t * registry_find_entry_by_short (char short_name)
 Get a registry entry by short name.
 
option_descriptor_t registry_entry_to_descriptor (const registry_entry_t *entry)
 Convert registry entry to option descriptor.
 
bool registry_entry_applies_to_mode (const registry_entry_t *entry, asciichat_mode_t mode, bool for_binary_help)
 Check if an option applies to the given mode for display purposes.
 

Detailed Description

Internal helper functions for registry implementation.

This file contains all the static helper functions used internally by the registry implementation. These functions are not part of the public API and are only used by public_api.c.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

Definition in file core.c.

Function Documentation

◆ registry_entry_applies_to_mode()

bool registry_entry_applies_to_mode ( const registry_entry_t *  entry,
asciichat_mode_t  mode,
bool  for_binary_help 
)

Check if an option applies to the given mode for display purposes.

This implements the same filtering logic as the help system's option_applies_to_mode(). Used by options_registry_get_for_display() to ensure completions match help output.

Parameters
entryRegistry entry to check
modeMode to check (use MODE_DISCOVERY for binary help)
for_binary_helpIf true, show all options for any mode; if false, filter by mode
Returns
true if option should be displayed for this mode

Definition at line 200 of file core.c.

200 {
201 if (!entry) {
202 SET_ERRNO(ERROR_INVALID_PARAM, "Entry is NULL");
203 return false;
204 }
205
206 // Hardcoded list of options to hide from binary help (matches builder.c line 752)
207 // These are options that have hide_from_binary_help=true set in builder.c
208 const char *hidden_from_binary[] = {NULL};
209
210 // When for_binary_help is true (i.e., for 'ascii-chat --help'),
211 // we want to show all options that apply to any mode, plus binary-level options.
212 if (for_binary_help) {
213 // Check if this option is explicitly hidden from binary help
214 for (int i = 0; hidden_from_binary[i] != NULL; i++) {
215 if (strcmp(entry->long_name, hidden_from_binary[i]) == 0) {
216 return false; // Hidden from binary help
217 }
218 }
219
220 // An option applies if its mode_bitmask has any bit set for any valid mode.
221 // OPTION_MODE_ALL is a bitmask of all modes (including OPTION_MODE_BINARY).
222 return (entry->mode_bitmask & OPTION_MODE_ALL) != 0;
223 }
224
225 // For mode-specific help, show only options for that mode.
226 // Do not show binary options here unless it also specifically applies to the mode.
227 if (mode < 0 || mode > MODE_DISCOVERY) {
228 return false;
229 }
230 option_mode_bitmask_t mode_bit = (1 << mode);
231
232 // Check if it's a binary option. If so, only show if it also explicitly applies to this mode.
233 if ((entry->mode_bitmask & OPTION_MODE_BINARY) && !(entry->mode_bitmask & mode_bit)) {
234 return false; // Binary options not shown in mode-specific help unless also mode-specific
235 }
236
237 return (entry->mode_bitmask & mode_bit) != 0;
238}

Referenced by options_registry_get_for_display().

◆ registry_entry_to_descriptor()

option_descriptor_t registry_entry_to_descriptor ( const registry_entry_t *  entry)

Convert registry entry to option descriptor.

Definition at line 161 of file core.c.

161 {
162 option_descriptor_t desc = {0};
163 if (entry) {
164 desc.long_name = entry->long_name;
165 desc.short_name = entry->short_name;
166 desc.type = entry->type;
167 desc.offset = entry->offset;
168 desc.help_text = entry->help_text;
169 desc.group = entry->group;
170 desc.arg_placeholder = entry->arg_placeholder;
171 desc.hide_from_mode_help = false;
172 // Hide discovery service options from binary-level help (they're for discovery-service mode only)
173 desc.hide_from_binary_help = (entry->mode_bitmask == OPTION_MODE_DISCOVERY_SVC);
174 desc.default_value = entry->default_value;
175 desc.required = entry->required;
176 desc.env_var_name = entry->env_var_name;
177 desc.validate = entry->validate_fn;
178 desc.parse_fn = entry->parse_fn;
179 desc.action_fn = NULL;
180 desc.owns_memory = entry->owns_memory;
181 desc.optional_arg = entry->optional_arg;
182 desc.mode_bitmask = entry->mode_bitmask;
183 desc.metadata = entry->metadata;
184 desc.mode_default_getter = entry->mode_default_getter;
185 }
186 return desc;
187}

Referenced by options_registry_get_binary_options(), options_registry_get_for_display(), and options_registry_get_for_mode().

◆ registry_find_entry_by_name()

const registry_entry_t * registry_find_entry_by_name ( const char *  long_name)

Get a registry entry by long name.

Note
This is used internally for option lookup

Definition at line 127 of file core.c.

127 {
128 if (!long_name) {
129 SET_ERRNO(ERROR_INVALID_PARAM, "Long name is NULL");
130 return NULL;
131 }
132
133 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
134 if (strcmp(g_options_registry[i].long_name, long_name) == 0) {
135 return &g_options_registry[i];
136 }
137 }
138 return NULL;
139}
registry_entry_t g_options_registry[2048]
Definition registry.c:35

References g_options_registry.

Referenced by options_registry_find_by_name().

◆ registry_find_entry_by_short()

const registry_entry_t * registry_find_entry_by_short ( char  short_name)

Get a registry entry by short name.

Note
This is used internally for option lookup

Definition at line 145 of file core.c.

145 {
146 if (short_name == '\0') {
147 return NULL;
148 }
149
150 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
151 if (g_options_registry[i].short_name == short_name) {
152 return &g_options_registry[i];
153 }
154 }
155 return NULL;
156}

References g_options_registry.

Referenced by options_registry_find_by_short().

◆ registry_init_from_builders()

void registry_init_from_builders ( void  )

Initialize registry from category builders Populates g_options_registry by concatenating all category arrays.

Definition at line 23 of file core.c.

23 {
24 static bool initialized = false;
25 if (initialized) {
26 return;
27 }
28
29 size_t offset = 0;
30 for (int i = 0; g_category_builders[i].entries != NULL; i++) {
31 // Count entries in this category (until sentinel terminator)
32 size_t count = 0;
33 for (const registry_entry_t *e = g_category_builders[i].entries; e->long_name != NULL; e++) {
34 count++;
35 }
36
37 // Copy category entries (count already excludes sentinel)
38 if (offset + count <= 2048) {
39 memcpy(&g_options_registry[offset], g_category_builders[i].entries, count * sizeof(registry_entry_t));
40 offset += count;
41 }
42 }
43
44 // Add final null terminator
45 if (offset < 2048) {
46 g_options_registry[offset] = (registry_entry_t){.long_name = NULL,
47 .short_name = '\0',
48 .type = OPTION_TYPE_BOOL,
49 .offset = 0,
50 .default_value = NULL,
51 .default_value_size = 0,
52 .help_text = NULL,
53 .group = NULL,
54 .required = false,
55 .env_var_name = NULL,
56 .validate_fn = NULL,
57 .parse_fn = NULL,
58 .owns_memory = false,
59 .optional_arg = false,
60 .mode_bitmask = OPTION_MODE_NONE,
61 .metadata = {0}};
62 }
63
64 initialized = true;
65}
bool initialized
Definition mmap.c:38
category_builder_t g_category_builders[]
Definition registry.c:26

References g_category_builders, g_options_registry, and initialized.

Referenced by registry_init_size().

◆ registry_init_size()

void registry_init_size ( void  )

Initialize registry size and metadata.

Definition at line 108 of file core.c.

108 {
110
111 if (g_registry_size == 0) {
112 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
114 }
115 // Validate that all options have unique short and long names
117 // DEPRECATED: Metadata is now initialized compile-time in registry entries
118 // registry_populate_metadata_for_critical_options();
120 }
121}
void registry_init_from_builders(void)
Initialize registry from category builders Populates g_options_registry by concatenating all category...
Definition core.c:23
asciichat_error_t registry_validate_unique_options(void)
Validate that no short or long options appear more than once in the registry.
Definition core.c:71
bool g_metadata_populated
Definition registry.c:38
size_t g_registry_size
Definition registry.c:37

References g_metadata_populated, g_options_registry, g_registry_size, registry_init_from_builders(), and registry_validate_unique_options().

Referenced by options_get_help_text(), options_registry_add_all_to_builder(), options_registry_find_by_name(), options_registry_find_by_short(), options_registry_get_binary_options(), options_registry_get_count(), options_registry_get_for_display(), options_registry_get_for_mode(), options_registry_get_metadata(), and options_registry_get_raw().

◆ registry_validate_unique_options()

asciichat_error_t registry_validate_unique_options ( void  )

Validate that no short or long options appear more than once in the registry.

Returns
Result of SET_ERRNO if duplicates found, ASCIICHAT_OK if valid

Definition at line 71 of file core.c.

71 {
72 // Check for duplicate long options
73 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
74 const char *long_name = g_options_registry[i].long_name;
75 if (!long_name || long_name[0] == '\0') {
76 continue; // Skip empty long names
77 }
78
79 for (size_t j = i + 1; g_options_registry[j].long_name != NULL; j++) {
80 if (strcmp(g_options_registry[j].long_name, long_name) == 0) {
81 return SET_ERRNO(ERROR_CONFIG, "Duplicate long option '--%s' at registry indices %zu and %zu", long_name, i, j);
82 }
83 }
84 }
85
86 // Check for duplicate short options (skip if '\0')
87 for (size_t i = 0; g_options_registry[i].long_name != NULL; i++) {
88 char short_name = g_options_registry[i].short_name;
89 if (short_name == '\0') {
90 continue; // Skip if no short option
91 }
92
93 for (size_t j = i + 1; g_options_registry[j].long_name != NULL; j++) {
94 if (g_options_registry[j].short_name == short_name) {
95 return SET_ERRNO(ERROR_CONFIG,
96 "Duplicate short option '-%c' for '--%s' and '--%s' at registry indices %zu and %zu",
97 short_name, g_options_registry[i].long_name, g_options_registry[j].long_name, i, j);
98 }
99 }
100 }
101
102 return ASCIICHAT_OK;
103}

References g_options_registry.

Referenced by registry_init_size().