brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · db5d1ae Raw
157 lines · c
1//===----------------------------------------------------------------------===////2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===////8 9#ifndef FILESYSTEM_ERROR_H10#define FILESYSTEM_ERROR_H11 12#include <__assert>13#include <__chrono/time_point.h>14#include <__config>15#include <cerrno>16#include <cstdarg>17#include <cstddef>18#include <cstdint>19#include <filesystem>20#include <string>21#include <system_error>22#include <utility> // __libcpp_unreachable23 24#include "format_string.h"25 26#if defined(_LIBCPP_WIN32API)27#  define WIN32_LEAN_AND_MEAN28#  define NOMINMAX29#  include <windows.h> // ERROR_* macros30#endif31 32_LIBCPP_BEGIN_NAMESPACE_FILESYSTEM33 34namespace detail {35 36// On windows, libc functions use errno, but system functions use GetLastError.37// So, callers need to be careful which of these next functions they call!38 39inline error_code capture_errno() {40  _LIBCPP_ASSERT_INTERNAL(errno != 0, "Expected errno to be non-zero");41  return error_code(errno, generic_category());42}43 44inline error_code get_last_error() {45#if defined(_LIBCPP_WIN32API)46  return std::error_code(GetLastError(), std::system_category());47#else48  return capture_errno();49#endif50}51 52template <class T>53T error_value();54template <>55inline constexpr void error_value<void>() {}56template <>57inline bool error_value<bool>() {58  return false;59}60#if __SIZEOF_SIZE_T__ != __SIZEOF_LONG_LONG__61template <>62inline size_t error_value<size_t>() {63  return size_t(-1);64}65#endif66template <>67inline uintmax_t error_value<uintmax_t>() {68  return uintmax_t(-1);69}70template <>71inline constexpr file_time_type error_value<file_time_type>() {72  return file_time_type::min();73}74template <>75inline path error_value<path>() {76  return {};77}78 79template <class T>80struct ErrorHandler {81  const char* func_name_;82  error_code* ec_ = nullptr;83  const path* p1_ = nullptr;84  const path* p2_ = nullptr;85 86  ErrorHandler(const char* fname, error_code* ec, const path* p1 = nullptr, const path* p2 = nullptr)87      : func_name_(fname), ec_(ec), p1_(p1), p2_(p2) {88    if (ec_)89      ec_->clear();90  }91 92  T report(const error_code& ec) const {93    if (ec_) {94      *ec_ = ec;95      return error_value<T>();96    }97    string what = string("in ") + func_name_;98    switch (bool(p1_) + bool(p2_)) {99    case 0:100      filesystem::__throw_filesystem_error(what, ec);101    case 1:102      filesystem::__throw_filesystem_error(what, *p1_, ec);103    case 2:104      filesystem::__throw_filesystem_error(what, *p1_, *p2_, ec);105    }106    __libcpp_unreachable();107  }108 109  _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 0)110  void report_impl(const error_code& ec, const char* msg, va_list ap) const {111    if (ec_) {112      *ec_ = ec;113      return;114    }115    string what = string("in ") + func_name_ + ": " + detail::vformat_string(msg, ap);116    switch (bool(p1_) + bool(p2_)) {117    case 0:118      filesystem::__throw_filesystem_error(what, ec);119    case 1:120      filesystem::__throw_filesystem_error(what, *p1_, ec);121    case 2:122      filesystem::__throw_filesystem_error(what, *p1_, *p2_, ec);123    }124    __libcpp_unreachable();125  }126 127  _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4)128  T report(const error_code& ec, const char* msg, ...) const {129    va_list ap;130    va_start(ap, msg);131    __scope_guard guard([&] { va_end(ap); });132    report_impl(ec, msg, ap);133    return error_value<T>();134  }135 136  T report(errc const& err) const { return report(make_error_code(err)); }137 138  _LIBCPP_ATTRIBUTE_FORMAT(__printf__, 3, 4)139  T report(errc const& err, const char* msg, ...) const {140    va_list ap;141    va_start(ap, msg);142    __scope_guard guard([&] { va_end(ap); });143    report_impl(make_error_code(err), msg, ap);144    return error_value<T>();145  }146 147private:148  ErrorHandler(ErrorHandler const&)            = delete;149  ErrorHandler& operator=(ErrorHandler const&) = delete;150};151 152} // namespace detail153 154_LIBCPP_END_NAMESPACE_FILESYSTEM155 156#endif // FILESYSTEM_ERROR_H157