1 //===-- Implementation of a class for mapping errors to strings -----------===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "error_to_string.h" 10 #include "platform_errors.h" 11 12 #include "src/__support/CPP/span.h" 13 #include "src/__support/CPP/string_view.h" 14 #include "src/__support/CPP/stringstream.h" 15 #include "src/__support/StringUtil/message_mapper.h" 16 #include "src/__support/integer_to_string.h" 17 #include "src/__support/macros/attributes.h" 18 #include "src/__support/macros/config.h" 19 20 #include <stddef.h> 21 22 namespace LIBC_NAMESPACE_DECL { 23 namespace internal { 24 25 constexpr size_t max_buff_size() { 26 constexpr size_t unknown_str_len = sizeof("Unknown error"); 27 // the buffer should be able to hold "Unknown error" + ' ' + num_str 28 return (unknown_str_len + 1 + IntegerToString<int>::buffer_size()) * 29 sizeof(char); 30 } 31 32 // This is to hold error strings that have to be custom built. It may be 33 // rewritten on every call to strerror (or other error to string function). 34 constexpr size_t ERR_BUFFER_SIZE = max_buff_size(); 35 LIBC_THREAD_LOCAL char error_buffer[ERR_BUFFER_SIZE]; 36 37 constexpr size_t TOTAL_STR_LEN = total_str_len(PLATFORM_ERRORS); 38 39 // Since the StringMappings array is a map from error numbers to their 40 // corresponding strings, we have to have an array large enough we can use the 41 // error numbers as indexes. The current linux configuration has 132 values with 42 // the maximum value being 133 (41 and 58 are skipped). If other platforms use 43 // negative numbers or discontiguous ranges, then the array should be turned 44 // into a proper hashmap. 45 constexpr size_t ERR_ARRAY_SIZE = max_key_val(PLATFORM_ERRORS) + 1; 46 47 constexpr MessageMapper<ERR_ARRAY_SIZE, TOTAL_STR_LEN> 48 ERROR_MAPPER(PLATFORM_ERRORS); 49 50 constexpr MessageMapper<ERR_ARRAY_SIZE, TOTAL_STR_LEN> 51 ERRNO_NAME_MAPPER(PLATFORM_ERRNO_NAMES); 52 53 cpp::string_view build_error_string(int err_num, cpp::span<char> buffer) { 54 // if the buffer can't hold "Unknown error" + ' ' + num_str, then just 55 // return "Unknown error". 56 if (buffer.size() < 57 (sizeof("Unknown error") + 1 + IntegerToString<int>::buffer_size())) 58 return const_cast<char *>("Unknown error"); 59 60 cpp::StringStream buffer_stream( 61 {const_cast<char *>(buffer.data()), buffer.size()}); 62 buffer_stream << "Unknown error" << ' ' << err_num << '\0'; 63 return buffer_stream.str(); 64 } 65 66 } // namespace internal 67 68 cpp::string_view get_error_string(int err_num) { 69 return get_error_string(err_num, 70 {internal::error_buffer, internal::ERR_BUFFER_SIZE}); 71 } 72 73 cpp::string_view get_error_string(int err_num, cpp::span<char> buffer) { 74 auto opt_str = internal::ERROR_MAPPER.get_str(err_num); 75 if (opt_str) 76 return *opt_str; 77 else 78 return internal::build_error_string(err_num, buffer); 79 } 80 81 cpp::optional<cpp::string_view> try_get_errno_name(int err_num) { 82 return internal::ERRNO_NAME_MAPPER.get_str(err_num); 83 } 84 85 } // namespace LIBC_NAMESPACE_DECL 86