|
16 | 16 |
|
17 | 17 | #include <algorithm>
|
18 | 18 | #include <cerrno>
|
| 19 | +#include <cstdint> |
| 20 | +#include <cstdio> |
19 | 21 | #include <cstdlib>
|
20 | 22 | #include <cstring>
|
21 | 23 | #include <filesystem>
|
22 |
| -#include <fstream> |
23 |
| -#include <iostream> |
24 | 24 | #include <memory>
|
25 | 25 | #include <string>
|
26 | 26 | #include <system_error>
|
@@ -154,34 +154,35 @@ absl::Status FileExists(const std::string &filename) {
|
154 | 154 |
|
155 | 155 | absl::StatusOr<std::string> GetContentAsString(absl::string_view filename) {
|
156 | 156 | std::string content;
|
157 |
| - std::ifstream fs; |
158 |
| - std::istream *stream = nullptr; |
| 157 | + FILE *stream = nullptr; |
159 | 158 | const bool use_stdin = IsStdin(filename);
|
160 | 159 | if (use_stdin) {
|
161 |
| - stream = &std::cin; |
| 160 | +#ifdef _WIN32 |
| 161 | + _setmode(_fileno(stdin), _O_BINARY); // Work around DOS/Win silliness. |
| 162 | +#endif |
| 163 | + stream = stdin; |
162 | 164 | } else {
|
163 | 165 | const std::string filename_str = std::string{filename};
|
164 | 166 | if (absl::Status status = FileExists(filename_str); !status.ok()) {
|
165 | 167 | return status; // Bail
|
166 | 168 | }
|
167 |
| - fs.open(filename_str.c_str()); |
| 169 | + stream = fopen(filename_str.c_str(), "rb"); |
168 | 170 | std::error_code err;
|
169 | 171 | const size_t prealloc = fs::file_size(filename_str, err);
|
170 | 172 | if (err.value() == 0) content.reserve(prealloc);
|
171 |
| - stream = &fs; |
172 | 173 | }
|
173 |
| - if (!stream->good()) { |
| 174 | + if (!stream) { |
174 | 175 | return CreateErrorStatusFromErrno(filename, "can't read");
|
175 | 176 | }
|
176 | 177 | char buffer[4096];
|
177 |
| - while (stream->good() && !stream->eof()) { |
178 |
| - stream->read(buffer, sizeof(buffer)); |
179 |
| - content.append(buffer, stream->gcount()); |
180 |
| - } |
181 |
| - |
182 |
| - // Allow stdin to be reopened for more input. |
183 |
| - if (use_stdin && std::cin.eof()) std::cin.clear(); |
184 |
| - return std::move(content); |
| 178 | + int bytes_read; |
| 179 | + do { |
| 180 | + bytes_read = fread(buffer, 1, sizeof(buffer), stream); |
| 181 | + content.append(buffer, bytes_read); |
| 182 | + } while (bytes_read > 0); |
| 183 | + fclose(stream); |
| 184 | + |
| 185 | + return content; |
185 | 186 | }
|
186 | 187 |
|
187 | 188 | static absl::StatusOr<std::unique_ptr<MemBlock>> AttemptMemMapFile(
|
@@ -244,11 +245,21 @@ absl::StatusOr<std::unique_ptr<MemBlock>> GetContentAsMemBlock(
|
244 | 245 | absl::Status SetContents(absl::string_view filename,
|
245 | 246 | absl::string_view content) {
|
246 | 247 | VLOG(1) << __FUNCTION__ << ": Writing file: " << filename;
|
247 |
| - std::ofstream f(std::string(filename).c_str()); |
248 |
| - if (!f.good()) return CreateErrorStatusFromErrno(filename, "can't write."); |
249 |
| - f << content; |
250 |
| - f.close(); |
251 |
| - if (!f.good()) return CreateErrorStatusFromErrno(filename, "closing."); |
| 248 | + FILE *out = fopen(std::string(filename).c_str(), "wb"); |
| 249 | + if (!out) return CreateErrorStatusFromErrno(filename, "can't write."); |
| 250 | + const int64_t expected_write = content.size(); |
| 251 | + int64_t total_written = 0; |
| 252 | + while (!content.empty()) { |
| 253 | + int64_t w = fwrite(content.data(), 1, content.size(), out); |
| 254 | + total_written += w; |
| 255 | + content.remove_prefix(w); |
| 256 | + } |
| 257 | + if (total_written != expected_write) { |
| 258 | + return CreateErrorStatusFromErrno(filename, "Could not write completely."); |
| 259 | + } |
| 260 | + if (fclose(out) != 0) { |
| 261 | + return CreateErrorStatusFromErrno(filename, "closing."); |
| 262 | + } |
252 | 263 | return absl::OkStatus();
|
253 | 264 | }
|
254 | 265 |
|
|
0 commit comments