db->ltags = newLtable(0);
db->hfiles = newHtable(0);
db->htags = newHtable(0);
+ db->fcount = newHtable(0);
+ db->tcount = newHtable(0);
db->map = newMtable(0);
return db;
}
if(!sameStr(header, "DB")){
fprintf(stderr, "Header is '%s' not 'DB'\n", header);
}
+
char name[32];
fread(&name, sizeof(char), 32, fp);
database *db = newDatabase(name);
db->ltags = loadLtable(fp);
db->hfiles = loadHtable(fp);
db->htags = loadHtable(fp);
+ db->fcount = loadHtable(fp);
+ db->tcount = loadHtable(fp);
db->map = loadMtable(fp);
- char end[4];
- fread(&end, sizeof(char), 3, fp);
+
+ char *end = calloc(3, sizeof(char));
+ fread(end, sizeof(char), 3, fp);
if(!sameStr(end, "END")){
fprintf(stderr, "End is '%s' not 'END'\n", end);
}
storeLtable(db->ltags, fp);
storeHtable(db->hfiles, fp);
storeHtable(db->htags, fp);
+ storeHtable(db->fcount, fp);
+ storeHtable(db->tcount, fp);
storeMtable(db->map, fp);
char end[3] = "END";
return 0;
}
+static void increaseCount(htable *ht, uint64_t i){
+ ht->table[i]++;
+}
+
+uint64_t addFile(database *db, char *file){
+ uint32_t l;
+ file = normalizeStrLimit(file, &l, MAXPATH-1);
+ uint64_t h = crc64(0, file, l);
+ uint64_t i = htableSearch(db->hfiles, h);
+
+ if(i == -1){
+ ltableAdd(db->lfiles, file);
+ htableAdd(db->hfiles, h);
+ htableAdd(db->fcount, 0);
+ i = db->hfiles->size-1;
+ }
+ increaseCount(db->fcount, i);
+
+ return i;
+}
+
+uint64_t addTag(database *db, char *tag){
+ uint32_t l;
+ tag = normalizeStrLimit(tag, &l, MAXPATH-1);
+ uint64_t h = crc64(0, tag, l);
+ uint64_t i = htableSearch(db->htags, h);
+
+ if(i == -1){
+ ltableAdd(db->ltags, tag);
+ htableAdd(db->htags, h);
+ htableAdd(db->tcount, 0);
+ i = db->htags->size-1;
+ }
+ increaseCount(db->tcount, i);
+
+ return i;
+}
+
static int addRelation(database *db, relation r){
if(mtableSearch(db->map, r) != -1){
return -1;
}
int addFileTag(database *db, char *file, char *tag){
- uint32_t lf, lt;
- file = normalizeStrLimit(file, &lf, MAXPATH-1);
- tag = normalizeStrLimit(tag, <, MAXPATH-1);
- uint64_t hf = crc64(0, file, lf), ht = crc64(0, tag, lt);
- uint64_t fi = htableSearch(db->hfiles, hf), ti = htableSearch(db->htags, ht);
-
- if(fi == -1){
- ltableAdd(db->lfiles, file);
- htableAdd(db->hfiles, hf);
- fi = db->hfiles->size-1;
- }
- if(ti == -1){
- ltableAdd(db->ltags, tag);
- htableAdd(db->htags, ht);
- ti = db->htags->size-1;
- }
-
+ uint64_t fi = addFile(db, file), ti = addTag(db, tag);
addRelation(db, (relation){.file = fi, .tag = ti});
+
return 0;
}
int addFileTags(database *db, char *file, int ntags, ...){
- uint32_t lf;
- file = normalizeStrLimit(file, &lf, MAXPATH-1);
- uint64_t hf = crc64(0, file, lf);
- uint64_t fi = htableSearch(db->hfiles, hf);
-
- if(fi == -1){
- ltableAdd(db->lfiles, file);
- htableAdd(db->hfiles, hf);
- fi = db->hfiles->size-1;
- }
-
va_list tags;
va_start(tags, ntags);
for(uint64_t i = 0; i < ntags; ++i){
char *tag = va_arg(tags, char*);
- uint32_t lt;
- tag = normalizeStrLimit(tag, <, MAXPATH-1);
- uint64_t ht = crc64(0, tag, lt);
- uint64_t ti = htableSearch(db->htags, ht);
-
- if(ti == -1){
- ltableAdd(db->ltags, tag);
- htableAdd(db->htags, ht);
- ti = db->htags->size-1;
- }
-
- addRelation(db, (relation){.file = fi, .tag = ti});
+ addFileTag(db, file, tag);
}
va_end(tags);
return 0;
}
-// Should return a list with the indexes of the files that have this tag
-int searchTag(database *db, char *tag, uint64_t *rl){
+// Stores in r a list with the indexes of the first n files that have this tag
+// If n is 0 or lower, it returns all of them. Stores in rl the length of r
+int searchTag(database *db, char *tag, uint64_t n, uint64_t **r, uint64_t *rl){
uint32_t l;
tag = normalizeStrLimit(tag, &l, MAXPATH-1);
uint64_t h = crc64(0, tag, l);
uint64_t ti = htableSearch(db->htags, h);
- // TODO: error checking
+ if(ti == -1){
+ return -1;
+ }
- uint64_t c = 0;
+ *rl = 0;
for(uint64_t i = 0; i < db->map->size; ++i){
+ if(n < 1 || *rl < n){
+ if(db->map->table[i].tag == ti){
+ ++(*rl);
+ }
+ }
+ }
+ *r = malloc((*rl)*sizeof(uint64_t));
+ uint64_t c = 0;
+ for(uint64_t i = 0; i < db->map->size && c < *rl; ++i){
if(db->map->table[i].tag == ti){
- ++c;
+ (*r)[c++] = db->map->table[i].file;
}
}
- uint64_t *r = malloc(c*sizeof(uint64_t));
- c = 0;
+
+ return 0;
+}
+
+// Stores in r a list with the indexes of the first n tags that this file has
+// If n is 0 or lower, it returns all of them. Stores in rl the length of r
+int searchFile(database *db, char *file, uint64_t n, uint64_t **r, uint64_t *rl){
+ uint32_t l;
+ file = normalizeStrLimit(file, &l, MAXPATH-1);
+ uint64_t h = crc64(0, file, l);
+ uint64_t fi = htableSearch(db->hfiles, h);
+ if(fi == -1){
+ return -1;
+ }
+
+ *rl = 0;
for(uint64_t i = 0; i < db->map->size; ++i){
- if(db->map->table[i].tag == ti){
- r[c++] = db->map->table[i].file;
+ if(n < 1 || *rl < n){
+ if(db->map->table[i].file == fi){
+ ++(*rl);
+ }
}
}
- rl = r;
+ *r = malloc((*rl)*sizeof(uint64_t));
+ uint64_t c = 0;
+ for(uint64_t i = 0; i < db->map->size && c < *rl; ++i){
+ if(db->map->table[i].file == fi){
+ (*r)[c++] = db->map->table[i].tag;
+ }
+ }
+
return 0;
}
printf("Name: %s\n", db->name);
printf("\t-lfiles: %d\n", db->lfiles->size);
for(uint64_t i = 0; i < db->lfiles->size; ++i){
- printf("\t\t+%s\n", db->lfiles->table[i]);
+ printf("\t\t+%s (%" PRIu64 ")\n", db->lfiles->table[i], db->fcount->table[i]);
}
printf("\t-ltags: %d\n", db->ltags->size);
for(uint64_t i = 0; i < db->ltags->size; ++i){
- printf("\t\t+%s\n", db->ltags->table[i]);
+ printf("\t\t+%s (%" PRIu64 ")\n", db->ltags->table[i], db->tcount->table[i]);
}
printf("\t-hfiles: %d\n", db->hfiles->size);
for(uint64_t i = 0; i < db->hfiles->size; ++i){