add option to print binary file contents. ie treat a file as ascii

This commit is contained in:
rexy712 2019-05-18 08:42:29 -07:00
parent af6734f8ef
commit df44c75bdb
3 changed files with 65 additions and 12 deletions

View File

@ -58,6 +58,7 @@ struct cmd_args{
unsigned squeeze:1;
unsigned tabs:1;
unsigned nonprinting:1;
unsigned treatbinary:1;
//flags
unsigned error:1;

View File

@ -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<EQ
static constexpr const char SHOW_TABS_DESC[] = "display TAB characters as ^I";
static constexpr const char* U_IGNORED_DESC = IGNORED_DESC;
static constexpr const char NONPRINTING_DESC[] = "should use ^ and M- notation, except for LFD and TAB (not supported as of now)";
static constexpr const char BINARY_DESC[] = "treat FILE as a binary file";
static constexpr const char USAGE_DESC[] = "display this help and exit";
static constexpr const char VERSION_DESC[] = "output version information and exit";
static constexpr const char SEED_DESC[] = "Rainbow seed, 0 = random (default: 0)";
static constexpr const char SPREAD_DESC[] = "Rainbow spread (default: Not yet decided)";
static constexpr const char FREQ_DESC[] = "Rainbow frequency (default: Not yet decided)";
static constexpr const char SPREAD_DESC[] = "Rainbow spread (default: 0.3)";
static constexpr const char FREQ_DESC[] = "Rainbow frequency (default: 0.2)";
static constexpr const char TRUECOLOR_DESC[] = "24-bit (truecolor)";
static constexpr const char FORCE_COLOR_DESC[] = "Force color even when stdout is not a tty";
static constexpr const char DISABLE_COLOR_DESC_BASE[] = "Suppress color even when stdout is a tty, overrides -";
@ -263,6 +266,9 @@ cmd_args process_cmd_args(int argc, char** argv){
case SHORT_OPT(NONPRINTING):
ret.nonprinting = 1;
break;
case SHORT_OPT(BINARY):
ret.treatbinary = 1;
break;
case SHORT_OPT(USAGE):
ret.usage = 1;
break;
@ -325,6 +331,8 @@ cmd_args process_cmd_args(int argc, char** argv){
ret.tabs = 1;
}else if(CHECK_LONG_OPTION(NONPRINTING, arg)){
ret.nonprinting = 1;
}else if(CHECK_LONG_OPTION(BINARY, arg)){
ret.treatbinary = 1;
}else if(CHECK_LONG_OPTION(USAGE, arg)){
ret.usage = 1;
}else if(CHECK_LONG_OPTION(VERSION, arg)){
@ -381,6 +389,8 @@ const cmd_options cmd_arguments_list[] = {
OPTION(U_IGNORED),
OPTION(NONPRINTING),
{nullptr,0,nullptr}, //add newline to output
OPTION(BINARY),
{nullptr,0,nullptr},
OPTION(SEED),
OPTION(SPREAD),
OPTION(FREQ),

View File

@ -105,16 +105,7 @@ constexpr void print_version(Printer&& p){
//Use the given type of printer to output the contents of files and/or stdin
template<class Printer>
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<class Printer>
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<char>(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<char>(in));
p.reset();
fclose(fp);
}
}
p.reset();
return ret;
}
template<class Printer>
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<Printer>(args);
}else{
return print_normal_files<Printer>(args);
}
}
auto get_time(void){
auto time = std::chrono::high_resolution_clock::now();
auto eptime = time.time_since_epoch();