316 lines
6.3 KiB
C
316 lines
6.3 KiB
C
#include <Eina.h>
|
|
#include <Ecore.h>
|
|
#include <Eet.h>
|
|
#include <Ecore_Ipc.h>
|
|
#include <Ecore_File.h>
|
|
|
|
#include "mrk-db.h"
|
|
|
|
static char *repodir = "./repo";
|
|
static Mdb *db = NULL;
|
|
|
|
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, const void *key, void *data, 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;
|
|
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, const void *key, void *data, 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 int
|
|
index_file(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 0;
|
|
|
|
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 1;
|
|
}
|
|
|
|
static Eina_Bool
|
|
index_out_cb(const Eina_Hash *hash, 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 int
|
|
index_dir(const char *dir)
|
|
{
|
|
Eina_List *files;
|
|
char *s;
|
|
char tmp[4096];
|
|
FILE *f;
|
|
|
|
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(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;
|
|
}
|
|
|
|
int
|
|
main(int argc, char **argv)
|
|
{
|
|
int i;
|
|
|
|
if (argc < 2)
|
|
{
|
|
printf("usage:\n"
|
|
" mrk-index /path/to/repo\n"
|
|
"\n");
|
|
exit(1);
|
|
}
|
|
eina_init();
|
|
ecore_init();
|
|
eet_init();
|
|
ecore_file_init();
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
repodir = ecore_file_realpath(argv[i]);
|
|
index_dir(repodir);
|
|
free(repodir);
|
|
repodir = NULL;
|
|
}
|
|
|
|
ecore_file_shutdown();
|
|
eet_shutdown();
|
|
ecore_shutdown();
|
|
eina_shutdown();
|
|
return 0;
|
|
}
|