// Main.cpp
// FIXME: fix buffer input (now reads from stdin instead of pipe when pipe is unavailable)
#include <cstdlib>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/ioctl.h>
#include <unistd.h>
#endif
#include <algorithm>
#include <filesystem>
#include <ostream>
#include <regex>
#include <sstream>
#include <string>
#include <vector>
#include <opencv2/opencv.hpp>
#include "Converter.h"
using namespace std;
using namespace cv;
vector<char> buffer;
string filename;
string palette = " .:-=+*#%@";
string resolution = "";
bool color = false;
string seen = "";
char expect;
Mat image;
regex absolute_size ("^[1-9][0-9]*x[1-9][0-9]*$");
regex relative_size ("^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?x$");
void error (string message) noexcept
{
cerr << "\e[31m" << message << "\e[0m" << endl;
exit (1);
}
int main (int arguments_count, char* arguments[])
{
for (int index = 1; index < arguments_count; index++)
{
string argument = arguments [index];
switch (expect)
{
case 'P':
if (seen.find('P') != string::npos) error ("Ambiguity detected!");
palette = argument;
seen += 'P';
expect = '\0';
continue;
case 'S':
if (seen.find('S') != string::npos) error ("Ambiguity detected!");
if (regex_match (argument, absolute_size) || regex_match (argument, relative_size) || argument == "auto") resolution = argument;
else error ("Invalid size!");
seen += 'S';
expect = '\0';
continue;
}
if (argument == "help")
{
cout << "Not done yet :|" << endl;
return 0;
}
else if (argument == "version")
{
cout << "Beta++" << endl;
return 0;
}
else if (argument == "-p") expect = 'P';
else if (argument == "-s") expect = 'S';
else if (argument == "--color")
{
if (seen.find('C') != string::npos) error ("Ambiguity detected!");
color = true;
}
else
{
if (seen.find('F') != string::npos) error ("Invalid arguments!");
if (!filesystem::exists (argument)) error ("File does not exist!");
if (!filesystem::is_regular_file (argument)) error ("File is invalid!");
filename = argument;
image = read (filename);
if (image.empty()) error ("File is not an image!");
seen += 'F';
}
}
if (filename.empty())
{
buffer.assign (
istreambuf_iterator<char>(cin),
istreambuf_iterator<char>()
);
image = read (buffer);
if (image.empty()) error ("Filename is not specified and pipe data is not an image stream!");
}
float width = image.cols;
float height = image.rows;
if (regex_match (resolution, absolute_size))
{
stringstream size_stream (resolution);
size_stream >> width;
size_stream.ignore(1);
size_stream >> height;
}
else if (regex_match (resolution, relative_size))
{
resolution.pop_back();
if (resolution.find('-') != string::npos)
{
resolution = resolution.substr(1);
width /= stof (resolution);
height /= stof (resolution);
}
else
{
width *= stof (resolution);
height *= stof (resolution);
}
}
else if (resolution == "auto")
{
width = image.cols;
height = image.rows;
int columns;
int rows;
#ifdef _WIN32
CONSOLE_SCREEN_BUFFER_INFO info;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info))
{
columns = info.srWindow.Right - info.srWindow.Left + 1;
rows = info.srWindow.Bottom - info.srWindow.Top + 1;
}
else goto escape;
#else
struct winsize window_size;
ioctl (STDOUT_FILENO, TIOCGWINSZ, &window_size);
if (window_size.ws_col == 0 || window_size.ws_row == 0) goto escape;
columns = window_size.ws_col;
rows = window_size.ws_row;
#endif
float width_C = width / columns;
float height_C = height / rows;
float multiplier = max (width_C, height_C);
width /= multiplier;
height /= multiplier;
} escape:;
width = static_cast<int>(width);
height = static_cast<int>(height);
width *= 2;
string output = convert (image, width, height, palette, color);
if (output.empty())
{
error ("Unable to convert image!");
}
output.pop_back();
cout << output << endl;
}
Сейчас если ничего не передать через пайп, программа читает данные из терминала (как input() в Python) вместо того чтобы вернуть пустой буфер и перейти на обработку ошибок. Как мне прочитать именно пайп-буфер, без падения на TTY ввод?