diff options
Diffstat (limited to 'lldb/tools/lldb-vscode/IOStream.cpp')
-rw-r--r-- | lldb/tools/lldb-vscode/IOStream.cpp | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/lldb/tools/lldb-vscode/IOStream.cpp b/lldb/tools/lldb-vscode/IOStream.cpp new file mode 100644 index 00000000000..1b578bfa6d4 --- /dev/null +++ b/lldb/tools/lldb-vscode/IOStream.cpp @@ -0,0 +1,153 @@ +//===-- IOStream.cpp --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "IOStream.h" + +#if defined(_WIN32) +#include <io.h> +#else +#include <netinet/in.h> +#include <sys/socket.h> +#include <unistd.h> +#endif + +#include <fstream> +#include <string> +#include <vector> + +using namespace lldb_vscode; + +StreamDescriptor::StreamDescriptor() {} + +StreamDescriptor::StreamDescriptor(StreamDescriptor &&other) { + *this = std::move(other); +} + +StreamDescriptor::~StreamDescriptor() { + if (!m_close) + return; + + if (m_is_socket) +#if defined(_WIN32) + ::closesocket(m_socket); +#else + ::close(m_socket); +#endif + else + ::close(m_fd); +} + +StreamDescriptor &StreamDescriptor::operator=(StreamDescriptor &&other) { + m_close = other.m_close; + other.m_close = false; + m_is_socket = other.m_is_socket; + if (m_is_socket) + m_socket = other.m_socket; + else + m_fd = other.m_fd; + return *this; +} + +StreamDescriptor StreamDescriptor::from_socket(SOCKET s, bool close) { + StreamDescriptor sd; + sd.m_is_socket = true; + sd.m_socket = s; + sd.m_close = close; + return sd; +} + +StreamDescriptor StreamDescriptor::from_file(int fd, bool close) { + StreamDescriptor sd; + sd.m_is_socket = false; + sd.m_fd = fd; + sd.m_close = close; + return sd; +} + +bool OutputStream::write_full(llvm::StringRef str) { + while (!str.empty()) { + int bytes_written = 0; + if (descriptor.m_is_socket) + bytes_written = ::send(descriptor.m_socket, str.data(), str.size(), 0); + else + bytes_written = ::write(descriptor.m_fd, str.data(), str.size()); + + if (bytes_written < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + return false; + } + str = str.drop_front(bytes_written); + } + + return true; +} + +bool InputStream::read_full(std::ofstream *log, size_t length, + std::string &text) { + std::string data; + data.resize(length); + + char *ptr = &data[0]; + while (length != 0) { + int bytes_read = 0; + if (descriptor.m_is_socket) + bytes_read = ::recv(descriptor.m_socket, ptr, length, 0); + else + bytes_read = ::read(descriptor.m_fd, ptr, length); + + if (bytes_read < 0) { + int reason = 0; +#if defined(_WIN32) + if (descriptor.m_is_socket) + reason = WSAGetLastError(); + else + reason = errno; +#else + reason = errno; + if (reason == EINTR || reason == EAGAIN) + continue; +#endif + + if (log) + *log << "Error " << reason << " reading from input file.\n"; + return false; + } + + assert(bytes_read <= length); + ptr += bytes_read; + length -= bytes_read; + } + text += data; + return true; +} + +bool InputStream::read_line(std::ofstream *log, std::string &line) { + line.clear(); + while (true) { + if (!read_full(log, 1, line)) + return false; + + if (llvm::StringRef(line).endswith("\r\n")) + break; + } + line.erase(line.size() - 2); + return true; +} + +bool InputStream::read_expected(std::ofstream *log, llvm::StringRef expected) { + std::string result; + if (!read_full(log, expected.size(), result)) + return false; + if (expected != result) { + if (log) + *log << "Warning: Expected '" << expected.str() << "', got '" << result + << "\n"; + } + return true; +} |