aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile11
-rw-r--r--config-parser.c226
-rw-r--r--config-parser.h12
-rw-r--r--stdu.c152
-rw-r--r--tests.c8
6 files changed, 262 insertions, 148 deletions
diff --git a/.gitignore b/.gitignore
index 26e8cf8..09bf9a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
stdu
stdu.o
intmath.o
+config-parser.o
test
diff --git a/Makefile b/Makefile
index 685f42a..3c3b8ae 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
-stdu : stdu.o intmath.o intmath.h
- cc -o stdu stdu.o intmath.o
+stdu : stdu.o intmath.o intmath.h config-parser.h config-parser.o
+ cc -o stdu stdu.o intmath.o config-parser.o
stdu.o : stdu.c
cc -c stdu.c
@@ -8,9 +8,12 @@ stdu.o : stdu.c
intmath.o : intmath.c minitest.h intmath.h
cc -c intmath.c
-test : tests.c minitest.h intmath.c
+config-parser.o : config-parser.c config-parser.h minitest.h
+ cc -c config-parser.c
+
+test : tests.c minitest.h intmath.c config-parser.c
cc -o test tests.c
./test
clean :
- rm stdu stdu.o intmath.o test
+ rm stdu stdu.o intmath.o test config-parser.o
diff --git a/config-parser.c b/config-parser.c
new file mode 100644
index 0000000..cd97dc7
--- /dev/null
+++ b/config-parser.c
@@ -0,0 +1,226 @@
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include "minitest.h"
+#include "config-parser.h"
+
+Result parse_config(int argc, char* argv[]) {
+ Result res;
+ res.success = false;
+ Config tmp;
+ tmp.precision = 0;
+ tmp.human_readable = false;
+
+ size_t i = 1;
+ char* argument;
+ char* precision = NULL;
+ while (i < argc) {
+ argument = argv[i];
+ int comp1 = strcmp(argument, "--precision") == 0;
+ if (
+ comp1 || strncmp(argument, "-p", 2) == 0
+ ) {
+ 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;
+ }
+ i++;
+ if (strlen(argument) != 2 && !comp1) {
+ precision = argument + 2;
+ continue;
+ }
+ if (i == argc) {
+ char* error_msg = malloc(57);
+ snprintf(
+ error_msg,
+ 57,
+ "`%s` should be followed by an integer argument",
+ argument
+ );
+ res.result = error_msg;
+ return res;
+ }
+ precision = argv[i];
+ } else if (
+ strcmp(argument, "--human-readable") == 0
+ || strcmp(argument, "-h") == 0
+ ) {
+ if (tmp.human_readable != false) {
+ char* error_msg = malloc(52);
+ snprintf(
+ error_msg,
+ 52,
+ "human readability can't be specified multiple times"
+ );
+ res.result = error_msg;
+ return res;
+ }
+ tmp.human_readable = true;
+ } 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;
+ }
+
+ i++;
+ }
+
+ if (precision != NULL) {
+ char* endptr;
+ errno = 0;
+ tmp.precision = (int) strtol(precision, &endptr, 10);
+ if (errno != 0) {
+ char* error_msg = malloc(64);
+ char* errno_str = strerror(errno);
+ snprintf(
+ error_msg,
+ 64,
+ "invalid precision: %s",
+ errno_str
+ );
+ free(errno_str);
+ res.result = error_msg;
+ return res;
+ }
+ if (*endptr != '\0') {
+ char* error_msg = malloc(53);
+ snprintf(
+ error_msg,
+ 53,
+ "the precision may not contain non-numeric characters",
+ precision
+ );
+ res.result = error_msg;
+ return res;
+ }
+ if (tmp.precision <= 0) {
+ char* error_msg = malloc(50);
+ snprintf(
+ error_msg,
+ 50,
+ "the precision can't be less than or equal to zero"
+ );
+ res.result = error_msg;
+ return res;
+ }
+ }
+
+ Config* conf = malloc(sizeof(int) + sizeof(bool));
+ conf->precision = tmp.precision;
+ conf->human_readable = tmp.human_readable;
+
+ res.success = true;
+ res.result = conf;
+ return res;
+}
+
+char* test_default_config() {
+ int argc = 1;
+ char* argv[] = { "stdu" };
+ 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);
+ return 0;
+}
+
+char* test_precision_parsing() {
+ int argc;
+ Result res;
+ Config* conf;
+ char* error_msg;
+
+ argc = 3;
+ char* argv[] = { "stdu", "--precision", "3" };
+ res = parse_config(argc, argv);
+ conf = (Config*) res.result;
+ mt_assert_eq(res.success, true);
+ mt_assert_eq(conf->precision, 3);
+ mt_assert_eq(conf->human_readable, false);
+ free(conf);
+
+ argc = 2;
+ char* argv2[] = { "stdu", "-p" };
+ res = parse_config(argc, argv2);
+ mt_assert(
+ res.success == false,
+ "not specifying precision after `-p` didn't error"
+ );
+ free(error_msg);
+
+ argc = 4;
+ char* argv3[] = { "stdu", "--precision", "1", "-p3" };
+ res = parse_config(argc, argv3);
+ mt_assert(
+ res.success == false,
+ "specifying precision multiple times didn't error"
+ );
+ free(res.result);
+
+ return 0;
+
+}
+
+char* test_human_readability_parsing() {
+ int argc;
+ Result res;
+ Config* conf;
+ char* error_msg;
+
+ argc = 2;
+ char* argv[] = {
+ "stdu",
+ "--human-readable"
+ };
+ 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* argv3[] = {
+ "stdu",
+ "-h",
+ "-h"
+ };
+ res = parse_config(argc, argv3);
+ error_msg = (char*) res.result;
+ mt_assert_eq(res.success, false);
+ mt_assert(
+ strcmp(
+ error_msg,
+ "human readability can't be specified multiple times"
+ ),
+ "should error on double argument of human readability"
+ );
+ free(error_msg);
+
+ return 0;
+}
+
+void parsing_tests() {
+ mt_run_test(test_default_config);
+ mt_run_test(test_precision_parsing);
+ mt_run_test(test_human_readability_parsing);
+}
diff --git a/config-parser.h b/config-parser.h
new file mode 100644
index 0000000..1026a98
--- /dev/null
+++ b/config-parser.h
@@ -0,0 +1,12 @@
+
+struct Config {
+ int precision;
+ bool human_readable;
+};
+typedef struct Config Config;
+struct Result {
+ bool success;
+ void* result;
+};
+typedef struct Result Result;
+Result/*Config*/ parse_config(int argc, char* argv[]);
diff --git a/stdu.c b/stdu.c
index 43038a8..f7f5511 100644
--- a/stdu.c
+++ b/stdu.c
@@ -6,144 +6,11 @@
#include <stdbool.h>
#include "intmath.h"
+#include "config-parser.h"
int tests_run = 0;
int tests_failed = 0;
-struct Config {
- int precision;
- bool human_readable;
-};
-typedef struct Config Config;
-struct Result {
- bool success;
- void* result;
-};
-typedef struct Result Result;
-
-Result parse_config(int argc, char* argv[]) {
- Result res;
- res.success = false;
- Config tmp;
- tmp.precision = 0;
- tmp.human_readable = false;
-
- size_t i = 1;
- char* argument;
- char* precision = NULL;
- while (i < argc) {
- argument = argv[i];
- int comp1 = strcmp(argument, "--precision") == 0;
- if (
- comp1 || strncmp(argument, "-p", 2) == 0
- ) {
- 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;
- }
- i++;
- if (strlen(argument) != 2 && !comp1) {
- precision = argument + 2;
- continue;
- }
- if (i == argc) {
- char* error_msg = malloc(57);
- snprintf(
- error_msg,
- 57,
- "`%s` should be followed by an integer argument",
- argument
- );
- res.result = error_msg;
- return res;
- }
- precision = argv[i];
- } else if (
- strcmp(argument, "--human-readable") == 0
- || strcmp(argument, "-h") == 0
- ) {
- if (tmp.human_readable != false) {
- char* error_msg = malloc(52);
- snprintf(
- error_msg,
- 52,
- "human readability can't be specified multiple times"
- );
- res.result = error_msg;
- return res;
- }
- tmp.human_readable = true;
- } 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;
- }
-
- i++;
- }
-
- if (precision != NULL) {
- char* endptr;
- errno = 0;
- tmp.precision = (int) strtol(precision, &endptr, 10);
- if (errno != 0) {
- char* error_msg = malloc(64);
- char* errno_str = strerror(errno);
- snprintf(
- error_msg,
- 64,
- "invalid precision: %s",
- errno_str
- );
- free(errno_str);
- res.result = error_msg;
- return res;
- }
- if (*endptr != '\0') {
- char* error_msg = malloc(53);
- snprintf(
- error_msg,
- 53,
- "the precision may not contain non-numeric characters",
- precision
- );
- res.result = error_msg;
- return res;
- }
- if (tmp.precision <= 0) {
- char* error_msg = malloc(50);
- snprintf(
- error_msg,
- 50,
- "the precision can't be less than or equal to zero"
- );
- res.result = error_msg;
- return res;
- }
- }
-
- Config* conf = malloc(sizeof(int) + sizeof(bool));
- conf->precision = tmp.precision;
- conf->human_readable = tmp.human_readable;
-
- res.success = true;
- res.result = conf;
- return res;
-}
-
int main (int argc, char* argv[]) {
Result res = parse_config(argc, argv);
if (res.success == false) {
@@ -157,14 +24,11 @@ int main (int argc, char* argv[]) {
}
Config* conf = (Config*) res.result;
- int precision = conf->precision;
- bool human_readable = conf->human_readable;
- printf("precision: %d\n", precision);
- if (human_readable) printf("human readable\n");
+ if (conf->human_readable) printf("human readable\n");
unsigned int base = 10;
- if (human_readable && precision == 0) {
- precision = 1;
+ if (conf->human_readable && conf->precision == 0) {
+ conf->precision = 1;
base = 1024;
}
@@ -172,10 +36,10 @@ int main (int argc, char* argv[]) {
size_t bufsize = 1;
unsigned int bytes_read = 0;
size_t new_read_bytes = 0;
- if (precision != 0) {
+ if (conf->precision != 0) {
blocksize = exp_notated_to_int(int_ceiled_exponent_notation_base(
bytes_read + 1,
- precision,
+ conf->precision,
base))
- bytes_read;
bufsize = 1024;
@@ -214,10 +78,10 @@ int main (int argc, char* argv[]) {
/* resizing buffer and blocksize to read as much as possible
* at once
*/
- if (precision == 0) continue;
+ if (conf->precision == 0) continue;
blocksize = exp_notated_to_int(int_ceiled_exponent_notation_base(
bytes_read + 1,
- precision,
+ conf->precision,
base))
- bytes_read;
if (blocksize > bufsize) {
diff --git a/tests.c b/tests.c
index 138a994..f4a047d 100644
--- a/tests.c
+++ b/tests.c
@@ -1,13 +1,21 @@
#include "minitest.h"
+#include "config-parser.c"
#include "intmath.c"
int tests_run = 0;
int tests_failed = 0;
+void intmath_tests();
+void main_tests();
+
int main() {
printf("[INFO] Running tests...\n\n");
+ printf("[INFO] Running main-tests...\n");
+ parsing_tests();
+ printf("\n");
+
printf("[INFO] Running intmath-tests...\n");
intmath_tests();
printf("\n");