strset: set errno to ENOENT even if we return NULL.
authorRusty Russell <rusty@rustcorp.com.au>
Tue, 1 Nov 2011 23:06:29 +0000 (09:36 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 1 Nov 2011 23:06:29 +0000 (09:36 +1030)
It seems redundant: strset_test() and strset_clear() 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.

ccan/strset/strset.c
ccan/strset/strset.h
ccan/strset/test/run.c

index 7c64b0cd016631017024da239cc29ad7e5470ec0..a5441d4462e27da84ca1cf01ccfc897564c0bb98 100644 (file)
@@ -61,12 +61,13 @@ char *strset_test(const struct strset *set, const char *member)
 {
        const char *str;
 
-       /* Empty set? */
-       if (!set->u.n)
-               return NULL;
-       str = closest(*set, member);
-       if (streq(member, str))
-               return (char *)str;
+       /* Non-empty set? */
+       if (set->u.n) {
+               str = closest(*set, member);
+               if (streq(member, str))
+                       return (char *)str;
+       }
+       errno = ENOENT;
        return NULL;
 }
 
@@ -171,8 +172,10 @@ char *strset_clear(struct strset *set, const char *member)
        u8 direction = 0; /* prevent bogus gcc warning. */
 
        /* Empty set? */
-       if (!set->u.n)
+       if (!set->u.n) {
+               errno = ENOENT;
                return NULL;
+       }
 
        /* Find closest, but keep track of parent. */
        n = set;
@@ -184,8 +187,10 @@ char *strset_clear(struct strset *set, const char *member)
                if (unlikely(n->u.n->byte_num == (size_t)-1)) {
                        const char *empty_str = n->u.n->child[0].u.s;
 
-                       if (member[0])
+                       if (member[0]) {
+                               errno = ENOENT;
                                return NULL;
+                       }
 
                        /* Sew empty string back so remaining logic works */
                        free(n->u.n);
@@ -203,8 +208,10 @@ char *strset_clear(struct strset *set, const char *member)
        }
 
        /* Did we find it? */
-       if (!streq(member, n->u.s))
+       if (!streq(member, n->u.s)) {
+               errno = ENOENT;
                return NULL;
+       }
 
        ret = n->u.s;
 
index b8116c35c471813e5330d10b930aaaf82b26e69b..250ce7189614a357b89cb2bc7620283a2254caaa 100644 (file)
@@ -52,7 +52,8 @@ static inline bool strset_empty(const struct strset *set)
  * @set: the set.
  * @member: the string to search for.
  *
- * Returns the member, or NULL if it isn't in the set.
+ * Returns the member, or NULL if it isn't in the set (and sets errno
+ * = ENOENT).
  *
  * Example:
  *     if (strset_test(&set, "hello"))
@@ -82,7 +83,9 @@ bool strset_set(struct strset *set, const char *member);
  * @set: the set.
  * @member: the string to remove from the set.
  *
- * This returns the string which was passed to strset_set(), or NULL.
+ * This returns the string which was passed to strset_set(), or NULL if
+ * the string was not in the map (in which case it sets errno = ENOENT).
+ *
  * This means that if you allocated a string (eg. using strdup()), you can
  * free it here.
  *
index cfda0ee38f0ce998a16c5779fc793d8bf0722565..412a1fdfb1b1532ccb41e03569bee8feff5c0cc7 100644 (file)
@@ -10,20 +10,25 @@ int main(void)
        char *dup = strdup(str);
 
        /* This is how many tests you plan to run */
-       plan_tests(26);
+       plan_tests(36);
 
        strset_init(&set);
 
        ok1(!strset_test(&set, str));
+       ok1(errno == ENOENT);
        ok1(!strset_test(&set, none));
+       ok1(errno == ENOENT);
        ok1(!strset_clear(&set, str));
+       ok1(errno == ENOENT);
        ok1(!strset_clear(&set, none));
+       ok1(errno == ENOENT);
 
        ok1(strset_set(&set, str));
        ok1(strset_test(&set, str));
        /* We compare the string, not the pointer. */
        ok1(strset_test(&set, dup));
        ok1(!strset_test(&set, none));
+       ok1(errno == ENOENT);
 
        /* Add of duplicate should fail. */
        ok1(!strset_set(&set, dup));
@@ -32,17 +37,22 @@ int main(void)
        /* Delete should return original string. */
        ok1(strset_clear(&set, dup) == str);
        ok1(!strset_test(&set, str));
+       ok1(errno == ENOENT);
        ok1(!strset_test(&set, none));
+       ok1(errno == ENOENT);
 
        /* Try insert and delete of empty string. */
        ok1(strset_set(&set, none));
        ok1(strset_test(&set, none));
        ok1(!strset_test(&set, str));
+       ok1(errno == ENOENT);
 
        /* Delete should return original string. */
        ok1(strset_clear(&set, "") == none);
        ok1(!strset_test(&set, str));
+       ok1(errno == ENOENT);
        ok1(!strset_test(&set, none));
+       ok1(errno == ENOENT);
 
        /* Both at once... */
        ok1(strset_set(&set, none));