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 58 fillMessageArgs(const std::span<const std::string_view> messageArgs, 59 std::string_view msg) 60 { 61 std::string ret; 62 size_t reserve = msg.size(); 63 for (std::string_view arg : messageArgs) 64 { 65 reserve += arg.size(); 66 } 67 ret.reserve(reserve); 68 69 for (size_t stringIndex = msg.find('%'); stringIndex != std::string::npos; 70 stringIndex = msg.find('%')) 71 { 72 ret += msg.substr(0, stringIndex); 73 msg.remove_prefix(stringIndex + 1); 74 size_t number = 0; 75 auto it = std::from_chars(msg.data(), &*msg.end(), number); 76 if (it.ec != std::errc()) 77 { 78 return ""; 79 } 80 msg.remove_prefix(1); 81 // Redfish message args are 1 indexed. 82 number--; 83 if (number >= messageArgs.size()) 84 { 85 return ""; 86 } 87 ret += messageArgs[number]; 88 } 89 ret += msg; 90 return ret; 91 } 92 93 inline nlohmann::json::object_t 94 getLogFromRegistry(const Header& header, 95 std::span<const MessageEntry> registry, size_t index, 96 std::span<const std::string_view> args) 97 { 98 const redfish::registries::MessageEntry& entry = registry[index]; 99 // Intentionally make a copy of the string, so we can append in the 100 // parameters. 101 std::string msg = 102 redfish::registries::fillMessageArgs(args, entry.second.message); 103 nlohmann::json jArgs = nlohmann::json::array(); 104 for (std::string_view arg : args) 105 { 106 jArgs.push_back(arg); 107 } 108 std::string msgId = header.id; 109 msgId += "."; 110 msgId += entry.first; 111 112 nlohmann::json::object_t response; 113 response["@odata.type"] = "#Message.v1_1_1.Message"; 114 response["MessageId"] = std::move(msgId); 115 response["Message"] = std::move(msg); 116 response["MessageArgs"] = std::move(jArgs); 117 response["MessageSeverity"] = entry.second.messageSeverity; 118 response["Resolution"] = entry.second.resolution; 119 return response; 120 } 121 122 const Message* getMessage(std::string_view messageID); 123 124 const Message* getMessageFromRegistry(const std::string& messageKey, 125 std::span<const MessageEntry> registry); 126 127 } // namespace redfish::registries 128