303 lines
6.2 KiB
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;
|
|
}
|