Add a portable thread-safe version of strerror.

This commit is contained in:
Victor Zverovich 2014-04-30 09:42:48 -07:00
parent 5019b6b0f4
commit 2c6372d790
3 changed files with 46 additions and 1 deletions

View File

@ -248,6 +248,22 @@ TEST(UtilTest, UTF8ToUTF16) {
// TODO: test UTF16ToUTF8::Convert
#endif // _WIN32
TEST(UtilTest, StrError) {
using fmt::internal::StrError;
EXPECT_DEBUG_DEATH(StrError(EDOM, 0, 0), "Assertion");
char buffer[BUFFER_SIZE];
EXPECT_DEBUG_DEATH(StrError(EDOM, buffer, 0), "Assertion");
buffer[0] = 'x';
const char *message = StrError(-1, buffer, 1);
EXPECT_EQ(ERANGE, errno);
EXPECT_STREQ("", message);
message = StrError(-1, buffer, BUFFER_SIZE);
EXPECT_EQ(0, errno);
EXPECT_GE(BUFFER_SIZE - 1, std::strlen(message));
message = StrError(-1, buffer, std::strlen(message));
EXPECT_EQ(ERANGE, errno);
}
class TestString {
private:
std::string value_;

View File

@ -204,6 +204,26 @@ int fmt::internal::UTF16ToUTF8::Convert(fmt::WStringRef s) {
#endif
char *fmt::internal::StrError(
int error_code, char *buffer, std::size_t buffer_size) {
assert(buffer != 0 && buffer_size != 0);
errno = 0;
#ifdef _GNU_SOURCE
char *message = strerror_r(error_code, buffer, buffer_size);
if (message == buffer && strlen(buffer) == buffer_size - 1)
errno = ERANGE; // The buffer is full so the message is probably truncated.
return message;
#elif _WIN32
errno = strerror_s(buffer, buflen, error_code);
if (errno == 0 && std::strlen(buffer) == buffer_size - 1)
errno = ERANGE; // The buffer is full so the message is probably truncated.
return buffer;
#else
strerror_r(error_code, buffer, buffer_size);
return buffer;
#endif
}
void fmt::internal::FormatSystemErrorMessage(
fmt::Writer &out, int error_code, fmt::StringRef message) {
#ifndef _WIN32

View File

@ -489,6 +489,16 @@ class UTF16ToUTF8 {
};
#endif
// Portable thread-safe version of strerror.
// Returns a pointer to a string describing the error code. This can be
// either a pointer to a string stored in buffer, or a pointer to some
// static immutable string. Sets errno to one of the following values:
// 0 - success
// ERANGE - buffer is not large enough to store the error message
// other - failure
// Buffer should be at least of size 1.
char *StrError(int error_code, char *buffer, std::size_t buffer_size);
// Formats a system error message writing the output to out.
void FormatSystemErrorMessage(Writer &out, int error_code, StringRef message);
@ -1521,7 +1531,6 @@ inline Formatter<NullSink, wchar_t> Format(WStringRef format) {
return f;
}
/**
A sink that gets the system error message corresponding to the error code
and throws SystemError.