1
0
Files
BasaltMeter/BasaltPresenter/Shared/pipe_operator.cpp

168 lines
5.3 KiB
C++
Raw Normal View History

2025-11-27 20:48:35 +08:00
#include "pipe_operator.hpp"
#include <format>
#if defined(BASALT_OS_WINDOWS)
#include <Windows.h>
#else
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#endif
namespace Basalt::Shared {
PipeOperator::PipeOperator(const std::basic_string_view<BSCHAR> name) {
#if defined(BASALT_OS_WINDOWS)
// Create Windows pipe name from given name
auto fullname = std::format(BSTEXT("\\\\.\\pipe\\{}"), name);
m_Handle = CreateFileW(fullname.c_str(), // <20>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD><EFBFBD>
GENERIC_READ | GENERIC_WRITE, // <20><>дȨ<D0B4><C8A8>
0, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
NULL, // Ĭ<>ϰ<EFBFBD>ȫ<EFBFBD><C8AB><EFBFBD><EFBFBD>
OPEN_EXISTING, // <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD><D1B4>ڵĹܵ<C4B9>
0, // Ĭ<><C4AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
NULL // <20><>ģ<EFBFBD><C4A3><EFBFBD>ļ<EFBFBD>
);
if (m_Handle == BAD_PIPE_HANDLE) {
throw std::runtime_error("Failed to open named pipe.");
}
#else
// Create Linux pipe name from given name
auto fullname = std::format(BSTEXT("/tmp/{}"), name);
m_Handle = open(fullname.c_str(), O_RDWR);
if (m_Handle == BAD_PIPE_HANDLE) {
throw std::runtime_error("Failed to open named pipe.");
}
#endif
}
PipeOperator::~PipeOperator() {
#if defined(BASALT_OS_WINDOWS)
if (m_Handle != BAD_PIPE_HANDLE) {
CloseHandle(m_Handle);
}
#else
if (m_Handle != BAD_PIPE_HANDLE) {
close(m_Handle);
}
#endif
}
PipeOperator::PipeOperator(PipeOperator &&rhs) noexcept {
#if defined(BASALT_OS_WINDOWS)
m_Handle = rhs.m_Handle;
rhs.m_Handle = BAD_PIPE_HANDLE;
#else
m_Handle = rhs.m_Handle;
rhs.m_Handle = BAD_PIPE_HANDLE;
#endif
}
PipeOperator &PipeOperator::operator=(PipeOperator &&rhs) noexcept {
#if defined(BASALT_OS_WINDOWS)
if (m_Handle != BAD_PIPE_HANDLE) {
CloseHandle(m_Handle);
}
m_Handle = rhs.m_Handle;
rhs.m_Handle = BAD_PIPE_HANDLE;
#else
if (m_Handle != BAD_PIPE_HANDLE) {
close(m_Handle);
}
m_Handle = rhs.m_Handle;
rhs.m_Handle = BAD_PIPE_HANDLE;
#endif
return *this;
}
void PipeOperator::Read(void *buffer, size_t size) {
if (size == 0) {
return; // <20><>ȡ0<C8A1>ֽ<EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
}
#if defined(BASALT_OS_WINDOWS)
DWORD bytesRead = 0;
BOOL success = ReadFile(m_Handle, // <20>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD><EFBFBD>
buffer, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
static_cast<DWORD>(size), // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
&bytesRead, // ʵ<>ʶ<EFBFBD>ȡ<EFBFBD><C8A1><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
NULL // <20><>ʹ<EFBFBD><CAB9><EFBFBD>ص<EFBFBD>I/O
);
if (!success) {
throw std::runtime_error("Failed to read from named pipe.");
}
if (bytesRead != static_cast<DWORD>(size)) {
throw std::runtime_error("Incomplete read from named pipe.");
}
#else
// Due to POSIX "write" may write bytes less than given,
// so we need use "while" syntax to implement it.
size_t totalRead = 0;
while (totalRead < size) {
ssize_t bytesRead = read(m_Handle, static_cast<char *>(buffer) + totalRead, size - totalRead);
if (bytesRead == -1) {
throw std::runtime_error("Failed to read from named pipe");
}
if (bytesRead == 0) {
// <20>ܵ<EFBFBD><DCB5>ѹرջ򵽴<D5BB>ĩβ
throw std::runtime_error("Named pipe closed during read.");
}
totalRead += bytesRead;
}
if (totalRead != size) {
throw std::runtime_error("Incomplete read from named pipe.");
}
#endif
}
void PipeOperator::Write(const void *buffer, size_t size) {
if (size == 0) {
return; // д<><D0B4>0<EFBFBD>ֽ<EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
}
#if defined(BASALT_OS_WINDOWS)
DWORD bytesWritten = 0;
BOOL success = WriteFile(m_Handle, // <20>ܵ<EFBFBD><DCB5><EFBFBD><EFBFBD><EFBFBD>
buffer, // <20><><EFBFBD>ݻ<EFBFBD><DDBB><EFBFBD><EFBFBD><EFBFBD>
static_cast<DWORD>(size), // <20><><EFBFBD>ݴ<EFBFBD>С
&bytesWritten, // ʵ<><CAB5>д<EFBFBD><D0B4><EFBFBD><EFBFBD><EFBFBD>ֽ<EFBFBD><D6BD><EFBFBD>
NULL // <20><>ʹ<EFBFBD><CAB9><EFBFBD>ص<EFBFBD>I/O
);
if (!success) {
throw std::runtime_error("Failed to write to named pipe.");
}
if (bytesWritten != static_cast<DWORD>(size)) {
throw std::runtime_error("Incomplete write to named pipe.");
}
#else
// Due to the same reason, use "while" syntax.
size_t totalWritten = 0;
while (totalWritten < size) {
ssize_t bytesWritten = write(m_Handle, static_cast<const char *>(buffer) + totalWritten, size - totalWritten);
if (bytesWritten == -1) {
throw std::runtime_error("Failed to write to named pipe.");
}
totalWritten += bytesWritten;
}
if (totalWritten != size) {
throw std::runtime_error("Incomplete write to named pipe.");
}
#endif
}
} // namespace Basalt::Shared