1 // Formatting library for C++ - custom Google Test assertions
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
6 // For the license information refer to format.h.
8 #include "gtest-extra.h"
14 output_redirect::output_redirect(FILE* f
, bool flush
) : file_(f
) {
15 if (flush
) this->flush();
16 int fd
= FMT_POSIX(fileno(f
));
17 // Create a file object referring to the original file.
18 original_
= file::dup(fd
);
20 auto pipe
= fmt::pipe();
21 read_end_
= std::move(pipe
.read_end
);
22 // Connect the passed FILE object to the write end of the pipe.
23 pipe
.write_end
.dup2(fd
);
26 output_redirect::~output_redirect() noexcept
{
29 } catch (const std::exception
& e
) {
30 std::fputs(e
.what(), stderr
);
34 void output_redirect::flush() {
37 result
= fflush(file_
);
38 } while (result
== EOF
&& errno
== EINTR
);
39 if (result
!= 0) throw fmt::system_error(errno
, "cannot flush stream");
42 void output_redirect::restore() {
43 if (original_
.descriptor() == -1) return; // Already restored.
45 // Restore the original file.
46 original_
.dup2(FMT_POSIX(fileno(file_
)));
50 std::string
output_redirect::restore_and_read() {
54 // Read everything from the pipe.
56 if (read_end_
.descriptor() == -1) return content
; // Already read.
57 enum { BUFFER_SIZE
= 4096 };
58 char buffer
[BUFFER_SIZE
];
61 count
= read_end_
.read(buffer
, BUFFER_SIZE
);
62 content
.append(buffer
, count
);
68 std::string
read(file
& f
, size_t count
) {
69 std::string
buffer(count
, '\0');
70 size_t n
= 0, offset
= 0;
72 n
= f
.read(&buffer
[offset
], count
- offset
);
73 // We can't read more than size_t bytes since count has type size_t.
75 } while (offset
< count
&& n
!= 0);
76 buffer
.resize(offset
);
80 #endif // FMT_USE_FCNTL