1
0
mirror of https://github.com/systemd/systemd.git synced 2024-12-25 01:34:28 +03:00

Merge pull request #197 from dvdhrm/hashmap

hashmap: fix iterators to not skip entries
This commit is contained in:
Michal Schmidt 2015-06-16 14:44:43 +02:00
commit 9ef41ffeec
9 changed files with 56 additions and 41 deletions

View File

@ -267,8 +267,7 @@ bool fdset_isempty(FDSet *fds) {
int fdset_iterate(FDSet *s, Iterator *i) { int fdset_iterate(FDSet *s, Iterator *i) {
void *p; void *p;
p = set_iterate(MAKE_SET(s), i); if (!set_iterate(MAKE_SET(s), i, &p))
if (!p)
return -ENOENT; return -ENOENT;
return PTR_TO_FD(p); return PTR_TO_FD(p);

View File

@ -733,29 +733,33 @@ static unsigned hashmap_iterate_entry(HashmapBase *h, Iterator *i) {
: hashmap_iterate_in_internal_order(h, i); : hashmap_iterate_in_internal_order(h, i);
} }
void *internal_hashmap_iterate(HashmapBase *h, Iterator *i, const void **key) { bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key) {
struct hashmap_base_entry *e; struct hashmap_base_entry *e;
void *data; void *data;
unsigned idx; unsigned idx;
idx = hashmap_iterate_entry(h, i); idx = hashmap_iterate_entry(h, i);
if (idx == IDX_NIL) { if (idx == IDX_NIL) {
if (value)
*value = NULL;
if (key) if (key)
*key = NULL; *key = NULL;
return NULL; return false;
} }
e = bucket_at(h, idx); e = bucket_at(h, idx);
data = entry_value(h, e); data = entry_value(h, e);
if (value)
*value = data;
if (key) if (key)
*key = e->key; *key = e->key;
return data; return true;
} }
void *set_iterate(Set *s, Iterator *i) { bool set_iterate(Set *s, Iterator *i, void **value) {
return internal_hashmap_iterate(HASHMAP_BASE(s), i, NULL); return internal_hashmap_iterate(HASHMAP_BASE(s), i, value, NULL);
} }
#define HASHMAP_FOREACH_IDX(idx, h, i) \ #define HASHMAP_FOREACH_IDX(idx, h, i) \

View File

@ -65,6 +65,7 @@ typedef struct {
} Iterator; } Iterator;
#define _IDX_ITERATOR_FIRST (UINT_MAX - 1) #define _IDX_ITERATOR_FIRST (UINT_MAX - 1)
#define _IDX_ITERATOR_NIL (UINT_MAX)
#define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL }) #define ITERATOR_FIRST ((Iterator) { .idx = _IDX_ITERATOR_FIRST, .next_key = NULL })
typedef unsigned long (*hash_func_t)(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]); typedef unsigned long (*hash_func_t)(const void *p, const uint8_t hash_key[HASH_KEY_SIZE]);
@ -296,12 +297,12 @@ static inline unsigned ordered_hashmap_buckets(OrderedHashmap *h) {
return internal_hashmap_buckets(HASHMAP_BASE(h)); return internal_hashmap_buckets(HASHMAP_BASE(h));
} }
void *internal_hashmap_iterate(HashmapBase *h, Iterator *i, const void **key); bool internal_hashmap_iterate(HashmapBase *h, Iterator *i, void **value, const void **key);
static inline void *hashmap_iterate(Hashmap *h, Iterator *i, const void **key) { static inline bool hashmap_iterate(Hashmap *h, Iterator *i, void **value, const void **key) {
return internal_hashmap_iterate(HASHMAP_BASE(h), i, key); return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
} }
static inline void *ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, const void **key) { static inline bool ordered_hashmap_iterate(OrderedHashmap *h, Iterator *i, void **value, const void **key) {
return internal_hashmap_iterate(HASHMAP_BASE(h), i, key); return internal_hashmap_iterate(HASHMAP_BASE(h), i, value, key);
} }
void internal_hashmap_clear(HashmapBase *h); void internal_hashmap_clear(HashmapBase *h);
@ -386,24 +387,16 @@ static inline char **ordered_hashmap_get_strv(OrderedHashmap *h) {
* It is safe to remove the current entry. * It is safe to remove the current entry.
*/ */
#define HASHMAP_FOREACH(e, h, i) \ #define HASHMAP_FOREACH(e, h, i) \
for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), NULL); \ for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), NULL); )
(e); \
(e) = hashmap_iterate((h), &(i), NULL))
#define ORDERED_HASHMAP_FOREACH(e, h, i) \ #define ORDERED_HASHMAP_FOREACH(e, h, i) \
for ((i) = ITERATOR_FIRST, (e) = ordered_hashmap_iterate((h), &(i), NULL); \ for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), NULL); )
(e); \
(e) = ordered_hashmap_iterate((h), &(i), NULL))
#define HASHMAP_FOREACH_KEY(e, k, h, i) \ #define HASHMAP_FOREACH_KEY(e, k, h, i) \
for ((i) = ITERATOR_FIRST, (e) = hashmap_iterate((h), &(i), (const void**) &(k)); \ for ((i) = ITERATOR_FIRST; hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
(e); \
(e) = hashmap_iterate((h), &(i), (const void**) &(k)))
#define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \ #define ORDERED_HASHMAP_FOREACH_KEY(e, k, h, i) \
for ((i) = ITERATOR_FIRST, (e) = ordered_hashmap_iterate((h), &(i), (const void**) &(k)); \ for ((i) = ITERATOR_FIRST; ordered_hashmap_iterate((h), &(i), (void**)&(e), (const void**) &(k)); )
(e); \
(e) = ordered_hashmap_iterate((h), &(i), (const void**) &(k)))
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Hashmap*, hashmap_free_free);

