git repos / blockattack-game

blame: source/misc/embedded_libs/fmt-8.1.1/src/os.cc

normal view · raw

f8deb5b9 Poul Sander 2022-01-15 13:55 1
// Formatting library for C++ - optional OS-specific functionality
f8deb5b9 Poul Sander 2022-01-15 13:55 2
//
f8deb5b9 Poul Sander 2022-01-15 13:55 3
// Copyright (c) 2012 - 2016, Victor Zverovich
f8deb5b9 Poul Sander 2022-01-15 13:55 4
// All rights reserved.
f8deb5b9 Poul Sander 2022-01-15 13:55 5
//
f8deb5b9 Poul Sander 2022-01-15 13:55 6
// For the license information refer to format.h.
f8deb5b9 Poul Sander 2022-01-15 13:55 7
f8deb5b9 Poul Sander 2022-01-15 13:55 8
// Disable bogus MSVC warnings.
f8deb5b9 Poul Sander 2022-01-15 13:55 9
#if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER)
f8deb5b9 Poul Sander 2022-01-15 13:55 10
#  define _CRT_SECURE_NO_WARNINGS
f8deb5b9 Poul Sander 2022-01-15 13:55 11
#endif
f8deb5b9 Poul Sander 2022-01-15 13:55 12
f8deb5b9 Poul Sander 2022-01-15 13:55 13
#include "fmt/os.h"
f8deb5b9 Poul Sander 2022-01-15 13:55 14
f8deb5b9 Poul Sander 2022-01-15 13:55 15
#include <climits>
f8deb5b9 Poul Sander 2022-01-15 13:55 16
f8deb5b9 Poul Sander 2022-01-15 13:55 17
#if FMT_USE_FCNTL
f8deb5b9 Poul Sander 2022-01-15 13:55 18
#  include <sys/stat.h>
f8deb5b9 Poul Sander 2022-01-15 13:55 19
#  include <sys/types.h>
f8deb5b9 Poul Sander 2022-01-15 13:55 20
f8deb5b9 Poul Sander 2022-01-15 13:55 21
#  ifndef _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 22
#    include <unistd.h>
f8deb5b9 Poul Sander 2022-01-15 13:55 23
#  else
f8deb5b9 Poul Sander 2022-01-15 13:55 24
#    ifndef WIN32_LEAN_AND_MEAN
f8deb5b9 Poul Sander 2022-01-15 13:55 25
#      define WIN32_LEAN_AND_MEAN
f8deb5b9 Poul Sander 2022-01-15 13:55 26
#    endif
f8deb5b9 Poul Sander 2022-01-15 13:55 27
#    include <io.h>
f8deb5b9 Poul Sander 2022-01-15 13:55 28
f8deb5b9 Poul Sander 2022-01-15 13:55 29
#    ifndef S_IRUSR
f8deb5b9 Poul Sander 2022-01-15 13:55 30
#      define S_IRUSR _S_IREAD
f8deb5b9 Poul Sander 2022-01-15 13:55 31
#    endif
f8deb5b9 Poul Sander 2022-01-15 13:55 32
#    ifndef S_IWUSR
f8deb5b9 Poul Sander 2022-01-15 13:55 33
#      define S_IWUSR _S_IWRITE
f8deb5b9 Poul Sander 2022-01-15 13:55 34
#    endif
f8deb5b9 Poul Sander 2022-01-15 13:55 35
#    ifndef S_IRGRP
f8deb5b9 Poul Sander 2022-01-15 13:55 36
#      define S_IRGRP 0
f8deb5b9 Poul Sander 2022-01-15 13:55 37
#    endif
f8deb5b9 Poul Sander 2022-01-15 13:55 38
#    ifndef S_IROTH
f8deb5b9 Poul Sander 2022-01-15 13:55 39
#      define S_IROTH 0
f8deb5b9 Poul Sander 2022-01-15 13:55 40
#    endif
f8deb5b9 Poul Sander 2022-01-15 13:55 41
#  endif  // _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 42
#endif    // FMT_USE_FCNTL
f8deb5b9 Poul Sander 2022-01-15 13:55 43
f8deb5b9 Poul Sander 2022-01-15 13:55 44
#ifdef _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 45
#  include <windows.h>
f8deb5b9 Poul Sander 2022-01-15 13:55 46
#endif
f8deb5b9 Poul Sander 2022-01-15 13:55 47
f8deb5b9 Poul Sander 2022-01-15 13:55 48
#ifdef fileno
f8deb5b9 Poul Sander 2022-01-15 13:55 49
#  undef fileno
f8deb5b9 Poul Sander 2022-01-15 13:55 50
#endif
f8deb5b9 Poul Sander 2022-01-15 13:55 51
f8deb5b9 Poul Sander 2022-01-15 13:55 52
namespace {
f8deb5b9 Poul Sander 2022-01-15 13:55 53
#ifdef _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 54
// Return type of read and write functions.
f8deb5b9 Poul Sander 2022-01-15 13:55 55
using rwresult = int;
f8deb5b9 Poul Sander 2022-01-15 13:55 56
f8deb5b9 Poul Sander 2022-01-15 13:55 57
// On Windows the count argument to read and write is unsigned, so convert
f8deb5b9 Poul Sander 2022-01-15 13:55 58
// it from size_t preventing integer overflow.
f8deb5b9 Poul Sander 2022-01-15 13:55 59
inline unsigned convert_rwcount(std::size_t count) {
f8deb5b9 Poul Sander 2022-01-15 13:55 60
  return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
f8deb5b9 Poul Sander 2022-01-15 13:55 61
}
f8deb5b9 Poul Sander 2022-01-15 13:55 62
#elif FMT_USE_FCNTL
f8deb5b9 Poul Sander 2022-01-15 13:55 63
// Return type of read and write functions.
f8deb5b9 Poul Sander 2022-01-15 13:55 64
using rwresult = ssize_t;
f8deb5b9 Poul Sander 2022-01-15 13:55 65
f8deb5b9 Poul Sander 2022-01-15 13:55 66
inline std::size_t convert_rwcount(std::size_t count) { return count; }
f8deb5b9 Poul Sander 2022-01-15 13:55 67
#endif
f8deb5b9 Poul Sander 2022-01-15 13:55 68
}  // namespace
f8deb5b9 Poul Sander 2022-01-15 13:55 69
f8deb5b9 Poul Sander 2022-01-15 13:55 70
FMT_BEGIN_NAMESPACE
f8deb5b9 Poul Sander 2022-01-15 13:55 71
f8deb5b9 Poul Sander 2022-01-15 13:55 72
#ifdef _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 73
detail::utf16_to_utf8::utf16_to_utf8(basic_string_view<wchar_t> s) {
f8deb5b9 Poul Sander 2022-01-15 13:55 74
  if (int error_code = convert(s)) {
f8deb5b9 Poul Sander 2022-01-15 13:55 75
    FMT_THROW(windows_error(error_code,
f8deb5b9 Poul Sander 2022-01-15 13:55 76
                            "cannot convert string from UTF-16 to UTF-8"));
f8deb5b9 Poul Sander 2022-01-15 13:55 77
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 78
}
f8deb5b9 Poul Sander 2022-01-15 13:55 79
f8deb5b9 Poul Sander 2022-01-15 13:55 80
int detail::utf16_to_utf8::convert(basic_string_view<wchar_t> s) {
f8deb5b9 Poul Sander 2022-01-15 13:55 81
  if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER;
f8deb5b9 Poul Sander 2022-01-15 13:55 82
  int s_size = static_cast<int>(s.size());
f8deb5b9 Poul Sander 2022-01-15 13:55 83
  if (s_size == 0) {
f8deb5b9 Poul Sander 2022-01-15 13:55 84
    // WideCharToMultiByte does not support zero length, handle separately.
f8deb5b9 Poul Sander 2022-01-15 13:55 85
    buffer_.resize(1);
f8deb5b9 Poul Sander 2022-01-15 13:55 86
    buffer_[0] = 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 87
    return 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 88
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 89
f8deb5b9 Poul Sander 2022-01-15 13:55 90
  int length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, nullptr, 0,
f8deb5b9 Poul Sander 2022-01-15 13:55 91
                                   nullptr, nullptr);
f8deb5b9 Poul Sander 2022-01-15 13:55 92
  if (length == 0) return GetLastError();
f8deb5b9 Poul Sander 2022-01-15 13:55 93
  buffer_.resize(length + 1);
f8deb5b9 Poul Sander 2022-01-15 13:55 94
  length = WideCharToMultiByte(CP_UTF8, 0, s.data(), s_size, &buffer_[0],
f8deb5b9 Poul Sander 2022-01-15 13:55 95
                               length, nullptr, nullptr);
f8deb5b9 Poul Sander 2022-01-15 13:55 96
  if (length == 0) return GetLastError();
f8deb5b9 Poul Sander 2022-01-15 13:55 97
  buffer_[length] = 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 98
  return 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 99
}
f8deb5b9 Poul Sander 2022-01-15 13:55 100
f8deb5b9 Poul Sander 2022-01-15 13:55 101
namespace detail {
f8deb5b9 Poul Sander 2022-01-15 13:55 102
f8deb5b9 Poul Sander 2022-01-15 13:55 103
class system_message {
f8deb5b9 Poul Sander 2022-01-15 13:55 104
  system_message(const system_message&) = delete;
f8deb5b9 Poul Sander 2022-01-15 13:55 105
  void operator=(const system_message&) = delete;
f8deb5b9 Poul Sander 2022-01-15 13:55 106
f8deb5b9 Poul Sander 2022-01-15 13:55 107
  unsigned long result_;
f8deb5b9 Poul Sander 2022-01-15 13:55 108
  wchar_t* message_;
f8deb5b9 Poul Sander 2022-01-15 13:55 109
f8deb5b9 Poul Sander 2022-01-15 13:55 110
  static bool is_whitespace(wchar_t c) FMT_NOEXCEPT {
f8deb5b9 Poul Sander 2022-01-15 13:55 111
    return c == L' ' || c == L'\n' || c == L'\r' || c == L'\t' || c == L'\0';
f8deb5b9 Poul Sander 2022-01-15 13:55 112
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 113
f8deb5b9 Poul Sander 2022-01-15 13:55 114
 public:
f8deb5b9 Poul Sander 2022-01-15 13:55 115
  explicit system_message(unsigned long error_code)
f8deb5b9 Poul Sander 2022-01-15 13:55 116
      : result_(0), message_(nullptr) {
f8deb5b9 Poul Sander 2022-01-15 13:55 117
    result_ = FormatMessageW(
f8deb5b9 Poul Sander 2022-01-15 13:55 118
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
f8deb5b9 Poul Sander 2022-01-15 13:55 119
            FORMAT_MESSAGE_IGNORE_INSERTS,
f8deb5b9 Poul Sander 2022-01-15 13:55 120
        nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
f8deb5b9 Poul Sander 2022-01-15 13:55 121
        reinterpret_cast<wchar_t*>(&message_), 0, nullptr);
f8deb5b9 Poul Sander 2022-01-15 13:55 122
    if (result_ != 0) {
f8deb5b9 Poul Sander 2022-01-15 13:55 123
      while (result_ != 0 && is_whitespace(message_[result_ - 1])) {
f8deb5b9 Poul Sander 2022-01-15 13:55 124
        --result_;
f8deb5b9 Poul Sander 2022-01-15 13:55 125
      }
f8deb5b9 Poul Sander 2022-01-15 13:55 126
    }
f8deb5b9 Poul Sander 2022-01-15 13:55 127
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 128
  ~system_message() { LocalFree(message_); }
f8deb5b9 Poul Sander 2022-01-15 13:55 129
  explicit operator bool() const FMT_NOEXCEPT { return result_ != 0; }
f8deb5b9 Poul Sander 2022-01-15 13:55 130
  operator basic_string_view<wchar_t>() const FMT_NOEXCEPT {
f8deb5b9 Poul Sander 2022-01-15 13:55 131
    return basic_string_view<wchar_t>(message_, result_);
f8deb5b9 Poul Sander 2022-01-15 13:55 132
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 133
};
f8deb5b9 Poul Sander 2022-01-15 13:55 134
f8deb5b9 Poul Sander 2022-01-15 13:55 135
class utf8_system_category final : public std::error_category {
f8deb5b9 Poul Sander 2022-01-15 13:55 136
 public:
f8deb5b9 Poul Sander 2022-01-15 13:55 137
  const char* name() const FMT_NOEXCEPT override { return "system"; }
f8deb5b9 Poul Sander 2022-01-15 13:55 138
  std::string message(int error_code) const override {
f8deb5b9 Poul Sander 2022-01-15 13:55 139
    system_message msg(error_code);
f8deb5b9 Poul Sander 2022-01-15 13:55 140
    if (msg) {
f8deb5b9 Poul Sander 2022-01-15 13:55 141
      utf16_to_utf8 utf8_message;
f8deb5b9 Poul Sander 2022-01-15 13:55 142
      if (utf8_message.convert(msg) == ERROR_SUCCESS) {
f8deb5b9 Poul Sander 2022-01-15 13:55 143
        return utf8_message.str();
f8deb5b9 Poul Sander 2022-01-15 13:55 144
      }
f8deb5b9 Poul Sander 2022-01-15 13:55 145
    }
f8deb5b9 Poul Sander 2022-01-15 13:55 146
    return "unknown error";
f8deb5b9 Poul Sander 2022-01-15 13:55 147
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 148
};
f8deb5b9 Poul Sander 2022-01-15 13:55 149
f8deb5b9 Poul Sander 2022-01-15 13:55 150
}  // namespace detail
f8deb5b9 Poul Sander 2022-01-15 13:55 151
f8deb5b9 Poul Sander 2022-01-15 13:55 152
FMT_API const std::error_category& system_category() FMT_NOEXCEPT {
f8deb5b9 Poul Sander 2022-01-15 13:55 153
  static const detail::utf8_system_category category;
f8deb5b9 Poul Sander 2022-01-15 13:55 154
  return category;
f8deb5b9 Poul Sander 2022-01-15 13:55 155
}
f8deb5b9 Poul Sander 2022-01-15 13:55 156
f8deb5b9 Poul Sander 2022-01-15 13:55 157
std::system_error vwindows_error(int err_code, string_view format_str,
f8deb5b9 Poul Sander 2022-01-15 13:55 158
                                 format_args args) {
f8deb5b9 Poul Sander 2022-01-15 13:55 159
  auto ec = std::error_code(err_code, system_category());
f8deb5b9 Poul Sander 2022-01-15 13:55 160
  return std::system_error(ec, vformat(format_str, args));
f8deb5b9 Poul Sander 2022-01-15 13:55 161
}
f8deb5b9 Poul Sander 2022-01-15 13:55 162
f8deb5b9 Poul Sander 2022-01-15 13:55 163
void detail::format_windows_error(detail::buffer<char>& out, int error_code,
f8deb5b9 Poul Sander 2022-01-15 13:55 164
                                  const char* message) FMT_NOEXCEPT {
f8deb5b9 Poul Sander 2022-01-15 13:55 165
  FMT_TRY {
f8deb5b9 Poul Sander 2022-01-15 13:55 166
    system_message msg(error_code);
f8deb5b9 Poul Sander 2022-01-15 13:55 167
    if (msg) {
f8deb5b9 Poul Sander 2022-01-15 13:55 168
      utf16_to_utf8 utf8_message;
f8deb5b9 Poul Sander 2022-01-15 13:55 169
      if (utf8_message.convert(msg) == ERROR_SUCCESS) {
f8deb5b9 Poul Sander 2022-01-15 13:55 170
        format_to(buffer_appender<char>(out), "{}: {}", message, utf8_message);
f8deb5b9 Poul Sander 2022-01-15 13:55 171
        return;
f8deb5b9 Poul Sander 2022-01-15 13:55 172
      }
f8deb5b9 Poul Sander 2022-01-15 13:55 173
    }
f8deb5b9 Poul Sander 2022-01-15 13:55 174
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 175
  FMT_CATCH(...) {}
f8deb5b9 Poul Sander 2022-01-15 13:55 176
  format_error_code(out, error_code, message);
f8deb5b9 Poul Sander 2022-01-15 13:55 177
}
f8deb5b9 Poul Sander 2022-01-15 13:55 178
f8deb5b9 Poul Sander 2022-01-15 13:55 179
void report_windows_error(int error_code, const char* message) FMT_NOEXCEPT {
f8deb5b9 Poul Sander 2022-01-15 13:55 180
  report_error(detail::format_windows_error, error_code, message);
f8deb5b9 Poul Sander 2022-01-15 13:55 181
}
f8deb5b9 Poul Sander 2022-01-15 13:55 182
#endif  // _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 183
f8deb5b9 Poul Sander 2022-01-15 13:55 184
buffered_file::~buffered_file() FMT_NOEXCEPT {
f8deb5b9 Poul Sander 2022-01-15 13:55 185
  if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
f8deb5b9 Poul Sander 2022-01-15 13:55 186
    report_system_error(errno, "cannot close file");
f8deb5b9 Poul Sander 2022-01-15 13:55 187
}
f8deb5b9 Poul Sander 2022-01-15 13:55 188
f8deb5b9 Poul Sander 2022-01-15 13:55 189
buffered_file::buffered_file(cstring_view filename, cstring_view mode) {
f8deb5b9 Poul Sander 2022-01-15 13:55 190
  FMT_RETRY_VAL(file_, FMT_SYSTEM(fopen(filename.c_str(), mode.c_str())),
f8deb5b9 Poul Sander 2022-01-15 13:55 191
                nullptr);
f8deb5b9 Poul Sander 2022-01-15 13:55 192
  if (!file_)
f8deb5b9 Poul Sander 2022-01-15 13:55 193
    FMT_THROW(system_error(errno, "cannot open file {}", filename.c_str()));
f8deb5b9 Poul Sander 2022-01-15 13:55 194
}
f8deb5b9 Poul Sander 2022-01-15 13:55 195
f8deb5b9 Poul Sander 2022-01-15 13:55 196
void buffered_file::close() {
f8deb5b9 Poul Sander 2022-01-15 13:55 197
  if (!file_) return;
f8deb5b9 Poul Sander 2022-01-15 13:55 198
  int result = FMT_SYSTEM(fclose(file_));
f8deb5b9 Poul Sander 2022-01-15 13:55 199
  file_ = nullptr;
f8deb5b9 Poul Sander 2022-01-15 13:55 200
  if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
f8deb5b9 Poul Sander 2022-01-15 13:55 201
}
f8deb5b9 Poul Sander 2022-01-15 13:55 202
f8deb5b9 Poul Sander 2022-01-15 13:55 203
// A macro used to prevent expansion of fileno on broken versions of MinGW.
f8deb5b9 Poul Sander 2022-01-15 13:55 204
#define FMT_ARGS
f8deb5b9 Poul Sander 2022-01-15 13:55 205
f8deb5b9 Poul Sander 2022-01-15 13:55 206
int buffered_file::fileno() const {
f8deb5b9 Poul Sander 2022-01-15 13:55 207
  int fd = FMT_POSIX_CALL(fileno FMT_ARGS(file_));
f8deb5b9 Poul Sander 2022-01-15 13:55 208
  if (fd == -1) FMT_THROW(system_error(errno, "cannot get file descriptor"));
f8deb5b9 Poul Sander 2022-01-15 13:55 209
  return fd;
f8deb5b9 Poul Sander 2022-01-15 13:55 210
}
f8deb5b9 Poul Sander 2022-01-15 13:55 211
f8deb5b9 Poul Sander 2022-01-15 13:55 212
#if FMT_USE_FCNTL
f8deb5b9 Poul Sander 2022-01-15 13:55 213
file::file(cstring_view path, int oflag) {
f8deb5b9 Poul Sander 2022-01-15 13:55 214
#  ifdef _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 215
  using mode_t = int;
f8deb5b9 Poul Sander 2022-01-15 13:55 216
#  endif
f8deb5b9 Poul Sander 2022-01-15 13:55 217
  mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
f8deb5b9 Poul Sander 2022-01-15 13:55 218
#  if defined(_WIN32) && !defined(__MINGW32__)
f8deb5b9 Poul Sander 2022-01-15 13:55 219
  fd_ = -1;
f8deb5b9 Poul Sander 2022-01-15 13:55 220
  FMT_POSIX_CALL(sopen_s(&fd_, path.c_str(), oflag, _SH_DENYNO, mode));
f8deb5b9 Poul Sander 2022-01-15 13:55 221
#  else
f8deb5b9 Poul Sander 2022-01-15 13:55 222
  FMT_RETRY(fd_, FMT_POSIX_CALL(open(path.c_str(), oflag, mode)));
f8deb5b9 Poul Sander 2022-01-15 13:55 223
#  endif
f8deb5b9 Poul Sander 2022-01-15 13:55 224
  if (fd_ == -1)
f8deb5b9 Poul Sander 2022-01-15 13:55 225
    FMT_THROW(system_error(errno, "cannot open file {}", path.c_str()));
f8deb5b9 Poul Sander 2022-01-15 13:55 226
}
f8deb5b9 Poul Sander 2022-01-15 13:55 227
f8deb5b9 Poul Sander 2022-01-15 13:55 228
file::~file() FMT_NOEXCEPT {
f8deb5b9 Poul Sander 2022-01-15 13:55 229
  // Don't retry close in case of EINTR!
f8deb5b9 Poul Sander 2022-01-15 13:55 230
  // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
f8deb5b9 Poul Sander 2022-01-15 13:55 231
  if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
f8deb5b9 Poul Sander 2022-01-15 13:55 232
    report_system_error(errno, "cannot close file");
f8deb5b9 Poul Sander 2022-01-15 13:55 233
}
f8deb5b9 Poul Sander 2022-01-15 13:55 234
f8deb5b9 Poul Sander 2022-01-15 13:55 235
void file::close() {
f8deb5b9 Poul Sander 2022-01-15 13:55 236
  if (fd_ == -1) return;
f8deb5b9 Poul Sander 2022-01-15 13:55 237
  // Don't retry close in case of EINTR!
f8deb5b9 Poul Sander 2022-01-15 13:55 238
  // See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
f8deb5b9 Poul Sander 2022-01-15 13:55 239
  int result = FMT_POSIX_CALL(close(fd_));
f8deb5b9 Poul Sander 2022-01-15 13:55 240
  fd_ = -1;
f8deb5b9 Poul Sander 2022-01-15 13:55 241
  if (result != 0) FMT_THROW(system_error(errno, "cannot close file"));
f8deb5b9 Poul Sander 2022-01-15 13:55 242
}
f8deb5b9 Poul Sander 2022-01-15 13:55 243
f8deb5b9 Poul Sander 2022-01-15 13:55 244
long long file::size() const {
f8deb5b9 Poul Sander 2022-01-15 13:55 245
#  ifdef _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 246
  // Use GetFileSize instead of GetFileSizeEx for the case when _WIN32_WINNT
f8deb5b9 Poul Sander 2022-01-15 13:55 247
  // is less than 0x0500 as is the case with some default MinGW builds.
f8deb5b9 Poul Sander 2022-01-15 13:55 248
  // Both functions support large file sizes.
f8deb5b9 Poul Sander 2022-01-15 13:55 249
  DWORD size_upper = 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 250
  HANDLE handle = reinterpret_cast<HANDLE>(_get_osfhandle(fd_));
f8deb5b9 Poul Sander 2022-01-15 13:55 251
  DWORD size_lower = FMT_SYSTEM(GetFileSize(handle, &size_upper));
f8deb5b9 Poul Sander 2022-01-15 13:55 252
  if (size_lower == INVALID_FILE_SIZE) {
f8deb5b9 Poul Sander 2022-01-15 13:55 253
    DWORD error = GetLastError();
f8deb5b9 Poul Sander 2022-01-15 13:55 254
    if (error != NO_ERROR)
f8deb5b9 Poul Sander 2022-01-15 13:55 255
      FMT_THROW(windows_error(GetLastError(), "cannot get file size"));
f8deb5b9 Poul Sander 2022-01-15 13:55 256
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 257
  unsigned long long long_size = size_upper;
f8deb5b9 Poul Sander 2022-01-15 13:55 258
  return (long_size << sizeof(DWORD) * CHAR_BIT) | size_lower;
f8deb5b9 Poul Sander 2022-01-15 13:55 259
#  else
f8deb5b9 Poul Sander 2022-01-15 13:55 260
  using Stat = struct stat;
f8deb5b9 Poul Sander 2022-01-15 13:55 261
  Stat file_stat = Stat();
f8deb5b9 Poul Sander 2022-01-15 13:55 262
  if (FMT_POSIX_CALL(fstat(fd_, &file_stat)) == -1)
f8deb5b9 Poul Sander 2022-01-15 13:55 263
    FMT_THROW(system_error(errno, "cannot get file attributes"));
f8deb5b9 Poul Sander 2022-01-15 13:55 264
  static_assert(sizeof(long long) >= sizeof(file_stat.st_size),
f8deb5b9 Poul Sander 2022-01-15 13:55 265
                "return type of file::size is not large enough");
f8deb5b9 Poul Sander 2022-01-15 13:55 266
  return file_stat.st_size;
f8deb5b9 Poul Sander 2022-01-15 13:55 267
#  endif
f8deb5b9 Poul Sander 2022-01-15 13:55 268
}
f8deb5b9 Poul Sander 2022-01-15 13:55 269
f8deb5b9 Poul Sander 2022-01-15 13:55 270
std::size_t file::read(void* buffer, std::size_t count) {
f8deb5b9 Poul Sander 2022-01-15 13:55 271
  rwresult result = 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 272
  FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count))));
f8deb5b9 Poul Sander 2022-01-15 13:55 273
  if (result < 0) FMT_THROW(system_error(errno, "cannot read from file"));
f8deb5b9 Poul Sander 2022-01-15 13:55 274
  return detail::to_unsigned(result);
f8deb5b9 Poul Sander 2022-01-15 13:55 275
}
f8deb5b9 Poul Sander 2022-01-15 13:55 276
f8deb5b9 Poul Sander 2022-01-15 13:55 277
std::size_t file::write(const void* buffer, std::size_t count) {
f8deb5b9 Poul Sander 2022-01-15 13:55 278
  rwresult result = 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 279
  FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count))));
