File indexing completed on 2025-12-16 10:14:56
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef FMT_OS_H_
0009 #define FMT_OS_H_
0010
0011 #include <cerrno>
0012 #include <cstddef>
0013 #include <cstdio>
0014 #include <system_error> // std::system_error
0015
0016 #include "format.h"
0017
0018 #if defined __APPLE__ || defined(__FreeBSD__)
0019 # if FMT_HAS_INCLUDE(<xlocale.h>)
0020 # include <xlocale.h> // for LC_NUMERIC_MASK on OS X
0021 # endif
0022 #endif
0023
0024 #ifndef FMT_USE_FCNTL
0025
0026 # if FMT_HAS_INCLUDE("winapifamily.h")
0027 # include <winapifamily.h>
0028 # endif
0029 # if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
0030 defined(__linux__)) && \
0031 (!defined(WINAPI_FAMILY) || \
0032 (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
0033 # include <fcntl.h> // for O_RDONLY
0034 # define FMT_USE_FCNTL 1
0035 # else
0036 # define FMT_USE_FCNTL 0
0037 # endif
0038 #endif
0039
0040 #ifndef FMT_POSIX
0041 # if defined(_WIN32) && !defined(__MINGW32__)
0042
0043 # define FMT_POSIX(call) _##call
0044 # else
0045 # define FMT_POSIX(call) call
0046 # endif
0047 #endif
0048
0049
0050 #ifdef FMT_SYSTEM
0051 # define FMT_HAS_SYSTEM
0052 # define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
0053 #else
0054 # define FMT_SYSTEM(call) ::call
0055 # ifdef _WIN32
0056
0057 # define FMT_POSIX_CALL(call) ::_##call
0058 # else
0059 # define FMT_POSIX_CALL(call) ::call
0060 # endif
0061 #endif
0062
0063
0064
0065 #ifndef _WIN32
0066 # define FMT_RETRY_VAL(result, expression, error_result) \
0067 do { \
0068 (result) = (expression); \
0069 } while ((result) == (error_result) && errno == EINTR)
0070 #else
0071 # define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
0072 #endif
0073
0074 #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
0075
0076 FMT_BEGIN_NAMESPACE
0077 FMT_BEGIN_EXPORT
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 template <typename Char> class basic_cstring_view {
0105 private:
0106 const Char* data_;
0107
0108 public:
0109
0110 basic_cstring_view(const Char* s) : data_(s) {}
0111
0112
0113
0114
0115
0116
0117 basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}
0118
0119
0120 auto c_str() const -> const Char* { return data_; }
0121 };
0122
0123 using cstring_view = basic_cstring_view<char>;
0124 using wcstring_view = basic_cstring_view<wchar_t>;
0125
0126 #ifdef _WIN32
0127 FMT_API const std::error_category& system_category() noexcept;
0128
0129 namespace detail {
0130 FMT_API void format_windows_error(buffer<char>& out, int error_code,
0131 const char* message) noexcept;
0132 }
0133
0134 FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
0135 format_args args);
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 template <typename... Args>
0166 std::system_error windows_error(int error_code, string_view message,
0167 const Args&... args) {
0168 return vwindows_error(error_code, message, fmt::make_format_args(args...));
0169 }
0170
0171
0172
0173 FMT_API void report_windows_error(int error_code, const char* message) noexcept;
0174 #else
0175 inline auto system_category() noexcept -> const std::error_category& {
0176 return std::system_category();
0177 }
0178 #endif
0179
0180
0181 #ifdef __OSX__
0182 template <typename S, typename... Args, typename Char = char_t<S>>
0183 void say(const S& format_str, Args&&... args) {
0184 std::system(format("say \"{}\"", format(format_str, args...)).c_str());
0185 }
0186 #endif
0187
0188
0189 class buffered_file {
0190 private:
0191 FILE* file_;
0192
0193 friend class file;
0194
0195 explicit buffered_file(FILE* f) : file_(f) {}
0196
0197 public:
0198 buffered_file(const buffered_file&) = delete;
0199 void operator=(const buffered_file&) = delete;
0200
0201
0202 buffered_file() noexcept : file_(nullptr) {}
0203
0204
0205 FMT_API ~buffered_file() noexcept;
0206
0207 public:
0208 buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
0209 other.file_ = nullptr;
0210 }
0211
0212 auto operator=(buffered_file&& other) -> buffered_file& {
0213 close();
0214 file_ = other.file_;
0215 other.file_ = nullptr;
0216 return *this;
0217 }
0218
0219
0220 FMT_API buffered_file(cstring_view filename, cstring_view mode);
0221
0222
0223 FMT_API void close();
0224
0225
0226 auto get() const noexcept -> FILE* { return file_; }
0227
0228 FMT_API auto descriptor() const -> int;
0229
0230 void vprint(string_view format_str, format_args args) {
0231 fmt::vprint(file_, format_str, args);
0232 }
0233
0234 template <typename... Args>
0235 inline void print(string_view format_str, const Args&... args) {
0236 vprint(format_str, fmt::make_format_args(args...));
0237 }
0238 };
0239
0240 #if FMT_USE_FCNTL
0241
0242
0243
0244
0245
0246
0247 class FMT_API file {
0248 private:
0249 int fd_;
0250
0251
0252 explicit file(int fd) : fd_(fd) {}
0253
0254 public:
0255
0256 enum {
0257 RDONLY = FMT_POSIX(O_RDONLY),
0258 WRONLY = FMT_POSIX(O_WRONLY),
0259 RDWR = FMT_POSIX(O_RDWR),
0260 CREATE = FMT_POSIX(O_CREAT),
0261 APPEND = FMT_POSIX(O_APPEND),
0262 TRUNC = FMT_POSIX(O_TRUNC)
0263 };
0264
0265
0266 file() noexcept : fd_(-1) {}
0267
0268
0269 file(cstring_view path, int oflag);
0270
0271 public:
0272 file(const file&) = delete;
0273 void operator=(const file&) = delete;
0274
0275 file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
0276
0277
0278 auto operator=(file&& other) -> file& {
0279 close();
0280 fd_ = other.fd_;
0281 other.fd_ = -1;
0282 return *this;
0283 }
0284
0285
0286 ~file() noexcept;
0287
0288
0289 auto descriptor() const noexcept -> int { return fd_; }
0290
0291
0292 void close();
0293
0294
0295
0296 auto size() const -> long long;
0297
0298
0299 auto read(void* buffer, size_t count) -> size_t;
0300
0301
0302 auto write(const void* buffer, size_t count) -> size_t;
0303
0304
0305
0306 static auto dup(int fd) -> file;
0307
0308
0309
0310 void dup2(int fd);
0311
0312
0313
0314 void dup2(int fd, std::error_code& ec) noexcept;
0315
0316
0317
0318
0319 static void pipe(file& read_end, file& write_end);
0320
0321
0322
0323 auto fdopen(const char* mode) -> buffered_file;
0324
0325 # if defined(_WIN32) && !defined(__MINGW32__)
0326
0327
0328 static file open_windows_file(wcstring_view path, int oflag);
0329 # endif
0330 };
0331
0332
0333 auto getpagesize() -> long;
0334
0335 namespace detail {
0336
0337 struct buffer_size {
0338 buffer_size() = default;
0339 size_t value = 0;
0340 auto operator=(size_t val) const -> buffer_size {
0341 auto bs = buffer_size();
0342 bs.value = val;
0343 return bs;
0344 }
0345 };
0346
0347 struct ostream_params {
0348 int oflag = file::WRONLY | file::CREATE | file::TRUNC;
0349 size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768;
0350
0351 ostream_params() {}
0352
0353 template <typename... T>
0354 ostream_params(T... params, int new_oflag) : ostream_params(params...) {
0355 oflag = new_oflag;
0356 }
0357
0358 template <typename... T>
0359 ostream_params(T... params, detail::buffer_size bs)
0360 : ostream_params(params...) {
0361 this->buffer_size = bs.value;
0362 }
0363
0364
0365
0366 # if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000
0367 ostream_params(int new_oflag) : oflag(new_oflag) {}
0368 ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {}
0369 # endif
0370 };
0371
0372 class file_buffer final : public buffer<char> {
0373 file file_;
0374
0375 FMT_API void grow(size_t) override;
0376
0377 public:
0378 FMT_API file_buffer(cstring_view path, const ostream_params& params);
0379 FMT_API file_buffer(file_buffer&& other);
0380 FMT_API ~file_buffer();
0381
0382 void flush() {
0383 if (size() == 0) return;
0384 file_.write(data(), size() * sizeof(data()[0]));
0385 clear();
0386 }
0387
0388 void close() {
0389 flush();
0390 file_.close();
0391 }
0392 };
0393
0394 }
0395
0396
0397
0398 constexpr detail::buffer_size buffer_size{};
0399
0400
0401 class FMT_API ostream {
0402 private:
0403 FMT_MSC_WARNING(suppress : 4251)
0404 detail::file_buffer buffer_;
0405
0406 ostream(cstring_view path, const detail::ostream_params& params)
0407 : buffer_(path, params) {}
0408
0409 public:
0410 ostream(ostream&& other) : buffer_(std::move(other.buffer_)) {}
0411
0412 ~ostream();
0413
0414 void flush() { buffer_.flush(); }
0415
0416 template <typename... T>
0417 friend auto output_file(cstring_view path, T... params) -> ostream;
0418
0419 void close() { buffer_.close(); }
0420
0421
0422
0423
0424
0425 template <typename... T> void print(format_string<T...> fmt, T&&... args) {
0426 vformat_to(std::back_inserter(buffer_), fmt,
0427 fmt::make_format_args(args...));
0428 }
0429 };
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446 template <typename... T>
0447 inline auto output_file(cstring_view path, T... params) -> ostream {
0448 return {path, detail::ostream_params(params...)};
0449 }
0450 #endif
0451
0452 FMT_END_EXPORT
0453 FMT_END_NAMESPACE
0454
0455 #endif