Commit 9f2f2247 9f2f2247b8191614c4344dce26eb3336224eac06 by Sergey Poznyakoff

Implement bidirectional iteration over lists.

* include/mailutils/iterator.h (mu_itrctl_qry_direction)
(mu_itrctl_set_direction): New mu_itrctl_req constants.
* mailbox/iterator.c (mu_iterator_dup): Bugfix: copy dup as well.
* mailbox/list.c (struct list_iterator)
<backwards>: New member.
(first, next): Move direction depends on the value
of list_iterator.backwards.
(list_itrctl): Handle mu_itrctl_qry_direction and
mu_itrctl_set_direction

* examples/listop.c (ictl_dir): New function.
(ictl_ins): Handle new subcommand "dir".
(help): Show new subcommand "dir".
* mailbox/testsuite/mailbox/list.exp: Add tests for
iteration backwards.
1 parent 1413567b
......@@ -285,6 +285,41 @@ ictl_repl (mu_iterator_t itr, int argc, char **argv)
}
void
ictl_dir (mu_iterator_t itr, int argc, char **argv)
{
int rc;
int dir;
if (argc > 1)
{
fprintf (stderr, "ictl dir [backwards|forwards]?\n");
return;
}
if (argc == 1)
{
if (strcmp (argv[0], "backwards") == 0)
dir = 1;
else if (strcmp (argv[0], "forwards") == 0)
dir = 0;
else
{
fprintf (stderr, "ictl dir [backwards|forwards]?\n");
return;
}
rc = mu_iterator_ctl (itr, mu_itrctl_set_direction, &dir);
if (rc)
lperror ("mu_iterator_ctl", rc);
}
else
{
rc = mu_iterator_ctl (itr, mu_itrctl_qry_direction, &dir);
if (rc)
lperror ("mu_iterator_ctl", rc);
printf ("%s\n", dir ? "backwards" : "forwards");
}
}
void
ictl_ins (mu_iterator_t itr, int argc, char **argv)
{
int rc;
......@@ -324,6 +359,8 @@ ictl (mu_iterator_t itr, int argc, char **argv)
ictl_repl (itr, argc - 2, argv + 2);
else if (strcmp (argv[1], "ins") == 0)
ictl_ins (itr, argc - 2, argv + 2);
else if (strcmp (argv[1], "dir") == 0)
ictl_dir (itr, argc - 2, argv + 2);
else
fprintf (stderr, "unknown subcommand\n");
}
......@@ -391,6 +428,7 @@ help ()
printf ("ictl del\n");
printf ("ictl repl item\n");
printf ("ictl ins item [item*]\n");
printf ("ictl dir [backwards|forwards]\n");
printf ("print\n");
printf ("quit\n");
printf ("iter num\n");
......
......@@ -28,13 +28,15 @@ extern "C" {
enum mu_itrctl_req
{
mu_itrctl_tell, /* Return current position in the object */
mu_itrctl_delete, /* Delete current element */
mu_itrctl_delete_nd, /* Delete current element, non-destructive */
mu_itrctl_replace, /* Replace current element */
mu_itrctl_replace_nd, /* Replace current element, non-destructive */
mu_itrctl_insert, /* Insert new element in the current position */
mu_itrctl_insert_list, /* Insert a list of elements */
mu_itrctl_tell, /* Return current position in the object */
mu_itrctl_delete, /* Delete current element */
mu_itrctl_delete_nd, /* Delete current element, non-destructive */
mu_itrctl_replace, /* Replace current element */
mu_itrctl_replace_nd, /* Replace current element, non-destructive */
mu_itrctl_insert, /* Insert new element in the current position */
mu_itrctl_insert_list, /* Insert a list of elements */
mu_itrctl_qry_direction, /* Query iteration direction */
mu_itrctl_set_direction /* Set iteration direction */
};
extern int mu_iterator_create (mu_iterator_t *, void *);
......
......@@ -145,14 +145,15 @@ mu_iterator_dup (mu_iterator_t *piterator, mu_iterator_t orig)
return status;
}
iterator->is_advanced = orig->is_advanced;
iterator->dup = orig->dup;
iterator->destroy = orig->destroy;
iterator->first = orig->first;
iterator->next = orig->next;
iterator->getitem = orig->getitem;
iterator->finished_p = orig->finished_p;
iterator->curitem_p = orig->curitem_p;
iterator->dup = orig->dup;
iterator->destroy = orig->destroy;
iterator->finished_p = orig->finished_p;
iterator->itrctl = orig->itrctl;
*piterator = iterator;
return 0;
}
......
......@@ -479,13 +479,17 @@ struct list_iterator
{
mu_list_t list;
struct list_data *cur;
int backwards; /* true if iterating backwards */
};
static int
first (void *owner)
{
struct list_iterator *itr = owner;
itr->cur = itr->list->head.next;
if (itr->backwards)
itr->cur = itr->list->head.prev;
else
itr->cur = itr->list->head.next;
return 0;
}
......@@ -493,7 +497,10 @@ static int
next (void *owner)
{
struct list_iterator *itr = owner;
itr->cur = itr->cur->next;
if (itr->backwards)
itr->cur = itr->cur->prev;
else
itr->cur = itr->cur->next;
return 0;
}
......@@ -618,6 +625,20 @@ list_itrctl (void *owner, enum mu_itrctl_req req, void *arg)
_mu_list_clear (new_list);
}
break;
case mu_itrctl_qry_direction:
if (!arg)
return EINVAL;
else
*(int*)arg = itr->backwards;
break;
case mu_itrctl_set_direction:
if (!arg)
return EINVAL;
else
itr->backwards = !!*(int*)arg;
break;
default:
return ENOSYS;
......
......@@ -301,6 +301,29 @@ mailbox_prog_test "print" \
prompt_text "tres"
mailbox_prog_test "next"
mailbox_prog_test "ictl dir" "forwards"
mailbox_prog_test "ictl dir backwards"
prompt_text "dos"
mailbox_prog_test "next"
prompt_text "dwa"
mailbox_prog_test "next 4"
prompt_text "jeden"
mailbox_prog_test "ictl del"
mailbox_prog_test "next"
prompt_text "zero"
mailbox_prog_test "next"
mailbox_prog_test "ictl dir forwards"
prompt_text "jeden"
mailbox_prog_test "next"
mailbox_prog_send "quit"
mailbox_prog_stop
......