#include #include #include #include #include #include #include "intmath.h" #include "formatting.h" #include "config-parser.h" int tests_run = 0; int tests_failed = 0; int main (int argc, char* argv[]) { Result res = parse_config(argc, argv); if (res.success == false) { char* err_msg = (char*) res.result; fprintf( stderr, "Error parsing command line: %s.\nTry `stdu --help` for more info.\n", err_msg ); return 1; } Config* conf = (Config*) res.result; FILE* progress_destination = conf->forward ? stderr : stdout; if (conf->help) { printf( "Usage: stdu [-hm?] [-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\ --multiline | -m: output with line breaks\n\ --forward | -o: forward STDIN to STDOUT and print amount of transferred data to STDERR\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; base = 1024; } char* endl = ""; if (conf->multiline) { endl = "\n"; } int blocksize = 1; size_t bufsize = 1; int bufsize_tries = 10; 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, base)) - bytes_read; bufsize = 1024; } char* buf = malloc(bufsize); char* tmpbuf; size_t stdout_buffer_size = 16; char* stdout_buffer = malloc(stdout_buffer_size); int previous_line_strlen = 0; while (1) { /* output */ if (conf->human_readable && base == 10) { int res = ull_floored_with_prefix( &stdout_buffer, &stdout_buffer_size, bytes_read, conf->precision ); if (res < 0) { fprintf( progress_destination, "\r%llu \ (error when getting prefix)%s", bytes_read, endl ); continue; } fprintf( progress_destination, "\r%sB%*s", stdout_buffer, int_max(previous_line_strlen - res, 0), endl ); previous_line_strlen = int_max(res, previous_line_strlen); } else if (conf->human_readable && base == 1024) { int res = ull_floored_with_binary_prefix( &stdout_buffer, &stdout_buffer_size, bytes_read ); if (res < 0) { fprintf( progress_destination, "\r%llu \ (error when getting prefix)%s", bytes_read, endl ); } fprintf( progress_destination, "\r%sB%*s", stdout_buffer, int_max(previous_line_strlen - res, 0), endl ); previous_line_strlen = int_max(res, previous_line_strlen); } else { fprintf( progress_destination, "\r%llu%s", bytes_read, endl ); } if (fflush(progress_destination) == EOF) { printf("\n"); perror("error during fflush"); return 1; } /* reading */ new_read_bytes = fread( buf, 1, int_min(blocksize, bufsize)/* + (blocksize == 0)*/, stdin ); if (new_read_bytes == 0) { int err = ferror(stdin); if (err != 0) { printf("\n"); fprintf(stderr, "error reading stdin"); return err; } break; } bytes_read += new_read_bytes; /* writing */ if (conf->forward) { printf("%s", buf); } /* resizing buffer and blocksize to read as much as possible * at once */ if (bufsize_tries <= 0) continue; if (conf->precision == 0) continue; blocksize = exp_notated_to_ull(ull_ceiled_exponent_notation_base( bytes_read + 1, conf->precision, base)) - bytes_read; if (blocksize > bufsize) { tmpbuf = malloc(bufsize * 2); if (tmpbuf == NULL) { bufsize_tries--; free(tmpbuf); } else { free(buf); buf = tmpbuf; bufsize *= 2; } } } printf("\n"); free(stdout_buffer); return 0; }