View File

@ -47,12 +47,12 @@ static inline bool ordered_set_isempty(OrderedSet *s) {
return ordered_hashmap_isempty((OrderedHashmap*) s); return ordered_hashmap_isempty((OrderedHashmap*) s);
} }
static inline void *ordered_set_iterate(OrderedSet *s, Iterator *i) { static inline bool ordered_set_iterate(OrderedSet *s, Iterator *i, void **value) {
return ordered_hashmap_iterate((OrderedHashmap*) s, i, NULL); return ordered_hashmap_iterate((OrderedHashmap*) s, i, value, NULL);
} }
#define ORDERED_SET_FOREACH(e, s, i) \ #define ORDERED_SET_FOREACH(e, s, i) \
for ((i) = ITERATOR_FIRST, (e) = ordered_set_iterate((s), &(i)); (e); (e) = ordered_set_iterate((s), &(i))) for ((i) = ITERATOR_FIRST; ordered_set_iterate((s), &(i), (void**)&(e)); )
DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free); DEFINE_TRIVIAL_CLEANUP_FUNC(OrderedSet*, ordered_set_free);

View File

@ -91,7 +91,7 @@ static inline unsigned set_buckets(Set *s) {
return internal_hashmap_buckets(HASHMAP_BASE(s)); return internal_hashmap_buckets(HASHMAP_BASE(s));
} }
void *set_iterate(Set *s, Iterator *i); bool set_iterate(Set *s, Iterator *i, void **value);
static inline void set_clear(Set *s) { static inline void set_clear(Set *s) {
internal_hashmap_clear(HASHMAP_BASE(s)); internal_hashmap_clear(HASHMAP_BASE(s));
@ -125,7 +125,7 @@ int set_put_strdup(Set *s, const char *p);
int set_put_strdupv(Set *s, char **l); int set_put_strdupv(Set *s, char **l);
#define SET_FOREACH(e, s, i) \ #define SET_FOREACH(e, s, i) \
for ((i) = ITERATOR_FIRST, (e) = set_iterate((s), &(i)); (e); (e) = set_iterate((s), &(i))) for ((i) = ITERATOR_FIRST; set_iterate((s), &(i), (void**)&(e)); )
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free);
DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free); DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);

