]> git.xolatile.top Git - soikk-DB.git/commitdiff
More quality of life changes
authorSoikk <76824648+Soikk@users.noreply.github.com>
Thu, 5 May 2022 16:45:45 +0000 (18:45 +0200)
committerSoikk <76824648+Soikk@users.noreply.github.com>
Thu, 5 May 2022 16:45:45 +0000 (18:45 +0200)
12 files changed:
include/db.h [new file with mode: 0644]
include/parser.h [new file with mode: 0644]
include/repl.h [new file with mode: 0644]
include/storage.h [new file with mode: 0644]
include/str.h [new file with mode: 0644]
include/strnatcmp.h [new file with mode: 0644]
src/main.c [new file with mode: 0644]
src/parser.c [new file with mode: 0644]
src/repl.c [new file with mode: 0644]
src/storage.c [new file with mode: 0644]
src/str.c [new file with mode: 0644]
src/strnatcmp.c [new file with mode: 0644]

diff --git a/include/db.h b/include/db.h
new file mode 100644 (file)
index 0000000..a5fca10
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef DB_H
+#define DB_H
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+
+#include "strnatcmp.h"
+
+#include "repl.h"
+#include "parser.h"
+#include "storage.h"
+#include "str.h"
+
+
+#endif
\ No newline at end of file
diff --git a/include/parser.h b/include/parser.h
new file mode 100644 (file)
index 0000000..2e46967
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef PARSER_H
+#define PARSER_H
+
+#include "db.h"
+
+
+typedef enum {
+       META_COMMAND_SUCCESS,
+       META_COMMAND_FAIL,
+} metaCommandStatus;
+
+
+int handleMetaCommand(inputBuffer *in);
+
+int handleInput(inputBuffer *in);
+
+#endif
\ No newline at end of file
diff --git a/include/repl.h b/include/repl.h
new file mode 100644 (file)
index 0000000..9c9fb8e
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef REPL_H
+#define REPL_H
+
+#include "db.h"
+
+typedef struct {
+       char *buffer;
+       ssize_t inputSize;
+} inputBuffer;
+
+
+inputBuffer *newInputBuffer(void);
+
+void freeInputBuffer(inputBuffer *in);
+
+void getInput(inputBuffer *in);
+
+void prompt(void);
+
+#endif
\ No newline at end of file
diff --git a/include/storage.h b/include/storage.h
new file mode 100644 (file)
index 0000000..507c733
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef STORAGE_H
+#define STORAGE_H
+
+#include "db.h"
+
+#define MAXPATH 4096
+#define MAXTAGS 4096
+
+
+// When intializing the struct, it is recommended
+// to also initialize numTags and lenTags
+typedef struct{
+       char path[MAXPATH];
+       char tags[MAXTAGS];
+       uint16_t numTags;
+       uint16_t lenTags;
+} row;
+
+
+row *newRow(const char *path);
+
+void insertTag(row *r, char *tag);
+
+void removeTag(row *r, char *tag);
+
+#endif
\ No newline at end of file
diff --git a/include/str.h b/include/str.h
new file mode 100644 (file)
index 0000000..ffda145
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef STRINGS_H
+#define STRINGS_H
+
+#include "db.h"
+
+
+uint16_t len(const char *s);
+
+bool sameStr(const char *s1, const char *s2);
+
+ssize_t strInTags(const char *tags, int n, const char *ndl, int m, char sep); 
+
+
+#endif
\ No newline at end of file
diff --git a/include/strnatcmp.h b/include/strnatcmp.h
new file mode 100644 (file)
index 0000000..9d98198
--- /dev/null
@@ -0,0 +1,31 @@
+/* -*- mode: c; c-file-style: "k&r" -*-
+
+  strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
+  Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+/* CUSTOMIZATION SECTION
+ *
+ * You can change this typedef, but must then also change the inline
+ * functions in strnatcmp.c */
+typedef char nat_char;
+
+int strnatcmp(nat_char const *a, nat_char const *b);
+int strnatcasecmp(nat_char const *a, nat_char const *b);
\ No newline at end of file
diff --git a/src/main.c b/src/main.c
new file mode 100644 (file)
index 0000000..c3b2a67
--- /dev/null
@@ -0,0 +1,38 @@
+#include "db.h"
+
+
+int main(){
+
+       inputBuffer *in = newInputBuffer();
+
+
+       row r = {"C:/xd", "perro", 1, 5};
+       printf("%s %d %d\n", r.tags, r.numTags, r.lenTags);
+       insertTag(&r, "caca");
+       insertTag(&r, "mierda");
+       insertTag(&r, "perra");
+       insertTag(&r, "tu");
+       printf("%s %d %d\n", r.tags, r.numTags, r.lenTags);
+
+       printf("%d\n", strInTags(r.tags, r.lenTags, ";perro", 6, ';'));
+
+       row *r2 = newRow("test1test2test3testtesttesttesttesttettesttestestest");
+
+       while(0){
+
+               prompt();
+               getInput(in);
+               
+               insertTag(r2, in->buffer);
+               printf("Tags of row '%s': %s\n", r2->path, r2->tags);
+
+               /*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;
+               }*/
+       }
+}
\ No newline at end of file
diff --git a/src/parser.c b/src/parser.c
new file mode 100644 (file)
index 0000000..f26a0cb
--- /dev/null
@@ -0,0 +1,20 @@
+#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;
+       }
+}
+
+int handleInput(inputBuffer *in){
+       if(in->buffer[0] == '.'){
+               return handleMetaCommand(in);
+       }else{
+               printf("normal command\n");
+       }
+}
\ No newline at end of file
diff --git a/src/repl.c b/src/repl.c
new file mode 100644 (file)
index 0000000..c63ad44
--- /dev/null
@@ -0,0 +1,30 @@
+#include "db.h"
+
+
+inputBuffer *newInputBuffer(void){
+       inputBuffer *in = malloc(sizeof(inputBuffer));
+       in->buffer = NULL;
+       in->inputSize = 0;
+       
+       return in;
+}
+
+void freeInputBuffer(inputBuffer *in){
+       free(in->buffer);
+       free(in);
+}
+
+void getInput(inputBuffer *in){
+       size_t n;
+       ssize_t r = getline(&(in->buffer), &n, stdin);
+       if(r <= 0){
+               printf("Error\n");
+               exit(r);
+       }
+       in->inputSize = r-1;
+       in->buffer[in->inputSize] = 0;
+}
+
+void prompt(void){
+       printf("db > ");
+}
\ No newline at end of file
diff --git a/src/storage.c b/src/storage.c
new file mode 100644 (file)
index 0000000..f934c4f
--- /dev/null
@@ -0,0 +1,160 @@
+#include "db.h"
+
+
+row *newRow(const char path[MAXPATH]){
+       row *nr = malloc(sizeof(row));
+       memcpy(nr->path, path, MAXPATH);
+       memcpy(nr->tags, "\0", MAXTAGS);
+       nr->numTags = 0;
+       nr->lenTags = 0;
+
+       return nr;
+}
+
+// Splits src into words based on a separator character (sep) and stores them in arr,
+// and the length in len. Inspired by https://github.com/joshdk/tag/blob/master/src/dsv.c's split
+static void split(const char *src, char sep, char ***arr, int *len){
+       int slen = 0, ai = 0, wnum = 0, wlen = 0;
+
+       while(src[slen] != '\0'){
+               if(src[slen] == sep){
+                       ++wnum;
+               }
+               ++slen;
+       }
+       if(slen != 0 && src[slen-1] != sep){
+               ++wnum;
+       }
+       ++slen;
+
+       *arr = calloc((wnum+1), sizeof(char*));
+       for(int i = 0; i < slen; ++i){
+               if(src[i] == sep || src[i] == '\0'){
+                       (*arr)[ai] = calloc(wlen+1, sizeof(char));
+                       for(int j = i-wlen, k = 0; j < i; ++j, ++k){
+                               (*arr)[ai][k] = src[j];
+                       }
+                       ++ai;
+                       wlen = 0;
+               }else{
+                       ++wlen;
+               }
+       }
+       *len = wnum;
+}
+
+static void swapWords(char ***arr, int a, int b){
+       char *tmp = (*arr)[a];
+       (*arr)[a] = (*arr)[b];
+       (*arr)[b] = tmp;
+}
+
+static char *normalizeTag(char *tag){
+       uint16_t l = len(tag);
+       char *ntag = calloc(l+1, sizeof(char));
+       for(int i = 0; i < l; ++i){
+               ntag[i] = tolower(tag[i]);
+       }
+       return ntag;
+}
+
+// Adds a tag in the tags array in the row r, sorted by natural string
+// comparison with strnatcmp. We assume that when adding a tag all other
+// tags are already sorted. Nothing is done if the tag is already in the tags
+void insertTag(row *r, char *tag){
+       int l, ltag = len(tag);
+       if(ltag == 0){
+               return;
+       }
+
+       tag = normalizeTag(tag);
+
+       // Dump tags into array of strings and add tag
+       char **arr, **tmp;
+       split(r->tags, ';', &arr, &l);
+       
+       if((tmp = realloc(arr, (l+1)*sizeof(char*))) != NULL){
+               arr = tmp;
+               tmp = NULL;
+       }else{
+               fprintf(stderr, "Error reallocating array (insertTag)");
+               exit(EXIT_FAILURE);
+       }
+       arr[l] = malloc((len(tag)+1)*sizeof(char));
+       strcpy(arr[l], tag);
+       
+       // Sort tag by natural string comparison, starting from the last element (the new tag)
+       for(int i = l; i > 0; --i){
+               switch(strnatcmp(arr[i-1], arr[i])){
+                       case 1:
+                               // arr[i-1] is higher than arr[i]; swap them
+                               swapWords(&arr, i, i-1);
+                               break;
+                       case -1:
+                               // arr[i-1] is lower than arr[i]; exit loop
+                               i = 0;
+                               break;
+                       case 0:
+                               // The tag already exists, no need to alter anything
+                               free(arr);
+                               return;
+               }
+       }
+       ++l; // Succesfully added new tag
+
+       // Insert tags back into tags member of row structure with the ';' separator in between them
+       int tagnum = 0;
+       for(int i = 0; i < l; ++i){
+               int j = 0;
+               while(arr[i][j] != '\0'){
+                       r->tags[tagnum] = arr[i][j];
+                       ++j;
+                       ++tagnum;
+               }
+               r->tags[tagnum++] = ';';
+       }
+       r->tags[tagnum] = '\0';
+       r->numTags = l;
+       r->lenTags = tagnum;
+}
+
+// Remove a tag from the tags array in the row r
+// Nothing is done if the tag isnt in the tags
+void removeTag(row *r, char *tag){
+       int l, ltag = len(tag);
+       if(ltag == 0){
+               return;
+       }
+
+       tag = normalizeTag(tag);
+
+       // Dump tags into array of strings
+       char **arr;
+       split(r->tags, ';', &arr, &l);
+
+       // Search for tag and remove it
+       for(int i = 0; i <= l; ++i){
+               if(sameStr(arr[i], tag)){
+                       for(int j = i; j < l; ++j){
+                               arr[j] = arr[j+1];
+                       }
+                       --l;
+                       break;
+               }
+       }
+
+       // Insert tags back into tags member of row structure with the ';' separator in between them
+       int tagnum = 0;
+       for(int i = 0; i < l; ++i){
+               int j = 0;
+               while(arr[i][j] != '\0'){
+                       r->tags[tagnum] = arr[i][j];
+                       ++j;
+                       ++tagnum;
+               }
+               r->tags[tagnum++] = ';';
+       }
+       r->tags[tagnum] = '\0';
+       r->numTags = l;
+       r->lenTags = tagnum;
+}
\ No newline at end of file
diff --git a/src/str.c b/src/str.c
new file mode 100644 (file)
index 0000000..9cf5685
--- /dev/null
+++ b/src/str.c
@@ -0,0 +1,59 @@
+#include "db.h"
+
+
+uint16_t len(const char *s){
+       uint16_t l = -1;
+       while(s[++l]);
+       return l;
+}
+
+bool sameStr(const char *s1, const char *s2){
+       uint16_t i1 = 0, i2 = 0;
+       while(s1[i1] && s2[i2] && s1[i1] == s2[i2])
+               ++i1, ++i2;
+       return !s1[i1] && !s2[i2];
+}
+
+// Auxiliary function for creating a lookup table of the haystack
+// table[i] will be the number of shifts right until the next
+// separator when checking position i
+// Only really useful for this implementation of tags
+static int *table(const char *y, int n, char sep){
+       int *tb = calloc(n, sizeof(int));
+       if(tb == NULL){
+               fprintf(stderr, "Error callocating array (table)");
+               exit(EXIT_FAILURE);
+       }
+
+       int lSep = n-1;
+       for(int i = n-1; i >= 0; --i){
+               if(y[i] == sep){
+                       tb[i] = 1;
+                       lSep = i;
+               }else if(y[i] != '\0'){
+                       tb[i] = lSep-i;
+               }
+       }
+       return tb;
+}
+
+// Returns the position of ndl in tags, -1 if its not found
+// A return of 0 means ndl occurs in tags starting in position 0
+// Use 'if(strInTags(...) != -1)' when using this function
+ssize_t strInTags(const char *tags, int n, const char *ndl, int m, char sep){
+       int *tb = table(tags, n, sep);
+
+       for(int i = 0; i < n; ){
+               int j = 0;
+               while(j < m && tags[i+j] == ndl[j]){
+                       ++j;
+               }
+               if(j == m){
+                       return i;
+               }
+               if(tags[i+j] != ndl[j]){
+                       i += tb[i];
+               }
+       }
+       return -1;
+}
\ No newline at end of file
diff --git a/src/strnatcmp.c b/src/strnatcmp.c
new file mode 100644 (file)
index 0000000..46b7946
--- /dev/null
@@ -0,0 +1,187 @@
+/* -*- mode: c; c-file-style: "k&r" -*-
+
+  strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
+  Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+/* partial change history:
+ *
+ * 2004-10-10 mbp: Lift out character type dependencies into macros.
+ *
+ * Eric Sosman pointed out that ctype functions take a parameter whose
+ * value must be that of an unsigned int, even on platforms that have
+ * negative chars in their default char type.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+
+#include "strnatcmp.h"
+
+
+/* These are defined as macros to make it easier to adapt this code to
+ * different characters types or comparison functions. */
+static inline int
+nat_isdigit(nat_char a)
+{
+     return isdigit((unsigned char) a);
+}
+
+
+static inline int
+nat_isspace(nat_char a)
+{
+     return isspace((unsigned char) a);
+}
+
+
+static inline nat_char
+nat_toupper(nat_char a)
+{
+     return toupper((unsigned char) a);
+}
+
+
+
+static int
+compare_right(nat_char const *a, nat_char const *b)
+{
+     int bias = 0;
+     
+     /* The longest run of digits wins.  That aside, the greatest
+       value wins, but we can't know that it will until we've scanned
+       both numbers to know that they have the same magnitude, so we
+       remember it in BIAS. */
+     for (;; a++, b++) {
+         if (!nat_isdigit(*a)  &&  !nat_isdigit(*b))
+              return bias;
+         else if (!nat_isdigit(*a))
+              return -1;
+         else if (!nat_isdigit(*b))
+              return +1;
+         else if (*a < *b) {
+              if (!bias)
+                   bias = -1;
+         } else if (*a > *b) {
+              if (!bias)
+                   bias = +1;
+         } else if (!*a  &&  !*b)
+              return bias;
+     }
+
+     return 0;
+}
+
+
+static int
+compare_left(nat_char const *a, nat_char const *b)
+{
+     /* Compare two left-aligned numbers: the first to have a
+        different value wins. */
+     for (;; a++, b++) {
+         if (!nat_isdigit(*a)  &&  !nat_isdigit(*b))
+              return 0;
+         else if (!nat_isdigit(*a))
+              return -1;
+         else if (!nat_isdigit(*b))
+              return +1;
+         else if (*a < *b)
+              return -1;
+         else if (*a > *b)
+              return +1;
+     }
+         
+     return 0;
+}
+
+
+static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case)
+{
+     int ai, bi;
+     nat_char ca, cb;
+     int fractional, result;
+     
+     assert(a && b);
+     ai = bi = 0;
+     while (1) {
+         ca = a[ai]; cb = b[bi];
+
+         /* skip over leading spaces or zeros */
+         while (nat_isspace(ca))
+              ca = a[++ai];
+
+         while (nat_isspace(cb))
+              cb = b[++bi];
+
+         /* process run of digits */
+         if (nat_isdigit(ca)  &&  nat_isdigit(cb)) {
+               /*
+                       Modified by Soikk for the purpose of DB
+                       To revert to original version, remove this comment,
+                       the uncommented code inside this if statement and
+                       uncomment the remaining piece of code inside this
+                       if statement
+               */
+                  if ((result = compare_right(a+ai, b+bi)) != 0)
+                   return result;
+              /*fractional = (ca == '0' || cb == '0');
+
+              if (fractional) {
+                   if ((result = compare_left(a+ai, b+bi)) != 0)
+                        return result;
+              } else {
+                   if ((result = compare_right(a+ai, b+bi)) != 0)
+                        return result;
+              }*/
+         }
+
+         if (!ca && !cb) {
+              /* The strings compare the same.  Perhaps the caller
+                  will want to call strcmp to break the tie. */
+              return 0;
+         }
+
+         if (fold_case) {
+              ca = nat_toupper(ca);
+              cb = nat_toupper(cb);
+         }
+         
+         if (ca < cb)
+              return -1;
+         else if (ca > cb)
+              return +1;
+
+         ++ai; ++bi;
+     }
+}
+
+
+
+int strnatcmp(nat_char const *a, nat_char const *b) {
+     return strnatcmp0(a, b, 0);
+}
+
+
+/* Compare, recognizing numeric string and ignoring case. */
+int strnatcasecmp(nat_char const *a, nat_char const *b) {
+     return strnatcmp0(a, b, 1);
+}
\ No newline at end of file