From 9399f714068101bb92ac0e8c797dfcb7f486867e Mon Sep 17 00:00:00 2001 From: theBreadCompany Date: Tue, 3 Jun 2025 06:16:37 +0200 Subject: [PATCH] basic argument parsing, sql setups and other preparations --- .gitignore | 2 + CMakeLists.txt | 6 ++ src/CMakeLists.txt | 1 + src/main/CMakeLists.txt | 3 + src/main/include/sql.h | 30 ++++++++ src/main/include/util.h | 81 ++++++++++++++++++++++ src/main/main.c | 148 ++++++++++++++++++++++++++++++++++++++++ src/main/sql.c | 67 ++++++++++++++++++ src/main/util.c | 54 +++++++++++++++ 9 files changed, 392 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 src/CMakeLists.txt create mode 100644 src/main/CMakeLists.txt create mode 100644 src/main/include/sql.h create mode 100644 src/main/include/util.h create mode 100644 src/main/main.c create mode 100644 src/main/sql.c create mode 100644 src/main/util.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d822e99 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +cmake-*-debug +*.db diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..ea9785e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.31) +project(klist C) + +set(CMAKE_C_STANDARD 90) + +add_subdirectory(src) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..1602825 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(main) \ No newline at end of file diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt new file mode 100644 index 0000000..39cd1fa --- /dev/null +++ b/src/main/CMakeLists.txt @@ -0,0 +1,3 @@ +add_executable(klist main.c sql.c util.c) +target_include_directories(klist PRIVATE include) +target_link_libraries(klist sqlite3) \ No newline at end of file diff --git a/src/main/include/sql.h b/src/main/include/sql.h new file mode 100644 index 0000000..6431744 --- /dev/null +++ b/src/main/include/sql.h @@ -0,0 +1,30 @@ +#pragma once + +enum KLIST_SQL { + INIT, + ADD_USER, + GET_USER, + GET_USERS, + MOD_USER_NAME, + MOD_USER_LOCAL, + MOD_USER_DISCORD, + MOD_USER_GOOGLE, + ADD_LIST, + GET_LIST, + GET_LISTS, + MOD_LIST_NAME, + DEL_LIST, + ADD_STAGE, + GET_STAGE, + GET_STAGES_FOR_LIST, + DEL_STAGE, + ADD_TASK, + GET_TASK, + GET_TASKS, + MOD_TASK_NAME, + MOD_TASK_DESCRIPTION, + DEL_TASK, + _KLIST_SQL_COUNT +}; + +char *klist_sql_get(const enum KLIST_SQL); \ No newline at end of file diff --git a/src/main/include/util.h b/src/main/include/util.h new file mode 100644 index 0000000..d0d0a41 --- /dev/null +++ b/src/main/include/util.h @@ -0,0 +1,81 @@ +#pragma once +#include +#include + +/* + * command parsing + */ + +enum klist_command { + USER, + LIST, + TASK, +}; +struct klist { + sqlite3 *db; + sqlite3_stmt **stmts; + u_int cmd; + void *cmd_ctx; + int error; + +}; +typedef struct klist klist; + +klist *klist_init(char *db); +void klist_deinit(klist *list); + + +enum klist_user_command { + USER_GET, + USER_DELETE +}; +struct klist_user_context { + enum klist_command cmd; +}; +typedef struct klist_user_context klist_user_context; + +klist_user_context *klist_user_context_init(klist *list); +void klist_user_context_deinit(klist_user_context *ctx); + + +enum klist_list_command { + LIST_ADD, + LIST_EDIT, + LIST_GET, + LIST_DELETE, +}; +struct klist_list_context { + enum klist_user_command cmd; + char *name; + char **stages; +}; +typedef struct klist_list_context klist_list_context; + +klist_list_context *klist_list_context_init(klist *list); +void klist_list_context_deinit(klist_list_context *ctx); + + +enum klist_task_command { + TASK_ADD, + TASK_EDIT, + TASK_GET, + TASK_DELETE, +}; +struct klist_task_context { + enum klist_task_command cmd; + char *list; + char *name; + char *stage; +}; +typedef struct klist_task_context klist_task_context; + +klist_task_context *klist_task_context_init(klist *list); +void klist_task_context_deinit(klist_task_context *ctx); + + + +/* + * sql preparations + */ + +void klist_sql_prepare(klist *, char *db); \ No newline at end of file diff --git a/src/main/main.c b/src/main/main.c new file mode 100644 index 0000000..36b7679 --- /dev/null +++ b/src/main/main.c @@ -0,0 +1,148 @@ +#include +#include +#include +#include + +#include "util.h" + +void print_help(char **argv); +void setup(klist *ctx, int argc, char **argv); + +int main(int argc, char **argv) { + klist *ctx = klist_init("test.db"); + + if (argc == 1) { + print_help(argv); + ctx->error = 1; + } + + if (!ctx->error) { + setup(ctx, argc, argv); + switch (ctx->cmd) { + case USER: + switch (((klist_list_context *)ctx->cmd_ctx)->cmd) { + case USER_GET: + case USER_DELETE: + default: ; + } + case LIST: + switch (((klist_user_context *)ctx->cmd_ctx)->cmd) { + case LIST_ADD: + case LIST_EDIT: + case LIST_GET: + case LIST_DELETE: + default: ; + } + case TASK: + switch (((klist_task_context *)ctx->cmd_ctx)->cmd) { + case TASK_ADD: + case TASK_EDIT: + case TASK_GET: + case TASK_DELETE: + default: ; + } + default: ; + } + } + + const int error = ctx->error; + klist_deinit(ctx); + return error; +} + +void print_help(char **argv) { + fprintf(stderr, "Usage: %s \n", argv[0]); +} + +void setup(klist *ctx, int argc, char **argv) { + if (strcmp(argv[1], "user") == 0) + ctx->cmd = USER; + else if (strcmp(argv[1], "list") == 0) + ctx->cmd = LIST; + else if (strcmp(argv[1], "task") == 0) + ctx->cmd = TASK; + else print_help(argv); + + int opt; + switch (ctx->cmd) { + case USER: + optind = 2; + while ((opt = getopt(argc, argv, "dg")) != -1) + switch (opt) { + case 'd': + fprintf(stderr, "Deleting user %u\n", getuid()); + break; + case 'g': + fprintf(stderr, "Printing user lists\n"); + break; + default: + print_help(argv); + } + + break; + case LIST: + if (argc < 3) { + fprintf(stderr, "Prints all lists.\n"); + break; + } + klist_list_context *list_ctx = malloc(sizeof(struct klist_list_context)); + + optind = 3; + while ((opt = getopt(argc, argv, "aeds:")) != -1) + switch (opt) { + case 'a': + list_ctx->cmd = LIST_ADD; + break; + case 'e': + list_ctx->cmd = LIST_EDIT; + break; + case 'd': + list_ctx->cmd = LIST_DELETE; + break; + default: + print_help(argv); + fprintf(stderr, "" + "list options:" + "-a\tadd a list" + "-e\tedit a list" + "-d\tdelete a list" + "Not providing a parameter prints all lists."); + } + ctx->cmd_ctx = list_ctx; + break; + case TASK: + if (argc < 3) { + fprintf(stderr, "Prints all lists.\n"); + break; + } + klist_list_context *task_ctx = malloc(sizeof(struct klist_task_context)); + + optind = 3; + while ((opt = getopt(argc, argv, "aeds:")) != -1) + switch (opt) { + case 'a': + task_ctx->cmd = TASK_ADD; + break; + case 'e': + task_ctx->cmd = TASK_EDIT; + break; + case 'd': + task_ctx->cmd = TASK_DELETE; + break; + default: + print_help(argv); + fprintf(stderr, "" + "task options:" + "-a\tadd a task" + "-e\tedit a task" + "-d\tdelete a task" + "Not providing a parameter prints all tasks of a list."); + } + + ctx->cmd_ctx = task_ctx; + break; + default: + fprintf(stderr, "How did we land here?! Pls report argv[1] = %s\n", argv[1]); + print_help(argv); + } +} \ No newline at end of file diff --git a/src/main/sql.c b/src/main/sql.c new file mode 100644 index 0000000..617b5b0 --- /dev/null +++ b/src/main/sql.c @@ -0,0 +1,67 @@ +#include "include/sql.h" + + +char *klist_sql_get(const enum KLIST_SQL sql) { + switch (sql) { + case INIT: return + "create table if not exists users (" + " id integer primary key," + " name text not null," + " local_id integer, -- if the thing is running locally" + " discord_id integer, -- if logging in via web via discord" + " google_id integer -- if logging in via web via google" + ");" + "create table if not exists user_lists (" + " id integer primary key," + " user_id integer not null," + " list_id integer not null" + ");" + "create table if not exists lists (" + " id integer primary key," + " name text not null," + " desc text" + ");" + "create table if not exists task_stages (" + " id integer primary key," + " name text not null," + " desc text," + " list_id integer not null," + " foreign key (list_id) references lists(id)" + ");" + "-- this currently enables moving tasks _between lists_ (calculated of course)" + "create table if not exists tasks (" + " id integer primary key," + " name text not null," + " desc text," + " stage integer not null," + " due date," + " due_stage integer, -- more like target stage" + " foreign key (stage) references task_stages(id)," + " foreign key (due_stage) references task_stages(id)" + ")"; + case ADD_USER: return "insert into users values (?1, ?2, ?3, ?4)"; + case GET_USER: return "select * from users where id = ?1"; + case GET_USERS: return "select * from users"; + case MOD_USER_NAME: return "update users set name = ?1 where id = ?2"; + case MOD_USER_LOCAL: return "update users set local_id = ?1 where id = ?2";; + case MOD_USER_DISCORD: return "update users set discord_id = ?1 where id = ?2"; + case MOD_USER_GOOGLE: return "update users set google_id = ?1 where id = ?2"; + case ADD_LIST: return "insert into lists values (?1, ?2)"; + case GET_LIST: return "select * from lists where id = ?1"; + case GET_LISTS: return "select * from lists"; + case MOD_LIST_NAME: return "update lists set name = ?1 where id = ?2"; + case DEL_LIST: return "delete from lists where id = ?1"; + case ADD_STAGE: return "insert into task_stages values (?1, ?2, ?3)"; + case GET_STAGE: return "select * from task_stages where id = ?1"; + case GET_STAGES_FOR_LIST: return "select * from task_stages"; + case DEL_STAGE: return "delete from task_stages where id = ?1"; + case ADD_TASK: return "insert into tasks values (?1, ?2, ?3, ?4, ?5, ?6);"; + case GET_TASK: return "select * from tasks where id = ?1"; + case GET_TASKS: return "select * from tasks;"; + case MOD_TASK_NAME: return "update tasks set name = ?1 where id = ?2"; + case MOD_TASK_DESCRIPTION: return "update tasks set description = ?1 where id = ?2"; + case DEL_TASK: return "delete from tasks where id = ?1"; + case _KLIST_SQL_COUNT: return ";"; + } + return ""; +} diff --git a/src/main/util.c b/src/main/util.c new file mode 100644 index 0000000..2ee7956 --- /dev/null +++ b/src/main/util.c @@ -0,0 +1,54 @@ +#include +#include + +#include "util.h" +#include "sql.h" + +/* + * command parsing + */ + +klist *klist_init(char *db) { + klist *ctx = malloc(sizeof(klist)); + ctx->stmts = malloc(sizeof(sqlite3_stmt *) * _KLIST_SQL_COUNT); + ctx->cmd_ctx = NULL; + ctx->error = 0; + + klist_sql_prepare(ctx, db); + + return ctx; +} +void klist_deinit(klist *ctx) { + sqlite3_close(ctx->db); + if (ctx->cmd_ctx) free(ctx->cmd_ctx); + free(ctx->stmts); + free(ctx); +} + +klist_user_context *klist_user_context_init(klist *list) { + klist_user_context *ctx = malloc(sizeof(klist_user_context)); + + return ctx; +} +void klist_user_context_deinit(klist_user_context *ctx); + +klist_list_context *klist_list_context_init(klist *list); +void klist_list_context_deinit(klist_list_context *ctx); + +klist_task_context *klist_task_context_init(klist *list); +void klist_task_context_deinit(klist_task_context *ctx); + +/* + * sql preparations + */ + +void klist_sql_prepare(klist *ctx, char *db) { + ctx->stmts = malloc(sizeof(sqlite3_stmt *) * _KLIST_SQL_COUNT); + sqlite3_open(db ? db : ":memory:", &ctx->db); + + int i = 0; + for (i; i < _KLIST_SQL_COUNT; i++) + if (sqlite3_prepare(ctx->db, klist_sql_get(i), 0, &ctx->stmts[i], NULL) != SQLITE_OK) + fprintf(stderr, "sqlite3_prepare: %s\n", sqlite3_errmsg(ctx->db)); + +} \ No newline at end of file