blob: d88df36d3ec57efeb2af8cba05f21ede4b4a895e [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/container/flat_map.hpp>
7#include <boost/lexical_cast.hpp>
Alexander Hansen8feb0452025-09-15 14:29:20 +02008#include <phosphor-logging/lg2.hpp>
James Feist1df06a42019-04-11 14:23:04 -07009#include <sdbusplus/bus/match.hpp>
James Feist3cb5fec2018-01-23 14:41:51 -080010
George Liuce8d1d02025-08-25 08:58:25 +080011#include <algorithm>
12#include <cctype>
James Feist8c505da2020-05-28 10:06:33 -070013#include <filesystem>
Andrew Jefferya9c58922021-06-01 09:28:59 +093014#include <map>
George Liuce8d1d02025-08-25 08:58:25 +080015#include <ranges>
James Feist8c505da2020-05-28 10:06:33 -070016#include <regex>
George Liuce8d1d02025-08-25 08:58:25 +080017#include <string_view>
18#include <utility>
James Feist8c505da2020-05-28 10:06:33 -070019
Ed Tanous072e25d2018-12-16 21:45:20 -080020namespace fs = std::filesystem;
James Feist3cb5fec2018-01-23 14:41:51 -080021
James Feista465ccc2019-02-08 12:51:01 -080022bool findFiles(const fs::path& dirPath, const std::string& matchString,
23 std::vector<fs::path>& foundPaths)
James Feist3cb5fec2018-01-23 14:41:51 -080024{
James Feista3c180a2018-08-09 16:06:04 -070025 if (!fs::exists(dirPath))
Ed Tanous07d467b2021-02-23 14:48:37 -080026 {
James Feist3cb5fec2018-01-23 14:41:51 -080027 return false;
Ed Tanous07d467b2021-02-23 14:48:37 -080028 }
James Feist3cb5fec2018-01-23 14:41:51 -080029
James Feista3c180a2018-08-09 16:06:04 -070030 std::regex search(matchString);
James Feist3cb5fec2018-01-23 14:41:51 -080031 std::smatch match;
James Feista465ccc2019-02-08 12:51:01 -080032 for (const auto& p : fs::directory_iterator(dirPath))
James Feist3cb5fec2018-01-23 14:41:51 -080033 {
34 std::string path = p.path().string();
James Feistc95cb142018-02-26 10:41:42 -080035 if (std::regex_search(path, match, search))
James Feist3cb5fec2018-01-23 14:41:51 -080036 {
James Feista3c180a2018-08-09 16:06:04 -070037 foundPaths.emplace_back(p.path());
James Feist3cb5fec2018-01-23 14:41:51 -080038 }
39 }
40 return true;
James Feistb4383f42018-08-06 16:54:10 -070041}
42
Andrew Jefferya9c58922021-06-01 09:28:59 +093043bool findFiles(const std::vector<fs::path>&& dirPaths,
44 const std::string& matchString,
45 std::vector<fs::path>& foundPaths)
46{
47 std::map<fs::path, fs::path> paths;
48 std::regex search(matchString);
49 std::smatch match;
50 for (const auto& dirPath : dirPaths)
51 {
52 if (!fs::exists(dirPath))
Bruce Mitchella6d47332021-12-13 10:18:03 -060053 {
Andrew Jefferya9c58922021-06-01 09:28:59 +093054 continue;
Bruce Mitchella6d47332021-12-13 10:18:03 -060055 }
Andrew Jefferya9c58922021-06-01 09:28:59 +093056
Alexander Hansend8e86032025-04-25 14:49:15 +020057 for (const auto& p : fs::recursive_directory_iterator(dirPath))
Andrew Jefferya9c58922021-06-01 09:28:59 +093058 {
Alexander Hansend8e86032025-04-25 14:49:15 +020059 std::error_code ec;
60 if (p.is_directory(ec))
61 {
62 continue;
63 }
64
Andrew Jefferya9c58922021-06-01 09:28:59 +093065 std::string path = p.path().string();
66 if (std::regex_search(path, match, search))
67 {
68 paths[p.path().filename()] = p.path();
69 }
70 }
71 }
72
73 for (const auto& [key, value] : paths)
74 {
75 foundPaths.emplace_back(value);
76 }
77
78 return !foundPaths.empty();
79}
80
Nikhil Potaded8884f12019-03-27 13:27:13 -070081bool getI2cDevicePaths(const fs::path& dirPath,
82 boost::container::flat_map<size_t, fs::path>& busPaths)
83{
84 if (!fs::exists(dirPath))
85 {
86 return false;
87 }
88
89 // Regex for matching the path
90 std::regex searchPath(std::string(R"(i2c-\d+$)"));
91 // Regex for matching the bus numbers
92 std::regex searchBus(std::string(R"(\w[^-]*$)"));
93 std::smatch matchPath;
94 std::smatch matchBus;
95 for (const auto& p : fs::directory_iterator(dirPath))
96 {
97 std::string path = p.path().string();
98 if (std::regex_search(path, matchPath, searchPath))
99 {
100 if (std::regex_search(path, matchBus, searchBus))
101 {
102 size_t bus = stoul(*matchBus.begin());
103 busPaths.insert(std::pair<size_t, fs::path>(bus, p.path()));
104 }
105 }
106 }
107
108 return true;
109}
110
Brad Bishop5d525412020-08-26 08:50:50 -0400111/// \brief JSON/DBus matching Callable for std::variant (visitor)
112///
113/// Default match JSON/DBus match implementation
Andrew Jefferyeab49292022-04-05 14:42:20 +0930114/// \tparam T The concrete DBus value type from DBusValueVariant
Brad Bishop5d525412020-08-26 08:50:50 -0400115template <typename T>
116struct MatchProbe
117{
118 /// \param probe the probe statement to match against
119 /// \param value the property value being matched to a probe
120 /// \return true if the dbusValue matched the probe otherwise false
121 static bool match(const nlohmann::json& probe, const T& value)
122 {
123 return probe == value;
124 }
125};
126
127/// \brief JSON/DBus matching Callable for std::variant (visitor)
128///
129/// std::string specialization of MatchProbe enabling regex matching
130template <>
131struct MatchProbe<std::string>
132{
133 /// \param probe the probe statement to match against
134 /// \param value the string value being matched to a probe
135 /// \return true if the dbusValue matched the probe otherwise false
136 static bool match(const nlohmann::json& probe, const std::string& value)
137 {
138 if (probe.is_string())
139 {
140 try
141 {
142 std::regex search(probe);
143 std::smatch regMatch;
144 return std::regex_search(value, regMatch, search);
145 }
146 catch (const std::regex_error&)
147 {
Alexander Hansen8feb0452025-09-15 14:29:20 +0200148 lg2::error(
149 "Syntax error in regular expression: {PROBE} will never match",
150 "PROBE", probe);
Brad Bishop5d525412020-08-26 08:50:50 -0400151 }
152 }
153
154 // Skip calling nlohmann here, since it will never match a non-string
155 // to a std::string
156 return false;
157 }
158};
159
160/// \brief Forwarding JSON/DBus matching Callable for std::variant (visitor)
161///
162/// Forward calls to the correct template instantiation of MatchProbe
163struct MatchProbeForwarder
164{
165 explicit MatchProbeForwarder(const nlohmann::json& probe) : probeRef(probe)
166 {}
167 const nlohmann::json& probeRef;
168
169 template <typename T>
170 bool operator()(const T& dbusValue) const
171 {
172 return MatchProbe<T>::match(probeRef, dbusValue);
173 }
174};
175
Andrew Jefferyeab49292022-04-05 14:42:20 +0930176bool matchProbe(const nlohmann::json& probe, const DBusValueVariant& dbusValue)
Brad Bishop3cb8a602020-08-25 17:40:54 -0400177{
Brad Bishop5d525412020-08-26 08:50:50 -0400178 return std::visit(MatchProbeForwarder(probe), dbusValue);
179}
George Liuecf1a312025-08-25 10:43:12 +0800180
181std::vector<std::string> split(std::string_view str, char delim)
182{
183 std::vector<std::string> out;
184
185 size_t start = 0;
186 while (start <= str.size())
187 {
188 size_t end = str.find(delim, start);
189 if (end == std::string_view::npos)
190 {
191 out.emplace_back(str.substr(start));
192 break;
193 }
194
195 out.emplace_back(str.substr(start, end - start));
196 start = end + 1;
197 }
198
199 return out;
200}
George Liu5a61ec82025-08-25 11:16:44 +0800201
202void iReplaceAll(std::string& str, std::string_view search,
203 std::string_view replace)
204{
205 if (search.empty() || search == replace)
206 {
207 return;
208 }
209
210 while (true)
211 {
212 std::ranges::subrange<std::string::iterator> match =
213 iFindFirst(str, search);
214 if (!match)
215 {
216 break;
217 }
218
219 str.replace(match.begin(), match.end(), replace.begin(), replace.end());
220 }
221}
222
223void replaceAll(std::string& str, std::string_view search,
224 std::string_view replace)
225{
226 if (search.empty())
227 {
228 return;
229 }
230
231 size_t pos = 0;
232 while ((pos = str.find(search, pos)) != std::string::npos)
233 {
234 str.replace(pos, search.size(), replace);
235 pos += replace.size();
236 }
237}
George Liufd977ec2025-08-25 11:36:44 +0800238
239std::string toLowerCopy(std::string_view str)
240{
241 std::string result(str);
242 std::transform(result.begin(), result.end(), result.begin(),
243 [](unsigned char c) { return asciiToLower(c); });
244 return result;
245}