f8deb5b9 Poul Sander 2022-01-15 13:55 280
  if (result < 0) FMT_THROW(system_error(errno, "cannot write to file"));
f8deb5b9 Poul Sander 2022-01-15 13:55 281
  return detail::to_unsigned(result);
f8deb5b9 Poul Sander 2022-01-15 13:55 282
}
f8deb5b9 Poul Sander 2022-01-15 13:55 283
f8deb5b9 Poul Sander 2022-01-15 13:55 284
file file::dup(int fd) {
f8deb5b9 Poul Sander 2022-01-15 13:55 285
  // Don't retry as dup doesn't return EINTR.
f8deb5b9 Poul Sander 2022-01-15 13:55 286
  // http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
f8deb5b9 Poul Sander 2022-01-15 13:55 287
  int new_fd = FMT_POSIX_CALL(dup(fd));
f8deb5b9 Poul Sander 2022-01-15 13:55 288
  if (new_fd == -1)
f8deb5b9 Poul Sander 2022-01-15 13:55 289
    FMT_THROW(system_error(errno, "cannot duplicate file descriptor {}", fd));
f8deb5b9 Poul Sander 2022-01-15 13:55 290
  return file(new_fd);
f8deb5b9 Poul Sander 2022-01-15 13:55 291
}
f8deb5b9 Poul Sander 2022-01-15 13:55 292
f8deb5b9 Poul Sander 2022-01-15 13:55 293
void file::dup2(int fd) {
f8deb5b9 Poul Sander 2022-01-15 13:55 294
  int result = 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 295
  FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
f8deb5b9 Poul Sander 2022-01-15 13:55 296
  if (result == -1) {
f8deb5b9 Poul Sander 2022-01-15 13:55 297
    FMT_THROW(system_error(errno, "cannot duplicate file descriptor {} to {}",
f8deb5b9 Poul Sander 2022-01-15 13:55 298
                           fd_, fd));
f8deb5b9 Poul Sander 2022-01-15 13:55 299
  }
f8deb5b9 Poul Sander 2022-01-15 13:55 300
}
f8deb5b9 Poul Sander 2022-01-15 13:55 301
f8deb5b9 Poul Sander 2022-01-15 13:55 302
void file::dup2(int fd, std::error_code& ec) FMT_NOEXCEPT {
f8deb5b9 Poul Sander 2022-01-15 13:55 303
  int result = 0;
f8deb5b9 Poul Sander 2022-01-15 13:55 304
  FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
f8deb5b9 Poul Sander 2022-01-15 13:55 305
  if (result == -1) ec = std::error_code(errno, std::generic_category());
f8deb5b9 Poul Sander 2022-01-15 13:55 306
}
f8deb5b9 Poul Sander 2022-01-15 13:55 307
f8deb5b9 Poul Sander 2022-01-15 13:55 308
void file::pipe(file& read_end, file& write_end) {
f8deb5b9 Poul Sander 2022-01-15 13:55 309
  // Close the descriptors first to make sure that assignments don't throw
f8deb5b9 Poul Sander 2022-01-15 13:55 310
  // and there are no leaks.
f8deb5b9 Poul Sander 2022-01-15 13:55 311
  read_end.close();
f8deb5b9 Poul Sander 2022-01-15 13:55 312
  write_end.close();
f8deb5b9 Poul Sander 2022-01-15 13:55 313
  int fds[2] = {};
f8deb5b9 Poul Sander 2022-01-15 13:55 314
#  ifdef _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 315
  // Make the default pipe capacity same as on Linux 2.6.11+.
f8deb5b9 Poul Sander 2022-01-15 13:55 316
  enum { DEFAULT_CAPACITY = 65536 };
f8deb5b9 Poul Sander 2022-01-15 13:55 317
  int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
f8deb5b9 Poul Sander 2022-01-15 13:55 318
#  else
f8deb5b9 Poul Sander 2022-01-15 13:55 319
  // Don't retry as the pipe function doesn't return EINTR.
f8deb5b9 Poul Sander 2022-01-15 13:55 320
  // http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
f8deb5b9 Poul Sander 2022-01-15 13:55 321
  int result = FMT_POSIX_CALL(pipe(fds));
f8deb5b9 Poul Sander 2022-01-15 13:55 322
#  endif
f8deb5b9 Poul Sander 2022-01-15 13:55 323
  if (result != 0) FMT_THROW(system_error(errno, "cannot create pipe"));
f8deb5b9 Poul Sander 2022-01-15 13:55 324
  // The following assignments don't throw because read_fd and write_fd
f8deb5b9 Poul Sander 2022-01-15 13:55 325
  // are closed.
f8deb5b9 Poul Sander 2022-01-15 13:55 326
  read_end = file(fds[0]);
f8deb5b9 Poul Sander 2022-01-15 13:55 327
  write_end = file(fds[1]);
f8deb5b9 Poul Sander 2022-01-15 13:55 328
}
f8deb5b9 Poul Sander 2022-01-15 13:55 329
f8deb5b9 Poul Sander 2022-01-15 13:55 330
buffered_file file::fdopen(const char* mode) {
f8deb5b9 Poul Sander 2022-01-15 13:55 331
// Don't retry as fdopen doesn't return EINTR.
f8deb5b9 Poul Sander 2022-01-15 13:55 332
#  if defined(__MINGW32__) && defined(_POSIX_)
f8deb5b9 Poul Sander 2022-01-15 13:55 333
  FILE* f = ::fdopen(fd_, mode);
f8deb5b9 Poul Sander 2022-01-15 13:55 334
#  else
f8deb5b9 Poul Sander 2022-01-15 13:55 335
  FILE* f = FMT_POSIX_CALL(fdopen(fd_, mode));
f8deb5b9 Poul Sander 2022-01-15 13:55 336
#  endif
f8deb5b9 Poul Sander 2022-01-15 13:55 337
  if (!f)
f8deb5b9 Poul Sander 2022-01-15 13:55 338
    FMT_THROW(
f8deb5b9 Poul Sander 2022-01-15 13:55 339
        system_error(errno, "cannot associate stream with file descriptor"));
f8deb5b9 Poul Sander 2022-01-15 13:55 340
  buffered_file bf(f);
f8deb5b9 Poul Sander 2022-01-15 13:55 341
  fd_ = -1;
f8deb5b9 Poul Sander 2022-01-15 13:55 342
  return bf;
f8deb5b9 Poul Sander 2022-01-15 13:55 343
}
f8deb5b9 Poul Sander 2022-01-15 13:55 344
f8deb5b9 Poul Sander 2022-01-15 13:55 345
long getpagesize() {
f8deb5b9 Poul Sander 2022-01-15 13:55 346
#  ifdef _WIN32
f8deb5b9 Poul Sander 2022-01-15 13:55 347
  SYSTEM_INFO si;
f8deb5b9 Poul Sander 2022-01-15 13:55 348
  GetSystemInfo(&si);
f8deb5b9 Poul Sander 2022-01-15 13:55 349
  return si.dwPageSize;
f8deb5b9 Poul Sander 2022-01-15 13:55 350
#  else
f8deb5b9 Poul Sander 2022-01-15 13:55 351
  long size = FMT_POSIX_CALL(sysconf(_SC_PAGESIZE));
f8deb5b9 Poul Sander 2022-01-15 13:55 352
  if (size < 0) FMT_THROW(system_error(errno, "cannot get memory page size"));
f8deb5b9 Poul Sander 2022-01-15 13:55 353
  return size;
f8deb5b9 Poul Sander 2022-01-15 13:55 354
#  endif
f8deb5b9 Poul Sander 2022-01-15 13:55 355
}
f8deb5b9 Poul Sander 2022-01-15 13:55 356
f8deb5b9 Poul Sander 2022-01-15 13:55 357
FMT_API void ostream::grow(size_t) {
f8deb5b9 Poul Sander 2022-01-15 13:55 358
  if (this->size() == this->capacity()) flush();
f8deb5b9 Poul Sander 2022-01-15 13:55 359
}
f8deb5b9 Poul Sander 2022-01-15 13:55 360
#endif  // FMT_USE_FCNTL
f8deb5b9 Poul Sander 2022-01-15 13:55 361
FMT_END_NAMESPACE
1970-01-01 00:00 362