SoPlex Documentation
Loading...
Searching...
No Matches
os.h
Go to the documentation of this file.
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#if defined(__MINGW32__) || defined(__CYGWIN__)
12// Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/.
13# undef __STRICT_ANSI__
14#endif
15
16#include <cerrno>
17#include <clocale> // for locale_t
18#include <cstddef>
19#include <cstdio>
20#include <cstdlib> // for strtod_l
21
22#if defined __APPLE__ || defined(__FreeBSD__)
23# include <xlocale.h> // for LC_NUMERIC_MASK on OS X
24#endif
25
26#include "format.h"
27
28// UWP doesn't provide _pipe.
29#if FMT_HAS_INCLUDE("winapifamily.h")
30# include <winapifamily.h>
31#endif
32#if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
33 defined(__linux__)) && \
34 (!defined(WINAPI_FAMILY) || (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
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_POSIX_CALL(call) FMT_SYSTEM(call)
53#else
54# define FMT_SYSTEM(call) ::call
55# ifdef _WIN32
56// Fix warnings about deprecated symbols.
57# define FMT_POSIX_CALL(call) ::_##call
58# else
59# define FMT_POSIX_CALL(call) ::call
60# endif
61#endif
62
63// Retries the expression while it evaluates to error_result and errno
64// equals to EINTR.
65#ifndef _WIN32
66# define FMT_RETRY_VAL(result, expression, error_result) \
67 do { \
68 (result) = (expression); \
69 } while ((result) == (error_result) && errno == EINTR)
70#else
71# define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
72#endif
73
74#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
75
77
78/**
79 \rst
80 A reference to a null-terminated string. It can be constructed from a C
81 string or ``std::string``.
82
83 You can use one of the following type aliases for common character types:
84
85 +---------------+-----------------------------+
86 | Type | Definition |
87 +===============+=============================+
88 | cstring_view | basic_cstring_view<char> |
89 +---------------+-----------------------------+
90 | wcstring_view | basic_cstring_view<wchar_t> |
91 +---------------+-----------------------------+
92
93 This class is most useful as a parameter type to allow passing
94 different types of strings to a function, for example::
95
96 template <typename... Args>
97 std::string format(cstring_view format_str, const Args & ... args);
98
99 format("{}", 42);
100 format(std::string("{}"), 42);
101 \endrst
102 */
103template <typename Char> class basic_cstring_view {
104 private:
105 const Char* data_;
106
107 public:
108 /** Constructs a string reference object from a C string. */
109 basic_cstring_view(const Char* s) : data_(s) {}
110
111 /**
112 \rst
113 Constructs a string reference from an ``std::string`` object.
114 \endrst
115 */
116 basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}
117
118 /** Returns the pointer to a C string. */
119 const Char* c_str() const { return data_; }
120};
121
124
125// An error code.
127 private:
129
130 public:
131 explicit error_code(int value = 0) FMT_NOEXCEPT : value_(value) {}
132
133 int get() const FMT_NOEXCEPT { return value_; }
134};
135
136#ifdef _WIN32
137namespace detail {
138// A converter from UTF-16 to UTF-8.
139// It is only provided for Windows since other systems support UTF-8 natively.
140class utf16_to_utf8 {
141 private:
142 memory_buffer buffer_;
143
144 public:
145 utf16_to_utf8() {}
146 FMT_API explicit utf16_to_utf8(wstring_view s);
147 operator string_view() const { return string_view(&buffer_[0], size()); }
148 size_t size() const { return buffer_.size() - 1; }
149 const char* c_str() const { return &buffer_[0]; }
150 std::string str() const { return std::string(&buffer_[0], size()); }
151
152 // Performs conversion returning a system error code instead of
153 // throwing exception on conversion error. This method may still throw
154 // in case of memory allocation error.
155 FMT_API int convert(wstring_view s);
156};
157
158FMT_API void format_windows_error(buffer<char>& out, int error_code,
159 string_view message) FMT_NOEXCEPT;
160} // namespace detail
161
162/** A Windows error. */
163class windows_error : public system_error {
164 private:
165 FMT_API void init(int error_code, string_view format_str, format_args args);
166
167 public:
168 /**
169 \rst
170 Constructs a :class:`fmt::windows_error` object with the description
171 of the form
172
173 .. parsed-literal::
174 *<message>*: *<system-message>*
175
176 where *<message>* is the formatted message and *<system-message>* is the
177 system message corresponding to the error code.
178 *error_code* is a Windows error code as given by ``GetLastError``.
179 If *error_code* is not a valid error code such as -1, the system message
180 will look like "error -1".
181
182 **Example**::
183
184 // This throws a windows_error with the description
185 // cannot open file 'madeup': The system cannot find the file specified.
186 // or similar (system message may vary).
187 const char *filename = "madeup";
188 LPOFSTRUCT of = LPOFSTRUCT();
189 HFILE file = OpenFile(filename, &of, OF_READ);
190 if (file == HFILE_ERROR) {
191 throw fmt::windows_error(GetLastError(),
192 "cannot open file '{}'", filename);
193 }
194 \endrst
195 */
196 template <typename... Args>
197 windows_error(int error_code, string_view message, const Args&... args) {
198 init(error_code, message, make_format_args(args...));
199 }
200};
201
202// Reports a Windows error without throwing an exception.
203// Can be used to report errors from destructors.
204FMT_API void report_windows_error(int error_code,
205 string_view message) FMT_NOEXCEPT;
206#endif // _WIN32
207
208// A buffered file.
210 private:
211 FILE* file_;
212
213 friend class file;
214
215 explicit buffered_file(FILE* f) : file_(f) {}
216
217 public:
218 buffered_file(const buffered_file&) = delete;
219 void operator=(const buffered_file&) = delete;
220
221 // Constructs a buffered_file object which doesn't represent any file.
223
224 // Destroys the object closing the file it represents if any.
226
227 public:
229 other.file_ = nullptr;
230 }
231
233 close();
234 file_ = other.file_;
235 other.file_ = nullptr;
236 return *this;
237 }
238
239 // Opens a file.
241
242 // Closes the file.
244
245 // Returns the pointer to a FILE object representing this file.
246 FILE* get() const FMT_NOEXCEPT { return file_; }
247
248 // We place parentheses around fileno to workaround a bug in some versions
249 // of MinGW that define fileno as a macro.
250 FMT_API int(fileno)() const;
251
252 void vprint(string_view format_str, format_args args) {
253 fmt::vprint(file_, format_str, args);
254 }
255
256 template <typename... Args>
257 inline void print(string_view format_str, const Args&... args) {
258 vprint(format_str, make_format_args(args...));
259 }
260};
261
262#if FMT_USE_FCNTL
263// A file. Closed file is represented by a file object with descriptor -1.
264// Methods that are not declared with FMT_NOEXCEPT may throw
265// fmt::system_error in case of failure. Note that some errors such as
266// closing the file multiple times will cause a crash on Windows rather
267// than an exception. You can get standard behavior by overriding the
268// invalid parameter handler with _set_invalid_parameter_handler.
269class file {
270 private:
271 int fd_; // File descriptor.
272
273 // Constructs a file object with a given descriptor.
274 explicit file(int fd) : fd_(fd) {}
275
276 public:
277 // Possible values for the oflag argument to the constructor.
278 enum {
279 RDONLY = FMT_POSIX(O_RDONLY), // Open for reading only.
280 WRONLY = FMT_POSIX(O_WRONLY), // Open for writing only.
281 RDWR = FMT_POSIX(O_RDWR), // Open for reading and writing.
282 CREATE = FMT_POSIX(O_CREAT), // Create if the file doesn't exist.
283 APPEND = FMT_POSIX(O_APPEND) // Open in append mode.
284 };
285
286 // Constructs a file object which doesn't represent any file.
287 file() FMT_NOEXCEPT : fd_(-1) {}
288
289 // Opens a file and constructs a file object representing this file.
290 FMT_API file(cstring_view path, int oflag);
291
292 public:
293 file(const file&) = delete;
294 void operator=(const file&) = delete;
295
296 file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; }
297
298 file& operator=(file&& other) FMT_NOEXCEPT {
299 close();
300 fd_ = other.fd_;
301 other.fd_ = -1;
302 return *this;
303 }
304
305 // Destroys the object closing the file it represents if any.
306 FMT_API ~file() FMT_NOEXCEPT;
307
308 // Returns the file descriptor.
309 int descriptor() const FMT_NOEXCEPT { return fd_; }
310
311 // Closes the file.
312 FMT_API void close();
313
314 // Returns the file size. The size has signed type for consistency with
315 // stat::st_size.
316 FMT_API long long size() const;
317
318 // Attempts to read count bytes from the file into the specified buffer.
319 FMT_API size_t read(void* buffer, size_t count);
320
321 // Attempts to write count bytes from the specified buffer to the file.
322 FMT_API size_t write(const void* buffer, size_t count);
323
324 // Duplicates a file descriptor with the dup function and returns
325 // the duplicate as a file object.
326 FMT_API static file dup(int fd);
327
328 // Makes fd be the copy of this file descriptor, closing fd first if
329 // necessary.
330 FMT_API void dup2(int fd);
331
332 // Makes fd be the copy of this file descriptor, closing fd first if
333 // necessary.
334 FMT_API void dup2(int fd, error_code& ec) FMT_NOEXCEPT;
335
336 // Creates a pipe setting up read_end and write_end file objects for reading
337 // and writing respectively.
338 FMT_API static void pipe(file& read_end, file& write_end);
339
340 // Creates a buffered_file object associated with this file and detaches
341 // this file object from the file.
342 FMT_API buffered_file fdopen(const char* mode);
343};
344
345// Returns the memory page size.
346long getpagesize();
347
348namespace detail {
349
350struct buffer_size {
351 size_t value = 0;
352 buffer_size operator=(size_t val) const {
353 auto bs = buffer_size();
354 bs.value = val;
355 return bs;
356 }
357};
358
359struct ostream_params {
360 int oflag = file::WRONLY | file::CREATE;
361 size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
362
363 ostream_params() {}
364
365 template <typename... T>
366 ostream_params(T... params, int oflag) : ostream_params(params...) {
367 this->oflag = oflag;
368 }
369
370 template <typename... T>
371 ostream_params(T... params, detail::buffer_size bs)
372 : ostream_params(params...) {
373 this->buffer_size = bs.value;
374 }
375};
376} // namespace detail
377
378static constexpr detail::buffer_size buffer_size;
379
380// A fast output stream which is not thread-safe.
381class ostream final : private detail::buffer<char> {
382 private:
383 file file_;
384
385 void flush() {
386 if (size() == 0) return;
387 file_.write(data(), size());
388 clear();
389 }
390
391 FMT_API void grow(size_t) override final;
392
393 ostream(cstring_view path, const detail::ostream_params& params)
394 : file_(path, params.oflag) {
395 set(new char[params.buffer_size], params.buffer_size);
396 }
397
398 public:
399 ostream(ostream&& other)
400 : detail::buffer<char>(other.data(), other.size(), other.capacity()),
401 file_(std::move(other.file_)) {
402 other.set(nullptr, 0);
403 }
404 ~ostream() {
405 flush();
406 delete[] data();
407 }
408
409 template <typename... T>
410 friend ostream output_file(cstring_view path, T... params);
411
412 void close() {
413 flush();
414 file_.close();
415 }
416
417 template <typename S, typename... Args>
418 void print(const S& format_str, const Args&... args) {
419 format_to(detail::buffer_appender<char>(*this), format_str, args...);
420 }
421};
422
423/**
424 Opens a file for writing. Supported parameters passed in `params`:
425 * ``<integer>``: Output flags (``file::WRONLY | file::CREATE`` by default)
426 * ``buffer_size=<integer>``: Output buffer size
427 */
428template <typename... T>
429inline ostream output_file(cstring_view path, T... params) {
430 return {path, detail::ostream_params(params...)};
431}
432#endif // FMT_USE_FCNTL
433
434#ifdef FMT_LOCALE
435// A "C" numeric locale.
436class locale {
437 private:
438# ifdef _WIN32
439 using locale_t = _locale_t;
440
441 static void freelocale(locale_t loc) { _free_locale(loc); }
442
443 static double strtod_l(const char* nptr, char** endptr, _locale_t loc) {
444 return _strtod_l(nptr, endptr, loc);
445 }
446# endif
447
448 locale_t locale_;
449
450 public:
451 using type = locale_t;
452 locale(const locale&) = delete;
453 void operator=(const locale&) = delete;
454
455 locale() {
456# ifndef _WIN32
457 locale_ = FMT_SYSTEM(newlocale(LC_NUMERIC_MASK, "C", nullptr));
458# else
459 locale_ = _create_locale(LC_NUMERIC, "C");
460# endif
461 if (!locale_) FMT_THROW(system_error(errno, "cannot create locale"));
462 }
463 ~locale() { freelocale(locale_); }
464
465 type get() const { return locale_; }
466
467 // Converts string to floating-point number and advances str past the end
468 // of the parsed input.
469 double strtod(const char*& str) const {
470 char* end = nullptr;
471 double result = strtod_l(str, &end, locale_);
472 str = end;
473 return result;
474 }
475};
476using Locale FMT_DEPRECATED_ALIAS = locale;
477#endif // FMT_LOCALE
479
480#endif // FMT_OS_H_
const Char * c_str() const
Definition os.h:119
basic_cstring_view(const Char *s)
Definition os.h:109
basic_cstring_view(const std::basic_string< Char > &s)
Definition os.h:116
const Char * data_
Definition os.h:105
FILE * get() const FMT_NOEXCEPT
Definition os.h:246
void print(string_view format_str, const Args &... args)
Definition os.h:257
FMT_API buffered_file(cstring_view filename, cstring_view mode)
void vprint(string_view format_str, format_args args)
Definition os.h:252
friend class file
Definition os.h:213
FILE * file_
Definition os.h:211
FMT_API void close()
void operator=(const buffered_file &)=delete
buffered_file & operator=(buffered_file &&other)
Definition os.h:232
FMT_API int fileno() const
FMT_API ~buffered_file() FMT_NOEXCEPT
buffered_file(const buffered_file &)=delete
buffered_file(FILE *f)
Definition os.h:215
buffered_file() FMT_NOEXCEPT
Definition os.h:222
T * data() FMT_NOEXCEPT
Definition core.h:712
void set(T *buf_data, size_t buf_capacity) FMT_NOEXCEPT
Definition core.h:684
void clear()
Definition core.h:718
size_t size() const FMT_NOEXCEPT
Definition core.h:706
virtual void grow(size_t capacity)=0
int get() const FMT_NOEXCEPT
Definition os.h:133
error_code(int value=0) FMT_NOEXCEPT
Definition os.h:131
int value_
Definition os.h:128
void init(int err_code, string_view format_str, format_args args)
Definition format-inl.h:211
void print(std::FILE *f, const text_style &ts, const S &format_str, const Args &... args)
Definition color.h:519
auto format_to(OutputIt out, const text_style &ts, const S &format_str, Args &&... args) -> typename std::enable_if< enable, OutputIt >::type
Definition color.h:594
basic_string_view< char > string_view
Definition core.h:440
format_arg_store< Context, Args... > make_format_args(const Args &... args)
Definition core.h:1603
#define FMT_BEGIN_NAMESPACE
Definition core.h:203
#define FMT_API
Definition core.h:222
#define FMT_END_NAMESPACE
Definition core.h:198
#define FMT_NOEXCEPT
Definition core.h:139
#define FMT_THROW(x)
Definition format.h:116
OutputIt write(OutputIt out, basic_string_view< StrChar > s, const basic_format_specs< Char > &specs)
Definition format.h:1568
type
Definition core.h:977
#define FMT_POSIX(call)
Definition os.h:46
#define FMT_SYSTEM(call)
Definition os.h:54