STIR  6.3.0
os.h
1 // Formatting library for C++ - optional OS-specific functionality
2 //
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7 
8 #ifndef FMT_OS_H_
9 #define FMT_OS_H_
10 
11 #include "format.h"
12 
13 #ifndef FMT_MODULE
14 # include <cerrno>
15 # include <cstddef>
16 # include <cstdio>
17 # include <system_error> // std::system_error
18 
19 # if FMT_HAS_INCLUDE(<xlocale.h>)
20 # include <xlocale.h> // LC_NUMERIC_MASK on macOS
21 # endif
22 #endif // FMT_MODULE
23 
24 #ifndef FMT_USE_FCNTL
25 // UWP doesn't provide _pipe.
26 # if FMT_HAS_INCLUDE("winapifamily.h")
27 # include <winapifamily.h>
28 # endif
29 # if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
30  defined(__linux__)) && \
31  (!defined(WINAPI_FAMILY) || \
32  (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) && \
33  !defined(__wasm__)
34 # include <fcntl.h> // for O_RDONLY
35 # define FMT_USE_FCNTL 1
36 # else
37 # define FMT_USE_FCNTL 0
38 # endif
39 #endif
40 
41 #ifndef FMT_POSIX
42 # if defined(_WIN32) && !defined(__MINGW32__)
43 // Fix warnings about deprecated symbols.
44 # define FMT_POSIX(call) _##call
45 # else
46 # define FMT_POSIX(call) call
47 # endif
48 #endif
49 
50 // Calls to system functions are wrapped in FMT_SYSTEM for testability.
51 #ifdef FMT_SYSTEM
52 # define FMT_HAS_SYSTEM
53 # define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
54 #else
55 # define FMT_SYSTEM(call) ::call
56 # ifdef _WIN32
57 // Fix warnings about deprecated symbols.
58 # define FMT_POSIX_CALL(call) ::_##call
59 # else
60 # define FMT_POSIX_CALL(call) ::call
61 # endif
62 #endif
63 
64 // Retries the expression while it evaluates to error_result and errno
65 // equals to EINTR.
66 #ifndef _WIN32
67 # define FMT_RETRY_VAL(result, expression, error_result) \
68  do { \
69  (result) = (expression); \
70  } while ((result) == (error_result) && errno == EINTR)
71 #else
72 # define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
73 #endif
74 
75 #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
76 
77 FMT_BEGIN_NAMESPACE
78 FMT_BEGIN_EXPORT
79 
96 template <typename Char> class basic_cstring_view {
97  private:
98  const Char* data_;
99 
100  public:
102  basic_cstring_view(const Char* s) : data_(s) {}
103 
105  basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}
106 
108  auto c_str() const -> const Char* { return data_; }
109 };
110 
113 
114 #ifdef _WIN32
115 FMT_API const std::error_category& system_category() noexcept;
116 
117 namespace detail {
118 FMT_API void format_windows_error(buffer<char>& out, int error_code,
119  const char* message) noexcept;
120 }
121 
122 FMT_API std::system_error vwindows_error(int error_code, string_view fmt,
123  format_args args);
124 
150 template <typename... T>
151 auto windows_error(int error_code, string_view message, const T&... args)
152  -> std::system_error {
153  return vwindows_error(error_code, message, vargs<T...>{{args...}});
154 }
155 
156 // Reports a Windows error without throwing an exception.
157 // Can be used to report errors from destructors.
158 FMT_API void report_windows_error(int error_code, const char* message) noexcept;
159 #else
160 inline auto system_category() noexcept -> const std::error_category& {
161  return std::system_category();
162 }
163 #endif // _WIN32
164 
165 // std::system is not available on some platforms such as iOS (#2248).
166 #ifdef __OSX__
167 template <typename S, typename... Args, typename Char = char_t<S>>
168 void say(const S& fmt, Args&&... args) {
169  std::system(format("say \"{}\"", format(fmt, args...)).c_str());
170 }
171 #endif
172 
173 // A buffered file.
174 class buffered_file {
175  private:
176  FILE* file_;
177 
178  friend class file;
179 
180  inline explicit buffered_file(FILE* f) : file_(f) {}
181 
182  public:
183  buffered_file(const buffered_file&) = delete;
184  void operator=(const buffered_file&) = delete;
185 
186  // Constructs a buffered_file object which doesn't represent any file.
187  inline buffered_file() noexcept : file_(nullptr) {}
188 
189  // Destroys the object closing the file it represents if any.
190  FMT_API ~buffered_file() noexcept;
191 
192  public:
193  inline buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
194  other.file_ = nullptr;
195  }
196 
197  inline auto operator=(buffered_file&& other) -> buffered_file& {
198  close();
199  file_ = other.file_;
200  other.file_ = nullptr;
201  return *this;
202  }
203 
204  // Opens a file.
205  FMT_API buffered_file(cstring_view filename, cstring_view mode);
206 
207  // Closes the file.
208  FMT_API void close();
209 
210  // Returns the pointer to a FILE object representing this file.
211  inline auto get() const noexcept -> FILE* { return file_; }
212 
213  FMT_API auto descriptor() const -> int;
214 
215  template <typename... T>
216  inline void print(string_view fmt, const T&... args) {
217  fmt::vargs<T...> vargs = {{args...}};
218  detail::is_locking<T...>() ? fmt::vprint_buffered(file_, fmt, vargs)
219  : fmt::vprint(file_, fmt, vargs);
220  }
221 };
222 
223 #if FMT_USE_FCNTL
224 
225 // A file. Closed file is represented by a file object with descriptor -1.
226 // Methods that are not declared with noexcept may throw
227 // fmt::system_error in case of failure. Note that some errors such as
228 // closing the file multiple times will cause a crash on Windows rather
229 // than an exception. You can get standard behavior by overriding the
230 // invalid parameter handler with _set_invalid_parameter_handler.
231 class FMT_API file {
232  private:
233  int fd_; // File descriptor.
234 
235  // Constructs a file object with a given descriptor.
236  explicit file(int fd) : fd_(fd) {}
237 
238  friend struct pipe;
239 
240  public:
241  // Possible values for the oflag argument to the constructor.
242  enum {
243  RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
244  WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
245  RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing.
246  CREATE = FMT_POSIX(O_CREAT), // Create if the file doesn't exist.
247  APPEND = FMT_POSIX(O_APPEND), // Open in append mode.
248  TRUNC = FMT_POSIX(O_TRUNC) // Truncate the content of the file.
249  };
250 
251  // Constructs a file object which doesn't represent any file.
252  inline file() noexcept : fd_(-1) {}
253 
254  // Opens a file and constructs a file object representing this file.
255  file(cstring_view path, int oflag);
256 
257  public:
258  file(const file&) = delete;
259  void operator=(const file&) = delete;
260 
261  inline file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
262 
263  // Move assignment is not noexcept because close may throw.
264  inline auto operator=(file&& other) -> file& {
265  close();
266  fd_ = other.fd_;
267  other.fd_ = -1;
268  return *this;
269  }
270 
271  // Destroys the object closing the file it represents if any.
272  ~file() noexcept;
273 
274  // Returns the file descriptor.
275  inline auto descriptor() const noexcept -> int { return fd_; }
276 
277  // Closes the file.
278  void close();
279 
280  // Returns the file size. The size has signed type for consistency with
281  // stat::st_size.
282  auto size() const -> long long;
283 
284  // Attempts to read count bytes from the file into the specified buffer.
285  auto read(void* buffer, size_t count) -> size_t;
286 
287  // Attempts to write count bytes from the specified buffer to the file.
288  auto write(const void* buffer, size_t count) -> size_t;
289 
290  // Duplicates a file descriptor with the dup function and returns
291  // the duplicate as a file object.
292  static auto dup(int fd) -> file;
293 
294  // Makes fd be the copy of this file descriptor, closing fd first if
295  // necessary.
296  void dup2(int fd);
297 
298  // Makes fd be the copy of this file descriptor, closing fd first if
299  // necessary.
300  void dup2(int fd, std::error_code& ec) noexcept;
301 
302  // Creates a buffered_file object associated with this file and detaches
303  // this file object from the file.
304  auto fdopen(const char* mode) -> buffered_file;
305 
306 # if defined(_WIN32) && !defined(__MINGW32__)
307  // Opens a file and constructs a file object representing this file by
308  // wcstring_view filename. Windows only.
309  static file open_windows_file(wcstring_view path, int oflag);
310 # endif
311 };
312 
313 struct FMT_API pipe {
314  file read_end;
315  file write_end;
316 
317  // Creates a pipe setting up read_end and write_end file objects for reading
318  // and writing respectively.
319  pipe();
320 };
321 
322 // Returns the memory page size.
323 auto getpagesize() -> long;
324 
325 namespace detail {
326 
327 struct buffer_size {
328  constexpr buffer_size() = default;
329  size_t value = 0;
330  FMT_CONSTEXPR auto operator=(size_t val) const -> buffer_size {
331  auto bs = buffer_size();
332  bs.value = val;
333  return bs;
334  }
335 };
336 
337 struct ostream_params {
338  int oflag = file::WRONLY | file::CREATE | file::TRUNC;
339  size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
340 
341  constexpr ostream_params() {}
342 
343  template <typename... T>
344  ostream_params(T... params, int new_oflag) : ostream_params(params...) {
345  oflag = new_oflag;
346  }
347 
348  template <typename... T>
349  ostream_params(T... params, detail::buffer_size bs)
350  : ostream_params(params...) {
351  this->buffer_size = bs.value;
352  }
353 
354 // Intel has a bug that results in failure to deduce a constructor
355 // for empty parameter packs.
356 # if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000
357  ostream_params(int new_oflag) : oflag(new_oflag) {}
358  ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {}
359 # endif
360 };
361 
362 } // namespace detail
363 
364 FMT_INLINE_VARIABLE constexpr auto buffer_size = detail::buffer_size();
365 
368 class FMT_API ostream : private detail::buffer<char> {
369  private:
370  file file_;
371 
372  ostream(cstring_view path, const detail::ostream_params& params);
373 
374  static void grow(buffer<char>& buf, size_t);
375 
376  public:
377  ostream(ostream&& other) noexcept;
378  ~ostream();
379 
380  operator writer() {
381  detail::buffer<char>& buf = *this;
382  return buf;
383  }
384 
385  inline void flush() {
386  if (size() == 0) return;
387  file_.write(data(), size() * sizeof(data()[0]));
388  clear();
389  }
390 
391  template <typename... T>
392  friend auto output_file(cstring_view path, T... params) -> ostream;
393 
394  inline void close() {
395  flush();
396  file_.close();
397  }
398 
401  template <typename... T> void print(format_string<T...> fmt, T&&... args) {
402  vformat_to(appender(*this), fmt.str, vargs<T...>{{args...}});
403  }
404 };
405 
419 template <typename... T>
420 inline auto output_file(cstring_view path, T... params) -> ostream {
421  return {path, detail::ostream_params(params...)};
422 }
423 #endif // FMT_USE_FCNTL
424 
425 FMT_END_EXPORT
426 FMT_END_NAMESPACE
427 
428 #endif // FMT_OS_H_
basic_cstring_view(const Char *s)
Constructs a string reference object from a C string.
Definition: os.h:102
Converts a string literal into a format string that will be parsed at compile time and converted into...
Definition: args.h:20
A reference to a null-terminated string.
Definition: os.h:96
basic_cstring_view(const std::basic_string< Char > &s)
Constructs a string reference from an std::string object.
Definition: os.h:105
auto c_str() const -> const Char *
Returns the pointer to a C string.
Definition: os.h:108
A contiguous memory buffer with an optional growing ability. It is an internal class and shouldn&#39;t be...
Definition: base.h:1763