Commit 7b567629 authored by Cody P Schafer's avatar Cody P Schafer Committed by Rusty Russell

htable: add a htable_prev method to oppose _next

Useful for unwinding actions taken while iterating over a htable.
Signed-off-by: default avatarCody P Schafer <dev@codyps.com>
parent d81e79b8
......@@ -135,6 +135,17 @@ void *htable_next(const struct htable *ht, struct htable_iter *i)
return NULL;
}
void *htable_prev(const struct htable *ht, struct htable_iter *i)
{
for (;;) {
if (!i->off)
return NULL;
i->off --;
if (entry_is_valid(ht->table[i->off]))
return get_raw_ptr(ht, ht->table[i->off]);
}
}
/* This does not expand the hash table, that's up to caller. */
static void ht_add(struct htable *ht, const void *new, size_t h)
{
......
......@@ -178,6 +178,21 @@ void *htable_first(const struct htable *htable, struct htable_iter *i);
*/
void *htable_next(const struct htable *htable, struct htable_iter *i);
/**
* htable_prev - find the previous entry in the hash table
* @ht: the hashtable
* @i: the struct htable_iter to use
*
* Get previous entry in the hashtable; NULL if all done.
*
* "previous" here only means the item that would have been returned by
* htable_next() before the item it returned most recently.
*
* This is usually used in the middle of (or after) a htable_next iteration and
* to "unwind" actions taken.
*/
void *htable_prev(const struct htable *htable, struct htable_iter *i);
/**
* htable_delval - remove an iterated pointer from a hash table
* @ht: the htable
......
......@@ -43,6 +43,7 @@
* Iteration over hashtable is also supported:
* type *<name>_first(const struct <name> *ht, struct <name>_iter *i);
* type *<name>_next(const struct <name> *ht, struct <name>_iter *i);
* type *<name>_prev(const struct <name> *ht, struct <name>_iter *i);
*
* It's currently safe to iterate over a changing hashtable, but you might
* miss an element. Iteration isn't very efficient, either.
......@@ -137,6 +138,11 @@
struct name##_iter *iter) \
{ \
return htable_next(&ht->raw, &iter->i); \
} \
static inline UNNEEDED type *name##_prev(const struct name *ht, \
struct name##_iter *iter) \
{ \
return htable_prev(&ht->raw, &iter->i); \
}
#if HAVE_TYPEOF
......
......@@ -116,7 +116,7 @@ int main(int argc, char *argv[])
void *p;
struct htable_obj_iter iter;
plan_tests(26);
plan_tests(27);
for (i = 0; i < NUM_VALS; i++)
val[i].key = i;
dne = i;
......@@ -147,6 +147,10 @@ int main(int argc, char *argv[])
for (p = htable_obj_first(&ht,&iter); p; p = htable_obj_next(&ht, &iter))
i++;
ok1(i == NUM_VALS);
i = 0;
for (p = htable_obj_prev(&ht,&iter); p; p = htable_obj_prev(&ht, &iter))
i++;
ok1(i == NUM_VALS);
/* Delete all. */
del_vals(&ht, val, NUM_VALS);
......
......@@ -105,7 +105,7 @@ int main(int argc, char *argv[])
void *p;
struct htable_iter iter;
plan_tests(35);
plan_tests(36);
for (i = 0; i < NUM_VALS; i++)
val[i] = i;
dne = i;
......@@ -156,6 +156,11 @@ int main(int argc, char *argv[])
i++;
ok1(i == NUM_VALS);
i = 0;
for (p = htable_prev(&ht, &iter); p; p = htable_prev(&ht, &iter))
i++;
ok1(i == NUM_VALS);
/* Delete all. */
del_vals(&ht, val, NUM_VALS);
ok1(!htable_get(&ht, hash(&val[0], NULL), objcmp, &val[0]));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment