blob: 36bc1b3e68e00cefe9f3098d2922740ead1b3a0a [file] [log] [blame]
James Kuszmaul3224b8e2022-01-07 19:00:39 -08001#include "aos/util/scoped_pipe.h"
2
3#include <fcntl.h>
4#include "glog/logging.h"
5
6namespace aos::util {
7
8ScopedPipe::ScopedPipe(int fd) : fd_(fd) {}
9
10ScopedPipe::~ScopedPipe() {
11 if (fd_ != -1) {
12 PCHECK(close(fd_) != -1);
13 }
14}
15
16ScopedPipe::ScopedPipe(ScopedPipe &&scoped_pipe) : fd_(scoped_pipe.fd_) {
17 scoped_pipe.fd_ = -1;
18}
19
20ScopedPipe &ScopedPipe::operator=(ScopedPipe &&scoped_pipe) {
21 if (fd_ != -1) {
22 PCHECK(close(fd_) != -1);
23 }
24 fd_ = scoped_pipe.fd_;
25 scoped_pipe.fd_ = -1;
26 return *this;
27}
28
29std::tuple<ScopedPipe::ScopedReadPipe, ScopedPipe::ScopedWritePipe>
30ScopedPipe::MakePipe() {
31 int fds[2];
32 PCHECK(pipe(fds) != -1);
33 PCHECK(fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | O_NONBLOCK) != -1);
34 PCHECK(fcntl(fds[1], F_SETFL, fcntl(fds[1], F_GETFL) | O_NONBLOCK) != -1);
35 return {ScopedReadPipe(fds[0]), ScopedWritePipe(fds[1])};
36}
37
James Kuszmaul731a05d2022-01-07 17:59:26 -080038size_t ScopedPipe::ScopedReadPipe::Read(std::string *buffer) {
39 CHECK_NOTNULL(buffer);
40 constexpr ssize_t kBufferSize = 1024;
41 const size_t original_size = buffer->size();
42 size_t read_bytes = 0;
43 while (true) {
44 buffer->resize(buffer->size() + kBufferSize);
45 const ssize_t result =
46 read(fd(), buffer->data() + buffer->size() - kBufferSize, kBufferSize);
47 if (result == -1) {
48 if (errno == EAGAIN || errno == EWOULDBLOCK) {
49 buffer->resize(original_size);
50 return 0;
51 }
52 PLOG(FATAL) << "Error on reading pipe.";
53 } else if (result < kBufferSize) {
54 read_bytes += result;
55 buffer->resize(original_size + read_bytes);
56 break;
57 } else {
58 CHECK_EQ(result, kBufferSize);
59 read_bytes += result;
60 }
61 }
62 return read_bytes;
63}
64
James Kuszmaul3224b8e2022-01-07 19:00:39 -080065std::optional<uint32_t> ScopedPipe::ScopedReadPipe::Read() {
66 uint32_t buf;
67 ssize_t result = read(fd(), &buf, sizeof(buf));
68 if (result == sizeof(buf)) {
69 return buf;
70 } else {
71 return std::nullopt;
72 }
73}
74
75void ScopedPipe::ScopedWritePipe::Write(uint32_t data) {
76 ssize_t result = write(fd(), &data, sizeof(data));
77 PCHECK(result != -1);
James Kuszmaul731a05d2022-01-07 17:59:26 -080078 CHECK_EQ(static_cast<size_t>(result), sizeof(data));
79}
80
81void ScopedPipe::ScopedWritePipe::Write(absl::Span<const uint8_t> data) {
82 ssize_t result = write(fd(), data.data(), data.size());
83 PCHECK(result != -1);
84 CHECK_EQ(static_cast<size_t>(result), data.size());
James Kuszmaul3224b8e2022-01-07 19:00:39 -080085}
86
87} // namespace aos::util