Задать вопрос

Как прочитать данные из пайпа в C++ не перепутав с TTY stdin?

// 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 ввод?
  • Вопрос задан
  • 33 просмотра
Подписаться 1 Простой 1 комментарий
Помогут разобраться в теме Все курсы
  • Нетология
    Разработчик на C++: Профессия + специализация + нейросети
    12 месяцев
    Далее
  • Skillbox
    Разработчик на C++
    7 месяцев
    Далее
  • Яндекс Практикум
    Разработчик C++
    9 месяцев
    Далее
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы