diff options
author | Gabriel A. Giovanini <mail@gabrielgio.me> | 2024-02-17 11:41:23 +0100 |
---|---|---|
committer | gabrielgio <gabrielgio@workstation.lan> | 2024-02-17 16:48:54 +0100 |
commit | d102e028aee6571c0fd9dfd4074cfb3c15f4594e (patch) | |
tree | e0f3bdadc96019de0a7576ea591f8b304a962e67 | |
parent | c573d3b7954296d95a0f8a79b8ac2ca261d86a02 (diff) | |
download | dict-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.txt | 10 | ||||
-rw-r--r-- | dict/CMakeLists.txt | 6 | ||||
-rw-r--r-- | dict/main.c | 111 | ||||
-rw-r--r-- | importer/CMakeLists.txt | 9 | ||||
-rw-r--r-- | importer/main.c | 71 | ||||
-rw-r--r-- | lib/CMakeLists.txt | 5 | ||||
-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.c | 61 | ||||
-rw-r--r-- | lib/util.h | 15 | ||||
-rw-r--r-- | main.c | 104 |
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) @@ -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); @@ -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. @@ -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; +} @@ -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); @@ -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); @@ -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); @@ -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; -} |