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