summaryrefslogtreecommitdiff
path: root/read-cache.c
diff options
context:
space:
mode:
authorJeff Muizelaar <jeff@infidigm.net>2006-09-06 23:28:53 +0000
committerJeff Muizelaar <jeff@infidigm.net>2006-09-06 23:28:53 +0000
commitf6d8d8e8a9b57f8c6ebec9a2f9e82fea8a52403e (patch)
treec1d76cba71b38c5c5b7865e07d8dbbfe8d3d8557 /read-cache.c
parent1e0195ed5c1d9562af9138ad782fc8ee68443390 (diff)
Add support for a reference cache file that contains SHA1 hashes of the
reference images. Having the cache avoids the performance hit of reading and decompressing the reference pngs.
Diffstat (limited to 'read-cache.c')
-rw-r--r--read-cache.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/read-cache.c b/read-cache.c
new file mode 100644
index 0000000..17ac58f
--- /dev/null
+++ b/read-cache.c
@@ -0,0 +1,90 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <libgen.h>
+#include <openssl/sha.h>
+#include "read-cache.h"
+
+unsigned char *cache;
+unsigned char *cache_end;
+unsigned char *current_cache_entry;
+void cache_init(const char *path)
+{
+ FILE *f = cache_open(path, "r");
+ if (!f) {
+ printf("no cache\n");
+ return;
+ }
+ struct stat buf;
+ fstat(fileno(f), &buf);
+ cache = malloc(buf.st_size);
+ fread(cache, 1, buf.st_size, f);
+ fclose(f);
+
+ /* set the current entry to the begining of the cache */
+ current_cache_entry = cache;
+ cache_end = cache + buf.st_size;
+}
+
+FILE *cache_open(const char *path, const char *mode)
+{
+ FILE *cache;
+ char *cache_path;
+ char *path_copy = strdup(path);
+ char *dir = dirname(path_copy);
+ asprintf(&cache_path, "%s/cache", dir);
+ cache = fopen(cache_path, mode);
+ free(cache_path);
+ free(path_copy);
+ return cache;
+}
+
+#define MIN(a, b) (a) < (b) ? (a) : (b)
+
+static void print_hash(const unsigned char *hash)
+{
+ int i;
+ for (i=0; i<SHA_DIGEST_LENGTH; i++) {
+ printf("%02x", hash[i]);
+ }
+ printf("\n");
+}
+
+int cache_compare(const char *path, const unsigned char *buffer, unsigned int length)
+{
+ char *path_copy = strdup(path);
+ char *name = basename(path_copy);
+ int match = 0;
+ //printf("compare: %s\n", path);
+ int name_length = strlen(name);
+ while (current_cache_entry < cache_end) {
+ int cache_length = strlen(current_cache_entry);
+ int min_length = MIN(cache_length, name_length);
+ int result = memcmp(name, current_cache_entry, min_length);
+ if (result == 0) {
+ unsigned char *cache_hash = current_cache_entry + cache_length + 1;
+ unsigned char hash[SHA_DIGEST_LENGTH];
+ //printf("found entry\n");
+ SHA1(buffer, length, hash);
+ print_hash(cache_hash);
+ print_hash(hash);
+ current_cache_entry = cache_hash + SHA_DIGEST_LENGTH;
+ match = memcmp(hash, cache_hash, SHA_DIGEST_LENGTH) == 0 ? 1 : 0;
+ //printf("match %d\n", match);
+ break;
+ } else if (result < 0) {
+ //printf("moving to next entry: %s vs. %s did not match\n", name, current_cache_entry);
+ current_cache_entry += cache_length + 1 + SHA_DIGEST_LENGTH;
+ break;
+ } else {
+ //printf("trying next entry: %s vs. %s did not match\n", name, current_cache_entry);
+ current_cache_entry += cache_length + 1 + SHA_DIGEST_LENGTH;
+ }
+ }
+ free(path_copy);
+
+ return match;
+}