aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/fmt/test/gtest-extra.cc
blob: 3f38cbd1e69abac09aa0954cb346e84c0712891b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Formatting library for C++ - custom Google Test assertions 
// 
// Copyright (c) 2012 - present, Victor Zverovich 
// All rights reserved. 
// 
// For the license information refer to format.h. 
 
#include "gtest-extra.h" 
 
#if FMT_USE_FCNTL 
 
using fmt::file; 
 
void OutputRedirect::flush() { 
#  if EOF != -1 
#    error "FMT_RETRY assumes return value of -1 indicating failure" 
#  endif 
  int result = 0; 
  FMT_RETRY(result, fflush(file_)); 
  if (result != 0) throw fmt::system_error(errno, "cannot flush stream"); 
} 
 
void OutputRedirect::restore() { 
  if (original_.descriptor() == -1) return;  // Already restored. 
  flush(); 
  // Restore the original file. 
  original_.dup2(FMT_POSIX(fileno(file_))); 
  original_.close(); 
} 
 
OutputRedirect::OutputRedirect(FILE* f) : file_(f) { 
  flush(); 
  int fd = FMT_POSIX(fileno(f)); 
  // Create a file object referring to the original file. 
  original_ = file::dup(fd); 
  // Create a pipe. 
  file write_end; 
  file::pipe(read_end_, write_end); 
  // Connect the passed FILE object to the write end of the pipe. 
  write_end.dup2(fd); 
} 
 
OutputRedirect::~OutputRedirect() FMT_NOEXCEPT { 
  try { 
    restore(); 
  } catch (const std::exception& e) { 
    std::fputs(e.what(), stderr); 
  } 
} 
 
std::string OutputRedirect::restore_and_read() { 
  // Restore output. 
  restore(); 
 
  // Read everything from the pipe. 
  std::string content; 
  if (read_end_.descriptor() == -1) return content;  // Already read. 
  enum { BUFFER_SIZE = 4096 }; 
  char buffer[BUFFER_SIZE]; 
  size_t count = 0;
  do { 
    count = read_end_.read(buffer, BUFFER_SIZE); 
    content.append(buffer, count); 
  } while (count != 0); 
  read_end_.close(); 
  return content; 
} 
 
std::string read(file& f, size_t count) {
  std::string buffer(count, '\0'); 
  size_t n = 0, offset = 0;
  do { 
    n = f.read(&buffer[offset], count - offset); 
    // We can't read more than size_t bytes since count has type size_t. 
    offset += n; 
  } while (offset < count && n != 0); 
  buffer.resize(offset); 
  return buffer; 
} 
 
#endif  // FMT_USE_FCNTL 
 
std::string format_system_error(int error_code, fmt::string_view message) { 
  fmt::memory_buffer out; 
  format_system_error(out, error_code, message); 
  return to_string(out); 
}