diff options
author | Joel Kronqvist <joelkronqvist@proton.me> | 2024-04-10 16:54:50 +0300 |
---|---|---|
committer | Joel Kronqvist <joelkronqvist@proton.me> | 2024-04-11 16:01:36 +0300 |
commit | a793df3e2a07c65f36fb2f5f43d2c51ab0c47bf2 (patch) | |
tree | 49858b1ef415ce16c843c4fbb4ab7eccaa73033d | |
parent | 4ff6a08d73f0ef1e2fcb7a93a74cc6fa66c24e2b (diff) | |
download | stdu-a793df3e2a07c65f36fb2f5f43d2c51ab0c47bf2.tar.gz stdu-a793df3e2a07c65f36fb2f5f43d2c51ab0c47bf2.zip |
Added help message & fixed blocksize bug
The bug was caused by integer overflow with too large precisions.
-rw-r--r-- | config-parser.c | 29 | ||||
-rw-r--r-- | config-parser.h | 1 | ||||
-rw-r--r-- | intmath.c | 12 | ||||
-rw-r--r-- | intmath.h | 1 | ||||
-rw-r--r-- | stdu.c | 21 |
5 files changed, 48 insertions, 16 deletions
diff --git a/config-parser.c b/config-parser.c index 5e403f8..075ef47 100644 --- a/config-parser.c +++ b/config-parser.c @@ -17,6 +17,7 @@ Result parse_config(int argc, char* argv[]) { Config tmp; tmp.precision = 0; tmp.human_readable = false; + tmp.help = false; size_t i = 1; char* argument; @@ -25,6 +26,16 @@ Result parse_config(int argc, char* argv[]) { 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 ( comp1 || strncmp(argument, "-p", 2) == 0 ) { if (precision != NULL) { @@ -54,21 +65,6 @@ Result parse_config(int argc, char* argv[]) { 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); @@ -126,8 +122,9 @@ Result parse_config(int argc, char* argv[]) { } Config* conf = malloc(sizeof(int) + sizeof(bool)); - conf->precision = tmp.precision; + conf->help = tmp.help; conf->human_readable = tmp.human_readable; + conf->precision = tmp.precision; res.success = true; res.result = conf; diff --git a/config-parser.h b/config-parser.h index 1026a98..08aa934 100644 --- a/config-parser.h +++ b/config-parser.h @@ -2,6 +2,7 @@ struct Config { int precision; bool human_readable; + bool help; }; typedef struct Config Config; struct Result { @@ -14,6 +14,18 @@ int int_pown(unsigned int base, unsigned int exp) { return res; } +int int_logn(unsigned int base, unsigned int a) { + unsigned int exp = 1; + int res = (int) base; + int lastres = res - 1; + while ((res < a) && (lastres < res)) { + lastres = res; + res *= base; + exp++; + } + return exp; +} + unsigned long long ull_pown(unsigned int base, unsigned int exp) { unsigned long long res = 1; while (exp > 0) { @@ -1,5 +1,6 @@ int int_pown(unsigned int base, unsigned int exp); unsigned long long ull_pown(unsigned int base, unsigned int exp); +int int_logn(unsigned int base, unsigned int a); int int_pow10(unsigned int exp); int int_floor(int x, int precision); int int_ceil(int x, int precision); @@ -4,6 +4,7 @@ #include <string.h> #include <errno.h> #include <stdbool.h> +#include <limits.h> #include "intmath.h" #include "formatting.h" @@ -26,6 +27,17 @@ int main (int argc, char* argv[]) { Config* conf = (Config*) res.result; + if (conf->help) { + printf( +"Usage: stdu [-h] [-p n]\n\ +Print amount of data piped to stdin.\n\ +--help | -?: print this help message\n\ +--human-readable | -h: output in a human readable format\n\ +--precision n | -p n | -pn: output with n significant digits\n " + ); + return 0; + } + unsigned int base = 10; if (conf->human_readable && conf->precision == 0) { conf->precision = 1; @@ -38,6 +50,15 @@ int main (int argc, char* argv[]) { unsigned long long bytes_read = 0; size_t new_read_bytes = 0; if (conf->precision != 0) { + int max_precision = int_logn(base, (unsigned int) INT_MAX); + if (conf->precision > max_precision) { + fprintf( + stderr, + "Overflow error: precision may not be greater than %d\n", + max_precision + ); + return 1; + } blocksize = exp_notated_to_ull(ull_ceiled_exponent_notation_base( bytes_read + 1, conf->precision, |