1 //===-- A class for number to string mappings -------------------*- C++ -*-===// 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 #ifndef LLVM_LIBC_SRC___SUPPORT_STRINGUTIL_MESSAGE_MAPPER_H 10 #define LLVM_LIBC_SRC___SUPPORT_STRINGUTIL_MESSAGE_MAPPER_H 11 12 #include "src/__support/CPP/array.h" 13 #include "src/__support/CPP/optional.h" 14 #include "src/__support/CPP/string_view.h" 15 #include "src/__support/macros/config.h" 16 #include <stddef.h> 17 18 namespace LIBC_NAMESPACE_DECL { 19 20 struct MsgMapping { 21 int num; 22 cpp::string_view msg; 23 24 constexpr MsgMapping() : num(0), msg() { ; } 25 26 constexpr MsgMapping(int init_num, const char *init_msg) 27 : num(init_num), msg(init_msg) { 28 ; 29 } 30 }; 31 32 template <size_t N> using MsgTable = cpp::array<MsgMapping, N>; 33 34 template <size_t N> constexpr size_t total_str_len(const MsgTable<N> &table) { 35 size_t total = 0; 36 for (size_t i = 0; i < table.size(); ++i) { 37 // add 1 for the null terminator. 38 total += table[i].msg.size() + 1; 39 } 40 return total; 41 } 42 43 template <size_t N> constexpr size_t max_key_val(const MsgTable<N> &table) { 44 int max = 0; 45 for (size_t i = 0; i < table.size(); ++i) { 46 if (table[i].num > max) { 47 max = table[i].num; 48 } 49 } 50 // max will never be negative since the starting value is 0. This is good, 51 // since it's used as a length. 52 return static_cast<size_t>(max); 53 } 54 55 template <size_t ARR_SIZE, size_t TOTAL_STR_LEN> class MessageMapper { 56 int msg_offsets[ARR_SIZE] = {-1}; 57 char string_array[TOTAL_STR_LEN] = {'\0'}; 58 59 public: 60 template <size_t N> constexpr MessageMapper(const MsgTable<N> &table) { 61 cpp::string_view string_mappings[ARR_SIZE] = {""}; 62 for (size_t i = 0; i < table.size(); ++i) 63 string_mappings[table[i].num] = table[i].msg; 64 65 int string_array_index = 0; 66 for (size_t cur_num = 0; cur_num < ARR_SIZE; ++cur_num) { 67 if (string_mappings[cur_num].size() != 0) { 68 msg_offsets[cur_num] = string_array_index; 69 // No need to replace with proper strcpy, this is evaluated at compile 70 // time. 71 for (size_t i = 0; i < string_mappings[cur_num].size() + 1; 72 ++i, ++string_array_index) { 73 string_array[string_array_index] = string_mappings[cur_num][i]; 74 } 75 } else { 76 msg_offsets[cur_num] = -1; 77 } 78 } 79 } 80 81 cpp::optional<cpp::string_view> get_str(int num) const { 82 if (num >= 0 && static_cast<size_t>(num) < ARR_SIZE && 83 msg_offsets[num] != -1) { 84 return {string_array + msg_offsets[num]}; 85 } else { 86 return cpp::optional<cpp::string_view>(); 87 } 88 } 89 }; 90 91 template <size_t N1, size_t N2> 92 constexpr MsgTable<N1 + N2> operator+(const MsgTable<N1> &t1, 93 const MsgTable<N2> &t2) { 94 MsgTable<N1 + N2> res{}; 95 for (size_t i = 0; i < N1; ++i) 96 res[i] = t1[i]; 97 for (size_t i = 0; i < N2; ++i) 98 res[N1 + i] = t2[i]; 99 return res; 100 } 101 102 } // namespace LIBC_NAMESPACE_DECL 103 104 #endif // LLVM_LIBC_SRC___SUPPORT_STRINGUTIL_MESSAGE_MAPPER_H 105