summaryrefslogtreecommitdiff
path: root/absl/base/internal/strerror.cc
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2020-09-03 12:54:45 -0700
committerGravatar Derek Mauro <dmauro@google.com>2020-09-04 12:59:29 -0400
commit7ba8cdb56df3bf4fe4ab4606f3fe4b2ab825afac (patch)
tree058d9db0e1acfd979929ab48e9bfe9e802c94741 /absl/base/internal/strerror.cc
parent930fbec75b452af8bb8c796f5bb754e953e29cf5 (diff)
Export of internal Abseil changes
-- 8ae3cb636b81b6498ef30fbe59cc102a4098cad2 by Tom Manshreck <shreck@google.com>: Upgrade absl::StatusOr<T> docs to Abseil standards PiperOrigin-RevId: 329975341 -- 7c7baf586c7380497a751f1a186a4ef0e650161a by Tom Manshreck <shreck@google.com>: Update absl::Status to Abseil documentation standards PiperOrigin-RevId: 329942967 -- 6710d022ba987dbae7a5d83045a6697afeb972c4 by Derek Mauro <dmauro@google.com>: Internal change PiperOrigin-RevId: 329775111 -- fd182dc699e18522ef16d269731c57669c5487d2 by Abseil Team <absl-team@google.com>: Google-internal change. PiperOrigin-RevId: 329737362 -- c0df5e27ffb48d9c784e7019267580fcb4a3f92e by Xiaoyi Zhang <zhangxy@google.com>: Remove obsolete `static_assert`. PiperOrigin-RevId: 329727604 GitOrigin-RevId: 8ae3cb636b81b6498ef30fbe59cc102a4098cad2 Change-Id: Ic9dede0ab97f799e7f4093fae75ae0ec6cc21437
Diffstat (limited to 'absl/base/internal/strerror.cc')
-rw-r--r--absl/base/internal/strerror.cc37
1 files changed, 25 insertions, 12 deletions
diff --git a/absl/base/internal/strerror.cc b/absl/base/internal/strerror.cc
index af181513..d66ba120 100644
--- a/absl/base/internal/strerror.cc
+++ b/absl/base/internal/strerror.cc
@@ -14,6 +14,7 @@
#include "absl/base/internal/strerror.h"
+#include <array>
#include <cerrno>
#include <cstddef>
#include <cstdio>
@@ -21,13 +22,13 @@
#include <string>
#include <type_traits>
-#include "absl/base/attributes.h"
#include "absl/base/internal/errno_saver.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace base_internal {
namespace {
+
const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
#if defined(_WIN32)
int rc = strerror_s(buf, buflen, errnum);
@@ -35,15 +36,6 @@ const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
if (rc == 0 && strncmp(buf, "Unknown error", buflen) == 0) *buf = '\0';
return buf;
#else
-#if defined(__GLIBC__) || defined(__APPLE__)
- // Use the BSD sys_errlist API provided by GNU glibc and others to
- // avoid any need to copy the message into the local buffer first.
- if (0 <= errnum && errnum < sys_nerr) {
- if (const char* p = sys_errlist[errnum]) {
- return p;
- }
- }
-#endif
// The type of `ret` is platform-specific; both of these branches must compile
// either way but only one will execute on any given platform:
auto ret = strerror_r(errnum, buf, buflen);
@@ -57,9 +49,8 @@ const char* StrErrorAdaptor(int errnum, char* buf, size_t buflen) {
}
#endif
}
-} // namespace
-std::string StrError(int errnum) {
+std::string StrErrorInternal(int errnum) {
absl::base_internal::ErrnoSaver errno_saver;
char buf[100];
const char* str = StrErrorAdaptor(errnum, buf, sizeof buf);
@@ -70,6 +61,28 @@ std::string StrError(int errnum) {
return str;
}
+// kSysNerr is the number of errors from a recent glibc. `StrError()` falls back
+// to `StrErrorAdaptor()` if the value is larger than this.
+constexpr int kSysNerr = 135;
+
+std::array<std::string, kSysNerr>* NewStrErrorTable() {
+ auto* table = new std::array<std::string, kSysNerr>;
+ for (int i = 0; i < static_cast<int>(table->size()); ++i) {
+ (*table)[i] = StrErrorInternal(i);
+ }
+ return table;
+}
+
+} // namespace
+
+std::string StrError(int errnum) {
+ static const auto* table = NewStrErrorTable();
+ if (errnum >= 0 && errnum < static_cast<int>(table->size())) {
+ return (*table)[errnum];
+ }
+ return StrErrorInternal(errnum);
+}
+
} // namespace base_internal
ABSL_NAMESPACE_END
} // namespace absl