View File

@ -248,7 +248,7 @@ _public_ const char* sd_bus_track_first(sd_bus_track *track) {
track->modified = false; track->modified = false;
track->iterator = ITERATOR_FIRST; track->iterator = ITERATOR_FIRST;
hashmap_iterate(track->names, &track->iterator, (const void**) &n); hashmap_iterate(track->names, &track->iterator, NULL, (const void**) &n);
return n; return n;
} }
@ -261,7 +261,7 @@ _public_ const char* sd_bus_track_next(sd_bus_track *track) {
if (track->modified) if (track->modified)
return NULL; return NULL;
hashmap_iterate(track->names, &track->iterator, (const void**) &n); hashmap_iterate(track->names, &track->iterator, NULL, (const void**) &n);
return n; return n;
} }

View File

@ -1371,6 +1371,8 @@ _public_ int sd_device_get_usec_since_initialized(sd_device *device, uint64_t *u
} }
_public_ const char *sd_device_get_tag_first(sd_device *device) { _public_ const char *sd_device_get_tag_first(sd_device *device) {
void *v;
assert_return(device, NULL); assert_return(device, NULL);
(void) device_read_db(device); (void) device_read_db(device);
@ -1378,10 +1380,13 @@ _public_ const char *sd_device_get_tag_first(sd_device *device) {
device->tags_iterator_generation = device->tags_generation; device->tags_iterator_generation = device->tags_generation;
device->tags_iterator = ITERATOR_FIRST; device->tags_iterator = ITERATOR_FIRST;
return set_iterate(device->tags, &device->tags_iterator); set_iterate(device->tags, &device->tags_iterator, &v);
return v;
} }
_public_ const char *sd_device_get_tag_next(sd_device *device) { _public_ const char *sd_device_get_tag_next(sd_device *device) {
void *v;
assert_return(device, NULL); assert_return(device, NULL);
(void) device_read_db(device); (void) device_read_db(device);
@ -1389,10 +1394,13 @@ _public_ const char *sd_device_get_tag_next(sd_device *device) {
if (device->tags_iterator_generation != device->tags_generation) if (device->tags_iterator_generation != device->tags_generation)
return NULL; return NULL;
return set_iterate(device->tags, &device->tags_iterator); set_iterate(device->tags, &device->tags_iterator, &v);
return v;
} }
_public_ const char *sd_device_get_devlink_first(sd_device *device) { _public_ const char *sd_device_get_devlink_first(sd_device *device) {
void *v;
assert_return(device, NULL); assert_return(device, NULL);
(void) device_read_db(device); (void) device_read_db(device);
@ -1400,10 +1408,13 @@ _public_ const char *sd_device_get_devlink_first(sd_device *device) {
device->devlinks_iterator_generation = device->devlinks_generation; device->devlinks_iterator_generation = device->devlinks_generation;
device->devlinks_iterator = ITERATOR_FIRST; device->devlinks_iterator = ITERATOR_FIRST;
return set_iterate(device->devlinks, &device->devlinks_iterator); set_iterate(device->devlinks, &device->devlinks_iterator, &v);
return v;
} }
_public_ const char *sd_device_get_devlink_next(sd_device *device) { _public_ const char *sd_device_get_devlink_next(sd_device *device) {
void *v;
assert_return(device, NULL); assert_return(device, NULL);
(void) device_read_db(device); (void) device_read_db(device);
@ -1411,7 +1422,8 @@ _public_ const char *sd_device_get_devlink_next(sd_device *device) {
if (device->devlinks_iterator_generation != device->devlinks_generation) if (device->devlinks_iterator_generation != device->devlinks_generation)
return NULL; return NULL;
return set_iterate(device->devlinks, &device->devlinks_iterator); set_iterate(device->devlinks, &device->devlinks_iterator, &v);
return v;
} }
static int device_properties_prepare(sd_device *device) { static int device_properties_prepare(sd_device *device) {
@ -1482,7 +1494,7 @@ _public_ const char *sd_device_get_property_first(sd_device *device, const char
device->properties_iterator_generation = device->properties_generation; device->properties_iterator_generation = device->properties_generation;
device->properties_iterator = ITERATOR_FIRST; device->properties_iterator = ITERATOR_FIRST;
value = ordered_hashmap_iterate(device->properties, &device->properties_iterator, (const void**)&key); ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key);
if (_value) if (_value)
*_value = value; *_value = value;
@ -1504,7 +1516,7 @@ _public_ const char *sd_device_get_property_next(sd_device *device, const char *
if (device->properties_iterator_generation != device->properties_generation) if (device->properties_iterator_generation != device->properties_generation)
return NULL; return NULL;
value = ordered_hashmap_iterate(device->properties, &device->properties_iterator, (const void**)&key); ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key);
if (_value) if (_value)
*_value = value; *_value = value;
@ -1562,6 +1574,7 @@ static int device_sysattrs_read_all(sd_device *device) {
} }
_public_ const char *sd_device_get_sysattr_first(sd_device *device) { _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
void *v;
int r; int r;
assert_return(device, NULL); assert_return(device, NULL);
@ -1576,16 +1589,20 @@ _public_ const char *sd_device_get_sysattr_first(sd_device *device) {
device->sysattrs_iterator = ITERATOR_FIRST; device->sysattrs_iterator = ITERATOR_FIRST;
return set_iterate(device->sysattrs, &device->sysattrs_iterator); set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
return v;
} }
_public_ const char *sd_device_get_sysattr_next(sd_device *device) { _public_ const char *sd_device_get_sysattr_next(sd_device *device) {
void *v;
assert_return(device, NULL); assert_return(device, NULL);
if (!device->sysattrs_read) if (!device->sysattrs_read)
return NULL; return NULL;
return set_iterate(device->sysattrs, &device->sysattrs_iterator); set_iterate(device->sysattrs, &device->sysattrs_iterator, &v);
return v;
} }
_public_ int sd_device_has_tag(sd_device *device, const char *tag) { _public_ int sd_device_has_tag(sd_device *device, const char *tag) {

View File

@ -449,7 +449,8 @@ _public_ int sd_hwdb_seek(sd_hwdb *hwdb, const char *modalias) {
} }
_public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value) { _public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **value) {
const void *k, *v; const void *k;
void *v;
assert_return(hwdb, -EINVAL); assert_return(hwdb, -EINVAL);
assert_return(key, -EINVAL); assert_return(key, -EINVAL);
@ -458,7 +459,7 @@ _public_ int sd_hwdb_enumerate(sd_hwdb *hwdb, const char **key, const char **val
if (hwdb->properties_modified) if (hwdb->properties_modified)
return -EAGAIN; return -EAGAIN;
v = ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, &k); ordered_hashmap_iterate(hwdb->properties, &hwdb->properties_iterator, &v, &k);
if (!k) if (!k)
return 0; return 0;

View File

@ -465,6 +465,7 @@ static void test_hashmap_foreach_key(void) {
hashmap_put(m, key, (void*) (const char*) "my dummy val"); hashmap_put(m, key, (void*) (const char*) "my dummy val");
HASHMAP_FOREACH_KEY(s, key, m, i) { HASHMAP_FOREACH_KEY(s, key, m, i) {
assert(s);
if (!key_found[0] && streq(key, "key 1")) if (!key_found[0] && streq(key, "key 1"))
key_found[0] = true; key_found[0] = true;
else if (!key_found[1] && streq(key, "key 2")) else if (!key_found[1] && streq(key, "key 2"))