]> granicus.if.org Git - p11-kit/commitdiff
dict: Allow removal of current item in a p11_dict iteration
authorStef Walter <stefw@gnome.org>
Wed, 6 Mar 2013 18:12:28 +0000 (19:12 +0100)
committerStef Walter <stefw@gnome.org>
Fri, 15 Mar 2013 16:21:49 +0000 (17:21 +0100)
 * This was already possible to do safely before
 * Document and test this behavior

https://bugs.freedesktop.org/show_bug.cgi?id=61499

common/dict.h
common/tests/test-dict.c

index e13c5d61ca924a406f1f73a19f927d01d05118f8..080f6b8b7dac3a60eb70be723bf4607d20702899 100644 (file)
@@ -141,6 +141,8 @@ void                p11_dict_iterate           (p11_dict *dict,
  *  p11_dict_next: Enumerate through hash table
  * - sets key and value to key and/or value
  * - returns whether there was another entry
+ * - p11_dict_remove or p11_dict_steal is safe to use on
+ *   the current key.
  */
 bool                p11_dict_next              (p11_dictiter *iter,
                                                 void **key,
index 00b64c5872dfdf4166d80377103e6471603d6f75..316d9f567466ec05cb2a5a8be549dfa48839a8f2 100644 (file)
@@ -143,6 +143,65 @@ test_iterate (CuTest *tc)
        p11_dict_free (map);
 }
 
+static int
+compar_pointers (const void *one,
+                 const void *two)
+{
+       char **p1 = (char **)one;
+       char **p2 = (char **)two;
+       return *p1 - *p2;
+}
+
+static void
+test_iterate_remove (CuTest *tc)
+{
+       p11_dict *map;
+       p11_dictiter iter;
+       char *keys[] = { "one", "two", "three" };
+       char *values[] = { "four", "eight", "twelve" };
+       void *okeys[3];
+       void *ovalues[3];
+       bool ret;
+       int i;
+
+       map = p11_dict_new (p11_dict_direct_hash, p11_dict_direct_equal, NULL, NULL);
+       CuAssertPtrNotNull (tc, map);
+
+       for (i = 0; i < 3; i++) {
+               if (!p11_dict_set (map, keys[i], values[i]))
+                       CuFail (tc, "should not be reached");
+       }
+
+       p11_dict_iterate (map, &iter);
+
+       ret = p11_dict_next (&iter, &okeys[0], &ovalues[0]);
+       CuAssertIntEquals (tc, true, ret);
+
+       ret = p11_dict_next (&iter, &okeys[1], &ovalues[1]);
+       CuAssertIntEquals (tc, true, ret);
+       if (!p11_dict_remove (map, okeys[1]))
+               CuFail (tc, "should not be reached");
+
+       ret = p11_dict_next (&iter, &okeys[2], &ovalues[2]);
+       CuAssertIntEquals (tc, true, ret);
+
+       ret = p11_dict_next (&iter, NULL, NULL);
+       CuAssertIntEquals (tc, false, ret);
+
+       CuAssertIntEquals (tc, 2, p11_dict_size (map));
+       p11_dict_free (map);
+
+       qsort (okeys, 3, sizeof (void *), compar_pointers);
+       qsort (ovalues, 3, sizeof (void *), compar_pointers);
+
+       for (i = 0; i < 3; i++) {
+               CuAssertStrEquals (tc, keys[i], okeys[i]);
+               CuAssertPtrEquals (tc, keys[i], okeys[i]);
+               CuAssertStrEquals (tc, values[i], ovalues[i]);
+               CuAssertPtrEquals (tc, values[i], ovalues[i]);
+       }
+}
+
 static void
 test_set_get (CuTest *tc)
 {
@@ -455,6 +514,7 @@ main (void)
        SUITE_ADD_TEST (suite, test_free_null);
        SUITE_ADD_TEST (suite, test_free_destroys);
        SUITE_ADD_TEST (suite, test_iterate);
+       SUITE_ADD_TEST (suite, test_iterate_remove);
        SUITE_ADD_TEST (suite, test_hash_add_check_lots_and_collisions);
        SUITE_ADD_TEST (suite, test_hash_count);
        SUITE_ADD_TEST (suite, test_hash_ulongptr);