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