aboutsummaryrefslogtreecommitdiff
path: root/hash.c
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2010-01-30 16:03:10 -0800
committerJunio C Hamano <gitster@pobox.com>2010-01-30 16:03:10 -0800
commit00d3278c8534a8244ae3447189401111e017fd5d (patch)
treef1c19903bc10ffe4816642040080fb6cfd5da376 /hash.c
parentb9b727ddb3c9e005bc4e9af0b990b6ef06d7f621 (diff)
parentb319ef70a94731a5c6f18d07a49d5dda3f06f5d3 (diff)
downloadgit-00d3278c8534a8244ae3447189401111e017fd5d.tar.gz
git-00d3278c8534a8244ae3447189401111e017fd5d.tar.xz
Merge commit 'b319ef7' into jc/maint-fix-test-perm
* commit 'b319ef7': (8132 commits) Add a small patch-mode testing library git-apply--interactive: Refactor patch mode code t8005: Nobody writes Russian in shift_jis Fix severe breakage in "git-apply --whitespace=fix" Update release notes for 1.6.4 After renaming a section, print any trailing variable definitions Make section_name_match start on '[', and return the length on success send-email: detect cycles in alias expansion Show the presence of untracked files in the bash prompt. SunOS grep does not understand -C<n> nor -e Fix export_marks() error handling. git repack: keep commits hidden by a graft Add a test showing that 'git repack' throws away grafted-away parents git branch: clean up detached branch handling git branch: avoid unnecessary object lookups git branch: fix performance problem git svn: fix shallow clone when upstream revision is too new do_one_ref(): null_sha1 check is not about broken ref configure.ac: properly unset NEEDS_SSL_WITH_CRYPTO when sha1 func is missing janitor: useless checks before free ...
Diffstat (limited to 'hash.c')
-rw-r--r--hash.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/hash.c b/hash.c
new file mode 100644
index 000000000..1cd4c9d5c
--- /dev/null
+++ b/hash.c
@@ -0,0 +1,110 @@
+/*
+ * Some generic hashing helpers.
+ */
+#include "cache.h"
+#include "hash.h"
+
+/*
+ * Look up a hash entry in the hash table. Return the pointer to
+ * the existing entry, or the empty slot if none existed. The caller
+ * can then look at the (*ptr) to see whether it existed or not.
+ */
+static struct hash_table_entry *lookup_hash_entry(unsigned int hash, const struct hash_table *table)
+{
+ unsigned int size = table->size, nr = hash % size;
+ struct hash_table_entry *array = table->array;
+
+ while (array[nr].ptr) {
+ if (array[nr].hash == hash)
+ break;
+ nr++;
+ if (nr >= size)
+ nr = 0;
+ }
+ return array + nr;
+}
+
+
+/*
+ * Insert a new hash entry pointer into the table.
+ *
+ * If that hash entry already existed, return the pointer to
+ * the existing entry (and the caller can create a list of the
+ * pointers or do anything else). If it didn't exist, return
+ * NULL (and the caller knows the pointer has been inserted).
+ */
+static void **insert_hash_entry(unsigned int hash, void *ptr, struct hash_table *table)
+{
+ struct hash_table_entry *entry = lookup_hash_entry(hash, table);
+
+ if (!entry->ptr) {
+ entry->ptr = ptr;
+ entry->hash = hash;
+ table->nr++;
+ return NULL;
+ }
+ return &entry->ptr;
+}
+
+static void grow_hash_table(struct hash_table *table)
+{
+ unsigned int i;
+ unsigned int old_size = table->size, new_size;
+ struct hash_table_entry *old_array = table->array, *new_array;
+
+ new_size = alloc_nr(old_size);
+ new_array = xcalloc(sizeof(struct hash_table_entry), new_size);
+ table->size = new_size;
+ table->array = new_array;
+ table->nr = 0;
+ for (i = 0; i < old_size; i++) {
+ unsigned int hash = old_array[i].hash;
+ void *ptr = old_array[i].ptr;
+ if (ptr)
+ insert_hash_entry(hash, ptr, table);
+ }
+ free(old_array);
+}
+
+void *lookup_hash(unsigned int hash, const struct hash_table *table)
+{
+ if (!table->array)
+ return NULL;
+ return lookup_hash_entry(hash, table)->ptr;
+}
+
+void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table)
+{
+ unsigned int nr = table->nr;
+ if (nr >= table->size/2)
+ grow_hash_table(table);
+ return insert_hash_entry(hash, ptr, table);
+}
+
+int for_each_hash(const struct hash_table *table, int (*fn)(void *))
+{
+ int sum = 0;
+ unsigned int i;
+ unsigned int size = table->size;
+ struct hash_table_entry *array = table->array;
+
+ for (i = 0; i < size; i++) {
+ void *ptr = array->ptr;
+ array++;
+ if (ptr) {
+ int val = fn(ptr);
+ if (val < 0)
+ return val;
+ sum += val;
+ }
+ }
+ return sum;
+}
+
+void free_hash(struct hash_table *table)
+{
+ free(table->array);
+ table->array = NULL;
+ table->size = 0;
+ table->nr = 0;
+}