diff --git a/bench/compose-traversal.c b/bench/compose-traversal.c index 9ecbcca80..76bec9043 100644 --- a/bench/compose-traversal.c +++ b/bench/compose-traversal.c @@ -32,6 +32,16 @@ #define BENCHMARK_ITERATIONS 1000 +// #define USE_FOREACH + +#ifdef USE_FOREACH +static void +compose_fn(struct xkb_compose_table_entry *entry, void *data) +{ + assert (entry); +} +#endif + int main(void) { @@ -67,11 +77,15 @@ main(void) bench_start(&bench); for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { +#ifdef USE_FOREACH + xkb_compose_table_for_each(table, compose_fn, NULL); +#else iter = xkb_compose_table_iterator_new(table); while (xkb_compose_table_iterator_next(iter)) { assert (xkb_compose_table_iterator_current(iter)); } xkb_compose_table_iterator_free(iter); +#endif } bench_stop(&bench); diff --git a/include/xkbcommon/xkbcommon-compose.h b/include/xkbcommon/xkbcommon-compose.h index 4a95d07d6..f0e9b9454 100644 --- a/include/xkbcommon/xkbcommon-compose.h +++ b/include/xkbcommon/xkbcommon-compose.h @@ -378,6 +378,39 @@ xkb_compose_table_entry_keysym(struct xkb_compose_table_entry *entry); const char * xkb_compose_table_entry_utf8(struct xkb_compose_table_entry *entry); +/*******************************************************************************/ +/* [FIXME] FOR TESTING ONLY */ +/*******************************************************************************/ + +/** + * The iterator function type used by xkb_compose_table_for_each(). + * + * @sa xkb_compose_table_for_each + * @memberof xkb_compose + * @since 1.6.0 + */ +typedef void +(*xkb_compose_table_iter_t)(struct xkb_compose_table_entry *entry, + void *data); + +/** + * Run a specified function for every valid entry in the table. + * + * The entries are returned in lexicographic order of the left-hand + * side of entries. This does not correspond to the order in which + * the entries appear in the Compose file. + * + * @memberof xkb_compose_table + * @since 1.6.0 + */ +void +xkb_compose_table_for_each(struct xkb_compose_table *table, + xkb_compose_table_iter_t iter, + void *data); + +/*******************************************************************************/ +/*******************************************************************************/ + /** * @struct xkb_compose_table_iterator * Iterator over a compose table’s entries. diff --git a/src/compose/table.c b/src/compose/table.c index 4595a67ac..151d57b67 100644 --- a/src/compose/table.c +++ b/src/compose/table.c @@ -580,3 +580,48 @@ xkb_compose_table_iterator_next(struct xkb_compose_table_iterator *iter) #endif } + +/*******************************************************************************/ +/* [FIXME] FOR TESTING ONLY */ +/*******************************************************************************/ + +static void +for_each_helper(struct xkb_compose_table *table, + xkb_compose_table_iter_t iter, + void *data, + xkb_keysym_t *syms, + size_t nsyms, + uint16_t p) +{ + if (!p) { + return; + } + const struct compose_node *node = &darray_item(table->nodes, p); + for_each_helper(table, iter, data, syms, nsyms, node->lokid); + syms[nsyms++] = node->keysym; + if (node->is_leaf) { + struct xkb_compose_table_entry entry = { + .sequence = syms, + .sequence_length = nsyms, + .keysym = node->leaf.keysym, + .utf8 = &darray_item(table->utf8, node->leaf.utf8), + }; + iter(&entry, data); + } else { + for_each_helper(table, iter, data, syms, nsyms, node->internal.eqkid); + } + nsyms--; + for_each_helper(table, iter, data, syms, nsyms, node->hikid); +} + +XKB_EXPORT void +xkb_compose_table_for_each(struct xkb_compose_table *table, + xkb_compose_table_iter_t iter, + void *data) +{ + if (darray_size(table->nodes) <= 1) { + return; + } + xkb_keysym_t syms[MAX_LHS_LEN]; + for_each_helper(table, iter, data, syms, 0, 1); +} diff --git a/xkbcommon.map b/xkbcommon.map index 58bb513f2..85f4d67c1 100644 --- a/xkbcommon.map +++ b/xkbcommon.map @@ -119,4 +119,6 @@ global: xkb_compose_table_iterator_free; xkb_compose_table_iterator_current; xkb_compose_table_iterator_next; + // [FIXME] remove + xkb_compose_table_for_each; } V_1.0.0;