xref: /openbmc/bmcweb/redfish-core/include/registries.hpp (revision d78572018fc2022091ff8b8eb5a7fef2172ba3d6)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors
3 // SPDX-FileCopyrightText: Copyright 2019 Intel Corporation
4 #pragma once
5 
6 #include "bmcweb_config.h"
7 
8 #include <nlohmann/json.hpp>
9 
10 #include <array>
11 #include <charconv>
12 #include <cstddef>
13 #include <format>
14 #include <span>
15 #include <string>
16 #include <string_view>
17 #include <system_error>
18 #include <utility>
19 
20 namespace redfish::registries
21 {
22 struct Header
23 {
24     const char* copyright;
25     const char* type;
26     unsigned int versionMajor;
27     unsigned int versionMinor;
28     unsigned int versionPatch;
29     const char* name;
30     const char* language;
31     const char* description;
32     const char* registryPrefix;
33     const char* owningEntity;
34 };
35 
36 struct Message
37 {
38     const char* description;
39     const char* message;
40     const char* messageSeverity;
41     const size_t numberOfArgs;
42     std::array<const char*, 5> paramTypes;
43     const char* resolution;
44 };
45 using MessageEntry = std::pair<const char*, const Message>;
46 
fillMessageArgs(const std::span<const std::string_view> messageArgs,std::string_view msg)47 inline std::string fillMessageArgs(
48     const std::span<const std::string_view> messageArgs, std::string_view msg)
49 {
50     std::string ret;
51     size_t reserve = msg.size();
52     for (std::string_view arg : messageArgs)
53     {
54         reserve += arg.size();
55     }
56     ret.reserve(reserve);
57 
58     for (size_t stringIndex = msg.find('%'); stringIndex != std::string::npos;
59          stringIndex = msg.find('%'))
60     {
61         ret += msg.substr(0, stringIndex);
62         msg.remove_prefix(stringIndex + 1);
63         size_t number = 0;
64         auto it = std::from_chars(&*msg.begin(), &*msg.end(), number);
65         if (it.ec != std::errc())
66         {
67             return "";
68         }
69         msg.remove_prefix(1);
70         // Redfish message args are 1 indexed.
71         number--;
72         if (number >= messageArgs.size())
73         {
74             return "";
75         }
76         ret += messageArgs[number];
77     }
78     ret += msg;
79     return ret;
80 }
81 
getLogFromRegistry(const Header & header,std::span<const MessageEntry> registry,size_t index,std::span<const std::string_view> args)82 inline nlohmann::json::object_t getLogFromRegistry(
83     const Header& header, std::span<const MessageEntry> registry, size_t index,
84     std::span<const std::string_view> args)
85 {
86     const redfish::registries::MessageEntry& entry = registry[index];
87     // Intentionally make a copy of the string, so we can append in the
88     // parameters.
89     std::string msg =
90         redfish::registries::fillMessageArgs(args, entry.second.message);
91     nlohmann::json jArgs = nlohmann::json::array();
92     for (std::string_view arg : args)
93     {
94         jArgs.push_back(arg);
95     }
96     std::string msgId;
97     if (BMCWEB_REDFISH_USE_3_DIGIT_MESSAGEID)
98     {
99         msgId = std::format("{}.{}.{}.{}.{}", header.registryPrefix,
100                             header.versionMajor, header.versionMinor,
101                             header.versionPatch, entry.first);
102     }
103     else
104     {
105         msgId =
106             std::format("{}.{}.{}.{}", header.registryPrefix,
107                         header.versionMajor, header.versionMinor, entry.first);
108     }
109     nlohmann::json::object_t response;
110     response["@odata.type"] = "#Message.v1_1_1.Message";
111     response["MessageId"] = std::move(msgId);
112     response["Message"] = std::move(msg);
113     response["MessageArgs"] = std::move(jArgs);
114     response["MessageSeverity"] = entry.second.messageSeverity;
115     response["Resolution"] = entry.second.resolution;
116     return response;
117 }
118 
119 const Message* getMessage(std::string_view messageID);
120 
121 const Message* getMessageFromRegistry(const std::string& messageKey,
122                                       std::span<const MessageEntry> registry);
123 
124 } // namespace redfish::registries
125