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