summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Kos <okos@redhat.com>2013-04-02 17:28:32 +0200
committerOndrej Kos <okos@redhat.com>2013-04-05 14:02:07 +0200
commitf8a80797c298f4ebe2dc2ebcb2327fa1f3a38905 (patch)
treee902c809ff5d69dc9df0599f81b2f9a6dccc0ace
parente9a8759bcc696d78ce9d8187e263cfd90c96fdef (diff)
downloadding-libs-f8a80797c298f4ebe2dc2ebcb2327fa1f3a38905.zip
ding-libs-f8a80797c298f4ebe2dc2ebcb2327fa1f3a38905.tar.gz
ding-libs-f8a80797c298f4ebe2dc2ebcb2327fa1f3a38905.tar.xz
DHASH: Don't use backward jumps
https://fedorahosted.org/sssd/ticket/1855
-rw-r--r--dhash/dhash.c79
1 files changed, 56 insertions, 23 deletions
diff --git a/dhash/dhash.c b/dhash/dhash.c
index 72709af..ab1bebc 100644
--- a/dhash/dhash.c
+++ b/dhash/dhash.c
@@ -124,6 +124,14 @@ struct _hash_iter_context_t {
element_t *p;
};
+enum hash_iter_state {
+ HI_STATE_0,
+ HI_STATE_1,
+ HI_STATE_2,
+ HI_STATE_3A,
+ HI_STATE_3B
+};
+
/*****************************************************************************/
/********************** External Function Declarations *********************/
/*****************************************************************************/
@@ -709,32 +717,57 @@ static hash_entry_t *hash_iter_next(struct hash_iter_context_t *iter_arg)
{
struct _hash_iter_context_t *iter = (struct _hash_iter_context_t *) iter_arg;
hash_entry_t *entry;
+ enum hash_iter_state state = HI_STATE_3A;
if (iter->table == NULL) return NULL;
- goto state_3a;
-
- state_1:
- iter->i++;
- if(iter->i >= iter->table->segment_count) return NULL;
- /* test probably unnecessary */
- iter->s = iter->table->directory[iter->i];
- if (iter->s == NULL) goto state_1;
- iter->j = 0;
- state_2:
- if (iter->j >= iter->table->segment_size) goto state_1;
- iter->p = iter->s[iter->j];
- state_3a:
- if (iter->p == NULL) goto state_3b;
- entry = &iter->p->entry;
- iter->p = iter->p->next;
- return entry;
- state_3b:
- iter->j++;
- goto state_2;
- /* Should never reach here */
- fprintf(stderr, "ERROR hash_iter_next reached invalid state\n");
- return NULL;
+ while (state != HI_STATE_0) {
+
+ switch (state) {
+ case HI_STATE_1:
+ iter->i++;
+ if(iter->i >= iter->table->segment_count) return NULL;
+ /* test probably unnecessary */
+ iter->s = iter->table->directory[iter->i];
+ if (iter->s == NULL) {
+ state = HI_STATE_1;
+ break;
+ }
+ iter->j = 0;
+ state = HI_STATE_2;
+
+ case HI_STATE_2:
+ if (iter->j >= iter->table->segment_size) {
+ state = HI_STATE_1;
+ break;
+ }
+ iter->p = iter->s[iter->j];
+ state = HI_STATE_3A;
+
+ case HI_STATE_3A:
+ if (iter->p == NULL) {
+ state = HI_STATE_3B;
+ break;
+ }
+ entry = &iter->p->entry;
+ iter->p = iter->p->next;
+ state = HI_STATE_0;
+ break;
+
+ case HI_STATE_3B:
+ iter->j++;
+ state = HI_STATE_2;
+ break;
+
+ default:
+ /* Should never reach here */
+ fprintf(stderr, "ERROR hash_iter_next reached invalid state\n");
+ return NULL;
+ break;
+ }
+ }
+
+ return entry;
}
struct hash_iter_context_t *new_hash_iter_context(hash_table_t *table)