1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 2*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3*40e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2019 Intel Corporation 470304cb5SJason M. Bills #pragma once 5c5ba4c27SEd Tanous 656b81992SEd Tanous #include "bmcweb_config.h" 756b81992SEd Tanous 865e4f1f7SEd Tanous #include <nlohmann/json.hpp> 965e4f1f7SEd Tanous 10d5c80ad9SNan Zhou #include <array> 1180f595e7SEd Tanous #include <charconv> 12d5c80ad9SNan Zhou #include <cstddef> 1356b81992SEd Tanous #include <format> 1480f595e7SEd Tanous #include <numeric> 15c5ba4c27SEd Tanous #include <span> 16c5ba4c27SEd Tanous #include <string> 17c5ba4c27SEd Tanous #include <string_view> 18d5c80ad9SNan Zhou #include <utility> 19d5c80ad9SNan Zhou 20fffb8c1fSEd Tanous namespace redfish::registries 2170304cb5SJason M. Bills { 22351d3063SJason M. Bills struct Header 23351d3063SJason M. Bills { 24351d3063SJason M. Bills const char* copyright; 25351d3063SJason M. Bills const char* type; 2656b81992SEd Tanous unsigned int versionMajor; 2756b81992SEd Tanous unsigned int versionMinor; 2856b81992SEd Tanous unsigned int versionPatch; 29351d3063SJason M. Bills const char* name; 30351d3063SJason M. Bills const char* language; 31351d3063SJason M. Bills const char* description; 32351d3063SJason M. Bills const char* registryPrefix; 33351d3063SJason M. Bills const char* owningEntity; 34351d3063SJason M. Bills }; 3570304cb5SJason M. Bills 3670304cb5SJason M. Bills struct Message 3770304cb5SJason M. Bills { 3870304cb5SJason M. Bills const char* description; 3970304cb5SJason M. Bills const char* message; 40e7808c93SGunnar Mills const char* messageSeverity; 41271584abSEd Tanous const size_t numberOfArgs; 4270304cb5SJason M. Bills std::array<const char*, 5> paramTypes; 4370304cb5SJason M. Bills const char* resolution; 4470304cb5SJason M. Bills }; 4570304cb5SJason M. Bills using MessageEntry = std::pair<const char*, const Message>; 46c5ba4c27SEd Tanous 47bd79bce8SPatrick Williams inline std::string fillMessageArgs( 48bd79bce8SPatrick Williams const std::span<const std::string_view> messageArgs, std::string_view msg) 49c5ba4c27SEd Tanous { 5080f595e7SEd Tanous std::string ret; 5180f595e7SEd Tanous size_t reserve = msg.size(); 5226ccae32SEd Tanous for (std::string_view arg : messageArgs) 53c5ba4c27SEd Tanous { 5480f595e7SEd Tanous reserve += arg.size(); 55c5ba4c27SEd Tanous } 5680f595e7SEd Tanous ret.reserve(reserve); 5780f595e7SEd Tanous 5880f595e7SEd Tanous for (size_t stringIndex = msg.find('%'); stringIndex != std::string::npos; 5980f595e7SEd Tanous stringIndex = msg.find('%')) 6080f595e7SEd Tanous { 6180f595e7SEd Tanous ret += msg.substr(0, stringIndex); 6280f595e7SEd Tanous msg.remove_prefix(stringIndex + 1); 6380f595e7SEd Tanous size_t number = 0; 647da633f0SEd Tanous auto it = std::from_chars(&*msg.begin(), &*msg.end(), number); 6580f595e7SEd Tanous if (it.ec != std::errc()) 6680f595e7SEd Tanous { 6780f595e7SEd Tanous return ""; 68c5ba4c27SEd Tanous } 6980f595e7SEd Tanous msg.remove_prefix(1); 7080f595e7SEd Tanous // Redfish message args are 1 indexed. 7180f595e7SEd Tanous number--; 7280f595e7SEd Tanous if (number >= messageArgs.size()) 7380f595e7SEd Tanous { 7480f595e7SEd Tanous return ""; 7580f595e7SEd Tanous } 7680f595e7SEd Tanous ret += messageArgs[number]; 7780f595e7SEd Tanous } 7880f595e7SEd Tanous ret += msg; 7980f595e7SEd Tanous return ret; 80c5ba4c27SEd Tanous } 81c5ba4c27SEd Tanous 82bd79bce8SPatrick Williams inline nlohmann::json::object_t getLogFromRegistry( 83bd79bce8SPatrick Williams const Header& header, std::span<const MessageEntry> registry, size_t index, 8465e4f1f7SEd Tanous std::span<const std::string_view> args) 8565e4f1f7SEd Tanous { 8665e4f1f7SEd Tanous const redfish::registries::MessageEntry& entry = registry[index]; 8765e4f1f7SEd Tanous // Intentionally make a copy of the string, so we can append in the 8865e4f1f7SEd Tanous // parameters. 892e30bc2dSKrzysztof Grobelny std::string msg = 902e30bc2dSKrzysztof Grobelny redfish::registries::fillMessageArgs(args, entry.second.message); 9165e4f1f7SEd Tanous nlohmann::json jArgs = nlohmann::json::array(); 9226ccae32SEd Tanous for (std::string_view arg : args) 9365e4f1f7SEd Tanous { 9465e4f1f7SEd Tanous jArgs.push_back(arg); 9565e4f1f7SEd Tanous } 9656b81992SEd Tanous std::string msgId; 9756b81992SEd Tanous if (BMCWEB_REDFISH_USE_3_DIGIT_MESSAGEID) 9856b81992SEd Tanous { 9956b81992SEd Tanous msgId = std::format("{}.{}.{}.{}.{}", header.registryPrefix, 10056b81992SEd Tanous header.versionMajor, header.versionMinor, 10156b81992SEd Tanous header.versionPatch, entry.first); 10256b81992SEd Tanous } 10356b81992SEd Tanous else 10456b81992SEd Tanous { 10556b81992SEd Tanous msgId = 10656b81992SEd Tanous std::format("{}.{}.{}.{}", header.registryPrefix, 10756b81992SEd Tanous header.versionMajor, header.versionMinor, entry.first); 10856b81992SEd Tanous } 10965e4f1f7SEd Tanous nlohmann::json::object_t response; 11065e4f1f7SEd Tanous response["@odata.type"] = "#Message.v1_1_1.Message"; 11165e4f1f7SEd Tanous response["MessageId"] = std::move(msgId); 11265e4f1f7SEd Tanous response["Message"] = std::move(msg); 11365e4f1f7SEd Tanous response["MessageArgs"] = std::move(jArgs); 11465e4f1f7SEd Tanous response["MessageSeverity"] = entry.second.messageSeverity; 11565e4f1f7SEd Tanous response["Resolution"] = entry.second.resolution; 11665e4f1f7SEd Tanous return response; 11765e4f1f7SEd Tanous } 11865e4f1f7SEd Tanous 119d1d411f9SSui Chen const Message* getMessage(std::string_view messageID); 120d1d411f9SSui Chen 121d1d411f9SSui Chen const Message* getMessageFromRegistry(const std::string& messageKey, 122d1d411f9SSui Chen std::span<const MessageEntry> registry); 123d1d411f9SSui Chen 124fffb8c1fSEd Tanous } // namespace redfish::registries 125