xref: /openbmc/telemetry/src/utils/make_id_name.cpp (revision 583ba441654657bb4ba9d051b747144a7258c159)
132305f14SSzymon Dompke #include "utils/make_id_name.hpp"
232305f14SSzymon Dompke 
332305f14SSzymon Dompke #include "utils/dbus_path_utils.hpp"
432305f14SSzymon Dompke 
532305f14SSzymon Dompke #include <sdbusplus/exception.hpp>
632305f14SSzymon Dompke 
732305f14SSzymon Dompke #include <algorithm>
832305f14SSzymon Dompke #include <system_error>
932305f14SSzymon Dompke 
1032305f14SSzymon Dompke namespace utils
1132305f14SSzymon Dompke {
1232305f14SSzymon Dompke namespace details
1332305f14SSzymon Dompke {
1432305f14SSzymon Dompke 
countDigits(size_t value)1532305f14SSzymon Dompke size_t countDigits(size_t value)
1632305f14SSzymon Dompke {
1732305f14SSzymon Dompke     size_t result = 1;
1832305f14SSzymon Dompke     while (value >= 10)
1932305f14SSzymon Dompke     {
2032305f14SSzymon Dompke         ++result;
2132305f14SSzymon Dompke         value /= 10;
2232305f14SSzymon Dompke     }
2332305f14SSzymon Dompke     return result;
2432305f14SSzymon Dompke }
2532305f14SSzymon Dompke 
generateId(std::string_view idIn,std::string_view nameIn,std::string_view defaultName,const std::vector<std::string> & conflictIds)2632305f14SSzymon Dompke std::string generateId(std::string_view idIn, std::string_view nameIn,
2732305f14SSzymon Dompke                        std::string_view defaultName,
2832305f14SSzymon Dompke                        const std::vector<std::string>& conflictIds)
2932305f14SSzymon Dompke {
3032305f14SSzymon Dompke     verifyIdCharacters(idIn);
3132305f14SSzymon Dompke     verifyIdPrefixes(idIn);
3232305f14SSzymon Dompke 
3332305f14SSzymon Dompke     if (!idIn.empty() && !idIn.ends_with('/'))
3432305f14SSzymon Dompke     {
3532305f14SSzymon Dompke         if (std::find(conflictIds.begin(), conflictIds.end(), idIn) !=
3632305f14SSzymon Dompke             conflictIds.end())
3732305f14SSzymon Dompke         {
3832305f14SSzymon Dompke             throw sdbusplus::exception::SdBusError(
3932305f14SSzymon Dompke                 static_cast<int>(std::errc::file_exists), "Duplicated id");
4032305f14SSzymon Dompke         }
4132305f14SSzymon Dompke         return std::string(idIn);
4232305f14SSzymon Dompke     }
4332305f14SSzymon Dompke 
4432305f14SSzymon Dompke     const std::string prefixes(idIn);
4532305f14SSzymon Dompke 
4632305f14SSzymon Dompke     std::string strippedId(nameIn);
4732305f14SSzymon Dompke     if (strippedId.find_first_of(utils::constants::allowedCharactersInPath) ==
4832305f14SSzymon Dompke         std::string::npos)
4932305f14SSzymon Dompke     {
5032305f14SSzymon Dompke         strippedId = defaultName;
5132305f14SSzymon Dompke     }
52*583ba441SPatrick Williams     strippedId.erase(
53*583ba441SPatrick Williams         std::remove_if(
54*583ba441SPatrick Williams             strippedId.begin(), strippedId.end(),
5532305f14SSzymon Dompke             [](char c) {
56*583ba441SPatrick Williams                 return c == '/' ||
57*583ba441SPatrick Williams                        utils::constants::allowedCharactersInPath.find(c) ==
5832305f14SSzymon Dompke                            std::string_view::npos;
5932305f14SSzymon Dompke             }),
6032305f14SSzymon Dompke         strippedId.end());
6132305f14SSzymon Dompke 
6232305f14SSzymon Dompke     size_t idx = 0;
63*583ba441SPatrick Williams     std::string tmpId =
64*583ba441SPatrick Williams         prefixes + strippedId.substr(0, constants::maxIdNameLength);
6532305f14SSzymon Dompke 
6632305f14SSzymon Dompke     while (std::find(conflictIds.begin(), conflictIds.end(), tmpId) !=
6732305f14SSzymon Dompke            conflictIds.end())
6832305f14SSzymon Dompke     {
6932305f14SSzymon Dompke         size_t digitsInIdx = countDigits(idx);
7032305f14SSzymon Dompke 
7132305f14SSzymon Dompke         if (digitsInIdx > constants::maxIdNameLength)
7232305f14SSzymon Dompke         {
7332305f14SSzymon Dompke             throw sdbusplus::exception::SdBusError(
7432305f14SSzymon Dompke                 static_cast<int>(std::errc::file_exists),
7532305f14SSzymon Dompke                 "Unique indices are depleted");
7632305f14SSzymon Dompke         }
7732305f14SSzymon Dompke 
7832305f14SSzymon Dompke         tmpId = prefixes +
7932305f14SSzymon Dompke                 strippedId.substr(0, constants::maxIdNameLength - digitsInIdx) +
8032305f14SSzymon Dompke                 std::to_string(idx);
8132305f14SSzymon Dompke         ++idx;
8232305f14SSzymon Dompke     }
8332305f14SSzymon Dompke 
8432305f14SSzymon Dompke     return tmpId;
8532305f14SSzymon Dompke }
8632305f14SSzymon Dompke 
8732305f14SSzymon Dompke } // namespace details
8832305f14SSzymon Dompke 
makeIdName(std::string_view id,std::string_view name,std::string_view defaultName,const std::vector<std::string> & conflictIds)89*583ba441SPatrick Williams std::pair<std::string, std::string> makeIdName(
90*583ba441SPatrick Williams     std::string_view id, std::string_view name, std::string_view defaultName,
9132305f14SSzymon Dompke     const std::vector<std::string>& conflictIds)
9232305f14SSzymon Dompke {
9332305f14SSzymon Dompke     if (name.length() > constants::maxIdNameLength)
9432305f14SSzymon Dompke     {
9562c08e9bSKrzysztof Grobelny         throw errors::InvalidArgument("Name", "Too long.");
9632305f14SSzymon Dompke     }
9732305f14SSzymon Dompke 
9832305f14SSzymon Dompke     if (name.empty() && !id.ends_with('/'))
9932305f14SSzymon Dompke     {
10032305f14SSzymon Dompke         name = id;
10132305f14SSzymon Dompke 
10232305f14SSzymon Dompke         if (auto pos = name.find_last_of("/"); pos != std::string::npos)
10332305f14SSzymon Dompke         {
10432305f14SSzymon Dompke             name = name.substr(pos + 1);
10532305f14SSzymon Dompke         }
10632305f14SSzymon Dompke 
10732305f14SSzymon Dompke         name = name.substr(0, constants::maxIdNameLength);
10832305f14SSzymon Dompke     }
10932305f14SSzymon Dompke 
11032305f14SSzymon Dompke     if (name.empty())
11132305f14SSzymon Dompke     {
11232305f14SSzymon Dompke         name = defaultName;
11332305f14SSzymon Dompke     }
11432305f14SSzymon Dompke 
11532305f14SSzymon Dompke     return std::make_pair(
11632305f14SSzymon Dompke         details::generateId(id, name, defaultName, conflictIds),
11732305f14SSzymon Dompke         std::string{name});
11832305f14SSzymon Dompke }
11932305f14SSzymon Dompke 
12032305f14SSzymon Dompke } // namespace utils
121