Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Carter Li 2015-03-15 09:23:19 +08:00
commit c97c0fbbc9

View File

@ -99,6 +99,15 @@ using fmt::internal::Arg;
# pragma warning(disable: 4702) // unreachable code # pragma warning(disable: 4702) // unreachable code
#endif #endif
// Dummy implementations of strerror_r and strerror_s called if corresponding
// system functions are not available.
static fmt::internal::None<void> strerror_r(int, char *, ...) {
return fmt::internal::None<void>();
}
static fmt::internal::None<void> strerror_s(char *, std::size_t, ...) {
return fmt::internal::None<void>();
}
namespace { namespace {
#ifndef _MSC_VER #ifndef _MSC_VER
@ -155,35 +164,55 @@ typedef void (*FormatFunc)(fmt::Writer &, int, fmt::StringRef);
int safe_strerror( int safe_strerror(
int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT { int error_code, char *&buffer, std::size_t buffer_size) FMT_NOEXCEPT {
assert(buffer != 0 && buffer_size != 0); assert(buffer != 0 && buffer_size != 0);
int result = 0;
#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE) || __ANDROID__ // strerror result handler.
// XSI-compliant version of strerror_r. class StrError {
result = strerror_r(error_code, buffer, buffer_size); private:
if (result != 0) int error_code_;
result = errno; char *&buffer_;
#elif _GNU_SOURCE std::size_t buffer_size_;
// GNU-specific version of strerror_r.
char *message = strerror_r(error_code, buffer, buffer_size); // Handle the result of XSI-compliant version of strerror_r.
// If the buffer is full then the message is probably truncated. int handle(int result) {
if (message == buffer && strlen(buffer) == buffer_size - 1) // glibc versions before 2.13 return result in errno.
result = ERANGE; return result == -1 ? errno : result;
buffer = message; }
#elif __MINGW32__
errno = 0; // Handle the result of GNU-specific version of strerror_r.
(void)buffer_size; int handle(char *message) {
buffer = strerror(error_code); // If the buffer is full then the message is probably truncated.
result = errno; if (message == buffer_ && strlen(buffer_) == buffer_size_ - 1)
#elif _WIN32 return ERANGE;
result = strerror_s(buffer, buffer_size, error_code); buffer_ = message;
// If the buffer is full then the message is probably truncated. return 0;
if (result == 0 && std::strlen(buffer) == buffer_size - 1) }
result = ERANGE;
#else // Handle the case when strerror_r is not available.
result = strerror_r(error_code, buffer, buffer_size); int handle(fmt::internal::None<void>) {
if (result == -1) return fallback(strerror_s(buffer_, buffer_size_, error_code_));
result = errno; // glibc versions before 2.13 return result in errno. }
#endif
return result; // Fallback to strerror_s when strerror_r is not available.
int fallback(int result) {
// If the buffer is full then the message is probably truncated.
return result == 0 && strlen(buffer_) == buffer_size_ - 1 ?
ERANGE : result;
}
// Fallback to strerror if strerror_r and strerror_s are not available.
int fallback(fmt::internal::None<void>) {
errno = 0;
buffer_ = strerror(error_code_);
return errno;
}
public:
StrError(int error_code, char *&buffer, std::size_t buffer_size)
: error_code_(error_code), buffer_(buffer), buffer_size_(buffer_size) {}
int run() { return handle(strerror_r(error_code_, buffer_, buffer_size_)); }
};
return StrError(error_code, buffer, buffer_size).run();
} }
void format_error_code(fmt::Writer &out, int error_code, void format_error_code(fmt::Writer &out, int error_code,