129e87541SZachary Turner //===-- IOStream.cpp --------------------------------------------*- C++ -*-===//
229e87541SZachary Turner //
329e87541SZachary Turner // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
429e87541SZachary Turner // See https://llvm.org/LICENSE.txt for license information.
529e87541SZachary Turner // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
629e87541SZachary Turner //
729e87541SZachary Turner //===----------------------------------------------------------------------===//
829e87541SZachary Turner 
929e87541SZachary Turner #include "IOStream.h"
1029e87541SZachary Turner 
1136496cc2SWalter Erquinigo #if defined(_WIN32)
1229e87541SZachary Turner #include <io.h>
1329e87541SZachary Turner #else
1429e87541SZachary Turner #include <netinet/in.h>
1529e87541SZachary Turner #include <sys/socket.h>
1629e87541SZachary Turner #include <unistd.h>
1729e87541SZachary Turner #endif
1829e87541SZachary Turner 
1929e87541SZachary Turner #include <fstream>
2029e87541SZachary Turner #include <string>
2129e87541SZachary Turner #include <vector>
2229e87541SZachary Turner 
2329e87541SZachary Turner using namespace lldb_vscode;
2429e87541SZachary Turner 
25*24f9a2f5SShafik Yaghmour StreamDescriptor::StreamDescriptor() = default;
2629e87541SZachary Turner 
StreamDescriptor(StreamDescriptor && other)2729e87541SZachary Turner StreamDescriptor::StreamDescriptor(StreamDescriptor &&other) {
2829e87541SZachary Turner   *this = std::move(other);
2929e87541SZachary Turner }
3029e87541SZachary Turner 
~StreamDescriptor()3129e87541SZachary Turner StreamDescriptor::~StreamDescriptor() {
3229e87541SZachary Turner   if (!m_close)
3329e87541SZachary Turner     return;
3429e87541SZachary Turner 
3529e87541SZachary Turner   if (m_is_socket)
3636496cc2SWalter Erquinigo #if defined(_WIN32)
3729e87541SZachary Turner     ::closesocket(m_socket);
3829e87541SZachary Turner #else
3929e87541SZachary Turner     ::close(m_socket);
4029e87541SZachary Turner #endif
4129e87541SZachary Turner   else
4229e87541SZachary Turner     ::close(m_fd);
4329e87541SZachary Turner }
4429e87541SZachary Turner 
operator =(StreamDescriptor && other)4529e87541SZachary Turner StreamDescriptor &StreamDescriptor::operator=(StreamDescriptor &&other) {
4629e87541SZachary Turner   m_close = other.m_close;
4729e87541SZachary Turner   other.m_close = false;
4829e87541SZachary Turner   m_is_socket = other.m_is_socket;
4929e87541SZachary Turner   if (m_is_socket)
5029e87541SZachary Turner     m_socket = other.m_socket;
5129e87541SZachary Turner   else
5229e87541SZachary Turner     m_fd = other.m_fd;
5329e87541SZachary Turner   return *this;
5429e87541SZachary Turner }
5529e87541SZachary Turner 
from_socket(SOCKET s,bool close)5629e87541SZachary Turner StreamDescriptor StreamDescriptor::from_socket(SOCKET s, bool close) {
5729e87541SZachary Turner   StreamDescriptor sd;
5829e87541SZachary Turner   sd.m_is_socket = true;
5929e87541SZachary Turner   sd.m_socket = s;
6029e87541SZachary Turner   sd.m_close = close;
6129e87541SZachary Turner   return sd;
6229e87541SZachary Turner }
6329e87541SZachary Turner 
from_file(int fd,bool close)6429e87541SZachary Turner StreamDescriptor StreamDescriptor::from_file(int fd, bool close) {
6529e87541SZachary Turner   StreamDescriptor sd;
6629e87541SZachary Turner   sd.m_is_socket = false;
6729e87541SZachary Turner   sd.m_fd = fd;
6829e87541SZachary Turner   sd.m_close = close;
6929e87541SZachary Turner   return sd;
7029e87541SZachary Turner }
7129e87541SZachary Turner 
write_full(llvm::StringRef str)7229e87541SZachary Turner bool OutputStream::write_full(llvm::StringRef str) {
7329e87541SZachary Turner   while (!str.empty()) {
7429e87541SZachary Turner     int bytes_written = 0;
7529e87541SZachary Turner     if (descriptor.m_is_socket)
7629e87541SZachary Turner       bytes_written = ::send(descriptor.m_socket, str.data(), str.size(), 0);
7729e87541SZachary Turner     else
7829e87541SZachary Turner       bytes_written = ::write(descriptor.m_fd, str.data(), str.size());
7929e87541SZachary Turner 
8029e87541SZachary Turner     if (bytes_written < 0) {
8129e87541SZachary Turner       if (errno == EINTR || errno == EAGAIN)
8229e87541SZachary Turner         continue;
8329e87541SZachary Turner       return false;
8429e87541SZachary Turner     }
8529e87541SZachary Turner     str = str.drop_front(bytes_written);
8629e87541SZachary Turner   }
8729e87541SZachary Turner 
8829e87541SZachary Turner   return true;
8929e87541SZachary Turner }
9029e87541SZachary Turner 
read_full(std::ofstream * log,size_t length,std::string & text)9129e87541SZachary Turner bool InputStream::read_full(std::ofstream *log, size_t length,
9229e87541SZachary Turner                             std::string &text) {
9329e87541SZachary Turner   std::string data;
9429e87541SZachary Turner   data.resize(length);
9529e87541SZachary Turner 
9629e87541SZachary Turner   char *ptr = &data[0];
9729e87541SZachary Turner   while (length != 0) {
98fee5576fSJonas Devlieghere     int bytes_read = 0;
9929e87541SZachary Turner     if (descriptor.m_is_socket)
10029e87541SZachary Turner       bytes_read = ::recv(descriptor.m_socket, ptr, length, 0);
10129e87541SZachary Turner     else
10229e87541SZachary Turner       bytes_read = ::read(descriptor.m_fd, ptr, length);
10329e87541SZachary Turner 
104d0ac1888SJan Kratochvil     if (bytes_read == 0) {
105d0ac1888SJan Kratochvil       if (log)
106d0ac1888SJan Kratochvil         *log << "End of file (EOF) reading from input file.\n";
107d0ac1888SJan Kratochvil       return false;
108d0ac1888SJan Kratochvil     }
10929e87541SZachary Turner     if (bytes_read < 0) {
11029e87541SZachary Turner       int reason = 0;
11136496cc2SWalter Erquinigo #if defined(_WIN32)
11229e87541SZachary Turner       if (descriptor.m_is_socket)
11329e87541SZachary Turner         reason = WSAGetLastError();
11429e87541SZachary Turner       else
11529e87541SZachary Turner         reason = errno;
11629e87541SZachary Turner #else
11729e87541SZachary Turner       reason = errno;
11829e87541SZachary Turner       if (reason == EINTR || reason == EAGAIN)
11929e87541SZachary Turner         continue;
12029e87541SZachary Turner #endif
12129e87541SZachary Turner 
12229e87541SZachary Turner       if (log)
12329e87541SZachary Turner         *log << "Error " << reason << " reading from input file.\n";
12429e87541SZachary Turner       return false;
12529e87541SZachary Turner     }
12629e87541SZachary Turner 
127fee5576fSJonas Devlieghere     assert(bytes_read >= 0 && (size_t)bytes_read <= length);
12829e87541SZachary Turner     ptr += bytes_read;
12929e87541SZachary Turner     length -= bytes_read;
13029e87541SZachary Turner   }
13129e87541SZachary Turner   text += data;
13229e87541SZachary Turner   return true;
13329e87541SZachary Turner }
13429e87541SZachary Turner 
read_line(std::ofstream * log,std::string & line)13529e87541SZachary Turner bool InputStream::read_line(std::ofstream *log, std::string &line) {
13629e87541SZachary Turner   line.clear();
13729e87541SZachary Turner   while (true) {
13829e87541SZachary Turner     if (!read_full(log, 1, line))
13929e87541SZachary Turner       return false;
14029e87541SZachary Turner 
14129e87541SZachary Turner     if (llvm::StringRef(line).endswith("\r\n"))
14229e87541SZachary Turner       break;
14329e87541SZachary Turner   }
14429e87541SZachary Turner   line.erase(line.size() - 2);
14529e87541SZachary Turner   return true;
14629e87541SZachary Turner }
14729e87541SZachary Turner 
read_expected(std::ofstream * log,llvm::StringRef expected)14829e87541SZachary Turner bool InputStream::read_expected(std::ofstream *log, llvm::StringRef expected) {
14929e87541SZachary Turner   std::string result;
15029e87541SZachary Turner   if (!read_full(log, expected.size(), result))
15129e87541SZachary Turner     return false;
15229e87541SZachary Turner   if (expected != result) {
15329e87541SZachary Turner     if (log)
15429e87541SZachary Turner       *log << "Warning: Expected '" << expected.str() << "', got '" << result
15529e87541SZachary Turner            << "\n";
15629e87541SZachary Turner   }
15729e87541SZachary Turner   return true;
15829e87541SZachary Turner }
159