Skip to content

Instantly share code, notes, and snippets.

@loicmolinari
Created November 19, 2024 00:56
Show Gist options
  • Select an option

  • Save loicmolinari/4ca0107b5571bc9c5868cd5a85005e19 to your computer and use it in GitHub Desktop.

Select an option

Save loicmolinari/4ca0107b5571bc9c5868cd5a85005e19 to your computer and use it in GitHub Desktop.
Extension parser
/* Add extension flags to the bitfield that 'flags_out' points to. 'table'
* stores extension names and flags to check for and 'extensions' is the list
* usually returned by the EGL or GL implementation. New flags are stored using
* a binary OR in order to keep flags set from a previous call. Caller must
* ensure the bitfield is set to 0 at first call.
*/
void
gl_extensions_add(const struct gl_extension_table *table,
const char *extensions,
uint64_t *flags_out)
{
struct { const char *str; size_t len, prev, next; } *list;
size_t i = 0, n = 0;
uint64_t flags = 0;
char prev_char = ' ';
/* Get number of supported extensions. */
while (extensions[i]) {
if (prev_char == ' ' && extensions[i] != ' ')
n++;
prev_char = extensions[i++];
}
if (n == 0)
return;
/* Allocate data structure storing each supported extension string with
* their length. The 'prev' and 'next' members allow to skip extension
* strings already matched using a linked list. There's an additional
* entry to store the head of the list at index 0. */
list = xmalloc((n + 1) * sizeof *list);
list[0].prev = list[0].len = i = 0;
list[0].next = n = 1;
list[0].str = NULL;
prev_char = ' ';
while (prev_char) {
if (extensions[i] != ' ' && extensions[i] != '\0') {
if (prev_char == ' ')
list[n].str = &extensions[i];
} else if (prev_char != ' ') {
list[n].len = &extensions[i] - list[n].str;
list[n].prev = n - 1;
list[n].next = n + 1;
n++;
}
prev_char = extensions[i++];
}
list[n - 1].next = 0;
/* Match supported extensions not yet matched with table. */
for (; table->str && list[0].next; table++) {
for (i = list[0].next; i; i = list[i].next) {
if (table->len == list[i].len &&
!strncmp(table->str, list[i].str, table->len)) {
list[list[i].prev].next = list[i].next;
list[list[i].next].prev = list[i].prev;
flags |= table->flag;
break;
}
}
}
*flags_out |= flags;
free(list);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment