xref: /openbmc/bmcweb/features/redfish/include/registries.hpp (revision 4a102cd48c588d32c0a4d6610b4a9ed616f255f3)
140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
340e9b92eSEd 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>
14*4a102cd4SPatrick Williams #include <functional>
15*4a102cd4SPatrick Williams #include <map>
16*4a102cd4SPatrick Williams #include <optional>
17c5ba4c27SEd Tanous #include <span>
18c5ba4c27SEd Tanous #include <string>
19c5ba4c27SEd Tanous #include <string_view>
20d7857201SEd Tanous #include <system_error>
21d5c80ad9SNan Zhou #include <utility>
22d5c80ad9SNan Zhou 
23fffb8c1fSEd Tanous namespace redfish::registries
2470304cb5SJason M. Bills {
25351d3063SJason M. Bills struct Header
26351d3063SJason M. Bills {
27351d3063SJason M. Bills     const char* copyright;
28351d3063SJason M. Bills     const char* type;
2956b81992SEd Tanous     unsigned int versionMajor;
3056b81992SEd Tanous     unsigned int versionMinor;
3156b81992SEd Tanous     unsigned int versionPatch;
32351d3063SJason M. Bills     const char* name;
33351d3063SJason M. Bills     const char* language;
34351d3063SJason M. Bills     const char* description;
35351d3063SJason M. Bills     const char* registryPrefix;
36351d3063SJason M. Bills     const char* owningEntity;
37351d3063SJason M. Bills };
3870304cb5SJason M. Bills 
3970304cb5SJason M. Bills struct Message
4070304cb5SJason M. Bills {
4170304cb5SJason M. Bills     const char* description;
4270304cb5SJason M. Bills     const char* message;
43e7808c93SGunnar Mills     const char* messageSeverity;
44271584abSEd Tanous     const size_t numberOfArgs;
4570304cb5SJason M. Bills     std::array<const char*, 5> paramTypes;
4670304cb5SJason M. Bills     const char* resolution;
4770304cb5SJason M. Bills };
4870304cb5SJason M. Bills using MessageEntry = std::pair<const char*, const Message>;
49*4a102cd4SPatrick Williams using MessageEntries = std::span<const MessageEntry>;
50*4a102cd4SPatrick Williams 
51*4a102cd4SPatrick Williams struct RegistryEntry
52*4a102cd4SPatrick Williams {
53*4a102cd4SPatrick Williams     const Header& header;
54*4a102cd4SPatrick Williams     const char* url;
55*4a102cd4SPatrick Williams     MessageEntries entries;
56*4a102cd4SPatrick Williams };
57*4a102cd4SPatrick Williams using RegistryEntryRef = std::reference_wrapper<RegistryEntry>;
58*4a102cd4SPatrick Williams 
59*4a102cd4SPatrick Williams auto allRegistries() -> std::map<std::string, RegistryEntry>&;
60*4a102cd4SPatrick Williams 
61*4a102cd4SPatrick Williams auto getRegistryFromPrefix(const std::string& registryName)
62*4a102cd4SPatrick Williams     -> std::optional<RegistryEntryRef>;
63*4a102cd4SPatrick Williams 
64*4a102cd4SPatrick Williams auto getRegistryMessagesFromPrefix(const std::string& registryName)
65*4a102cd4SPatrick Williams     -> MessageEntries;
66*4a102cd4SPatrick Williams 
67*4a102cd4SPatrick Williams template <typename T>
68*4a102cd4SPatrick Williams void registerRegistry()
69*4a102cd4SPatrick Williams {
70*4a102cd4SPatrick Williams     allRegistries().emplace(T::header.registryPrefix,
71*4a102cd4SPatrick Williams                             RegistryEntry{T::header, T::url, T::registry});
72*4a102cd4SPatrick Williams }
73c5ba4c27SEd Tanous 
74bd79bce8SPatrick Williams inline std::string fillMessageArgs(
75bd79bce8SPatrick Williams     const std::span<const std::string_view> messageArgs, std::string_view msg)
76c5ba4c27SEd Tanous {
7780f595e7SEd Tanous     std::string ret;
7880f595e7SEd Tanous     size_t reserve = msg.size();
7926ccae32SEd Tanous     for (std::string_view arg : messageArgs)
80c5ba4c27SEd Tanous     {
8180f595e7SEd Tanous         reserve += arg.size();
82c5ba4c27SEd Tanous     }
8380f595e7SEd Tanous     ret.reserve(reserve);
8480f595e7SEd Tanous 
8580f595e7SEd Tanous     for (size_t stringIndex = msg.find('%'); stringIndex != std::string::npos;
8680f595e7SEd Tanous          stringIndex = msg.find('%'))
8780f595e7SEd Tanous     {
8880f595e7SEd Tanous         ret += msg.substr(0, stringIndex);
8980f595e7SEd Tanous         msg.remove_prefix(stringIndex + 1);
9080f595e7SEd Tanous         size_t number = 0;
917da633f0SEd Tanous         auto it = std::from_chars(&*msg.begin(), &*msg.end(), number);
9280f595e7SEd Tanous         if (it.ec != std::errc())
9380f595e7SEd Tanous         {
9480f595e7SEd Tanous             return "";
95c5ba4c27SEd Tanous         }
9680f595e7SEd Tanous         msg.remove_prefix(1);
9780f595e7SEd Tanous         // Redfish message args are 1 indexed.
9880f595e7SEd Tanous         number--;
9980f595e7SEd Tanous         if (number >= messageArgs.size())
10080f595e7SEd Tanous         {
10180f595e7SEd Tanous             return "";
10280f595e7SEd Tanous         }
10380f595e7SEd Tanous         ret += messageArgs[number];
10480f595e7SEd Tanous     }
10580f595e7SEd Tanous     ret += msg;
10680f595e7SEd Tanous     return ret;
107c5ba4c27SEd Tanous }
108c5ba4c27SEd Tanous 
109bd79bce8SPatrick Williams inline nlohmann::json::object_t getLogFromRegistry(
110bd79bce8SPatrick Williams     const Header& header, std::span<const MessageEntry> registry, size_t index,
11165e4f1f7SEd Tanous     std::span<const std::string_view> args)
11265e4f1f7SEd Tanous {
11365e4f1f7SEd Tanous     const redfish::registries::MessageEntry& entry = registry[index];
11465e4f1f7SEd Tanous     // Intentionally make a copy of the string, so we can append in the
11565e4f1f7SEd Tanous     // parameters.
1162e30bc2dSKrzysztof Grobelny     std::string msg =
1172e30bc2dSKrzysztof Grobelny         redfish::registries::fillMessageArgs(args, entry.second.message);
11865e4f1f7SEd Tanous     nlohmann::json jArgs = nlohmann::json::array();
11926ccae32SEd Tanous     for (std::string_view arg : args)
12065e4f1f7SEd Tanous     {
12165e4f1f7SEd Tanous         jArgs.push_back(arg);
12265e4f1f7SEd Tanous     }
12356b81992SEd Tanous     std::string msgId;
12456b81992SEd Tanous     if (BMCWEB_REDFISH_USE_3_DIGIT_MESSAGEID)
12556b81992SEd Tanous     {
12656b81992SEd Tanous         msgId = std::format("{}.{}.{}.{}.{}", header.registryPrefix,
12756b81992SEd Tanous                             header.versionMajor, header.versionMinor,
12856b81992SEd Tanous                             header.versionPatch, entry.first);
12956b81992SEd Tanous     }
13056b81992SEd Tanous     else
13156b81992SEd Tanous     {
13256b81992SEd Tanous         msgId =
13356b81992SEd Tanous             std::format("{}.{}.{}.{}", header.registryPrefix,
13456b81992SEd Tanous                         header.versionMajor, header.versionMinor, entry.first);
13556b81992SEd Tanous     }
13665e4f1f7SEd Tanous     nlohmann::json::object_t response;
13765e4f1f7SEd Tanous     response["@odata.type"] = "#Message.v1_1_1.Message";
13865e4f1f7SEd Tanous     response["MessageId"] = std::move(msgId);
13965e4f1f7SEd Tanous     response["Message"] = std::move(msg);
14065e4f1f7SEd Tanous     response["MessageArgs"] = std::move(jArgs);
14165e4f1f7SEd Tanous     response["MessageSeverity"] = entry.second.messageSeverity;
14265e4f1f7SEd Tanous     response["Resolution"] = entry.second.resolution;
14365e4f1f7SEd Tanous     return response;
14465e4f1f7SEd Tanous }
14565e4f1f7SEd Tanous 
146d1d411f9SSui Chen const Message* getMessage(std::string_view messageID);
147d1d411f9SSui Chen 
148d1d411f9SSui Chen const Message* getMessageFromRegistry(const std::string& messageKey,
149d1d411f9SSui Chen                                       std::span<const MessageEntry> registry);
150d1d411f9SSui Chen 
151fffb8c1fSEd Tanous } // namespace redfish::registries
152