Commit 7537c9fd authored by Tim Rühsen's avatar Tim Rühsen

Add iterators for hashmap and stringmap

* include/wget/wget.h: New functions wget_hashmap_iterator_alloc(),
  wget_hashmap_iterator_free(), wget_hashmap_iterator_next(),
  also for stringmap.
* libwget/hashmap.c: Implementation of the above functions
* libwget/stringmap.c: Add wget_stringmap_iterator_next()
* unit-tests/test.c: Add tests using stringmap iterator

This functionality is sometimes more handy than the *_browse() API
with callback functions and context variables.
parent 34ef48bb
Pipeline #42009145 failed with stages
in 27 minutes and 19 seconds
......@@ -694,6 +694,7 @@ WGETAPI void
*/
typedef struct _wget_hashmap_st wget_hashmap_t;
typedef struct _wget_hashmap_iterator_st wget_hashmap_iterator_t;
typedef int (*wget_hashmap_compare_t)(const void *key1, const void *key2);
typedef unsigned int (*wget_hashmap_hash_t)(const void *value);
typedef int (*wget_hashmap_browse_t)(void *ctx, const void *key, void *value);
......@@ -736,17 +737,29 @@ WGETAPI void
WGETAPI void
wget_hashmap_set_load_factor(wget_hashmap_t *h, float factor);
WGETAPI wget_hashmap_iterator_t
*wget_hashmap_iterator_alloc(wget_hashmap_t *h) G_GNUC_WGET_MALLOC;
WGETAPI void
wget_hashmap_iterator_free(wget_hashmap_iterator_t *it);
WGETAPI void
*wget_hashmap_iterator_next(wget_hashmap_iterator_t *it, void **value);
/*
* Stringmap datatype routines
*/
typedef wget_hashmap_t wget_stringmap_t;
typedef wget_hashmap_iterator_t wget_stringmap_iterator_t;
typedef int (*wget_stringmap_compare_t)(const char *key1, const char *key2);
typedef unsigned int (*wget_stringmap_hash_t)(const char *value);
typedef int (*wget_stringmap_browse_t)(void *ctx, const char *key, void *value);
typedef void (*wget_stringmap_key_destructor_t)(char *key);
typedef void (*wget_stringmap_value_destructor_t)(void *value);
#define wget_stringmap_iterator_alloc wget_hashmap_iterator_alloc
#define wget_stringmap_iterator_free wget_hashmap_iterator_free
// #define wget_stringmap_iterator_next(a,b) ((char *) wget_hashmap_iterator_next((a),(b)))
WGETAPI wget_stringmap_t *
wget_stringmap_create(int max) G_GNUC_WGET_MALLOC;
WGETAPI wget_stringmap_t *
......@@ -784,6 +797,8 @@ WGETAPI void
wget_stringmap_set_load_factor(wget_stringmap_t *h, float factor);
WGETAPI void
wget_stringmap_set_resize_factor(wget_stringmap_t *h, float factor);
WGETAPI void
*wget_stringmap_iterator_next(wget_stringmap_iterator_t *it, char **value);
/*
* Thread wrapper routines
......
......@@ -67,6 +67,57 @@ struct _wget_hashmap_st {
load_factor;
};
struct _wget_hashmap_iterator_st {
struct _wget_hashmap_st
*h;
_entry_t
*entry;
int
pos;
};
wget_hashmap_iterator_t *wget_hashmap_iterator_alloc(wget_hashmap_t *h)
{
struct _wget_hashmap_iterator_st *it = wget_calloc(1, sizeof(struct _wget_hashmap_iterator_st));
it->h = h;
return (wget_hashmap_iterator_t *) it;
}
void wget_hashmap_iterator_free(wget_hashmap_iterator_t *it)
{
xfree(it);
}
void *wget_hashmap_iterator_next(wget_hashmap_iterator_t *it, void **value)
{
struct _wget_hashmap_iterator_st *iter = (struct _wget_hashmap_iterator_st *) it;
struct _wget_hashmap_st *h = iter->h;
if (iter->entry) {
if ((iter->entry = iter->entry->next)) {
found:
if (value)
*value = iter->entry->value;
return iter->entry->key;
}
iter->pos++;
}
if (!iter->entry) {
for (; iter->pos < h->max; iter->pos++) {
if (h->entry[iter->pos]) {
iter->entry = h->entry[iter->pos];
goto found;
}
}
}
return NULL;
}
/**
* \file
* \brief Hashmap functions
......
......@@ -352,4 +352,9 @@ void wget_stringmap_set_resize_factor(wget_stringmap_t *h, float factor)
wget_hashmap_set_resize_factor(h, factor);
}
void *wget_stringmap_iterator_next(wget_stringmap_iterator_t *h, char **value)
{
return wget_hashmap_iterator_next(h, (void **) value);
}
/**@}*/
......@@ -38,6 +38,7 @@
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <c-ctype.h>
#include <wget.h>
#include "../libwget/private.h"
......@@ -1830,7 +1831,8 @@ static unsigned int hash_txt(G_GNUC_WGET_UNUSED const char *key)
static void test_stringmap(void)
{
wget_stringmap_t *m;
char key[128], value[128], *val;
wget_stringmap_iterator_t *iter;
char key[128], value[128], *val, *skey;
int run, it;
size_t valuesize;
......@@ -1858,6 +1860,22 @@ static void test_stringmap(void)
info_printf("stringmap_size() returned %d (expected %d)\n", it, 26);
} else ok++;
iter = wget_stringmap_iterator_alloc(m);
for (it = 0; (skey = wget_stringmap_iterator_next(iter, &val)); it++) {
int n = atoi(skey + 30), m = atoi(val);
if (!(c_isdigit(*val) && n >= 0 && n == m)) {
failed++;
info_printf("key/value don't match (%s | %s)\n", key, val);
} else ok++;
}
wget_stringmap_iterator_free(iter); iter = NULL;
if (it != wget_stringmap_size(m)) {
failed++;
info_printf("stringmap iterator just found %d items (expected %d)\n", it, wget_stringmap_size(m));
} else ok++;
// now, look up every single entry
for (it = 0; it < 26; it++) {
snprintf(key, sizeof(key), "http://www.example.com/subdir/%d.html", it);
......
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