marrakesh/mrklib_index.c

303 lines
6.2 KiB
C

#include "mrklib_priv.h"
typedef struct
{
Eina_Hash *name_hash;
Eina_Hash *category_hash;
Eina_Hash *tag_hash;
Eina_Hash *key_hash;
} Mdb;
static char *
read_string(Eet_File *ef, const char *key)
{
int size = 0;
char *str;
char *s = eet_read(ef, key, &size);
if (!s) return NULL;
str = malloc(size + 1);
if (!str)
{
free(s);
return NULL;
}
memcpy(str, s, size);
str[size] = 0;
free(s);
return str;
}
static void
key_register(Eina_Hash *hash, const char *key, const char *entry)
{
const char *ss;
Eina_List *entries;
ss = eina_stringshare_add(entry);
entries = eina_hash_find(hash, key);
entries = eina_list_sorted_insert(entries, EINA_COMPARE_CB(strcasecmp), ss);
eina_hash_set(hash, key, entries);
}
typedef struct
{
Eina_Hash *master;
const char *entry;
} Inf;
static Eina_Bool
key_enter_cb(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data EINA_UNUSED, void *fdata)
{
Inf *inf = fdata;
key_register(inf->master, key, inf->entry);
return EINA_TRUE;
}
static void
key_enter(Eina_Hash *master, Eina_Hash *keys, const char *entry)
{
Inf inf = { master, entry };
eina_hash_foreach(keys, key_enter_cb, &inf);
}
static Eina_Hash *
key_new(void)
{
return eina_hash_string_superfast_new(NULL);
}
static void
key_free(Eina_Hash *hash)
{
eina_hash_free(hash);
}
static void
key_add(Eina_Hash *hash, const char *key)
{
if (eina_hash_find(hash, key)) return;
eina_hash_add(hash, key, hash);
}
static void
key_str_add(Eina_Hash *hash, const char *str)
{
char *ts = strdup(str);
char *p, *pe = ts;
if (!ts) return;
for (p = ts; *p; p++)
{
if (!(((*p >= 'a') && (*p <= 'z')) ||
((*p >= 'A') && (*p <= 'Z')) ||
((*p >= '0') && (*p <= '9')))) *p = 0;
else *p = tolower(*p);
pe = p;
}
for (p = ts; p < pe; p++)
{
if (*p)
{
key_add(hash, p);
p += strlen(p);
}
}
free(ts);
}
static Eina_Bool
key_merge_cb(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data EINA_UNUSED, void *fdata)
{
key_add(fdata, key);
return EINA_TRUE;
}
static void
key_merge(Eina_Hash *master, Eina_Hash *keys)
{
eina_hash_foreach(keys, key_merge_cb, master);
}
static Eina_Bool
index_file(Mdb *db, const char *file, const char *fname)
{
Eet_File *ef;
char *s;
int i;
char tmp[4096];
Eina_Hash *ky;
Eina_Hash *tk;
ef = eet_open(file, EET_FILE_MODE_READ);
if (!ef) return EINA_FALSE;
ky = key_new();
s = read_string(ef, "name");
if (s)
{
tk = key_new();
key_add(tk, s);
key_str_add(ky, s);
key_enter(db->name_hash, tk, fname);
key_free(tk);
tk = key_new();
key_str_add(tk, s);
key_merge(ky, tk);
key_free(tk);
free(s);
}
for (i = 0; i < 9999; i++)
{
tk = key_new();
snprintf(tmp, sizeof(tmp), "tag/%i", i);
s = read_string(ef, tmp);
if (s)
{
key_str_add(tk, s);
free(s);
}
key_enter(db->tag_hash, tk, fname);
key_merge(ky, tk);
key_free(tk);
}
key_register(db->category_hash, "@", fname);
for (i = 0; i < 9999; i++)
{
tk = key_new();
snprintf(tmp, sizeof(tmp), "category/%i", i);
s = read_string(ef, tmp);
if (s)
{
key_str_add(tk, s);
free(s);
}
key_enter(db->category_hash, tk, fname);
key_merge(ky, tk);
key_free(tk);
}
s = read_string(ef, "brief");
if (s)
{
tk = key_new();
key_str_add(tk, s);
key_merge(ky, tk);
key_free(tk);
free(s);
}
key_enter(db->key_hash, ky, fname);
key_free(ky);
eet_close(ef);
return EINA_TRUE;
}
static Eina_Bool
index_out_cb(const Eina_Hash *hash EINA_UNUSED, const void *key, void *data, void *fdata)
{
FILE *f = fdata;
const char *s;
fprintf(f, "%s\n", (const char *)key);
EINA_LIST_FREE(data, s)
{
fprintf(f, "\t%s\n", s);
eina_stringshare_del(s);
}
return EINA_TRUE;
}
static Eina_Bool
index_dir(const char *dir)
{
Eina_List *files;
char *s;
char tmp[4096];
FILE *f;
Mdb *db;
db = calloc(1, sizeof(Mdb));
if (!db) return 0;
db->name_hash = eina_hash_string_superfast_new(NULL);
db->category_hash = eina_hash_string_superfast_new(NULL);
db->tag_hash = eina_hash_string_superfast_new(NULL);
db->key_hash = eina_hash_string_superfast_new(NULL);
files = ecore_file_ls(dir);
EINA_LIST_FREE(files, s)
{
char *lnk;
if (s[0] == '.')
{
free(s);
continue;
}
snprintf(tmp, sizeof(tmp), "%s/%s", dir, s);
lnk = ecore_file_readlink(tmp);
if (!lnk)
{
free(s);
continue;
}
index_file(db, tmp, s);
free(lnk);
free(s);
}
snprintf(tmp, sizeof(tmp), "%s/.mrkdb-name.txt", dir);
f = fopen(tmp, "wb");
if (f)
{
eina_hash_foreach(db->name_hash, index_out_cb, f);
eina_hash_free(db->name_hash);
fclose(f);
}
snprintf(tmp, sizeof(tmp), "%s/.mrkdb-tag.txt", dir);
f = fopen(tmp, "wb");
if (f)
{
eina_hash_foreach(db->tag_hash, index_out_cb, f);
eina_hash_free(db->tag_hash);
fclose(f);
}
snprintf(tmp, sizeof(tmp), "%s/.mrkdb-category.txt", dir);
f = fopen(tmp, "wb");
if (f)
{
eina_hash_foreach(db->category_hash, index_out_cb, f);
eina_hash_free(db->category_hash);
fclose(f);
}
snprintf(tmp, sizeof(tmp), "%s/.mrkdb-key.txt", dir);
f = fopen(tmp, "wb");
if (f)
{
eina_hash_foreach(db->key_hash, index_out_cb, f);
eina_hash_free(db->key_hash);
fclose(f);
}
free(db);
return 1;
}
EAPI Eina_Bool
mrk_index(const char *dir)
{
Eina_Bool ok = EINA_FALSE;
char *repodir;
const char *file;
file = ecore_file_file_get(dir);
if (!file) return ok;
if (!_mrk_util_arch_ok(file)) return ok;
repodir = ecore_file_realpath(dir);
if (repodir)
{
ok = index_dir(repodir);
free(repodir);
}
return ok;
}