aboutsummaryrefslogtreecommitdiff
path: root/config-parser.c
diff options
context:
space:
mode:
authorJoel Kronqvist <joelkronqvist@proton.me>2024-04-13 21:48:07 +0300
committerJoel Kronqvist <joelkronqvist@proton.me>2024-04-13 21:51:01 +0300
commitba5dd828bde07493ef5f2f8abf6921e0a040133d (patch)
tree3032f7429482f27afb015f9ab4605df0a4f3d460 /config-parser.c
parentf8f07ca39bd617ddaeb2149f138b12aa7a6532bf (diff)
downloadstdu-ba5dd828bde07493ef5f2f8abf6921e0a040133d.tar.gz
stdu-ba5dd828bde07493ef5f2f8abf6921e0a040133d.zip
Combined one-letter options support (eg. "-mhp 3")
Diffstat (limited to 'config-parser.c')
-rw-r--r--config-parser.c164
1 files changed, 118 insertions, 46 deletions
diff --git a/config-parser.c b/config-parser.c
index 3cebc73..0ef0a47 100644
--- a/config-parser.c
+++ b/config-parser.c
@@ -22,27 +22,13 @@ Result parse_config(int argc, char* argv[]) {
size_t i = 1;
char* argument;
char* precision = NULL;
+ bool next_is_precision = false;
while (i < argc) {
argument = argv[i];
- int comp1 = strcmp(argument, "--precision") == 0;
- if (
- strcmp(argument, "--help") == 0
- || strcmp(argument, "-?") == 0
- ) {
- tmp.help = true;
- } else if (
- strcmp(argument, "--human-readable") == 0
- || strcmp(argument, "-h") == 0
- ) {
- tmp.human_readable = true;
- } else if (
- strcmp(argument, "--multiline") == 0
- || strcmp(argument, "-m") == 0
- ) {
- tmp.multiline = true;
- } else if (
- comp1 || strncmp(argument, "-p", 2) == 0
- ) {
+ size_t arglen = strlen(argument);
+
+ if (next_is_precision) {
+ i += 1;
if (precision != NULL) {
char* error_msg = malloc(44);
snprintf(
@@ -53,11 +39,6 @@ Result parse_config(int argc, char* argv[]) {
res.result = error_msg;
return res;
}
- i++;
- if (strlen(argument) != 2 && !comp1) {
- precision = argument + 2;
- continue;
- }
if (i == argc) {
char* error_msg = malloc(57);
snprintf(
@@ -69,21 +50,98 @@ Result parse_config(int argc, char* argv[]) {
res.result = error_msg;
return res;
}
- precision = argv[i];
- } else {
- size_t msg_size = 21 + strlen(argument);
- char* error_msg = malloc(msg_size);
- snprintf(
- error_msg,
- msg_size,
- "unknown argument: `%s`",
- argument
- );
- res.result = error_msg;
- return res;
+ precision = argv[i++];
+ next_is_precision = false;
+ continue;
+ }
+
+ size_t tacktacklen = 2;
+ if (strncmp(argument, "--", tacktacklen) == 0) {
+ argument += tacktacklen;
+ if (strcmp(argument, "help") == 0) {
+ tmp.help = true;
+ } else if (strcmp(argument, "human-readable") == 0) {
+ tmp.human_readable = true;
+ } else if (strcmp(argument, "multiline") == 0) {
+ tmp.multiline = true;
+ } else if (strcmp(argument, "precision") == 0) {
+ next_is_precision = true;
+ continue;
+ } else {
+ argument -= tacktacklen;
+ size_t msg_size = 18 + strlen(argument);
+ char* error_msg = malloc(msg_size);
+ snprintf(
+ error_msg,
+ msg_size,
+ "unknown option `%s`",
+ argument
+ );
+ res.result = error_msg;
+ return res;
+ }
+ i++;
+ continue;
+ }
+
+ if (strncmp(argument, "-p", 2) == 0 && arglen != 2) {
+ if (precision != NULL) {
+ char* error_msg = malloc(44);
+ snprintf(
+ error_msg,
+ 44,
+ "precision can't be specified multiple times"
+ );
+ res.result = error_msg;
+ return res;
+ }
+ precision = argument + 2;
+ i++;
+ continue;
}
- i++;
+ size_t opt_i = 0;
+ while (++opt_i < arglen) {
+ char opt = *(argument + opt_i);
+ switch (opt) {
+ case 'h':
+ tmp.human_readable = true;
+ break;
+ case 'm':
+ tmp.multiline = true;
+ break;
+ case 'p':
+ next_is_precision = true;
+ if (opt_i != arglen - 1) {
+ size_t msg_size = 75;
+ char* error_msg
+ = malloc(msg_size);
+ snprintf(
+ error_msg,
+ msg_size,
+ "`-p` should be the last option when combined with other one-letter options"
+ );
+ res.result = error_msg;
+ return res;
+ }
+ break;
+ case '?':
+ tmp.help = true;
+ break;
+ default:
+ size_t msg_size = 20;
+ char* error_msg = malloc(msg_size);
+ snprintf(
+ error_msg,
+ msg_size,
+ "unknown option `-%c`",
+ opt
+ );
+ res.result = error_msg;
+ return res;
+ }
+ }
+ i += !next_is_precision;
}
if (precision != NULL) {
@@ -143,8 +201,10 @@ char* test_default_config() {
Result res = parse_config(argc, argv);
Config* conf = (Config*) res.result;
mt_assert_eq(res.success, true);
- mt_assert_eq(conf->precision, 0);
mt_assert_eq(conf->human_readable, false);
+ mt_assert_eq(conf->help, false);
+ mt_assert_eq(conf->multiline, false);
+ mt_assert_eq(conf->precision, 0);
free(conf);
return 0;
}
@@ -196,17 +256,28 @@ char* test_human_readability_parsing() {
res = parse_config(argc, argv);
conf = (Config*) res.result;
mt_assert_eq(res.success, true);
- mt_assert_eq(conf->precision, 0);
mt_assert_eq(conf->human_readable, true);
free(conf);
- argc = 3;
- char* argv2[] = { "stdu", "-h", "-h" };
- res = parse_config(argc, argv2);
- error_msg = (char*) res.result;
- mt_assert_eq(res.success, false);
- free(error_msg);
-
+ return 0;
+}
+
+char* test_multioption_parsing() {
+ Result res;
+ Config* conf;
+ char* error_msg;
+
+ int argc = 3;
+ char* argv[] = { "stdu", "-mh?p", "3"};
+ res = parse_config(argc, argv);
+ conf = (Config*) res.result;
+ mt_assert_eq(res.success, true);
+ mt_assert_eq(conf->help, true);
+ mt_assert_eq(conf->human_readable, true);
+ mt_assert_eq(conf->multiline, true);
+ mt_assert_eq(conf->precision, 3);
+ free(conf);
+
return 0;
}
@@ -214,4 +285,5 @@ void parsing_tests() {
mt_run_test(test_default_config);
mt_run_test(test_precision_parsing);
mt_run_test(test_human_readability_parsing);
+ mt_run_test(test_multioption_parsing);
}