1 /* 2 // Copyright (c) 2019 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 #pragma once 17 18 #include <nlohmann/json.hpp> 19 20 #include <array> 21 #include <charconv> 22 #include <cstddef> 23 #include <numeric> 24 #include <span> 25 #include <string> 26 #include <string_view> 27 #include <utility> 28 29 // IWYU pragma: no_include <stddef.h> 30 31 namespace redfish::registries 32 { 33 struct Header 34 { 35 const char* copyright; 36 const char* type; 37 const char* id; 38 const char* name; 39 const char* language; 40 const char* description; 41 const char* registryPrefix; 42 const char* registryVersion; 43 const char* owningEntity; 44 }; 45 46 struct Message 47 { 48 const char* description; 49 const char* message; 50 const char* messageSeverity; 51 const size_t numberOfArgs; 52 std::array<const char*, 5> paramTypes; 53 const char* resolution; 54 }; 55 using MessageEntry = std::pair<const char*, const Message>; 56 57 inline std::string fillMessageArgs( 58 const std::span<const std::string_view> messageArgs, std::string_view msg) 59 { 60 std::string ret; 61 size_t reserve = msg.size(); 62 for (std::string_view arg : messageArgs) 63 { 64 reserve += arg.size(); 65 } 66 ret.reserve(reserve); 67 68 for (size_t stringIndex = msg.find('%'); stringIndex != std::string::npos; 69 stringIndex = msg.find('%')) 70 { 71 ret += msg.substr(0, stringIndex); 72 msg.remove_prefix(stringIndex + 1); 73 size_t number = 0; 74 auto it = std::from_chars(msg.data(), &*msg.end(), number); 75 if (it.ec != std::errc()) 76 { 77 return ""; 78 } 79 msg.remove_prefix(1); 80 // Redfish message args are 1 indexed. 81 number--; 82 if (number >= messageArgs.size()) 83 { 84 return ""; 85 } 86 ret += messageArgs[number]; 87 } 88 ret += msg; 89 return ret; 90 } 91 92 inline nlohmann::json::object_t getLogFromRegistry( 93 const Header& header, std::span<const MessageEntry> registry, size_t index, 94 std::span<const std::string_view> args) 95 { 96 const redfish::registries::MessageEntry& entry = registry[index]; 97 // Intentionally make a copy of the string, so we can append in the 98 // parameters. 99 std::string msg = 100 redfish::registries::fillMessageArgs(args, entry.second.message); 101 nlohmann::json jArgs = nlohmann::json::array(); 102 for (std::string_view arg : args) 103 { 104 jArgs.push_back(arg); 105 } 106 std::string msgId = header.id; 107 msgId += "."; 108 msgId += entry.first; 109 110 nlohmann::json::object_t response; 111 response["@odata.type"] = "#Message.v1_1_1.Message"; 112 response["MessageId"] = std::move(msgId); 113 response["Message"] = std::move(msg); 114 response["MessageArgs"] = std::move(jArgs); 115 response["MessageSeverity"] = entry.second.messageSeverity; 116 response["Resolution"] = entry.second.resolution; 117 return response; 118 } 119 120 const Message* getMessage(std::string_view messageID); 121 122 const Message* getMessageFromRegistry(const std::string& messageKey, 123 std::span<const MessageEntry> registry); 124 125 } // namespace redfish::registries 126