/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 | } |