]> git.xolatile.top Git - soikk-DB.git/commitdiff
Added primitive repl, delete functions for database and remove tag from file function.
authorSoikk <76824648+Soikk@users.noreply.github.com>
Sat, 13 Aug 2022 16:49:30 +0000 (18:49 +0200)
committerSoikk <76824648+Soikk@users.noreply.github.com>
Sat, 13 Aug 2022 16:49:30 +0000 (18:49 +0200)
13 files changed:
CHANGELOG
DOC
TODO
include/database.h
include/db.h
include/parser.h
include/repl.h
include/storage.h
src/database.c
src/main.c
src/parser.c
src/repl.c
src/storage.c

index 6c5c7ba9494edb3c29d38340051343b1a4ac8d41..cd272516f2a0cbf9ecf79093ada153725cb0be1a 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,6 @@
+1660409336 (Sat Aug 13 2022 18:48:56 GMT+0200 (Central European Summer Time))
+Added primitive repl, delete functions for database and remove tag from file function.
+
 1660003394 (Tue Aug 09 2022 02:03:14 GMT+0200 (Central European Summer Time))
 Improved database name system.
 
diff --git a/DOC b/DOC
index 8aa33d4bc8c3e7ce325de9e39cd93355d0c05081..857cf0d1369a9c9e0f0ff1582127e2dbef0abb8a 100644 (file)
--- a/DOC
+++ b/DOC
@@ -1,5 +1,17 @@
 OBSERVATIONS
 
+Notation:
+       CREATE miDB -> creates new database called miDB.
+       CREATE miDB miDB2 -> creates two new databases
+       CREATE "miDB miDB2" -> creates a new database called "miDB miDB2" (without the quotation marks).
+       
+       OPEN ..
+       
+       TAG file WITH tag -> adds tag to file
+       TAG file1 file2 WITH tag -> adds tag to file1, file2
+       TAG file WITH tag1 tag2 -> adds tag1, tag2 to file
+
+
 STORAGE
 
        LTABLE
@@ -253,25 +265,6 @@ DATABASE
        static void decreaseCount(ctable *ct, uint64_t i);
                Auxiliary function that decreases the count of cell i at ct's table;
 
-       static int addRelation(database *db, relation r);
-               Auxiliary function that adds a relation to the mapping table in db.
-               This function returns 0 if r was inserted correctly or -1 if r was already on the database.
-
-       int addFileTag(database *db, char *file, char *tag);
-               This function uses the auxiliary functions addRelation and increaseCount.
-               Adds a file and a tag to the database, and its relation.
-               If the file or the tag or both were already on the database, it still adds the relation.
-               If the relation wasn't in the database, it adds one to the cfiles' table for the file index and another one to the ctags' table for the file index, and then returns 0.
-               If the relation was in the database, it returns -1.
-
-       int addFileTags(database *db, char *file, int ntags, ...);
-               Adds multiple tags to a single file using addFileTag.
-               Returns 0 upon completion.
-
-       int addTagFiles(database *db, char *tag, int nfiles, ...);
-               Adds the same tag to multiple files using addFileTag.
-               Returns 0 upon completion.
-
        static void decreaseHigherIndexNode(node *n, uint64_t i);
                Auxiliary function that decreases the indexes in the node structure of n by one if they're bigger than i.
 
@@ -293,6 +286,25 @@ DATABASE
                To counter this, we use the auxiliary functions decreaseHigherIndexNode and decreaseHigherTagIndexMap to update all the higher indexes in htags and map.
                This function returns 0 upon completion or -1 if the tag is not in the database.
 
+       static int addRelation(database *db, relation r);
+               Auxiliary function that adds a relation to the mapping table in db.
+               This function returns 0 if r was inserted correctly or -1 if r was already on the database.
+
+       int addFileTag(database *db, char *file, char *tag);
+               This function uses the auxiliary functions addRelation and increaseCount.
+               Adds a file and a tag to the database, and its relation.
+               If the file or the tag or both were already on the database, it still adds the relation.
+               If the relation wasn't in the database, it adds one to the cfiles' table for the file index and another one to the ctags' table for the file index, and then returns 0.
+               If the relation was in the database, it returns -1.
+
+       int addFileTags(database *db, char *file, int ntags, ...);
+               Adds multiple tags to a single file using addFileTag.
+               Returns 0 upon completion.
+
+       int addTagFiles(database *db, char *tag, int nfiles, ...);
+               Adds the same tag to multiple files using addFileTag.
+               Returns 0 upon completion.
+
        int searchFile(database *db, char *file, uint64_t n, uint64_t **r, uint64_t *rl);
                Stores in r a list with the indexes of the first n tags that this file has.
                If n is 0, it returns all of them. Stores in rl the length of r.
