Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/tools/lldb-vscode/IOStream.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- IOStream.cpp --------------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "IOStream.h"
10
11
#if defined(_WIN32)
12
#include <io.h>
13
#else
14
#include <netinet/in.h>
15
#include <sys/socket.h>
16
#include <unistd.h>
17
#endif
18
19
#include <fstream>
20
#include <string>
21
#include <vector>
22
23
using namespace lldb_vscode;
24
25
18
StreamDescriptor::StreamDescriptor() = default;
26
27
0
StreamDescriptor::StreamDescriptor(StreamDescriptor &&other) {
28
0
  *this = std::move(other);
29
0
}
30
31
8
StreamDescriptor::~StreamDescriptor() {
32
8
  if (!m_close)
33
8
    return;
34
35
0
  if (m_is_socket)
36
#if defined(_WIN32)
37
    ::closesocket(m_socket);
38
#else
39
0
    ::close(m_socket);
40
0
#endif
41
0
  else
42
0
    ::close(m_fd);
43
0
}
44
45
8
StreamDescriptor &StreamDescriptor::operator=(StreamDescriptor &&other) {
46
8
  m_close = other.m_close;
47
8
  other.m_close = false;
48
8
  m_is_socket = other.m_is_socket;
49
8
  if (m_is_socket)
50
0
    m_socket = other.m_socket;
51
8
  else
52
8
    m_fd = other.m_fd;
53
8
  return *this;
54
8
}
55
56
0
StreamDescriptor StreamDescriptor::from_socket(SOCKET s, bool close) {
57
0
  StreamDescriptor sd;
58
0
  sd.m_is_socket = true;
59
0
  sd.m_socket = s;
60
0
  sd.m_close = close;
61
0
  return sd;
62
0
}
63
64
8
StreamDescriptor StreamDescriptor::from_file(int fd, bool close) {
65
8
  StreamDescriptor sd;
66
8
  sd.m_is_socket = false;
67
8
  sd.m_fd = fd;
68
8
  sd.m_close = close;
69
8
  return sd;
70
8
}
71
72
128
bool OutputStream::write_full(llvm::StringRef str) {
73
256
  while (!str.empty()) {
74
128
    int bytes_written = 0;
75
128
    if (descriptor.m_is_socket)
76
0
      bytes_written = ::send(descriptor.m_socket, str.data(), str.size(), 0);
77
128
    else
78
128
      bytes_written = ::write(descriptor.m_fd, str.data(), str.size());
79
80
128
    if (bytes_written < 0) {
81
0
      if (errno == EINTR || errno == EAGAIN)
82
0
        continue;
83
0
      return false;
84
0
    }
85
128
    str = str.drop_front(bytes_written);
86
128
  }
87
88
128
  return true;
89
128
}
90
91
bool InputStream::read_full(std::ofstream *log, size_t length,
92
114
                            std::string &text) {
93
114
  std::string data;
94
114
  data.resize(length);
95
96
114
  char *ptr = &data[0];
97
228
  while (length != 0) {
98
114
    int bytes_read = 0;
99
114
    if (descriptor.m_is_socket)
100
0
      bytes_read = ::recv(descriptor.m_socket, ptr, length, 0);
101
114
    else
102
114
      bytes_read = ::read(descriptor.m_fd, ptr, length);
103
104
114
    if (bytes_read == 0) {
105
0
      if (log)
106
0
        *log << "End of file (EOF) reading from input file.\n";
107
0
      return false;
108
0
    }
109
114
    if (bytes_read < 0) {
110
0
      int reason = 0;
111
#if defined(_WIN32)
112
      if (descriptor.m_is_socket)
113
        reason = WSAGetLastError();
114
      else
115
        reason = errno;
116
#else
117
0
      reason = errno;
118
0
      if (reason == EINTR || reason == EAGAIN)
119
0
        continue;
120
0
#endif
121
122
0
      if (log)
123
0
        *log << "Error " << reason << " reading from input file.\n";
124
0
      return false;
125
0
    }
126
127
114
    assert(bytes_read >= 0 && (size_t)bytes_read <= length);
128
114
    ptr += bytes_read;
129
114
    length -= bytes_read;
130
114
  }
131
114
  text += data;
132
114
  return true;
133
114
}
134
135
15
bool InputStream::read_line(std::ofstream *log, std::string &line) {
136
15
  line.clear();
137
69
  while (true) {
138
69
    if (!read_full(log, 1, line))
139
0
      return false;
140
141
69
    if (llvm::StringRef(line).endswith("\r\n"))
142
15
      break;
143
69
  }
144
15
  line.erase(line.size() - 2);
145
15
  return true;
146
15
}
147
148
30
bool InputStream::read_expected(std::ofstream *log, llvm::StringRef expected) {
149
30
  std::string result;
150
30
  if (!read_full(log, expected.size(), result))
151
0
    return false;
152
30
  if (expected != result) {
153
0
    if (log)
154
0
      *log << "Warning: Expected '" << expected.str() << "', got '" << result
155
0
           << "\n";
156
0
  }
157
30
  return true;
158
30
}