blob: 171c236437caf309b27a04a20e213ccdd6c9429e [file] [log] [blame]
Alexander Hansen4e1142d2025-07-25 17:07:27 +02001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2017 Intel Corporation
James Feist3cb5fec2018-01-23 14:41:51 -08003
Brad Bishope45d8c72022-05-25 15:12:53 -04004#include "utils.hpp"
James Feist481c5d52019-08-13 14:40:40 -07005
James Feist481c5d52019-08-13 14:40:40 -07006#include <boost/algorithm/string/replace.hpp>
James Feist481c5d52019-08-13 14:40:40 -07007#include <boost/container/flat_map.hpp>
8#include <boost/lexical_cast.hpp>
Alexander Hansen8feb0452025-09-15 14:29:20 +02009#include <phosphor-logging/lg2.hpp>
James Feist1df06a42019-04-11 14:23:04 -070010#include <sdbusplus/bus/match.hpp>
James Feist3cb5fec2018-01-23 14:41:51 -080011
George Liuce8d1d02025-08-25 08:58:25 +080012#include <algorithm>
13#include <cctype>
James Feist8c505da2020-05-28 10:06:33 -070014#include <filesystem>
Andrew Jefferya9c58922021-06-01 09:28:59 +093015#include <map>
George Liuce8d1d02025-08-25 08:58:25 +080016#include <ranges>
James Feist8c505da2020-05-28 10:06:33 -070017#include <regex>
George Liuce8d1d02025-08-25 08:58:25 +080018#include <string_view>
19#include <utility>
James Feist8c505da2020-05-28 10:06:33 -070020
Ed Tanous072e25d2018-12-16 21:45:20 -080021namespace fs = std::filesystem;
James Feist3cb5fec2018-01-23 14:41:51 -080022
James Feista465ccc2019-02-08 12:51:01 -080023bool findFiles(const fs::path& dirPath, const std::string& matchString,
24 std::vector<fs::path>& foundPaths)
James Feist3cb5fec2018-01-23 14:41:51 -080025{
James Feista3c180a2018-08-09 16:06:04 -070026 if (!fs::exists(dirPath))
Ed Tanous07d467b2021-02-23 14:48:37 -080027 {
James Feist3cb5fec2018-01-23 14:41:51 -080028 return false;
Ed Tanous07d467b2021-02-23 14:48:37 -080029 }
James Feist3cb5fec2018-01-23 14:41:51 -080030
James Feista3c180a2018-08-09 16:06:04 -070031 std::regex search(matchString);
James Feist3cb5fec2018-01-23 14:41:51 -080032 std::smatch match;
James Feista465ccc2019-02-08 12:51:01 -080033 for (const auto& p : fs::directory_iterator(dirPath))
James Feist3cb5fec2018-01-23 14:41:51 -080034 {
35 std::string path = p.path().string();
James Feistc95cb142018-02-26 10:41:42 -080036 if (std::regex_search(path, match, search))
James Feist3cb5fec2018-01-23 14:41:51 -080037 {
James Feista3c180a2018-08-09 16:06:04 -070038 foundPaths.emplace_back(p.path());
James Feist3cb5fec2018-01-23 14:41:51 -080039 }
40 }
41 return true;
James Feistb4383f42018-08-06 16:54:10 -070042}
43
Andrew Jefferya9c58922021-06-01 09:28:59 +093044bool findFiles(const std::vector<fs::path>&& dirPaths,
45 const std::string& matchString,
46 std::vector<fs::path>& foundPaths)
47{
48 std::map<fs::path, fs::path> paths;
49 std::regex search(matchString);
50 std::smatch match;
51 for (const auto& dirPath : dirPaths)
52 {
53 if (!fs::exists(dirPath))
Bruce Mitchella6d47332021-12-13 10:18:03 -060054 {
Andrew Jefferya9c58922021-06-01 09:28:59 +093055 continue;
Bruce Mitchella6d47332021-12-13 10:18:03 -060056 }
Andrew Jefferya9c58922021-06-01 09:28:59 +093057
Alexander Hansend8e86032025-04-25 14:49:15 +020058 for (const auto& p : fs::recursive_directory_iterator(dirPath))
Andrew Jefferya9c58922021-06-01 09:28:59 +093059 {
Alexander Hansend8e86032025-04-25 14:49:15 +020060 std::error_code ec;
61 if (p.is_directory(ec))
62 {
63 continue;
64 }
65
Andrew Jefferya9c58922021-06-01 09:28:59 +093066 std::string path = p.path().string();
67 if (std::regex_search(path, match, search))
68 {
69 paths[p.path().filename()] = p.path();
70 }
71 }
72 }
73
74 for (const auto& [key, value] : paths)
75 {
76 foundPaths.emplace_back(value);
77 }
78
79 return !foundPaths.empty();
80}
81
Nikhil Potaded8884f12019-03-27 13:27:13 -070082bool getI2cDevicePaths(const fs::path& dirPath,
83 boost::container::flat_map<size_t, fs::path>& busPaths)
84{
85 if (!fs::exists(dirPath))
86 {
87 return false;
88 }
89
90 // Regex for matching the path
91 std::regex searchPath(std::string(R"(i2c-\d+$)"));
92 // Regex for matching the bus numbers
93 std::regex searchBus(std::string(R"(\w[^-]*$)"));
94 std::smatch matchPath;
95 std::smatch matchBus;
96 for (const auto& p : fs::directory_iterator(dirPath))
97 {
98 std::string path = p.path().string();
99 if (std::regex_search(path, matchPath, searchPath))
100 {
101 if (std::regex_search(path, matchBus, searchBus))
102 {
103 size_t bus = stoul(*matchBus.begin());
104 busPaths.insert(std::pair<size_t, fs::path>(bus, p.path()));
105 }
106 }
107 }
108
109 return true;
110}
111
Brad Bishop5d525412020-08-26 08:50:50 -0400112/// \brief JSON/DBus matching Callable for std::variant (visitor)
113///
114/// Default match JSON/DBus match implementation
Andrew Jefferyeab49292022-04-05 14:42:20 +0930115/// \tparam T The concrete DBus value type from DBusValueVariant
Brad Bishop5d525412020-08-26 08:50:50 -0400116template <typename T>
117struct MatchProbe
118{
119 /// \param probe the probe statement to match against
120 /// \param value the property value being matched to a probe
121 /// \return true if the dbusValue matched the probe otherwise false
122 static bool match(const nlohmann::json& probe, const T& value)
123 {
124 return probe == value;
125 }
126};
127
128/// \brief JSON/DBus matching Callable for std::variant (visitor)
129///
130/// std::string specialization of MatchProbe enabling regex matching
131template <>
132struct MatchProbe<std::string>
133{
134 /// \param probe the probe statement to match against
135 /// \param value the string value being matched to a probe
136 /// \return true if the dbusValue matched the probe otherwise false
137 static bool match(const nlohmann::json& probe, const std::string& value)
138 {
139 if (probe.is_string())
140 {
141 try
142 {
143 std::regex search(probe);
144 std::smatch regMatch;
145 return std::regex_search(value, regMatch, search);
146 }
147 catch (const std::regex_error&)
148 {
Alexander Hansen8feb0452025-09-15 14:29:20 +0200149 lg2::error(
150 "Syntax error in regular expression: {PROBE} will never match",
151 "PROBE", probe);
Brad Bishop5d525412020-08-26 08:50:50 -0400152 }
153 }
154
155 // Skip calling nlohmann here, since it will never match a non-string
156 // to a std::string
157 return false;
158 }
159};
160
161/// \brief Forwarding JSON/DBus matching Callable for std::variant (visitor)
162///
163/// Forward calls to the correct template instantiation of MatchProbe
164struct MatchProbeForwarder
165{
166 explicit MatchProbeForwarder(const nlohmann::json& probe) : probeRef(probe)
167 {}
168 const nlohmann::json& probeRef;
169
170 template <typename T>
171 bool operator()(const T& dbusValue) const
172 {
173 return MatchProbe<T>::match(probeRef, dbusValue);
174 }
175};
176
Andrew Jefferyeab49292022-04-05 14:42:20 +0930177bool matchProbe(const nlohmann::json& probe, const DBusValueVariant& dbusValue)
Brad Bishop3cb8a602020-08-25 17:40:54 -0400178{
Brad Bishop5d525412020-08-26 08:50:50 -0400179 return std::visit(MatchProbeForwarder(probe), dbusValue);
180}
George Liuecf1a312025-08-25 10:43:12 +0800181
182std::vector<std::string> split(std::string_view str, char delim)
183{
184 std::vector<std::string> out;
185
186 size_t start = 0;
187 while (start <= str.size())
188 {
189 size_t end = str.find(delim, start);
190 if (end == std::string_view::npos)
191 {
192 out.emplace_back(str.substr(start));
193 break;
194 }
195
196 out.emplace_back(str.substr(start, end - start));
197 start = end + 1;
198 }
199
200 return out;
201}