Skip to content

Commit

Permalink
Make iterator_next analogous to the recursive version
Browse files Browse the repository at this point in the history
  • Loading branch information
wismill committed Sep 16, 2023
1 parent f14d1e7 commit 21a1d61
Showing 1 changed file with 46 additions and 34 deletions.
80 changes: 46 additions & 34 deletions src/compose/table.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,28 +314,47 @@ xkb_compose_table_iterator_current(struct xkb_compose_table_iterator *iter)
XKB_EXPORT struct xkb_compose_table_entry *
xkb_compose_table_iterator_next(struct xkb_compose_table_iterator *iter)
{
/*
* This function takes the following recursive traversal function,
* and makes it non-recursive and resumable. The iter->cursors stack
* is analogous to the call stack, and cursor->direction to the
* instruction pointer of a stack frame.
*
* traverse(xkb_keysym_t *sequence, size_t sequence_length, uint16_t p) {
* if (!p) return
* // cursor->direction == NODE_LEFT
* node = &darray_item(table->nodes, p)
* traverse(sequence, sequence_length, node->lokid)
* // cursor->direction == NODE_DOWN
* sequence[sequence_length++] = node->keysym
* if (node->is_leaf)
* emit(sequence, sequence_length, node->leaf.keysym, table->utf[node->leaf.utf8])
* else
* traverse(sequence, sequence_length, node->internal.eqkid)
* sequence_length--
* // cursor->direction == NODE_RIGHT
* traverse(sequence, sequence_length, node->hikid)
* // cursor->direction == NODE_UP
* }
*/

struct xkb_compose_table_iterator_cursor *cursor;
struct xkb_compose_table_iterator_cursor new_cursor;
const struct compose_node *node;

cursor = &darray_item(iter->cursors, darray_size(iter->cursors) - 1);
new_cursor.direction = NODE_LEFT;

while (cursor->direction < NODE_UP) {
while (!darray_empty(iter->cursors)) {
cursor = &darray_item(iter->cursors, darray_size(iter->cursors) - 1);
node = &darray_item(iter->table->nodes, cursor->node_offset);

if (cursor->direction == NODE_LEFT) {
/* Left node */
switch (cursor->direction) {
case NODE_LEFT:
cursor->direction = NODE_DOWN;
if (node->lokid) {
new_cursor.node_offset = node->lokid;
struct xkb_compose_table_iterator_cursor new_cursor = {node->lokid, NODE_LEFT};
darray_append(iter->cursors, new_cursor);
cursor = &darray_item(iter->cursors, darray_size(iter->cursors) - 1);
continue;
}
}
if (cursor->direction == NODE_DOWN) {
/* Down node */
break;

case NODE_DOWN:
cursor->direction = NODE_RIGHT;
assert (iter->entry.sequence_length <= MAX_LHS_LEN);
iter->entry.sequence[iter->entry.sequence_length] = node->keysym;
Expand All @@ -345,32 +364,25 @@ xkb_compose_table_iterator_next(struct xkb_compose_table_iterator *iter)
iter->entry.utf8 = &darray_item(iter->table->utf8, node->leaf.utf8);
return &iter->entry;
} else {
new_cursor.node_offset = node->internal.eqkid;
struct xkb_compose_table_iterator_cursor new_cursor = {node->internal.eqkid, NODE_LEFT};
darray_append(iter->cursors, new_cursor);
cursor = &darray_item(iter->cursors, darray_size(iter->cursors) - 1);
continue;
}
}
cursor->direction = NODE_UP;
iter->entry.sequence_length--;
if (node->hikid) {
/* Right node */
new_cursor.node_offset = node->hikid;
darray_append(iter->cursors, new_cursor);
cursor = &darray_item(iter->cursors, darray_size(iter->cursors) - 1);
continue;
} else {
/* Look for next node in parents */
while (darray_size(iter->cursors) > 1) {
darray_remove_last(iter->cursors);
cursor = &darray_item(iter->cursors, darray_size(iter->cursors) - 1);
if (cursor->direction < NODE_UP) {
break;
}
break;

case NODE_RIGHT:
cursor->direction = NODE_UP;
iter->entry.sequence_length--;
if (node->hikid) {
struct xkb_compose_table_iterator_cursor new_cursor = {node->hikid, NODE_LEFT};
darray_append(iter->cursors, new_cursor);
}
break;

case NODE_UP:
darray_remove_last(iter->cursors);
break;
}
}

return NULL;

}

0 comments on commit 21a1d61

Please sign in to comment.