Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'libc/src/__support/StringUtil/error_to_string.cpp')
-rw-r--r--libc/src/__support/StringUtil/error_to_string.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/libc/src/__support/StringUtil/error_to_string.cpp b/libc/src/__support/StringUtil/error_to_string.cpp
new file mode 100644
index 000000000000..98e2fbdee82c
--- /dev/null
+++ b/libc/src/__support/StringUtil/error_to_string.cpp
@@ -0,0 +1,216 @@
+//===-- Implementation of a class for mapping errors to strings -----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/__support/StringUtil/error_to_string.h"
+
+#include "src/__support/CPP/span.h"
+#include "src/__support/CPP/string_view.h"
+#include "src/__support/CPP/stringstream.h"
+#include "src/__support/StringUtil/message_mapper.h"
+#include "src/__support/integer_to_string.h"
+
+#include <errno.h>
+#include <stddef.h>
+
+namespace __llvm_libc {
+namespace internal {
+
+constexpr size_t max_buff_size() {
+ constexpr size_t unknown_str_len = sizeof("Unknown error");
+ constexpr size_t max_num_len =
+ __llvm_libc::IntegerToString::dec_bufsize<int>();
+ // the buffer should be able to hold "Unknown error" + ' ' + num_str
+ return (unknown_str_len + 1 + max_num_len) * sizeof(char);
+}
+
+// This is to hold error strings that have to be custom built. It may be
+// rewritten on every call to strerror (or other error to string function).
+constexpr size_t ERR_BUFFER_SIZE = max_buff_size();
+thread_local char error_buffer[ERR_BUFFER_SIZE];
+
+// Since the StringMappings array is a map from error numbers to their
+// corresponding strings, we have to have an array large enough we can use the
+// error numbers as indexes. Thankfully there are 132 errors in the above list
+// (41 and 58 are skipped) and the highest number is 133. If other platforms use
+// different error numbers, then this number may need to be adjusted.
+// Also if negative numbers or particularly large numbers are used, then the
+// array should be turned into a proper hashmap.
+constexpr size_t ERR_ARRAY_SIZE = 134;
+
+constexpr MsgMapping raw_err_array[] = {
+ MsgMapping(0, "Success"),
+ MsgMapping(EPERM, "Operation not permitted"),
+ MsgMapping(ENOENT, "No such file or directory"),
+ MsgMapping(ESRCH, "No such process"),
+ MsgMapping(EINTR, "Interrupted system call"),
+ MsgMapping(EIO, "Input/output error"),
+ MsgMapping(ENXIO, "No such device or address"),
+ MsgMapping(E2BIG, "Argument list too long"),
+ MsgMapping(ENOEXEC, "Exec format error"),
+ MsgMapping(EBADF, "Bad file descriptor"),
+ MsgMapping(ECHILD, "No child processes"),
+ MsgMapping(EAGAIN, "Resource temporarily unavailable"),
+ MsgMapping(ENOMEM, "Cannot allocate memory"),
+ MsgMapping(EACCES, "Permission denied"),
+ MsgMapping(EFAULT, "Bad address"),
+ MsgMapping(ENOTBLK, "Block device required"),
+ MsgMapping(EBUSY, "Device or resource busy"),
+ MsgMapping(EEXIST, "File exists"),
+ MsgMapping(EXDEV, "Invalid cross-device link"),
+ MsgMapping(ENODEV, "No such device"),
+ MsgMapping(ENOTDIR, "Not a directory"),
+ MsgMapping(EISDIR, "Is a directory"),
+ MsgMapping(EINVAL, "Invalid argument"),
+ MsgMapping(ENFILE, "Too many open files in system"),
+ MsgMapping(EMFILE, "Too many open files"),
+ MsgMapping(ENOTTY, "Inappropriate ioctl for device"),
+ MsgMapping(ETXTBSY, "Text file busy"),
+ MsgMapping(EFBIG, "File too large"),
+ MsgMapping(ENOSPC, "No space left on device"),
+ MsgMapping(ESPIPE, "Illegal seek"),
+ MsgMapping(EROFS, "Read-only file system"),
+ MsgMapping(EMLINK, "Too many links"),
+ MsgMapping(EPIPE, "Broken pipe"),
+ MsgMapping(EDOM, "Numerical argument out of domain"),
+ MsgMapping(ERANGE, "Numerical result out of range"),
+ MsgMapping(EDEADLK, "Resource deadlock avoided"),
+ MsgMapping(ENAMETOOLONG, "File name too long"),
+ MsgMapping(ENOLCK, "No locks available"),
+ MsgMapping(ENOSYS, "Function not implemented"),
+ MsgMapping(ENOTEMPTY, "Directory not empty"),
+ MsgMapping(ELOOP, "Too many levels of symbolic links"),
+ // No error for 41. Would be EWOULDBLOCK
+ MsgMapping(ENOMSG, "No message of desired type"),
+ MsgMapping(EIDRM, "Identifier removed"),
+ MsgMapping(ECHRNG, "Channel number out of range"),
+ MsgMapping(EL2NSYNC, "Level 2 not synchronized"),
+ MsgMapping(EL3HLT, "Level 3 halted"),
+ MsgMapping(EL3RST, "Level 3 reset"),
+ MsgMapping(ELNRNG, "Link number out of range"),
+ MsgMapping(EUNATCH, "Protocol driver not attached"),
+ MsgMapping(ENOCSI, "No CSI structure available"),
+ MsgMapping(EL2HLT, "Level 2 halted"),
+ MsgMapping(EBADE, "Invalid exchange"),
+ MsgMapping(EBADR, "Invalid request descriptor"),
+ MsgMapping(EXFULL, "Exchange full"),
+ MsgMapping(ENOANO, "No anode"),
+ MsgMapping(EBADRQC, "Invalid request code"),
+ MsgMapping(EBADSLT, "Invalid slot"),
+ // No error for 58. Would be EDEADLOCK.
+ MsgMapping(EBFONT, "Bad font file format"),
+ MsgMapping(ENOSTR, "Device not a stream"),
+ MsgMapping(ENODATA, "No data available"),
+ MsgMapping(ETIME, "Timer expired"),
+ MsgMapping(ENOSR, "Out of streams resources"),
+ MsgMapping(ENONET, "Machine is not on the network"),
+ MsgMapping(ENOPKG, "Package not installed"),
+ MsgMapping(EREMOTE, "Object is remote"),
+ MsgMapping(ENOLINK, "Link has been severed"),
+ MsgMapping(EADV, "Advertise error"),
+ MsgMapping(ESRMNT, "Srmount error"),
+ MsgMapping(ECOMM, "Communication error on send"),
+ MsgMapping(EPROTO, "Protocol error"),
+ MsgMapping(EMULTIHOP, "Multihop attempted"),
+ MsgMapping(EDOTDOT, "RFS specific error"),
+ MsgMapping(EBADMSG, "Bad message"),
+ MsgMapping(EOVERFLOW, "Value too large for defined data type"),
+ MsgMapping(ENOTUNIQ, "Name not unique on network"),
+ MsgMapping(EBADFD, "File descriptor in bad state"),
+ MsgMapping(EREMCHG, "Remote address changed"),
+ MsgMapping(ELIBACC, "Can not access a needed shared library"),
+ MsgMapping(ELIBBAD, "Accessing a corrupted shared library"),
+ MsgMapping(ELIBSCN, ".lib section in a.out corrupted"),
+ MsgMapping(ELIBMAX, "Attempting to link in too many shared libraries"),
+ MsgMapping(ELIBEXEC, "Cannot exec a shared library directly"),
+ MsgMapping(EILSEQ, "Invalid or incomplete multibyte or wide character"),
+ MsgMapping(ERESTART, "Interrupted system call should be restarted"),
+ MsgMapping(ESTRPIPE, "Streams pipe error"),
+ MsgMapping(EUSERS, "Too many users"),
+ MsgMapping(ENOTSOCK, "Socket operation on non-socket"),
+ MsgMapping(EDESTADDRREQ, "Destination address required"),
+ MsgMapping(EMSGSIZE, "Message too long"),
+ MsgMapping(EPROTOTYPE, "Protocol wrong type for socket"),
+ MsgMapping(ENOPROTOOPT, "Protocol not available"),
+ MsgMapping(EPROTONOSUPPORT, "Protocol not supported"),
+ MsgMapping(ESOCKTNOSUPPORT, "Socket type not supported"),
+ MsgMapping(ENOTSUP, "Operation not supported"),
+ MsgMapping(EPFNOSUPPORT, "Protocol family not supported"),
+ MsgMapping(EAFNOSUPPORT, "Address family not supported by protocol"),
+ MsgMapping(EADDRINUSE, "Address already in use"),
+ MsgMapping(EADDRNOTAVAIL, "Cannot assign requested address"),
+ MsgMapping(ENETDOWN, "Network is down"),
+ MsgMapping(ENETUNREACH, "Network is unreachable"),
+ MsgMapping(ENETRESET, "Network dropped connection on reset"),
+ MsgMapping(ECONNABORTED, "Software caused connection abort"),
+ MsgMapping(ECONNRESET, "Connection reset by peer"),
+ MsgMapping(ENOBUFS, "No buffer space available"),
+ MsgMapping(EISCONN, "Transport endpoint is already connected"),
+ MsgMapping(ENOTCONN, "Transport endpoint is not connected"),
+ MsgMapping(ESHUTDOWN, "Cannot send after transport endpoint shutdown"),
+ MsgMapping(ETOOMANYREFS, "Too many references: cannot splice"),
+ MsgMapping(ETIMEDOUT, "Connection timed out"),
+ MsgMapping(ECONNREFUSED, "Connection refused"),
+ MsgMapping(EHOSTDOWN, "Host is down"),
+ MsgMapping(EHOSTUNREACH, "No route to host"),
+ MsgMapping(EALREADY, "Operation already in progress"),
+ MsgMapping(EINPROGRESS, "Operation now in progress"),
+ MsgMapping(ESTALE, "Stale file handle"),
+ MsgMapping(EUCLEAN, "Structure needs cleaning"),
+ MsgMapping(ENOTNAM, "Not a XENIX named type file"),
+ MsgMapping(ENAVAIL, "No XENIX semaphores available"),
+ MsgMapping(EISNAM, "Is a named type file"),
+ MsgMapping(EREMOTEIO, "Remote I/O error"),
+ MsgMapping(EDQUOT, "Disk quota exceeded"),
+ MsgMapping(ENOMEDIUM, "No medium found"),
+ MsgMapping(EMEDIUMTYPE, "Wrong medium type"),
+ MsgMapping(ECANCELED, "Operation canceled"),
+ MsgMapping(ENOKEY, "Required key not available"),
+ MsgMapping(EKEYEXPIRED, "Key has expired"),
+ MsgMapping(EKEYREVOKED, "Key has been revoked"),
+ MsgMapping(EKEYREJECTED, "Key was rejected by service"),
+ MsgMapping(EOWNERDEAD, "Owner died"),
+ MsgMapping(ENOTRECOVERABLE, "State not recoverable"),
+ MsgMapping(ERFKILL, "Operation not possible due to RF-kill"),
+ MsgMapping(EHWPOISON, "Memory page has hardware error"),
+};
+
+constexpr size_t RAW_ARRAY_LEN = sizeof(raw_err_array) / sizeof(MsgMapping);
+constexpr size_t TOTAL_STR_LEN = total_str_len(raw_err_array, RAW_ARRAY_LEN);
+
+static constexpr MessageMapper<ERR_ARRAY_SIZE, TOTAL_STR_LEN>
+ error_mapper(raw_err_array, RAW_ARRAY_LEN);
+
+cpp::string_view build_error_string(int err_num, cpp::span<char> buffer) {
+ // if the buffer can't hold "Unknown error" + ' ' + num_str, then just
+ // return "Unknown error".
+ if (buffer.size() <
+ (sizeof("Unknown error") + 1 + IntegerToString::dec_bufsize<int>()))
+ return const_cast<char *>("Unknown error");
+
+ cpp::StringStream buffer_stream(
+ {const_cast<char *>(buffer.data()), buffer.size()});
+ buffer_stream << "Unknown error" << ' ' << err_num << '\0';
+ return buffer_stream.str();
+}
+
+} // namespace internal
+
+cpp::string_view get_error_string(int err_num) {
+ return get_error_string(err_num,
+ {internal::error_buffer, internal::ERR_BUFFER_SIZE});
+}
+
+cpp::string_view get_error_string(int err_num, cpp::span<char> buffer) {
+ auto opt_str = internal::error_mapper.get_str(err_num);
+ if (opt_str)
+ return *opt_str;
+ else
+ return internal::build_error_string(err_num, buffer);
+}
+
+} // namespace __llvm_libc