aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGabriel A. Giovanini <mail@gabrielgio.me>2024-02-17 11:41:23 +0100
committergabrielgio <gabrielgio@workstation.lan>2024-02-17 16:48:54 +0100
commitd102e028aee6571c0fd9dfd4074cfb3c15f4594e (patch)
treee0f3bdadc96019de0a7576ea591f8b304a962e67
parentc573d3b7954296d95a0f8a79b8ac2ca261d86a02 (diff)
downloaddict-d102e028aee6571c0fd9dfd4074cfb3c15f4594e.tar.gz
dict-d102e028aee6571c0fd9dfd4074cfb3c15f4594e.tar.bz2
dict-d102e028aee6571c0fd9dfd4074cfb3c15f4594e.zip
ref: Refactor newer folder structure
Create a lib dict and importer project. * dict: holds the main application * importer: code to read from source to a common database. * lib: shared code
-rw-r--r--CMakeLists.txt10
-rw-r--r--dict/CMakeLists.txt6
-rw-r--r--dict/main.c111
-rw-r--r--importer/CMakeLists.txt9
-rw-r--r--importer/main.c71
-rw-r--r--lib/CMakeLists.txt5
-rw-r--r--lib/data.c (renamed from data.c)12
-rw-r--r--lib/data.h (renamed from data.h)2
-rw-r--r--lib/list.c (renamed from list.c)11
-rw-r--r--lib/list.h (renamed from list.h)4
-rw-r--r--lib/ui.c (renamed from ui.c)7
-rw-r--r--lib/ui.h (renamed from ui.h)3
-rw-r--r--lib/util.c61
-rw-r--r--lib/util.h15
-rw-r--r--main.c104
15 files changed, 311 insertions, 120 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f253be6..a88fc55 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,12 +2,6 @@ cmake_minimum_required(VERSION 3.26)
project(dict VERSION 0.1 LANGUAGES C)
-file(GLOB src CONFIGURE_DEPENDS "*.h" "*.c")
-add_executable(dict ${src})
-
-target_compile_options(dict PRIVATE -Wall -Wextra -Wpedantic -Werror)
-target_include_directories(dict PUBLIC "${PROJECT_BINARY_DIR}")
-target_link_libraries(dict sqlite3 ncursesw m c)
-
-
add_subdirectory(ext)
+add_subdirectory(importer)
+add_subdirectory(lib)
diff --git a/dict/CMakeLists.txt b/dict/CMakeLists.txt
new file mode 100644
index 0000000..051635b
--- /dev/null
+++ b/dict/CMakeLists.txt
@@ -0,0 +1,6 @@
+file(GLOB src CONFIGURE_DEPENDS "*.c")
+add_executable(dict ${src})
+
+target_compile_options(dict PRIVATE -Wall -Wextra -Wpedantic -Werror)
+target_include_directories(dict PUBLIC "${PROJECT_BINARY_DIR}")
+target_link_libraries(dict sqlite3 ncursesw m c lib)
diff --git a/dict/main.c b/dict/main.c
new file mode 100644
index 0000000..8240b75
--- /dev/null
+++ b/dict/main.c
@@ -0,0 +1,111 @@
+#include <unistd.h>
+#include <string.h>
+#include <locale.h>
+#include <stdio.h>
+#include <sqlite3.h>
+#include <ncurses.h>
+
+#include "../lib/data.h"
+#include "../lib/ui.h"
+#include "../lib/util.h"
+
+Data *data;
+
+void search(char*, int);
+int run(const char*, const char*);
+
+int main(int argc, char** argv) {
+ int opt;
+ char* txt = NULL;
+ char* db = NULL;
+
+ while ((opt = getopt(argc, argv, "t:d:h")) != -1) {
+ switch(opt) {
+ case 't':
+ txt = copy_achar(optarg);
+ break;
+ case 'd':
+ db = copy_achar(optarg);
+ break;
+ case 'h':
+ // fall through
+ default:
+ printf("Usage: %s", argv[0]);
+ goto end;
+ }
+ }
+
+ int r = run(db, txt);
+
+end:
+ if (txt != NULL)
+ free(txt);
+ if (db != NULL)
+ free(db);
+
+ return r;
+}
+
+int run(const char *db, const char *txt) {
+ data = new_data(db);
+ bootstrap(data);
+
+ setlocale(LC_ALL, "");
+ initscr();
+ noecho();
+ cbreak();
+ keypad(stdscr, TRUE);
+
+ FILE *f = fopen(txt, "r");
+ unsigned int lines = count_file_lines(f);
+ fseek(f, 0, SEEK_SET);
+
+ char * line = NULL;
+ size_t len = 0;
+ ssize_t read;
+ PROGRESS_BAR *bar = new_progress_bar(stdscr, lines);
+ while ((read = getline(&line, &len, f)) != -1) {
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+
+ insert(data, line, read-1);
+ bar_step(bar, 1);
+ }
+
+ move(2,0);
+ printw("Saving db...");
+ refresh();
+ load_or_save_db(data->db, "backup.db", 1);
+
+ clear();
+ refresh();
+
+ TEXT_BOX *box = new_text_box(stdscr, 100);
+ get_char(box, search);
+
+ clear();
+ refresh();
+
+ endwin();
+
+ free_data(data);
+ return 0;
+}
+
+void search(char *sch, int len) {
+ char s[len+2];
+
+ sprintf(s, "%%%*s%%", len, sch);
+
+ LIST* l = data_select(data, s, len+2);
+
+ for (int y = 1; y < 20; y++) {
+ move(y, 0);
+ Word *item = (Word*)list_get(l, y);
+ if (item != NULL)
+ printw("%s", item->Line);
+ }
+ refresh();
+}
+
+
diff --git a/importer/CMakeLists.txt b/importer/CMakeLists.txt
new file mode 100644
index 0000000..587952e
--- /dev/null
+++ b/importer/CMakeLists.txt
@@ -0,0 +1,9 @@
+project(dict_importer VERSION 0.1 LANGUAGES C)
+
+file(GLOB src CONFIGURE_DEPENDS "*.c")
+add_executable(dict_importer ${src})
+
+target_compile_options(dict_importer PRIVATE -Wall -Wextra -Wpedantic -Werror)
+target_include_directories(dict_importer PUBLIC "${PROJECT_BINARY_DIR}" "${PROJECT_SOURCE_DIR}")
+target_link_libraries(dict_importer sqlite3 lib)
+
diff --git a/importer/main.c b/importer/main.c
new file mode 100644
index 0000000..a1850f8
--- /dev/null
+++ b/importer/main.c
@@ -0,0 +1,71 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "../lib/util.h"
+#include "../lib/data.h"
+
+int run(const char *db, const char *txt);
+
+int main(int argc, char** argv) {
+ int opt;
+ char* txt = NULL;
+ char* db = NULL;
+
+ while ((opt = getopt(argc, argv, "t:d:h")) != -1) {
+ switch(opt) {
+ case 't':
+ txt = copy_achar(optarg);
+ break;
+ case 'd':
+ db = copy_achar(optarg);
+ break;
+ case 'h':
+ // fall through
+ default:
+ printf("Usage: %s", argv[0]);
+ goto end;
+ }
+ }
+
+
+ int r = run(db, txt);
+
+end:
+ if (txt != NULL)
+ free(txt);
+ if (db != NULL)
+ free(db);
+
+ return r;
+}
+
+int run(const char *db, const char *txt) {
+ char * line = NULL;
+ size_t len = 0;
+ int count = 0;
+ ssize_t read;
+ Data *data;
+ FILE *f;
+ int total;
+
+ data = new_data(":memory:");
+ f = fopen(txt, "r");
+
+ bootstrap(data);
+
+ total = count_file_lines(f);
+ fseek(f, 0, SEEK_SET);
+
+ while ((read = getline(&line, &len, f)) != -1) {
+ if (line[0] == '#' || line[0] == '\n')
+ continue;
+
+ insert(data, line, read-1);
+
+ float t = ((float)count/(float)total)*100;
+ printf("\rLoading data [%03.0f%%] %d/%d", t, count, total);
+ }
+
+ return load_or_save_db(data->db, db, 1);
+}
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100644
index 0000000..023cdf1
--- /dev/null
+++ b/lib/CMakeLists.txt
@@ -0,0 +1,5 @@
+file(GLOB lib CONFIGURE_DEPENDS "*.h" "*.c")
+
+add_library(lib ${lib})
+target_compile_options(lib PRIVATE -Wall -Wextra -Wpedantic -Werror)
+target_link_libraries(lib sqlite3 ncursesw m c)
diff --git a/data.c b/lib/data.c
index 2c3f3bb..7ebf597 100644
--- a/data.c
+++ b/lib/data.c
@@ -1,10 +1,11 @@
+#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "data.h"
const char *insert_into = "INSERT INTO words (LINE) VALUES($VVV);";
-const char *select_words = "SELECT Id, Line FROM words LIMIT 10;";
+const char *select_words = "SELECT Id, Line FROM words WHERE line like $VVV LIMIT 10;";
const char *create_table = "CREATE TABLE IF NOT EXISTS words (ID INTEGER PRIMARY KEY AUTOINCREMENT, LINE TEXT NOT NULL);";
Data* new_data(const char* con) {
@@ -42,7 +43,6 @@ void insert(Data* data, char* line, int len) {
return;
}
- // binds the paremets to the statement, in this case the line;
sqlite3_bind_text(stmt, 1, line, len, NULL);
int c = sqlite3_step(stmt);
@@ -76,7 +76,7 @@ void bootstrap(Data* data) {
sqlite3_finalize(stmt);
}
-LIST* data_select(Data* data) {
+LIST* data_select(Data* data, char *sch, int len) {
sqlite3_stmt *stmt;
int r = sqlite3_prepare_v2(data->db, select_words, -1, &stmt, NULL);
@@ -89,15 +89,19 @@ LIST* data_select(Data* data) {
LIST *list = NULL;
+ sqlite3_bind_text(stmt, 1, sch, len, NULL);
+
int m = sqlite3_step(stmt);
while(m == SQLITE_ROW) {
Word *word = (Word*)malloc(sizeof(Word));
int id = sqlite3_column_int(stmt, 0);
const unsigned char *line = sqlite3_column_text(stmt, 1);
+ unsigned char *line2 = malloc(sizeof(char*)+strlen((char*)line));
+ memcpy(line2, line, strlen((char*)line));
word->Id = id;
- word->Line = line;
+ word->Line = line2;
list = list_add(list, word);
m = sqlite3_step(stmt);
diff --git a/data.h b/lib/data.h
index 8bc30e9..56edd34 100644
--- a/data.h
+++ b/lib/data.h
@@ -39,7 +39,7 @@ void insert(Data*, char*, int);
/*
* Select all words.
*/
-LIST* data_select(Data*);
+LIST* data_select(Data*, char*, int);
/*
* Print result code from sqlite.
diff --git a/list.c b/lib/list.c
index a40dd57..fc0fddf 100644
--- a/list.c
+++ b/lib/list.c
@@ -42,3 +42,14 @@ void list_free(LIST* list) {
free(list->list);
free(list);
}
+
+
+void *list_get(LIST *list, unsigned int index) {
+ if (list == NULL)
+ return NULL;
+
+ if (index < list->size)
+ return list->list[index];
+
+ return NULL;
+}
diff --git a/list.h b/lib/list.h
index e33bf01..dd28722 100644
--- a/list.h
+++ b/lib/list.h
@@ -22,6 +22,8 @@ LIST* list_add(LIST* list, void* item);
* @list: array list structure.
* @pos: position of item to be removed.
*/
-LIST* list_remove(LIST* list, unsigned int pos);
+LIST *list_remove(LIST *list, unsigned int pos);
void list_free(LIST* list);
+
+void *list_get(LIST *list, unsigned int index);
diff --git a/ui.c b/lib/ui.c
index 9762859..1a285a0 100644
--- a/ui.c
+++ b/lib/ui.c
@@ -58,7 +58,7 @@ TEXT_BOX* new_text_box(WINDOW* scr, int length) {
return text;
}
-void get_char(TEXT_BOX* text) {
+void get_char(TEXT_BOX* text, void (*sch)(char*, int)) {
while(1){
wchar_t c;
get_wch((wint_t*)&c);
@@ -75,6 +75,11 @@ void get_char(TEXT_BOX* text) {
text->text[++text->current] = '\0';
}
}
+
+ char str[text->length];
+ wcstombs(str, text->text, sizeof(text->text));
+ sch(str, (int)strlen(str));
+
move(0,0);
wrefresh(text->scr);
wprintw(text->scr, "%*ls", text->current,text->text);
diff --git a/ui.h b/lib/ui.h
index cdc0539..90b352f 100644
--- a/ui.h
+++ b/lib/ui.h
@@ -1,3 +1,4 @@
+#pragma once
#include <ncurses.h>
typedef struct progress_bar {
@@ -18,5 +19,5 @@ typedef struct text_box {
} TEXT_BOX;
TEXT_BOX* new_text_box(WINDOW*, int);
-void get_char(TEXT_BOX* text);
+void get_char(TEXT_BOX* text, void (*sch)(char*, int));
diff --git a/lib/util.c b/lib/util.c
new file mode 100644
index 0000000..6720082
--- /dev/null
+++ b/lib/util.c
@@ -0,0 +1,61 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "util.h"
+
+#define BUF_SIZE 100
+
+char* copy_achar(const char* src) {
+ int len = strlen(src) + 1;
+ char* dest = (char*)malloc(sizeof(char)*len);
+ strcpy(dest, src);
+
+ return dest;
+}
+
+
+int load_or_save_db(sqlite3 *pInMemory, const char *zFilename, int isSave){
+ int rc; /* Function return code */
+ sqlite3 *pFile; /* Database connection opened on zFilename */
+ sqlite3_backup *pBackup; /* Backup object used to copy data */
+ sqlite3 *pTo; /* Database to copy to (pFile or pInMemory) */
+ sqlite3 *pFrom; /* Database to copy from (pFile or pInMemory) */
+
+ rc = sqlite3_open(zFilename, &pFile);
+ if( rc==SQLITE_OK ){
+ pFrom = (isSave ? pInMemory : pFile);
+ pTo = (isSave ? pFile : pInMemory);
+
+ pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
+ if( pBackup ){
+ (void)sqlite3_backup_step(pBackup, -1);
+ (void)sqlite3_backup_finish(pBackup);
+ }
+ rc = sqlite3_errcode(pTo);
+ }
+
+ (void)sqlite3_close(pFile);
+ return rc;
+}
+
+unsigned int count_file_lines(FILE *file) {
+ char buf[BUF_SIZE];
+ unsigned int counter = 0;
+ for(;;)
+ {
+ size_t res = fread(buf, 1, BUF_SIZE, file);
+ if (ferror(file))
+ return -1;
+
+ size_t i;
+ for(i = 0; i < res; i++)
+ if (buf[i] == '\n')
+ counter++;
+
+ if (feof(file))
+ break;
+ }
+
+ return counter;
+}
diff --git a/lib/util.h b/lib/util.h
new file mode 100644
index 0000000..c03dbae
--- /dev/null
+++ b/lib/util.h
@@ -0,0 +1,15 @@
+#pragma once
+
+#include <sqlite3.h>
+#include <stdio.h>
+
+/*
+ * Copy of a char to a newly created string of the same size.
+ */
+char* copy_achar(const char*);
+
+
+int load_or_save_db(sqlite3 *pInMemory, const char *zFilename, int isSave);
+
+
+unsigned int count_file_lines(FILE *file);
diff --git a/main.c b/main.c
deleted file mode 100644
index 026b4b5..0000000
--- a/main.c
+++ /dev/null
@@ -1,104 +0,0 @@
-#include <locale.h>
-#include <stdio.h>
-#include <sqlite3.h>
-#include <ncurses.h>
-#include "data.h"
-#include "ui.h"
-
-#define BUF_SIZE 100
-
-unsigned int count_lines(FILE* file);
-int load_or_save_db(sqlite3 *pInMemory, const char *zFilename, int isSave);
-
-int main() {
- Data *data = new_data(":memory:");
- bootstrap(data);
-
- setlocale(LC_ALL, "");
- noecho();
- cbreak();
- nonl();
- keypad(stdscr, TRUE);
- initscr();
-
- FILE *f = fopen("dict.txt", "r");
- unsigned int lines = count_lines(f);
- fseek(f, 0, SEEK_SET);
-
- char * line = NULL;
- size_t len = 0;
- ssize_t read;
- PROGRESS_BAR *bar = new_progress_bar(stdscr, lines);
- while ((read = getline(&line, &len, f)) != -1) {
- if (line[0] == '#' || line[0] == '\n')
- continue;
-
- insert(data, line, read-1);
- bar_step(bar, 1);
- }
-
- move(2,0);
- printw("Saving db...");
- refresh();
- load_or_save_db(data->db, "backup.db", 1);
-
- clear();
- refresh();
-
- TEXT_BOX *box = new_text_box(stdscr, 10);
- get_char(box);
-
- clear();
- refresh();
-
- endwin();
-
- free_data(data);
- return 0;
-}
-
-int load_or_save_db(sqlite3 *pInMemory, const char *zFilename, int isSave){
- int rc; /* Function return code */
- sqlite3 *pFile; /* Database connection opened on zFilename */
- sqlite3_backup *pBackup; /* Backup object used to copy data */
- sqlite3 *pTo; /* Database to copy to (pFile or pInMemory) */
- sqlite3 *pFrom; /* Database to copy from (pFile or pInMemory) */
-
- rc = sqlite3_open(zFilename, &pFile);
- if( rc==SQLITE_OK ){
- pFrom = (isSave ? pInMemory : pFile);
- pTo = (isSave ? pFile : pInMemory);
-
- pBackup = sqlite3_backup_init(pTo, "main", pFrom, "main");
- if( pBackup ){
- (void)sqlite3_backup_step(pBackup, -1);
- (void)sqlite3_backup_finish(pBackup);
- }
- rc = sqlite3_errcode(pTo);
- }
-
- (void)sqlite3_close(pFile);
- return rc;
-}
-
-unsigned int count_lines(FILE* file)
-{
- char buf[BUF_SIZE];
- unsigned int counter = 0;
- for(;;)
- {
- size_t res = fread(buf, 1, BUF_SIZE, file);
- if (ferror(file))
- return -1;
-
- size_t i;
- for(i = 0; i < res; i++)
- if (buf[i] == '\n')
- counter++;
-
- if (feof(file))
- break;
- }
-
- return counter;
-}