diff --git a/include/cmd.hpp b/include/cmd.hpp index 556fd64..6ea4d4e 100644 --- a/include/cmd.hpp +++ b/include/cmd.hpp @@ -58,6 +58,7 @@ struct cmd_args{ unsigned squeeze:1; unsigned tabs:1; unsigned nonprinting:1; + unsigned treatbinary:1; //flags unsigned error:1; diff --git a/src/cmd.cpp b/src/cmd.cpp index cec7a66..73e0654 100644 --- a/src/cmd.cpp +++ b/src/cmd.cpp @@ -74,6 +74,7 @@ static constexpr const char* VT_LONG_OPTION = NO_LONG_OPTION; static constexpr const char SHOW_TABS_LONG_OPTION[] = "show-tabs"; static constexpr const char* U_IGNORED_LONG_OPTION = NO_LONG_OPTION; static constexpr const char NONPRINTING_LONG_OPTION[] = "show-nonprinting"; +static constexpr const char BINARY_LONG_OPTION[] = "binary"; static constexpr const char USAGE_LONG_OPTION[] = "help"; static constexpr const char VERSION_LONG_OPTION[] = "version"; static constexpr const char SEED_LONG_OPTION[] = "seed" REQ_INTEGER_ARG; @@ -91,6 +92,7 @@ static constexpr const char IGNORE_SPEED_LONG_OPTION[] = "speed" REQ_FLOAT_A #define NO_SHORT_OPTION "" static constexpr const char SHOW_ALL_SHORT_OPTION[] = "A"; static constexpr const char NUMBER_NONBLANK_SHORT_OPTION[] = "b"; +static constexpr const char BINARY_SHORT_OPTION[] = "B"; static constexpr const char TRUECOLOR_SHORT_OPTION[] = "C"; static constexpr const char VE_SHORT_OPTION[] = "e"; static constexpr const char SHOW_ENDS_SHORT_OPTION[] = "E"; @@ -128,11 +130,12 @@ static constexpr const char* VT_DESC = concat_many_strs -int print_files(cmd_args& args){ - if(args.usage){ - args.clear_gnu_options(); - print_usage(Printer{args}); - return 0; - }else if(args.version){ - args.clear_gnu_options(); - print_version(Printer{args}); - return 0; - } +int print_normal_files(cmd_args& args){ int ret = 0; Printer p(args); for(size_t i = 0;i < args.filenames.size();++i){ @@ -146,6 +137,57 @@ int print_files(cmd_args& args){ p.reset(); return ret; } +//Use the given type of printer to output the contents of files and/or stdin +template +int print_binary_files(cmd_args& args){ + int ret = 0; + Printer p(args); + for(size_t i = 0;i < args.filenames.size();++i){ + if(!strcmp(args.filenames[i], "-")){ //stdin + + //Don't check if buf is empty because that's not how GNU cat handles Ctrl+D in middle of line + for(int in;(in = fgetc(stdin)) != WEOF;){ + p.print(static_cast(in)); + if(in == L'\n') //Only reset on newline to save print overhead + p.reset(); + } + clearerr(stdin); + }else{ //everything besides stdin + FILE* fp = fopen(args.filenames[i], "r"); + if(!fp){ + fflush(stdout); //force color update before error + fprintf(stderr, "Unable to open file %s\n", args.filenames[i]); + ret = 2; + continue; + } + for(int in;(in = fgetc(fp)) != WEOF;) + p.print(static_cast(in)); + p.reset(); + fclose(fp); + } + } + p.reset(); + return ret; +} +template +int print_files(cmd_args& args){ + if(args.usage){ + args.clear_gnu_options(); + print_usage(Printer{args}); + return 0; + }else if(args.version){ + args.clear_gnu_options(); + print_version(Printer{args}); + return 0; + } + + if(args.treatbinary){ + return print_binary_files(args); + }else{ + return print_normal_files(args); + } +} + auto get_time(void){ auto time = std::chrono::high_resolution_clock::now(); auto eptime = time.time_since_epoch();