diff --git a/TODO b/TODO
index 8295e2f5237f2495ffbb5229b36281fa804beba8..404586a492e80d0dec02cb8098f84e580472a75b 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,6 +1,12 @@
+TODO   Show files with multiple tags & viceversa
+
 TODO   Get rid of old functionalities (strnatcmp, BM)
 
 ----------------------------------------------------------------
+DONE   Add remove tag from file function
+
+DONE   Add delete functions
+
 DONE   Must update all indexes in map when removing a file or a tag
 
 DONE   Standarize function names
index bd60e72c214dcf32245226a46230d778ba82c4e5..d5ad8e98f7fed9a763d885ad5fadfdd43b65d405 100644 (file)
@@ -15,19 +15,25 @@ typedef struct database{
 
 database *newDatabase(char *name);
 
+int freeDatabase(database **db);
+
+int deleteDatabase(database **db);
+
 uint64_t addFile(database *db, char *file);
 
 uint64_t addTag(database *db, char *tag);
 
+int removeFile(database *db, char *file);
+
+int removeTag(database *db, char *tag);
+
 int addFileTag(database *db, char *file, char *tag);
 
 int addFileTags(database *db, char *file, int ntags, ...);
 
 int addTagFiles(database *db, char *tag, int nfiles, ...);
 
-int removeFile(database *db, char *file);
-
-int removeTag(database *db, char *tag);
+int removeFileTag(database *db, char *file, char *tag);
 
 int searchFile(database *db, char *file, uint64_t n, uint64_t **r, uint64_t *rl);
 
@@ -39,8 +45,6 @@ database *loadDatabase(const char* path);
 
 void printDatabase(database *db);
 
-void debugAVLtree(node *n);
-
 void debugDatabase(database *db);
 
 #endif
index ccdfc11140c1dfe30d9b1eb8c286653be51b8067..2571d02c889922c08293a0d96a697323d2e0684f 100644 (file)
 #include "strnatcmp.h"
 #include "crc64.h"
 
-#include "repl.h"
-#include "parser.h"
+#include "str.h"
 #include "storage.h"
 #include "database.h"
-#include "str.h"
+#include "repl.h"
+#include "parser.h"
 #include "bm.h"
 
 #endif
index 2e46967942e9c4dfffa24b0cc17f28dcd209daa1..6b68b48d1eb72f2a6ab01148132e34111ee01031 100644 (file)
@@ -4,14 +4,34 @@
 #include "db.h"
 
 
-typedef enum {
+#define NKEYWORDS 16
+#define EXIT_CODE 1
+
+typedef enum{
+       COMMAND_EXIT, COMMAND_DEBUG,
+       COMMAND_CREATE, COMMAND_DELETE, COMMAND_OPEN, COMMAND_SAVE, COMMAND_CLOSE,
+       COMMAND_ADDF, COMMAND_ADDT, COMMAND_DELETEF, COMMAND_DELETET,
+       COMMAND_TAG, COMMAND_REMOVE,
+       COMMAND_SHOW, COMMAND_SHOWT, COMMAND_SHOWF,
+} COMMANDS;
+
+typedef enum{
        META_COMMAND_SUCCESS,
        META_COMMAND_FAIL,
 } metaCommandStatus;
 
+typedef struct{
+       uint64_t argc;
+       char **argv;
+} argList;
+
+
+argList *newArgList(void);
+
+argList *splitInput(inputBuffer *in);
 
 int handleMetaCommand(inputBuffer *in);
 
-int handleInput(inputBuffer *in);
+int handleInput(argList *args, database **db);
 
-#endif
\ No newline at end of file
+#endif
index 26abe9bd697a0193261c69df25def61b6806b2b4..f9f05108313b102e21ed5a00c278bc4fe54bcee2 100644 (file)
@@ -4,9 +4,9 @@
 #include "db.h"
 
 
-typedef struct {
+typedef struct{
        char *buffer;
-       ssize_t inputSize;
+       int64_t inputSize;
 } inputBuffer;
 
 
@@ -16,6 +16,6 @@ void freeInputBuffer(inputBuffer *in);
 
 void getInput(inputBuffer *in);
 
-void prompt(void);
+void prompt(database *db);
 
 #endif
index 8edf8b0db8dd0638d7741225a895da44490714d6..e46c9a867165eae6af2de78609ebf6ba2547ca7f 100644 (file)
@@ -92,6 +92,8 @@ typedef node* tree;
 
 ltable *newLtable(uint64_t size);
 
+int deleteLtable(ltable **lt);
+
 int insertLtable(ltable *lt, char *str);
 
 int removeLtable(ltable *lt, char *str);
@@ -106,6 +108,8 @@ ltable *loadLtable(FILE *fp);
 
 ctable *newCtable(uint64_t size);
 
+int deleteCtable(ctable **ct);
+
 int insertCtable(ctable *ct, uint64_t n);
 
 int removeCtable(ctable *ct, uint64_t n);
@@ -120,6 +124,8 @@ ctable *loadCtable(FILE *fp);
 
 mtable *newMtable(uint64_t size);
 
+int deleteMtable(mtable **mt);
+
 int insertMtable(mtable *mt, relation r);
 
 int removeMtable(mtable *mt, relation r);
@@ -138,6 +144,8 @@ mtable *loadMtable(FILE *fp);
 
 node *newNode(uint64_t h, uint64_t i);
 
+int deleteTree(tree *root);
+
 node *insertNode(node *r, uint64_t h, uint64_t i);
 
 node *removeNode(node *r, uint64_t h);
index 461e02de85d806a1b3c30dfb23ac7997f48667e2..40ea86dfc2a2084913c715718bc667cecb0c9329 100644 (file)
@@ -16,6 +16,34 @@ database *newDatabase(char *name){
        return db;
 }
 
+int freeDatabase(database **db){
+       deleteLtable(&(*db)->lfiles);
+       deleteLtable(&(*db)->ltags);
+       deleteCtable(&(*db)->cfiles);
+       deleteCtable(&(*db)->ctags);
+       deleteTree(&(*db)->hfiles);
+       deleteTree(&(*db)->htags);
+       deleteMtable(&(*db)->map);
+       free((*db)->name);
+       free(*db);
+       *db = NULL;
+       return 0;
+}
+
+int deleteDatabase(database **db){
+       if(*db == NULL){
+               fprintf(stderr, "Error: can't delete NULL database\n");
+               return -1;
+       }
+       int r = remove((*db)->name);
+       if(r != 0){
+               fprintf(stderr, "Error deleting database '%s'\n", (*db)->name);
+               return -1;
+       }
+       freeDatabase(db);
+       return 0;
+}
+
 uint64_t addFile(database *db, char *file){
        uint32_t l;
        file = normalizeStrLimit(file, &l, MAXPATH-1);
@@ -53,47 +81,6 @@ static void decreaseCount(ctable *ct, uint64_t i){
        ct->table[i]--;
 }
 
-static int addRelation(database *db, relation r){
-       if(searchMtable(db->map, r) == UINTMAX_MAX){
-               insertMtable(db->map, r);
-               return 0;
-       }
-       return -1;
-}
-
-int addFileTag(database *db, char *file, char *tag){
-       uint64_t fi = addFile(db, file), ti = addTag(db, tag);
-       int r = addRelation(db, (relation){.file = fi, .tag = ti});
-       if(r == 0){
-               increaseCount(db->cfiles, fi);
-               increaseCount(db->ctags, ti);
-               return 0;
-       }
-       return -1;
-}
-
-int addFileTags(database *db, char *file, int ntags, ...){
-       va_list tags;
-       va_start(tags, ntags);
-       for(uint64_t i = 0; i < ntags; ++i){
-               char *tag = va_arg(tags, char*);
-               addFileTag(db, file, tag);
-       }
-       va_end(tags);
-       return 0;
-}
-
-int addTagFiles(database *db, char *tag, int nfiles, ...){
-       va_list files;
-       va_start(files, nfiles);
-       for(uint64_t i = 0; i < nfiles; ++i){
-               char *file = va_arg(files, char*);
-               addFileTag(db, file, tag);
-       }
-       va_end(files);
-       return 0;
-}
-
 static void decreaseHigherIndexNode(node *n, uint64_t i){
        if(n == NULL){
                return;
@@ -167,6 +154,69 @@ int removeTag(database *db, char *tag){
        return 0;
 }
 
+static int addRelation(database *db, relation r){
+       if(searchMtable(db->map, r) == UINTMAX_MAX){
+               insertMtable(db->map, r);
+               return 0;
+       }
+       return -1;
+}
+
+int addFileTag(database *db, char *file, char *tag){
+       uint64_t fi = addFile(db, file), ti = addTag(db, tag);
+       int r = addRelation(db, (relation){.file = fi, .tag = ti});
+       if(r == 0){
+               increaseCount(db->cfiles, fi);
+               increaseCount(db->ctags, ti);
+               return 0;
+       }
+       return -1;
+}
+
+int addFileTags(database *db, char *file, int ntags, ...){
+       va_list tags;
+       va_start(tags, ntags);
+       for(uint64_t i = 0; i < ntags; ++i){
+               char *tag = va_arg(tags, char*);
+               addFileTag(db, file, tag);
+       }
+       va_end(tags);
+       return 0;
+}
+
+int addTagFiles(database *db, char *tag, int nfiles, ...){
+       va_list files;
+       va_start(files, nfiles);
+       for(uint64_t i = 0; i < nfiles; ++i){
+               char *file = va_arg(files, char*);
+               addFileTag(db, file, tag);
+       }
+       va_end(files);
+       return 0;
+}
+
+int removeFileTag(database *db, char *file, char *tag){
+       uint32_t lf, lt;
+       file = normalizeStrLimit(file, &lf, MAXPATH-1);
+       tag = normalizeStrLimit(tag, &lt, MAXPATH-1);
+       uint64_t hf = crc64(0, file, lf), ht = crc64(0, tag, lt);
+       uint64_t fi = searchNode(db->hfiles, hf), ti = searchNode(db->htags, ht);
+       if(fi == UINTMAX_MAX){
+               fprintf(stderr, "Error: no such file '%s'\n", file);
+               return -1;
+       }
+       if(ti == UINTMAX_MAX){
+               fprintf(stderr, "Error: no such tag '%s'\n", tag);
+               return -1;
+       }
+       int status = removeMtable(db->map, (relation){.file = fi, .tag = ti});
+       if(status == -1){
+               fprintf(stderr, "Error: tag '%s' not associated with file '%s'\n", tag, file);
+               return -1;
+       }
+       return 0;
+}
+
 int searchFile(database *db, char *file, uint64_t n, uint64_t **r, uint64_t *rl){
        uint32_t l;
        file = normalizeStrLimit(file, &l, MAXPATH-1);
@@ -244,6 +294,10 @@ int storeDatabase(database *db, const char *path){
 
 database *loadDatabase(const char* path){
        FILE *fp = fopen(path, "rb");
+       if(fp == NULL){
+               fprintf(stderr, "Error: no such file (%s)\n", path);
+               return NULL;
+       }
        char *header = calloc(2, sizeof(char));
        fread(header, sizeof(char), 2, fp);
        if(!sameStr(header, "DB")){
@@ -277,7 +331,7 @@ void printDatabase(database *db){
        printf("\n");
 }
 
-void debugAVLtree(node *n){
+static void debugAVLtree(node *n){
        if(n != NULL){
                printf("\t\t+ %" PRIu64 " -> %" PRIu64 "\n", n->h, n->i);
                debugAVLtree(n->left);
@@ -286,6 +340,10 @@ void debugAVLtree(node *n){
 }
 
 void debugDatabase(database *db){
+       if(db == NULL){
+               fprintf(stderr, "Error: database is NULL\n");
+               return;
+       }
        printf("\n");
        printf("Name: %s\n", db->name);
        printf("\t-lfiles: %d\n", db->lfiles->size);
index b24dcb85065c251cc88d19c88c032d8c9202ae48..23e1fee0051b41a069c3be01a3416e2f5c7e6661 100644 (file)
@@ -4,16 +4,17 @@
 
 int main(){
 
+
        inputBuffer *in = newInputBuffer();
-       database *db = newDatabase("miDB");
+       /*database *test = newDatabase("miDB");
        
-       addFileTag(db, "vaca.png", "naturalezas");      
-       addFileTags(db, "terry-davis.jpg", 3, "holyC", "programmer", "very cool");
-       addFileTag(db, "vaca.png", "lovely");
-       addFileTags(db, "vaca.png", 3, "nature", "animal", "very cool");
-       addFileTag(db, "terry-davis.jpg", "based");
+       addFileTag(test, "vaca.png", "naturalezas");    
+       addFileTags(test, "terry-davis.jpg", 3, "holyC", "programmer", "very cool");
+       addFileTag(test, "vaca.png", "lovely");
+       addFileTags(test, "vaca.png", 3, "nature", "animal", "very cool");
+       addFileTag(test, "terry-davis.jpg", "based");
 
-       storeDatabase(db, "db.db");
+       storeDatabase(test, "db.db");
 
        printDatabase(db);
 
@@ -26,29 +27,18 @@ int main(){
        for(uint64_t j = 0; j < i; ++j){
                printf("\t%s\n", db->ltags->table[l[j]]);
        
-       }
-       
-       
-
-       while(0){
+       }*/
 
-               prompt();
+       database *db = NULL;
+       while(1){
+               prompt(db);
                getInput(in);
-               
-               /*
-               insertTag(r, in->buffer);
-               printf("Tags of row '%s': %s\n", r->path, r->tags);
-               printf("Number of tags: %u. Length of tags: %u\n", r->numTags, r->lenTags);
-               */
-
-               /*switch(handleInput(in)){
-                       case META_COMMAND_SUCCESS:
-                               printf("we done it nigger\n");
-                               break;
-                       case META_COMMAND_FAIL:
-                               printf("uh-oh nigga i dunno what '%s' is!\n", in->buffer);
-                               break;
-               }*/
+               argList *args = splitInput(in);
+               int status = handleInput(args, &db);
+               if(status == EXIT_CODE){
+                       printf("Exiting db\n");
+                       break;
+               }
        }
 
        return 0;
index f26a0cb4985b68a16cf32d97bb8754a70703eebc..0401f4354a619c9bc75489a3496670bd87af9526 100644 (file)
 #include "db.h"
 
 
-int handleMetaCommand(inputBuffer *in){
-       if(sameStr(in->buffer, ".exit")){
-               freeInputBuffer(in);
-               printf("EXIT M'NIGGA\n");
-               exit(EXIT_SUCCESS);
-       }else{
-               return META_COMMAND_FAIL;
+char *keywords[NKEYWORDS] = {"EXIT", "DEBUG",
+       "CREATE", "DELETE", "OPEN", "SAVE", "CLOSE",
+       "ADDF", "ADDT", "DELETEF", "DELETET",
+       "TAG", "REMOVE",
+       "SHOW", "SHOWT", "SHOWF"};
+
+argList *newArgList(void){
+       argList *args = malloc(sizeof(argList));
+       args->argc = 0;
+       args->argv = NULL;
+       return args;
+}
+
+argList *splitInput(inputBuffer *in){
+       if(in->inputSize == 0){
+               return NULL;
+       }
+       argList *args = newArgList();
+       uint64_t len = args->argc = 0;
+
+       // Remove leading spaces
+       while(isspace(in->buffer[len])){
+               ++len;
+       }
+       // Count words (alone or quoted)
+       while(in->buffer[len] != '\0'){
+               while(isspace(in->buffer[len])){
+                       ++len;
+               }
+               if(in->buffer[len] == '"'){
+                       do{
+                               ++len;
+                       }while(in->buffer[len] != '"');
+                       ++args->argc;
+               }else if(in->buffer[len] == '\''){
+                       do{
+                               ++len;
+                       }while(in->buffer[len] != '\'');
+                       ++args->argc;
+               }else{
+                       while(in->buffer[len] != '\0' && !isspace(in->buffer[len])){
+                               ++len;
+                       }
+                       ++args->argc;
+               }
+               ++len;
+       }
+       uint64_t *wstarts = malloc(args->argc*sizeof(uint64_t)), *wlens = malloc(args->argc*sizeof(uint64_t));
+       len = args->argc = 0;
+       while(in->buffer[len] != '\0'){
+               while(isspace(in->buffer[len])){
+                       ++len;
+               }
+               if(in->buffer[len] == '"'){
+                       wstarts[args->argc] = len+1;
+                       do{
+                               ++len;
+                       }while(in->buffer[len] != '"');
+                       wlens[args->argc] = len - wstarts[args->argc];
+                       ++args->argc;
+               }else if(in->buffer[len] == '\''){
+                       wstarts[args->argc] = len+1;
+                       do{
+                               ++len;
+                       }while(in->buffer[len] != '\'');
+                       wlens[args->argc] = len -wstarts[args->argc];
+                       ++args->argc;
+               }else{
+                       wstarts[args->argc] = len;
+                       while(in->buffer[len] != '\0' && !isspace(in->buffer[len])){
+                               ++len;
+                       }
+                       wlens[args->argc] = len - wstarts[args->argc];
+                       ++args->argc;
+               }
+               ++len;
+       }
+       
+       args->argv = malloc(args->argc*sizeof(char*));
+       for(uint64_t i = 0; i < args->argc; ++i){
+               args->argv[i] = calloc(wlens[i]+1, sizeof(char));
+               memcpy(args->argv[i], &in->buffer[wstarts[i]], wlens[i]);
+       }
+       return args;
+}
+
+static int commandExit(argList *args, database **db){
+       // TODO: cleanup functions
+       return EXIT_CODE;
+}
+
+static int commandDebug(argList *args, database **db){
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to debug\n");
+               return -1;
+       }
+       debugDatabase(*db);
+       return 0;
+}
+
+static int commandCreate(argList *args, database **db){
+       if(args->argc < 2){
+               fprintf(stderr, "Error, not enough arguments for command '%s'\n", args->argv[0]);
+               return -1;
+       }
+       for(int i = 1; i < args->argc; ++i){
+               int status = storeDatabase(newDatabase(args->argv[i]), args->argv[i]);
+               if(status != 0){
+                       fprintf(stderr, "Error creating and storing database '%s'\n", args->argv[i]);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+static int commandDelete(argList *args, database **db){
+       if(args->argc < 2){
+               fprintf(stderr, "Error, not enough arguments for command '%s'\n", args->argv[0]);
+               return -1;
+       }
+       for(int i = 1; i < args->argc; ++i){
+               database *t = loadDatabase(args->argv[i]);
+               int status = deleteDatabase(&t);
+               if(status != 0){
+                       fprintf(stderr, "Error deleting database '%s'\n", args->argv[i]);
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+static int commandOpen(argList *args, database **db){
+       if(args->argc < 2){
+               fprintf(stderr, "Error: not enough arguments for command '%s'\n", args->argv[0]);
+               return -1;
+       }else if(args->argc > 2){
+               fprintf(stderr, "Error: too many arguments for command 'OPEN'. Only opening first one ('%s')\n", args->argv[1]);
+       }
+       if(*db != NULL){
+               fprintf(stderr, "Error: database '%s' already opened. Close it before proceeding with \"CLOSE '%s'\"\n", (*db)->name, (*db)->name);
+               return -1;
        }
+       *db = loadDatabase(args->argv[1]);
+       if(*db == NULL){
+               fprintf(stderr, "Error loading database '%s'\n", args->argv[1]);
+               return -1;
+       }
+       return 0;
 }
 
-int handleInput(inputBuffer *in){
-       if(in->buffer[0] == '.'){
-               return handleMetaCommand(in);
-       }else{
-               printf("normal command\n");
+static int commandSave(argList *args, database **db){
+       if(args->argc > 1){
+               fprintf(stderr, "Error: too many arguments for function 'SAVE'. Only saving loaded database ('%s')\n", (*db)->name);
+       }
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to save\n");
+               return -1;
+       }
+       int status = storeDatabase(*db, (*db)->name);
+       if(status != 0){
+               fprintf(stderr, "Error storing database '%s'\n", (*db)->name);
+               return -1;
+       }
+       return 0;
+}
+
+static int commandClose(argList *args, database **db){
+       if(args->argc > 1){
+               fprintf(stderr, "Error: too many arguments for function 'CLOSE'. Only closing loaded database ('%s')\n", (*db)->name);
+       }
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to close\n");
+               return -1;
+       }
+       int status = storeDatabase(*db, (*db)->name);
+       if(status != 0){
+               fprintf(stderr, "Error storing database '%s' before closing it\n", (*db)->name);
+               return -1;
+       }
+       freeDatabase(db);
+       return 0;
+}
+
+static int commandAddf(argList *args, database **db){
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to add files to\n");
+               return -1;
+       }
+       char **files = malloc((args->argc-1)*sizeof(char*));
+       uint64_t fi = 0;
+       for(uint64_t i = 1; i < args->argc; ++i){
+               files[fi++] = args->argv[i];
+       }
+       if(fi == 0){
+               fprintf(stderr, "Error: no files given to add to database\n");
+               return -1;
+       }
+       for(uint64_t i = 0; i < fi; ++i){
+               addFile(*db, files[i]);
+       }
+       return 0;
+}
+
+static int commandAddt(argList *args, database **db){
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to add tags to\n");
+               return -1;
+       }
+       char **tags = malloc((args->argc-1)*sizeof(char*));
+       uint64_t ti = 0;
+       for(uint64_t i = 1; i < args->argc; ++i){
+               tags[ti++] = args->argv[i];
+       }
+       if(ti == 0){
+               fprintf(stderr, "Error: no tags given to add to database\n");
+               return -1;
+       }
+       for(uint64_t i = 0; i < ti; ++i){
+               addTag(*db, tags[i]);
+       }
+       return 0;
+}
+
+static int commandDeletef(argList *args, database **db){
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to delete files from\n");
+               return -1;
+       }
+       char **files = malloc((args->argc-1)*sizeof(char*));
+       uint64_t fi = 0;
+       for(uint64_t i = 1; i < args->argc; ++i){
+               files[fi++] = args->argv[i];
+       }
+       if(fi == 0){
+               fprintf(stderr, "Error: no files given to remove from database\n");
+               return -1;
        }
-}
\ No newline at end of file
+       for(uint64_t i = 0; i < fi; ++i){
+               removeFile(*db, files[i]);
+       }
+       return 0;
+}
+
+static int commandDeletet(argList *args, database **db){
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to remove tags from\n");
+               return -1;
+       }
+       char **tags = malloc((args->argc-1)*sizeof(char*));
+       uint64_t ti = 0;
+       for(uint64_t i = 1; i < args->argc; ++i){
+               tags[ti++] = args->argv[i];
+       }
+       if(ti == 0){
+               fprintf(stderr, "Error: no tags given to remove from database\n");
+               return -1;
+       }
+       for(uint64_t i = 0; i < ti; ++i){
+               removeTag(*db, tags[i]);
+       }
+       return 0;
+}
+
+static int commandTag(argList *args, database **db){
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to add files and tags to\n");
+               return -1;
+       }
+       char **files = malloc((args->argc-1)*sizeof(char*));
+       uint64_t i, fi = 0, ti = 0;
+       bool with = false;
+       for(i = 1; i < args->argc; ++i){
+               uint32_t l1, l2;
+               if(sameStr(normalizeStr(args->argv[i], &l1), normalizeStr("WITH", &l2))){
+                       with = true;
+                       ++i;
+                       break;
+               }
+               files[fi++] = args->argv[i];
+       }
+       if(fi == 0){
+               fprintf(stderr, "Error: no files given to tag\n");
+               return -1;
+       }
+       if(with == false){
+               fprintf(stderr, "Error: missing 'WITH' keyword on 'TAG' command\n");
+               return -1;
+       }
+       char **tags = malloc((args->argc-i)*sizeof(char*));
+       for(; i < args->argc; ++i){
+               tags[ti++] = args->argv[i];
+       }
+       if(ti == 0){
+               fprintf(stderr, "Error: no tags given to tag files\n");
+               return -1;
+       }
+
+       for(uint64_t f = 0; f < fi; ++f){
+               for(uint64_t t = 0; t < ti; ++t){
+                       int status = addFileTag(*db, files[f], tags[t]);
+                       if(status != 0){
+                               fprintf(stderr, "Error: couldnt add tag '%s' to file '%s'\n", tags[t], files[f]);
+                               return -1;
+                       }
+               }
+       }
+       return 0;
+}
+
+static int commandRemove(argList *args, database **db){
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to remove files and tags from\n");
+               return -1;
+       }
+       char **tags = malloc((args->argc-1)*sizeof(char*));
+       uint64_t i, ti = 0, fi = 0;
+       bool from = false;
+       for(i = 1; i < args->argc; ++i){
+               uint32_t l1, l2;
+               if(sameStr(normalizeStr(args->argv[i], &l1), normalizeStr("FROM", &l2))){
+                       from = true;
+                       ++i;
+                       break;
+               }
+               tags[ti++] = args->argv[i];
+       }
+       if(ti == 0){
+               fprintf(stderr, "Error: no tags given to remove\n");
+               return -1;
+       }
+       if(from == false){
+               fprintf(stderr, "Error: missing 'FROM' keyword on 'REMOVE' command\n");
+               return -1;
+       }
+       char **files = malloc((args->argc-i)*sizeof(char*));
+       for(; i < args->argc; ++i){
+               files[fi++] = args->argv[i];
+       }
+       if(fi == 0){
+               fprintf(stderr, "Error: no files given to remove\n");
+               return -1;
+       }
+
+       for(uint64_t f = 0; f < fi; ++f){
+               for(uint64_t t = 0; t < ti; ++t){
+                       int status = removeFileTag(*db, files[f], tags[t]);
+                       if(status != 0){
+                               fprintf(stderr, "Error: couldnt remove tag '%s' from file '%s'\n", tags[t], files[f]);
+                               return -1;
+                       }
+               }
+       }
+       return 0;
+}
+
+static int commandShow(argList *args, database **db){
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to show\n");
+               return -1;
+       }
+       printDatabase(*db);
+       return 0;
+}
+
+static int commandShowt(argList *args, database **db){
+       // We only show the files of one tag
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to show tags of file\n");
+               return -1;
+       }
+       if(args->argc > 2){
+               fprintf(stderr, "Error: too many arguments for 'SHOWT', current support for only one file. Only showing tags of first file ('%s')\n", args->argv[1]);
+       }
+       
+       uint64_t rl, *r;
+       int status = searchFile(*db, args->argv[1], 0, &r, &rl);
+       if(status == -1){
+               fprintf(stderr, "Error searching for file '%s'\n", args->argv[1]);
+               return -1;
+       }
+       printf("Tags of file '%s' (%"PRIu64"):\n", args->argv[1], rl);
+       for(uint64_t i = 0; i < rl; ++i){
+               printf("\t- %s\n", (*db)->ltags->table[r[i]]);
+       }
+       printf("\n");
+}
+
+static int commandShowf(argList *args, database **db){
+       // We only show the tags of one file
+       if(*db == NULL){
+               fprintf(stderr, "Error: no database to show files of tag\n");
+               return -1;
+       }
+       if(args->argc > 2){
+               fprintf(stderr, "Error: too many arguments for 'SHOWF', current support for only one tag. Only showing files of first tag ('%s')\n", args->argv[1]);
+       }
+       
+       uint64_t rl, *r;
+       int status = searchTag(*db, args->argv[1], 0, &r, &rl);
+       if(status == -1){
+               fprintf(stderr, "Error searching for tag '%s'\n", args->argv[1]);
+               return -1;
+       }
+       printf("Files of tag '%s' (%"PRIu64"):\n", args->argv[1], rl);
+       for(uint64_t i = 0; i < rl; ++i){
+               printf("\t- %s\n", (*db)->lfiles->table[r[i]]);
+       }
+       printf("\n");
+}
+
+ int (*commands[])(argList*, database**) = {
+       commandExit, commandDebug,
+       commandCreate, commandDelete, commandOpen, commandSave, commandClose,
+       commandAddf, commandAddt, commandDeletef, commandDeletet,
+       commandTag, commandRemove,
+       commandShow, commandShowt, commandShowf
+       };
+
+int handleInput(argList *args, database **db){
+       if(args == NULL){
+               return 0;
+       }
+       int command = -1;
+       for(int i = 0; i < NKEYWORDS; ++i){
+               uint32_t l1, l2;
+               if(sameStr(normalizeStr(args->argv[0], &l1), normalizeStr(keywords[i], &l2))){
+                       command = i;
+                       break;
+               }
+       }
+       if(command == -1){
+               fprintf(stderr, "Error: command '%s' not found\n", args->argv[0]);
+               return -1;
+       }
+       return commands[command](args, db);
+}
index c63ad447635b475fd11eadddc5e5a64aecfef8f2..ed829d1e0ecea79d1151c179aa6e58a67e69e6a7 100644 (file)
@@ -5,7 +5,6 @@ inputBuffer *newInputBuffer(void){
        inputBuffer *in = malloc(sizeof(inputBuffer));
        in->buffer = NULL;
        in->inputSize = 0;
-       
        return in;
 }
 
@@ -18,13 +17,17 @@ void getInput(inputBuffer *in){
        size_t n;
        ssize_t r = getline(&(in->buffer), &n, stdin);
        if(r <= 0){
-               printf("Error\n");
+               fprintf(stderr, "Error\n");
                exit(r);
        }
        in->inputSize = r-1;
        in->buffer[in->inputSize] = 0;
 }
 
-void prompt(void){
-       printf("db > ");
-}
\ No newline at end of file
+void prompt(database *db){
+       if(db == NULL){
+               printf("db > ");
+       }else{
+               printf("%s > ", db->name);
+       }
+}
index 9afede75ac9b983de0b6bc6a52d32c9243dd6711..bc5ab6b876291359d218c2335c8c1241de81c58e 100644 (file)
@@ -10,6 +10,13 @@ ltable *newLtable(uint64_t size){
        return lt;
 }
 
+int deleteLtable(ltable **lt){
+       free((*lt)->table);
+       free(*lt);
+       *lt = NULL;
+       return 0;
+}
+
 int insertLtable(ltable *lt, char *str){
        uint32_t ls;
        str = normalizeStrLimit(str, &ls, MAXPATH-1);
@@ -105,6 +112,13 @@ ctable *newCtable(uint64_t size){
        return ct;
 }
 
+int deleteCtable(ctable **ct){
+       free((*ct)->table);
+       free(*ct);
+       *ct = NULL;
+       return 0;
+}
+
 int insertCtable(ctable *ct, uint64_t n){
        uint64_t *nct = malloc((ct->size+1)*sizeof(uint64_t));
        for(uint64_t i = 0; i < ct->size; ++i){
@@ -184,6 +198,13 @@ mtable *newMtable(uint64_t size){
        return mt;
 }
 
+int deleteMtable(mtable **mt){
+       free((*mt)->table);
+       free(*mt);
+       *mt = NULL;
+       return 0;
+}
+
 int insertMtable(mtable *mt, relation r){
        relation *nmt = malloc((mt->size+1)*sizeof(relation));
        for(uint64_t i = 0; i < mt->size; ++i){
@@ -301,6 +322,17 @@ node *newNode(uint64_t h, uint64_t i){
        return n;
 }
 
+int deleteTree(tree *root){
+       if(*root == NULL){
+               return -1;
+       }
+       deleteTree(&(*root)->left);
+       deleteTree(&(*root)->right);
+       free(*root);
+       *root = NULL;
+       return 0;
+}
+
 static node *rotateNodeRight(node *r){
        node *nr = r->left;
        node *nc = nr->right;