Add sortedcache APIs to lookup index and remove This adds two other APIs that I need to the sortedcache type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
diff --git a/src/sortedcache.c b/src/sortedcache.c
index 6015d61..2efa3c4 100644
--- a/src/sortedcache.c
+++ b/src/sortedcache.c
@@ -295,3 +295,62 @@ void *git_sortedcache_entry(const git_sortedcache *sc, size_t pos)
{
return git_vector_get(&sc->items, pos);
}
+
+struct sortedcache_magic_key {
+ size_t offset;
+ const char *key;
+};
+
+static int sortedcache_magic_cmp(const void *key, const void *value)
+{
+ const struct sortedcache_magic_key *magic = key;
+ const char *value_key = ((const char *)value) + magic->offset;
+ return strcmp(magic->key, value_key);
+}
+
+/* lookup index of item by key */
+int git_sortedcache_lookup_index(
+ size_t *out, git_sortedcache *sc, const char *key)
+{
+ struct sortedcache_magic_key magic;
+
+ magic.offset = sc->item_path_offset;
+ magic.key = key;
+
+ return git_vector_bsearch2(out, &sc->items, sortedcache_magic_cmp, &magic);
+}
+
+/* remove entry from cache */
+int git_sortedcache_remove(git_sortedcache *sc, size_t pos, bool lock)
+{
+ int error = 0;
+ char *item;
+ khiter_t mappos;
+
+ if (lock && git_sortedcache_lock(sc) < 0)
+ return -1;
+
+ /* because of pool allocation, this can't actually remove the item,
+ * but we can remove it from the items vector and the hash table.
+ */
+
+ if ((item = git_vector_get(&sc->items, pos)) == NULL) {
+ giterr_set(GITERR_INVALID, "Removing item out of range");
+ error = GIT_ENOTFOUND;
+ goto done;
+ }
+
+ (void)git_vector_remove(&sc->items, pos);
+
+ mappos = git_strmap_lookup_index(sc->map, item + sc->item_path_offset);
+ git_strmap_delete_at(sc->map, mappos);
+
+ if (sc->free_item)
+ sc->free_item(sc->free_item_payload, item);
+
+done:
+ if (lock)
+ git_sortedcache_unlock(sc);
+ return error;
+}
+
diff --git a/src/sortedcache.h b/src/sortedcache.h
index 5d0d8f5..f63ad64 100644
--- a/src/sortedcache.h
+++ b/src/sortedcache.h
@@ -98,4 +98,11 @@ size_t git_sortedcache_entrycount(const git_sortedcache *sc);
/* lookup item by index */
void *git_sortedcache_entry(const git_sortedcache *sc, size_t pos);
+/* lookup index of item by key */
+int git_sortedcache_lookup_index(
+ size_t *out, git_sortedcache *sc, const char *key);
+
+/* remove entry from cache */
+int git_sortedcache_remove(git_sortedcache *sc, size_t pos, bool lock);
+
#endif
diff --git a/tests-clar/core/sortedcache.c b/tests-clar/core/sortedcache.c
index f192af3..9141594 100644
--- a/tests-clar/core/sortedcache.c
+++ b/tests-clar/core/sortedcache.c
@@ -10,6 +10,7 @@ void test_core_sortedcache__name_only(void)
{
git_sortedcache *sc;
void *item;
+ size_t pos;
cl_git_pass(git_sortedcache_new(
&sc, 0, NULL, NULL, name_only_cmp, NULL));
@@ -44,6 +45,15 @@ void test_core_sortedcache__name_only(void)
cl_assert_equal_s("zzz", item);
cl_assert(git_sortedcache_entry(sc, 5) == NULL);
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "aaa"));
+ cl_assert_equal_sz(0, pos);
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "iii"));
+ cl_assert_equal_sz(2, pos);
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "zzz"));
+ cl_assert_equal_sz(4, pos);
+ cl_assert_equal_i(
+ GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "abc"));
+
git_sortedcache_clear(sc, true);
cl_assert_equal_sz(0, git_sortedcache_entrycount(sc));
@@ -182,6 +192,34 @@ void test_core_sortedcache__in_memory(void)
cl_assert_equal_i(10, item->value);
cl_assert(git_sortedcache_entry(sc, 3) == NULL);
+ {
+ size_t pos;
+
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "again"));
+ cl_assert_equal_sz(0, pos);
+ cl_git_pass(git_sortedcache_remove(sc, pos, true));
+ cl_assert_equal_i(
+ GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "again"));
+
+ cl_assert_equal_sz(2, git_sortedcache_entrycount(sc));
+
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "testing"));
+ cl_assert_equal_sz(1, pos);
+ cl_git_pass(git_sortedcache_remove(sc, pos, true));
+ cl_assert_equal_i(
+ GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "testing"));
+
+ cl_assert_equal_sz(1, git_sortedcache_entrycount(sc));
+
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "final"));
+ cl_assert_equal_sz(0, pos);
+ cl_git_pass(git_sortedcache_remove(sc, pos, true));
+ cl_assert_equal_i(
+ GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "final"));
+
+ cl_assert_equal_sz(0, git_sortedcache_entrycount(sc));
+ }
+
git_sortedcache_free(sc);
cl_assert_equal_i(3, free_count);
@@ -223,6 +261,7 @@ void test_core_sortedcache__on_disk(void)
git_sortedcache *sc;
sortedcache_test_struct *item;
int free_count = 0;
+ size_t pos;
cl_git_mkfile("cacheitems.txt", "10 abc\n20 bcd\n30 cde\n");
@@ -291,6 +330,19 @@ void test_core_sortedcache__on_disk(void)
cl_assert_equal_s("zzz", item->path);
cl_assert_equal_i(200, item->value);
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "aaa"));
+ cl_assert_equal_sz(0, pos);
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "abc"));
+ cl_assert_equal_sz(1, pos);
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "final"));
+ cl_assert_equal_sz(2, pos);
+ cl_git_pass(git_sortedcache_lookup_index(&pos, sc, "zzz"));
+ cl_assert_equal_sz(3, pos);
+ cl_assert_equal_i(
+ GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "missing"));
+ cl_assert_equal_i(
+ GIT_ENOTFOUND, git_sortedcache_lookup_index(&pos, sc, "cde"));
+
git_sortedcache_free(sc);
cl_assert_equal_i(7, free_count);