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 <iostream> 24 #include <numeric> 25 #include <span> 26 #include <string> 27 #include <string_view> 28 #include <utility> 29 30 // IWYU pragma: no_include <stddef.h> 31 32 namespace redfish::registries 33 { 34 struct Header 35 { 36 const char* copyright; 37 const char* type; 38 const char* id; 39 const char* name; 40 const char* language; 41 const char* description; 42 const char* registryPrefix; 43 const char* registryVersion; 44 const char* owningEntity; 45 }; 46 47 struct Message 48 { 49 const char* description; 50 const char* message; 51 const char* messageSeverity; 52 const size_t numberOfArgs; 53 std::array<const char*, 5> paramTypes; 54 const char* resolution; 55 }; 56 using MessageEntry = std::pair<const char*, const Message>; 57 58 inline std::string 59 fillMessageArgs(const std::span<const std::string_view> messageArgs, 60 std::string_view msg) 61 { 62 std::string ret; 63 size_t reserve = msg.size(); 64 for (std::string_view arg : messageArgs) 65 { 66 reserve += arg.size(); 67 } 68 ret.reserve(reserve); 69 70 for (size_t stringIndex = msg.find('%'); stringIndex != std::string::npos; 71 stringIndex = msg.find('%')) 72 { 73 ret += msg.substr(0, stringIndex); 74 msg.remove_prefix(stringIndex + 1); 75 size_t number = 0; 76 auto it = std::from_chars(msg.data(), &*msg.end(), number); 77 if (it.ec != std::errc()) 78 { 79 return ""; 80 } 81 msg.remove_prefix(1); 82 // Redfish message args are 1 indexed. 83 number--; 84 if (number >= messageArgs.size()) 85 { 86 return ""; 87 } 88 ret += messageArgs[number]; 89 } 90 ret += msg; 91 return ret; 92 } 93 94 inline nlohmann::json::object_t 95 getLogFromRegistry(const Header& header, 96 std::span<const MessageEntry> registry, size_t index, 97 std::span<const std::string_view> args) 98 { 99 const redfish::registries::MessageEntry& entry = registry[index]; 100 // Intentionally make a copy of the string, so we can append in the 101 // parameters. 102 std::string msg = 103 redfish::registries::fillMessageArgs(args, entry.second.message); 104 nlohmann::json jArgs = nlohmann::json::array(); 105 for (std::string_view arg : args) 106 { 107 jArgs.push_back(arg); 108 } 109 std::string msgId = header.id; 110 msgId += "."; 111 msgId += entry.first; 112 113 nlohmann::json::object_t response; 114 response["@odata.type"] = "#Message.v1_1_1.Message"; 115 response["MessageId"] = std::move(msgId); 116 response["Message"] = std::move(msg); 117 response["MessageArgs"] = std::move(jArgs); 118 response["MessageSeverity"] = entry.second.messageSeverity; 119 response["Resolution"] = entry.second.resolution; 120 return response; 121 } 122 123 const Message* getMessage(std::string_view messageID); 124 125 const Message* getMessageFromRegistry(const std::string& messageKey, 126 std::span<const MessageEntry> registry); 127 128 } // namespace redfish::registries 129