From 126fc422c58b84d5ad2e0bb76c2e2870a2fdc8c0 Mon Sep 17 00:00:00 2001 From: Tilo-K Date: Fri, 20 Jun 2025 15:34:49 +0200 Subject: [PATCH] feat: add basic parsing and readme --- README.md | 59 ++++++++++++++++++++++++ includes/seaflags.h | 29 ++++++++++++ src/seaflags.c | 109 ++++++++++++++++++++++++++++++++++++++++++++ tests/test_main.c | 108 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 README.md create mode 100644 includes/seaflags.h diff --git a/README.md b/README.md new file mode 100644 index 0000000..9cc0040 --- /dev/null +++ b/README.md @@ -0,0 +1,59 @@ +
+:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
+::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.
+::.::::::.::::.::.::::.::.:::::.:::::.::::::::.:::.::.::::::.::::
+:::::.::::::.:::::::.:::::::.::::::::::::.::.:::::::::::.::::::.:
+:::::::::::::::::::::::::::::::::::.:::.:::::::::::::::::::::::::
+:.::::::.::::::.:::::::.::::::::::::::::::::::::.::::.::::.::.::.
+::::.::::::.::::::.:::::::.::::::::::.::::::.::::::.::::.::::::::
+::::::::::::::.::::::::::::::.::.::.:::::.:::::::::::::::::::::::
+:.::::.:::::::::::::.::.:::::::::::::::::::::::.::::::.::::.:.::.
+::::.::::.:::::::.:::::::::.::::::::::.:::::::::::.::::::::::::::
+::::::::::::.::.::::::::::::::.::::::::::::::.:::::::::::.:::::.:
+::.::::::::::::::::::::::::::::::.::::::::::::::.:::.::.:::::::::
+:::::.::::::::::::::.::-@:::::::::::.::.::.:::::::::::::::::.::::
+.:::::::.::.::::::.::::-@+**********=:::::::::::+::::::::::::::.:
+:::.::::::::::.::::::::-@************************::::.:::.:::::::
+::::::.::::::::::::::::-@************************:::::::::::.:::.
+:::::::::.:::::::::::::-@***********************=::::::.:::::::::
+::.::::::::::::::::::.:-@***********************::::.::::::::::::
+:::::.:::::.::.::.:::::-@***********************=:::::::::.::.::.
+:::::::::.:::::::::::::-@************************::::::.:::::::::
+::.::::::::::::::::::::-@****====****************::::::::::::::::
+:::::.::::::::.::::::::-@:::::::::::::=*******+-:::::.:::::.::.::
+.:::::::.::::::::::.:::-@::::::::::::::::::::::::::::::::.:::::::
+:::::::::::.:::::::::::-@:::::::::::::::::::::::::::::::::::::::.
+:::.::::::::::.::::::::-@::::::.:::::::::::::::.::.::::::::::::::
+:::::::::::::::::.:::::-@:::::::::::::::::::::::::::::::.:::::::.
+:::::::::::::::::::::::-@:::::::::::::::.::::::::::::.::::::.::::
+:::.::.::.:::::::::::::-@::::::::.:::::::::::.::.::.:::::::::::::
+::::::::::::::.::::::::-@:::::::::::::::::::::::::::::::::.::::.:
+:.:::::::::::::::::::::-@::::::::::::.:::::::::::::::::::::::::::
+:::::::::::::::::::::::-@::::::::::::::::::::::::.:::::::::::.:::
+:::::::::::::.::.::::::-@::::::::.:::::::::::::.:::::::::.::::::.
+:::.:::::.::::::::::.::-@::::::::::::::::::::::::::::::::::::::::
+:::::::::::::::::::::::-@:::::::::::::::::::.::::::::.::::::::.::
+:::::::::::::::::::::::-@::::::::::::::::::::::::::::::::::::::::
+::+***********=::::::::-@-=***********+:::::::::::+***********=::
+***********************#@****************************************
+***********************#@****************************************
+************************@****************************************
+*************#%%%##%%%##@#%%%%#%%%##*****************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+*****************************************************************
+
+# SeaFlags +### SeaFlags is a simple library for parsing command line arguments. + + diff --git a/includes/seaflags.h b/includes/seaflags.h new file mode 100644 index 0000000..a2ff1a9 --- /dev/null +++ b/includes/seaflags.h @@ -0,0 +1,29 @@ +#include + +struct SeaFlag { + char* name; + char* short_name; + bool is_required; + + char** value; + struct SeaFlag* next; +}; + +struct SeaFlagSet { + struct SeaFlag* firstFlag; + + char* programName; + char* programVersion; + char* programAuthor; + char* programDescription; +}; + +#define SEAFLAGS_UNKNOWN_FLAG 0b00000001 +#define SEAFLAGS_UNKNOWN_POSITIONAL_ARG 0b00000010 +#define SEAFLAGS_MISSING_REQUIRED_FLAG 0b00000100 + + +void seaflags_init(struct SeaFlagSet* flags, char* programName, char* programVersion, char* programAuthor, char* programDescription); +void seaflags_add_flag(struct SeaFlagSet* flags, char* name, char* short_name, bool is_required, char** value); +int seaflags_parse(struct SeaFlagSet* flags, int argc, char** argv); +void seaflags_free(struct SeaFlagSet* flags); diff --git a/src/seaflags.c b/src/seaflags.c index e69de29..a5d875d 100644 --- a/src/seaflags.c +++ b/src/seaflags.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +#include "../includes/seaflags.h" + +#define SEAFLAGS_DEBUG + +void seaflags_init(struct SeaFlagSet *flags, char *programName, char *programVersion, char *programAuthor, char *programDescription) { + flags->firstFlag = NULL; + + flags->programName = programName; + flags->programVersion = programVersion; + flags->programAuthor = programAuthor; + flags->programDescription = programDescription; +} + +void seaflags_add_flag(struct SeaFlagSet *flags, char *name, char *short_name, bool is_required, char** value) { + struct SeaFlag* flag = malloc(sizeof(struct SeaFlag)); + flag->name = name; + flag->short_name = short_name; + flag->is_required = is_required; + flag->value = value; + flag->next = NULL; + + if (flags->firstFlag == NULL) { + flags->firstFlag = flag; + return; + } + + struct SeaFlag* current = flags->firstFlag; + if(current == NULL) { + flags->firstFlag = flag; + return; + } + while (current->next != NULL) { + current = current->next; + } + + current->next = flag; +} + +void seaflags_free(struct SeaFlagSet *flags){ + struct SeaFlag* current = flags->firstFlag; + while (current != NULL) { + struct SeaFlag* next = current->next; + free(current->name); + free(current->short_name); + free(current->value); + free(current); + current = next; + } + free(flags); +} + +struct SeaFlag* _seaflags_find_flag(struct SeaFlagSet *flags, char *name) { + struct SeaFlag* current = flags->firstFlag; + while (current != NULL) { + if (strcmp(current->name, name) == 0 || strcmp(current->short_name, name) == 0) { + return current; + } + current = current->next; + } + return NULL; +} + +int seaflags_parse(struct SeaFlagSet *flags, int argc, char **argv) { + int i = 1; + int result = 0; + + #ifdef SEAFLAGS_DEBUG + printf("Parsing %d arguments\n", argc); + #endif + + while (i < argc) { + char* current = argv[i]; + struct SeaFlag* flag = _seaflags_find_flag(flags, current); + + if (flag == NULL) { + fprintf(stderr, "Unknown flag: %s\n", current); + result |= SEAFLAGS_UNKNOWN_FLAG; + } + + if(flag != NULL && i+1 < argc) { + #ifdef SEAFLAGS_DEBUG + printf("Setting value for %s to %s\n", current, argv[i+1]); + #endif + + *(flag->value) = argv[i+1]; + i++; + } + + i++; + } + + struct SeaFlag* current = flags->firstFlag; + while (current != NULL) { + if (*(current->value) == NULL) { + if (current->is_required == true) { + fprintf(stderr, "Missing required flag: %s\n", current->name); + result |= SEAFLAGS_MISSING_REQUIRED_FLAG; + } + } + current = current->next; + } + + return result; +} diff --git a/tests/test_main.c b/tests/test_main.c index 9942f73..09b5265 100644 --- a/tests/test_main.c +++ b/tests/test_main.c @@ -1,4 +1,108 @@ -int main(void) { - return 0; +#include +#include +#include +#include +#define SEAFLAGS_DEBUG +#include "../includes/seaflags.h" + +int test_basic_create() { + printf("Running test_basic_create\n"); + struct SeaFlagSet flags; + seaflags_init(&flags, "Sea Flag Test", "0.0.0", "Tilo-K" , "A test for the seaflags library"); + char* name = NULL; + seaflags_add_flag(&flags, "name", "n", true, &name); + + if (flags.firstFlag == NULL) { + printf("Flags not created\n"); + return 1; + } + + if (flags.firstFlag->name == NULL) { + printf("Flag name not set\n"); + return 1; + } + + if (flags.firstFlag->short_name == NULL) { + printf("Flag short name not set\n"); + return 1; + } + + if (flags.firstFlag->is_required != true) { + printf("Flag is_required not set\n"); + return 1; + } + + if (flags.firstFlag->value == NULL) { + printf("Flag value not set\n"); + return 1; + } + + return 0; +} + +int test_get_flag_value() { + printf("Running test_get_flag_value\n"); + struct SeaFlagSet flags; + seaflags_init(&flags, "Sea Flag Test", "0.0.0", "Tilo-K" , "A test for the seaflags library"); + char* name = NULL; + + printf("Adding flag\n"); + seaflags_add_flag(&flags, "--name", "-n", true, &name); + printf("Parsing\n"); + seaflags_parse(&flags, 3, (char*[]){"./test", "--name", "test"}); + printf("Parsed\n"); + + + if (name == NULL || strcmp(name, "test") != 0) { + printf("Flag value name not set, found %s\n", name); + return 1; + } + + return 0; +} + +int test_missing_required_flag() { + printf("Running test_missing_required_flag\n"); + struct SeaFlagSet flags; + seaflags_init(&flags, "Sea Flag Test", "0.0.0", "Tilo-K" , "A test for the seaflags library"); + char* name = NULL; + + printf("Adding flag\n"); + seaflags_add_flag(&flags, "--name", "-n", true, &name); + printf("Parsing\n"); + int result = seaflags_parse(&flags, 1, (char*[]){"./test"}); + printf("Parsed\n"); + + if ((result & SEAFLAGS_MISSING_REQUIRED_FLAG) > 0) { + return 0; + } + + printf("Missing required flag not detected %d\n", result); + + return 1; +} + +int main(void) { + printf("Running main\n"); + + int result = test_basic_create(); + if (result != 0) { + printf("Basic Test failed with result %d\n", result); + return 1; + } + + result = test_get_flag_value(); + if (result != 0) { + printf("Get Flag Value Test failed with result %d\n", result); + return 1; + } + + result = test_missing_required_flag(); + if (result != 0) { + printf("Missing Required Flag Test failed with result %d\n", result); + return 1; + } + + return 0; }