107793f95SMichael Jones //===-- Implementation of a class for mapping errors to strings -----------===// 207793f95SMichael Jones // 307793f95SMichael Jones // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 407793f95SMichael Jones // See https://llvm.org/LICENSE.txt for license information. 507793f95SMichael Jones // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 607793f95SMichael Jones // 707793f95SMichael Jones //===----------------------------------------------------------------------===// 807793f95SMichael Jones 925174976SSiva Chandra Reddy #include "error_to_string.h" 1025174976SSiva Chandra Reddy #include "platform_errors.h" 1107793f95SMichael Jones 1207793f95SMichael Jones #include "src/__support/CPP/span.h" 1307793f95SMichael Jones #include "src/__support/CPP/string_view.h" 1407793f95SMichael Jones #include "src/__support/CPP/stringstream.h" 1507793f95SMichael Jones #include "src/__support/StringUtil/message_mapper.h" 1607793f95SMichael Jones #include "src/__support/integer_to_string.h" 17daeee567SSiva Chandra Reddy #include "src/__support/macros/attributes.h" 185ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 190acb639fSMichael Jones 2007793f95SMichael Jones #include <stddef.h> 2107793f95SMichael Jones 225ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 2307793f95SMichael Jones namespace internal { 2407793f95SMichael Jones 2507793f95SMichael Jones constexpr size_t max_buff_size() { 2607793f95SMichael Jones constexpr size_t unknown_str_len = sizeof("Unknown error"); 2707793f95SMichael Jones // the buffer should be able to hold "Unknown error" + ' ' + num_str 28b555912eSGuillaume Chatelet return (unknown_str_len + 1 + IntegerToString<int>::buffer_size()) * 29b555912eSGuillaume Chatelet sizeof(char); 3007793f95SMichael Jones } 3107793f95SMichael Jones 3207793f95SMichael Jones // This is to hold error strings that have to be custom built. It may be 3307793f95SMichael Jones // rewritten on every call to strerror (or other error to string function). 3407793f95SMichael Jones constexpr size_t ERR_BUFFER_SIZE = max_buff_size(); 35daeee567SSiva Chandra Reddy LIBC_THREAD_LOCAL char error_buffer[ERR_BUFFER_SIZE]; 3607793f95SMichael Jones 37bb2ebbd1SSiva Chandra Reddy constexpr size_t TOTAL_STR_LEN = total_str_len(PLATFORM_ERRORS); 380acb639fSMichael Jones 3907793f95SMichael Jones // Since the StringMappings array is a map from error numbers to their 4007793f95SMichael Jones // corresponding strings, we have to have an array large enough we can use the 410acb639fSMichael Jones // error numbers as indexes. The current linux configuration has 132 values with 420acb639fSMichael Jones // the maximum value being 133 (41 and 58 are skipped). If other platforms use 430acb639fSMichael Jones // negative numbers or discontiguous ranges, then the array should be turned 440acb639fSMichael Jones // into a proper hashmap. 45bb2ebbd1SSiva Chandra Reddy constexpr size_t ERR_ARRAY_SIZE = max_key_val(PLATFORM_ERRORS) + 1; 4607793f95SMichael Jones 47bb2ebbd1SSiva Chandra Reddy constexpr MessageMapper<ERR_ARRAY_SIZE, TOTAL_STR_LEN> 48*f009f72dSMichael Jones ERROR_MAPPER(PLATFORM_ERRORS); 49*f009f72dSMichael Jones 50*f009f72dSMichael Jones constexpr MessageMapper<ERR_ARRAY_SIZE, TOTAL_STR_LEN> 51*f009f72dSMichael Jones ERRNO_NAME_MAPPER(PLATFORM_ERRNO_NAMES); 5207793f95SMichael Jones 5307793f95SMichael Jones cpp::string_view build_error_string(int err_num, cpp::span<char> buffer) { 5407793f95SMichael Jones // if the buffer can't hold "Unknown error" + ' ' + num_str, then just 5507793f95SMichael Jones // return "Unknown error". 5607793f95SMichael Jones if (buffer.size() < 57b555912eSGuillaume Chatelet (sizeof("Unknown error") + 1 + IntegerToString<int>::buffer_size())) 5807793f95SMichael Jones return const_cast<char *>("Unknown error"); 5907793f95SMichael Jones 6007793f95SMichael Jones cpp::StringStream buffer_stream( 6107793f95SMichael Jones {const_cast<char *>(buffer.data()), buffer.size()}); 6207793f95SMichael Jones buffer_stream << "Unknown error" << ' ' << err_num << '\0'; 6307793f95SMichael Jones return buffer_stream.str(); 6407793f95SMichael Jones } 6507793f95SMichael Jones 6607793f95SMichael Jones } // namespace internal 6707793f95SMichael Jones 6807793f95SMichael Jones cpp::string_view get_error_string(int err_num) { 6907793f95SMichael Jones return get_error_string(err_num, 7007793f95SMichael Jones {internal::error_buffer, internal::ERR_BUFFER_SIZE}); 7107793f95SMichael Jones } 7207793f95SMichael Jones 7307793f95SMichael Jones cpp::string_view get_error_string(int err_num, cpp::span<char> buffer) { 74*f009f72dSMichael Jones auto opt_str = internal::ERROR_MAPPER.get_str(err_num); 7507793f95SMichael Jones if (opt_str) 7607793f95SMichael Jones return *opt_str; 7707793f95SMichael Jones else 7807793f95SMichael Jones return internal::build_error_string(err_num, buffer); 7907793f95SMichael Jones } 8007793f95SMichael Jones 81*f009f72dSMichael Jones cpp::optional<cpp::string_view> try_get_errno_name(int err_num) { 82*f009f72dSMichael Jones return internal::ERRNO_NAME_MAPPER.get_str(err_num); 83*f009f72dSMichael Jones } 84*f009f72dSMichael Jones 855ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 86