168 lines
5.3 KiB
C++
168 lines
5.3 KiB
C++
|
|
#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
|