From: Rusty Russell Date: Tue, 1 Nov 2011 23:05:29 +0000 (+1030) Subject: strmap: set errno to ENOENT even if we return NULL. X-Git-Url: http://git.ozlabs.org/?p=ccan;a=commitdiff_plain;h=8bb0697b44f0dc4168f72ee621a291d68fefd4ad strmap: set errno to ENOENT even if we return NULL. It seems redundant: strmap_get() and strmap_del() can only return NULL when the string is not a member. However, it became clear in writing ccan/tsort that it's much more convenient for callers if we set errno in this case too, so they can pass it up. --- diff --git a/ccan/strmap/strmap.c b/ccan/strmap/strmap.c index 2b89fe0d..872ca544 100644 --- a/ccan/strmap/strmap.c +++ b/ccan/strmap/strmap.c @@ -39,12 +39,13 @@ void *strmap_get_(const struct strmap *map, const char *member) { struct strmap *n; - /* Empty map? */ - if (!map->u.n) - return NULL; - n = closest((struct strmap *)map, member); - if (streq(member, n->u.s)) - return n->v; + /* Not empty map? */ + if (map->u.n) { + n = closest((struct strmap *)map, member); + if (streq(member, n->u.s)) + return n->v; + } + errno = ENOENT; return NULL; } @@ -129,8 +130,10 @@ char *strmap_del_(struct strmap *map, const char *member, void **valuep) u8 direction = 0; /* prevent bogus gcc warning. */ /* Empty map? */ - if (!map->u.n) + if (!map->u.n) { + errno = ENOENT; return NULL; + } /* Find closest, but keep track of parent. */ n = map; @@ -148,8 +151,10 @@ char *strmap_del_(struct strmap *map, const char *member, void **valuep) } /* Did we find it? */ - if (!streq(member, n->u.s)) + if (!streq(member, n->u.s)) { + errno = ENOENT; return NULL; + } ret = n->u.s; if (valuep) diff --git a/ccan/strmap/strmap.h b/ccan/strmap/strmap.h index e85b8c8f..d6104942 100644 --- a/ccan/strmap/strmap.h +++ b/ccan/strmap/strmap.h @@ -77,7 +77,7 @@ static inline bool strmap_empty_(const struct strmap *map) * @map: the typed strmap to search. * @member: the string to search for. * - * Returns the value, or NULL if it isn't in the map. + * Returns the value, or NULL if it isn't in the map (and sets errno = ENOENT). * * Example: * int *val = strmap_get(&map, "hello"); @@ -118,7 +118,9 @@ bool strmap_add_(struct strmap *map, const char *member, const void *value); * @member: the string to remove from the map. * @valuep: the value (if non-NULL) * - * This returns the string which was passed to strmap_map(), or NULL. + * This returns the string which was passed to strmap_map(), or NULL if + * it was not in the map (and sets errno = ENOENT). + * * This means that if you allocated a string (eg. using strdup()), you * can free it here. Similarly, the value is returned in @valuep if * @valuep is not NULL. diff --git a/ccan/strmap/test/run.c b/ccan/strmap/test/run.c index 34302846..aaa86181 100644 --- a/ccan/strmap/test/run.c +++ b/ccan/strmap/test/run.c @@ -14,20 +14,25 @@ int main(void) char *v; /* This is how many tests you plan to run */ - plan_tests(32); + plan_tests(42); strmap_init(&map); ok1(!strmap_get(&map, str)); + ok1(errno == ENOENT); ok1(!strmap_get(&map, none)); + ok1(errno == ENOENT); ok1(!strmap_del(&map, str, NULL)); + ok1(errno == ENOENT); ok1(!strmap_del(&map, none, NULL)); + ok1(errno == ENOENT); ok1(strmap_add(&map, str, val)); ok1(strmap_get(&map, str) == val); /* We compare the string, not the pointer. */ ok1(strmap_get(&map, dup) == val); ok1(!strmap_get(&map, none)); + ok1(errno == ENOENT); /* Add a duplicate should fail. */ ok1(!strmap_add(&map, dup, val)); @@ -38,18 +43,23 @@ int main(void) ok1(strmap_del(&map, dup, &v) == str); ok1(v == val); ok1(!strmap_get(&map, str)); + ok1(errno == ENOENT); ok1(!strmap_get(&map, none)); + ok1(errno == ENOENT); /* Try insert and delete of empty string. */ ok1(strmap_add(&map, none, none)); ok1(strmap_get(&map, none) == none); ok1(!strmap_get(&map, str)); + ok1(errno == ENOENT); /* Delete should return original string. */ ok1(strmap_del(&map, "", &v) == none); ok1(v == none); ok1(!strmap_get(&map, str)); + ok1(errno == ENOENT); ok1(!strmap_get(&map, none)); + ok1(errno == ENOENT); /* Both at once... */ ok1(strmap_add(&map, none, none));