1e45d8c71SBrad Bishop /*
2e45d8c71SBrad Bishop // Copyright (c) 2017 Intel Corporation
3e45d8c71SBrad Bishop //
4e45d8c71SBrad Bishop // Licensed under the Apache License, Version 2.0 (the "License");
5e45d8c71SBrad Bishop // you may not use this file except in compliance with the License.
6e45d8c71SBrad Bishop // You may obtain a copy of the License at
7e45d8c71SBrad Bishop //
8e45d8c71SBrad Bishop // http://www.apache.org/licenses/LICENSE-2.0
9e45d8c71SBrad Bishop //
10e45d8c71SBrad Bishop // Unless required by applicable law or agreed to in writing, software
11e45d8c71SBrad Bishop // distributed under the License is distributed on an "AS IS" BASIS,
12e45d8c71SBrad Bishop // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e45d8c71SBrad Bishop // See the License for the specific language governing permissions and
14e45d8c71SBrad Bishop // limitations under the License.
15e45d8c71SBrad Bishop */
16e45d8c71SBrad Bishop /// \file utils.cpp
17e45d8c71SBrad Bishop
18e45d8c71SBrad Bishop #include "utils.hpp"
19e45d8c71SBrad Bishop
20e45d8c71SBrad Bishop #include "expression.hpp"
21e45d8c71SBrad Bishop #include "variant_visitors.hpp"
22e45d8c71SBrad Bishop
23e45d8c71SBrad Bishop #include <boost/algorithm/string/classification.hpp>
24e45d8c71SBrad Bishop #include <boost/algorithm/string/find.hpp>
25e45d8c71SBrad Bishop #include <boost/algorithm/string/predicate.hpp>
26e45d8c71SBrad Bishop #include <boost/algorithm/string/replace.hpp>
27e45d8c71SBrad Bishop #include <boost/algorithm/string/split.hpp>
28e45d8c71SBrad Bishop #include <boost/container/flat_map.hpp>
29e45d8c71SBrad Bishop #include <boost/lexical_cast.hpp>
30e45d8c71SBrad Bishop #include <sdbusplus/bus/match.hpp>
31e45d8c71SBrad Bishop #include <valijson/adapters/nlohmann_json_adapter.hpp>
32e45d8c71SBrad Bishop #include <valijson/schema.hpp>
33e45d8c71SBrad Bishop #include <valijson/schema_parser.hpp>
34e45d8c71SBrad Bishop #include <valijson/validator.hpp>
35e45d8c71SBrad Bishop
36e45d8c71SBrad Bishop #include <charconv>
37e45d8c71SBrad Bishop #include <filesystem>
38e45d8c71SBrad Bishop #include <fstream>
39e45d8c71SBrad Bishop #include <map>
40e45d8c71SBrad Bishop #include <regex>
41e45d8c71SBrad Bishop
42e45d8c71SBrad Bishop constexpr const char* templateChar = "$";
43e45d8c71SBrad Bishop
44e45d8c71SBrad Bishop namespace fs = std::filesystem;
45fc171428SEd Tanous // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
46e45d8c71SBrad Bishop static bool powerStatusOn = false;
47fc171428SEd Tanous // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
482af39224SPatrick Williams static std::unique_ptr<sdbusplus::bus::match_t> powerMatch = nullptr;
49e45d8c71SBrad Bishop
findFiles(const fs::path & dirPath,const std::string & matchString,std::vector<fs::path> & foundPaths)50e45d8c71SBrad Bishop bool findFiles(const fs::path& dirPath, const std::string& matchString,
51e45d8c71SBrad Bishop std::vector<fs::path>& foundPaths)
52e45d8c71SBrad Bishop {
53e45d8c71SBrad Bishop if (!fs::exists(dirPath))
54e45d8c71SBrad Bishop {
55e45d8c71SBrad Bishop return false;
56e45d8c71SBrad Bishop }
57e45d8c71SBrad Bishop
58e45d8c71SBrad Bishop std::regex search(matchString);
59e45d8c71SBrad Bishop std::smatch match;
60e45d8c71SBrad Bishop for (const auto& p : fs::directory_iterator(dirPath))
61e45d8c71SBrad Bishop {
62e45d8c71SBrad Bishop std::string path = p.path().string();
63e45d8c71SBrad Bishop if (std::regex_search(path, match, search))
64e45d8c71SBrad Bishop {
65e45d8c71SBrad Bishop foundPaths.emplace_back(p.path());
66e45d8c71SBrad Bishop }
67e45d8c71SBrad Bishop }
68e45d8c71SBrad Bishop return true;
69e45d8c71SBrad Bishop }
70e45d8c71SBrad Bishop
findFiles(const std::vector<fs::path> && dirPaths,const std::string & matchString,std::vector<fs::path> & foundPaths)71e45d8c71SBrad Bishop bool findFiles(const std::vector<fs::path>&& dirPaths,
72e45d8c71SBrad Bishop const std::string& matchString,
73e45d8c71SBrad Bishop std::vector<fs::path>& foundPaths)
74e45d8c71SBrad Bishop {
75e45d8c71SBrad Bishop std::map<fs::path, fs::path> paths;
76e45d8c71SBrad Bishop std::regex search(matchString);
77e45d8c71SBrad Bishop std::smatch match;
78e45d8c71SBrad Bishop for (const auto& dirPath : dirPaths)
79e45d8c71SBrad Bishop {
80e45d8c71SBrad Bishop if (!fs::exists(dirPath))
81e45d8c71SBrad Bishop {
82e45d8c71SBrad Bishop continue;
83e45d8c71SBrad Bishop }
84e45d8c71SBrad Bishop
85e45d8c71SBrad Bishop for (const auto& p : fs::directory_iterator(dirPath))
86e45d8c71SBrad Bishop {
87e45d8c71SBrad Bishop std::string path = p.path().string();
88e45d8c71SBrad Bishop if (std::regex_search(path, match, search))
89e45d8c71SBrad Bishop {
90e45d8c71SBrad Bishop paths[p.path().filename()] = p.path();
91e45d8c71SBrad Bishop }
92e45d8c71SBrad Bishop }
93e45d8c71SBrad Bishop }
94e45d8c71SBrad Bishop
95e45d8c71SBrad Bishop for (const auto& [key, value] : paths)
96e45d8c71SBrad Bishop {
97e45d8c71SBrad Bishop foundPaths.emplace_back(value);
98e45d8c71SBrad Bishop }
99e45d8c71SBrad Bishop
100e45d8c71SBrad Bishop return !foundPaths.empty();
101e45d8c71SBrad Bishop }
102e45d8c71SBrad Bishop
getI2cDevicePaths(const fs::path & dirPath,boost::container::flat_map<size_t,fs::path> & busPaths)103e45d8c71SBrad Bishop bool getI2cDevicePaths(const fs::path& dirPath,
104e45d8c71SBrad Bishop boost::container::flat_map<size_t, fs::path>& busPaths)
105e45d8c71SBrad Bishop {
106e45d8c71SBrad Bishop if (!fs::exists(dirPath))
107e45d8c71SBrad Bishop {
108e45d8c71SBrad Bishop return false;
109e45d8c71SBrad Bishop }
110e45d8c71SBrad Bishop
111e45d8c71SBrad Bishop // Regex for matching the path
112e45d8c71SBrad Bishop std::regex searchPath(std::string(R"(i2c-\d+$)"));
113e45d8c71SBrad Bishop // Regex for matching the bus numbers
114e45d8c71SBrad Bishop std::regex searchBus(std::string(R"(\w[^-]*$)"));
115e45d8c71SBrad Bishop std::smatch matchPath;
116e45d8c71SBrad Bishop std::smatch matchBus;
117e45d8c71SBrad Bishop for (const auto& p : fs::directory_iterator(dirPath))
118e45d8c71SBrad Bishop {
119e45d8c71SBrad Bishop std::string path = p.path().string();
120e45d8c71SBrad Bishop if (std::regex_search(path, matchPath, searchPath))
121e45d8c71SBrad Bishop {
122e45d8c71SBrad Bishop if (std::regex_search(path, matchBus, searchBus))
123e45d8c71SBrad Bishop {
124e45d8c71SBrad Bishop size_t bus = stoul(*matchBus.begin());
125e45d8c71SBrad Bishop busPaths.insert(std::pair<size_t, fs::path>(bus, p.path()));
126e45d8c71SBrad Bishop }
127e45d8c71SBrad Bishop }
128e45d8c71SBrad Bishop }
129e45d8c71SBrad Bishop
130e45d8c71SBrad Bishop return true;
131e45d8c71SBrad Bishop }
132e45d8c71SBrad Bishop
validateJson(const nlohmann::json & schemaFile,const nlohmann::json & input)133e45d8c71SBrad Bishop bool validateJson(const nlohmann::json& schemaFile, const nlohmann::json& input)
134e45d8c71SBrad Bishop {
135e45d8c71SBrad Bishop valijson::Schema schema;
136e45d8c71SBrad Bishop valijson::SchemaParser parser;
137e45d8c71SBrad Bishop valijson::adapters::NlohmannJsonAdapter schemaAdapter(schemaFile);
138e45d8c71SBrad Bishop parser.populateSchema(schemaAdapter, schema);
139e45d8c71SBrad Bishop valijson::Validator validator;
140e45d8c71SBrad Bishop valijson::adapters::NlohmannJsonAdapter targetAdapter(input);
1413013fb49SEd Tanous return validator.validate(schema, targetAdapter, nullptr);
142e45d8c71SBrad Bishop }
143e45d8c71SBrad Bishop
isPowerOn()144a3ca14a6SDelphine CC Chiu bool isPowerOn()
145e45d8c71SBrad Bishop {
146e45d8c71SBrad Bishop if (!powerMatch)
147e45d8c71SBrad Bishop {
148e45d8c71SBrad Bishop throw std::runtime_error("Power Match Not Created");
149e45d8c71SBrad Bishop }
150e45d8c71SBrad Bishop return powerStatusOn;
151e45d8c71SBrad Bishop }
152e45d8c71SBrad Bishop
setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection> & conn)153e45d8c71SBrad Bishop void setupPowerMatch(const std::shared_ptr<sdbusplus::asio::connection>& conn)
154e45d8c71SBrad Bishop {
1552af39224SPatrick Williams powerMatch = std::make_unique<sdbusplus::bus::match_t>(
1562af39224SPatrick Williams static_cast<sdbusplus::bus_t&>(*conn),
157e45d8c71SBrad Bishop "type='signal',interface='" + std::string(properties::interface) +
158e45d8c71SBrad Bishop "',path='" + std::string(power::path) + "',arg0='" +
159e45d8c71SBrad Bishop std::string(power::interface) + "'",
1602af39224SPatrick Williams [](sdbusplus::message_t& message) {
161e45d8c71SBrad Bishop std::string objectName;
162e45d8c71SBrad Bishop boost::container::flat_map<std::string, std::variant<std::string>>
163e45d8c71SBrad Bishop values;
164e45d8c71SBrad Bishop message.read(objectName, values);
165e45d8c71SBrad Bishop auto findState = values.find(power::property);
166e45d8c71SBrad Bishop if (findState != values.end())
167e45d8c71SBrad Bishop {
168e45d8c71SBrad Bishop powerStatusOn = boost::ends_with(
169e45d8c71SBrad Bishop std::get<std::string>(findState->second), "Running");
170e45d8c71SBrad Bishop }
171e45d8c71SBrad Bishop });
172e45d8c71SBrad Bishop
173e45d8c71SBrad Bishop conn->async_method_call(
174e45d8c71SBrad Bishop [](boost::system::error_code ec,
175e45d8c71SBrad Bishop const std::variant<std::string>& state) {
176e45d8c71SBrad Bishop if (ec)
177e45d8c71SBrad Bishop {
178e45d8c71SBrad Bishop return;
179e45d8c71SBrad Bishop }
180*b7077437SPatrick Williams powerStatusOn =
181*b7077437SPatrick Williams boost::ends_with(std::get<std::string>(state), "Running");
182e45d8c71SBrad Bishop },
183e45d8c71SBrad Bishop power::busname, power::path, properties::interface, properties::get,
184e45d8c71SBrad Bishop power::interface, power::property);
185e45d8c71SBrad Bishop }
186e45d8c71SBrad Bishop
187e45d8c71SBrad Bishop // Replaces the template character like the other version of this function,
188e45d8c71SBrad Bishop // but checks all properties on all interfaces provided to do the substitution
189e45d8c71SBrad Bishop // with.
templateCharReplace(nlohmann::json::iterator & keyPair,const DBusObject & object,const size_t index,const std::optional<std::string> & replaceStr)190*b7077437SPatrick Williams std::optional<std::string> templateCharReplace(
191*b7077437SPatrick Williams nlohmann::json::iterator& keyPair, const DBusObject& object,
192*b7077437SPatrick Williams const size_t index, const std::optional<std::string>& replaceStr)
193e45d8c71SBrad Bishop {
194e45d8c71SBrad Bishop for (const auto& [_, interface] : object)
195e45d8c71SBrad Bishop {
196e45d8c71SBrad Bishop auto ret = templateCharReplace(keyPair, interface, index, replaceStr);
197e45d8c71SBrad Bishop if (ret)
198e45d8c71SBrad Bishop {
199e45d8c71SBrad Bishop return ret;
200e45d8c71SBrad Bishop }
201e45d8c71SBrad Bishop }
202e45d8c71SBrad Bishop return std::nullopt;
203e45d8c71SBrad Bishop }
204e45d8c71SBrad Bishop
205e45d8c71SBrad Bishop // finds the template character (currently set to $) and replaces the value with
206e45d8c71SBrad Bishop // the field found in a dbus object i.e. $ADDRESS would get populated with the
207e45d8c71SBrad Bishop // ADDRESS field from a object on dbus
templateCharReplace(nlohmann::json::iterator & keyPair,const DBusInterface & interface,const size_t index,const std::optional<std::string> & replaceStr)208*b7077437SPatrick Williams std::optional<std::string> templateCharReplace(
209*b7077437SPatrick Williams nlohmann::json::iterator& keyPair, const DBusInterface& interface,
210*b7077437SPatrick Williams const size_t index, const std::optional<std::string>& replaceStr)
211e45d8c71SBrad Bishop {
212e45d8c71SBrad Bishop std::optional<std::string> ret = std::nullopt;
213e45d8c71SBrad Bishop
214e45d8c71SBrad Bishop if (keyPair.value().type() == nlohmann::json::value_t::object ||
215e45d8c71SBrad Bishop keyPair.value().type() == nlohmann::json::value_t::array)
216e45d8c71SBrad Bishop {
217e45d8c71SBrad Bishop for (auto nextLayer = keyPair.value().begin();
218e45d8c71SBrad Bishop nextLayer != keyPair.value().end(); nextLayer++)
219e45d8c71SBrad Bishop {
220e45d8c71SBrad Bishop templateCharReplace(nextLayer, interface, index, replaceStr);
221e45d8c71SBrad Bishop }
222e45d8c71SBrad Bishop return ret;
223e45d8c71SBrad Bishop }
224e45d8c71SBrad Bishop
225e45d8c71SBrad Bishop std::string* strPtr = keyPair.value().get_ptr<std::string*>();
226e45d8c71SBrad Bishop if (strPtr == nullptr)
227e45d8c71SBrad Bishop {
228e45d8c71SBrad Bishop return ret;
229e45d8c71SBrad Bishop }
230e45d8c71SBrad Bishop
231e45d8c71SBrad Bishop boost::replace_all(*strPtr, std::string(templateChar) + "index",
232e45d8c71SBrad Bishop std::to_string(index));
233e45d8c71SBrad Bishop if (replaceStr)
234e45d8c71SBrad Bishop {
235e45d8c71SBrad Bishop boost::replace_all(*strPtr, *replaceStr, std::to_string(index));
236e45d8c71SBrad Bishop }
237e45d8c71SBrad Bishop
2383013fb49SEd Tanous for (const auto& [propName, propValue] : interface)
239e45d8c71SBrad Bishop {
240e45d8c71SBrad Bishop std::string templateName = templateChar + propName;
241e45d8c71SBrad Bishop boost::iterator_range<std::string::const_iterator> find =
242e45d8c71SBrad Bishop boost::ifind_first(*strPtr, templateName);
243e45d8c71SBrad Bishop if (!find)
244e45d8c71SBrad Bishop {
245e45d8c71SBrad Bishop continue;
246e45d8c71SBrad Bishop }
247e45d8c71SBrad Bishop
248e45d8c71SBrad Bishop size_t start = find.begin() - strPtr->begin();
249e45d8c71SBrad Bishop
250e45d8c71SBrad Bishop // check for additional operations
2513013fb49SEd Tanous if ((start == 0U) && find.end() == strPtr->end())
252e45d8c71SBrad Bishop {
253e45d8c71SBrad Bishop std::visit([&](auto&& val) { keyPair.value() = val; }, propValue);
254e45d8c71SBrad Bishop return ret;
255e45d8c71SBrad Bishop }
256e45d8c71SBrad Bishop
257e45d8c71SBrad Bishop constexpr const std::array<char, 5> mathChars = {'+', '-', '%', '*',
258e45d8c71SBrad Bishop '/'};
259e45d8c71SBrad Bishop size_t nextItemIdx = start + templateName.size() + 1;
260e45d8c71SBrad Bishop
261e45d8c71SBrad Bishop if (nextItemIdx > strPtr->size() ||
262e45d8c71SBrad Bishop std::find(mathChars.begin(), mathChars.end(),
263e45d8c71SBrad Bishop strPtr->at(nextItemIdx)) == mathChars.end())
264e45d8c71SBrad Bishop {
265e45d8c71SBrad Bishop std::string val = std::visit(VariantToStringVisitor(), propValue);
266e45d8c71SBrad Bishop boost::ireplace_all(*strPtr, templateName, val);
267e45d8c71SBrad Bishop continue;
268e45d8c71SBrad Bishop }
269e45d8c71SBrad Bishop
270e45d8c71SBrad Bishop // save the prefix
271e45d8c71SBrad Bishop std::string prefix = strPtr->substr(0, start);
272e45d8c71SBrad Bishop
273e45d8c71SBrad Bishop // operate on the rest
274e45d8c71SBrad Bishop std::string end = strPtr->substr(nextItemIdx);
275e45d8c71SBrad Bishop
276e45d8c71SBrad Bishop std::vector<std::string> split;
277e45d8c71SBrad Bishop boost::split(split, end, boost::is_any_of(" "));
278e45d8c71SBrad Bishop
279e45d8c71SBrad Bishop // need at least 1 operation and number
280e45d8c71SBrad Bishop if (split.size() < 2)
281e45d8c71SBrad Bishop {
282e45d8c71SBrad Bishop std::cerr << "Syntax error on template replacement of " << *strPtr
283e45d8c71SBrad Bishop << "\n";
284e45d8c71SBrad Bishop for (const std::string& data : split)
285e45d8c71SBrad Bishop {
286e45d8c71SBrad Bishop std::cerr << data << " ";
287e45d8c71SBrad Bishop }
288e45d8c71SBrad Bishop std::cerr << "\n";
289e45d8c71SBrad Bishop continue;
290e45d8c71SBrad Bishop }
291e45d8c71SBrad Bishop
292e45d8c71SBrad Bishop // we assume that the replacement is a number, because we can
293e45d8c71SBrad Bishop // only do math on numbers.. we might concatenate strings in the
294e45d8c71SBrad Bishop // future, but thats later
295e45d8c71SBrad Bishop int number = std::visit(VariantToIntVisitor(), propValue);
296e45d8c71SBrad Bishop auto exprBegin = split.begin();
297e45d8c71SBrad Bishop auto exprEnd = split.end();
298e45d8c71SBrad Bishop
299e45d8c71SBrad Bishop number = expression::evaluate(number, exprBegin, exprEnd);
300e45d8c71SBrad Bishop
301e45d8c71SBrad Bishop std::string replaced(find.begin(), find.end());
302e45d8c71SBrad Bishop while (exprBegin != exprEnd)
303e45d8c71SBrad Bishop {
304e45d8c71SBrad Bishop replaced.append(" ").append(*exprBegin++);
305e45d8c71SBrad Bishop }
306e45d8c71SBrad Bishop ret = replaced;
307e45d8c71SBrad Bishop
308e45d8c71SBrad Bishop std::string result = prefix + std::to_string(number);
309e45d8c71SBrad Bishop while (exprEnd != split.end())
310e45d8c71SBrad Bishop {
311e45d8c71SBrad Bishop result.append(" ").append(*exprEnd++);
312e45d8c71SBrad Bishop }
313e45d8c71SBrad Bishop keyPair.value() = result;
314e45d8c71SBrad Bishop
315e45d8c71SBrad Bishop // We probably just invalidated the pointer abovei,
316e45d8c71SBrad Bishop // reset and continue to handle multiple templates
317e45d8c71SBrad Bishop strPtr = keyPair.value().get_ptr<std::string*>();
318e45d8c71SBrad Bishop if (strPtr == nullptr)
319e45d8c71SBrad Bishop {
320e45d8c71SBrad Bishop break;
321e45d8c71SBrad Bishop }
322e45d8c71SBrad Bishop }
323e45d8c71SBrad Bishop
324e45d8c71SBrad Bishop strPtr = keyPair.value().get_ptr<std::string*>();
325e45d8c71SBrad Bishop if (strPtr == nullptr)
326e45d8c71SBrad Bishop {
327e45d8c71SBrad Bishop return ret;
328e45d8c71SBrad Bishop }
329e45d8c71SBrad Bishop
330e45d8c71SBrad Bishop std::string_view strView = *strPtr;
331e45d8c71SBrad Bishop int base = 10;
332e45d8c71SBrad Bishop if (boost::starts_with(strView, "0x"))
333e45d8c71SBrad Bishop {
334e45d8c71SBrad Bishop strView.remove_prefix(2);
335e45d8c71SBrad Bishop base = 16;
336e45d8c71SBrad Bishop }
337e45d8c71SBrad Bishop
338e45d8c71SBrad Bishop uint64_t temp = 0;
339e45d8c71SBrad Bishop const char* strDataEndPtr = strView.data() + strView.size();
340e45d8c71SBrad Bishop const std::from_chars_result res =
341e45d8c71SBrad Bishop std::from_chars(strView.data(), strDataEndPtr, temp, base);
342e45d8c71SBrad Bishop if (res.ec == std::errc{} && res.ptr == strDataEndPtr)
343e45d8c71SBrad Bishop {
344e45d8c71SBrad Bishop keyPair.value() = temp;
345e45d8c71SBrad Bishop }
346e45d8c71SBrad Bishop
347e45d8c71SBrad Bishop return ret;
348e45d8c71SBrad Bishop }
349e45d8c71SBrad Bishop
350e45d8c71SBrad Bishop /// \brief JSON/DBus matching Callable for std::variant (visitor)
351e45d8c71SBrad Bishop ///
352e45d8c71SBrad Bishop /// Default match JSON/DBus match implementation
353e45d8c71SBrad Bishop /// \tparam T The concrete DBus value type from DBusValueVariant
354e45d8c71SBrad Bishop template <typename T>
355e45d8c71SBrad Bishop struct MatchProbe
356e45d8c71SBrad Bishop {
357e45d8c71SBrad Bishop /// \param probe the probe statement to match against
358e45d8c71SBrad Bishop /// \param value the property value being matched to a probe
359e45d8c71SBrad Bishop /// \return true if the dbusValue matched the probe otherwise false
matchMatchProbe360e45d8c71SBrad Bishop static bool match(const nlohmann::json& probe, const T& value)
361e45d8c71SBrad Bishop {
362e45d8c71SBrad Bishop return probe == value;
363e45d8c71SBrad Bishop }
364e45d8c71SBrad Bishop };
365e45d8c71SBrad Bishop
366e45d8c71SBrad Bishop /// \brief JSON/DBus matching Callable for std::variant (visitor)
367e45d8c71SBrad Bishop ///
368e45d8c71SBrad Bishop /// std::string specialization of MatchProbe enabling regex matching
369e45d8c71SBrad Bishop template <>
370e45d8c71SBrad Bishop struct MatchProbe<std::string>
371e45d8c71SBrad Bishop {
372e45d8c71SBrad Bishop /// \param probe the probe statement to match against
373e45d8c71SBrad Bishop /// \param value the string value being matched to a probe
374e45d8c71SBrad Bishop /// \return true if the dbusValue matched the probe otherwise false
matchMatchProbe375e45d8c71SBrad Bishop static bool match(const nlohmann::json& probe, const std::string& value)
376e45d8c71SBrad Bishop {
377e45d8c71SBrad Bishop if (probe.is_string())
378e45d8c71SBrad Bishop {
379e45d8c71SBrad Bishop try
380e45d8c71SBrad Bishop {
381e45d8c71SBrad Bishop std::regex search(probe);
382e45d8c71SBrad Bishop std::smatch regMatch;
383e45d8c71SBrad Bishop return std::regex_search(value, regMatch, search);
384e45d8c71SBrad Bishop }
385e45d8c71SBrad Bishop catch (const std::regex_error&)
386e45d8c71SBrad Bishop {
387e45d8c71SBrad Bishop std::cerr << "Syntax error in regular expression: " << probe
388e45d8c71SBrad Bishop << " will never match";
389e45d8c71SBrad Bishop }
390e45d8c71SBrad Bishop }
391e45d8c71SBrad Bishop
392e45d8c71SBrad Bishop // Skip calling nlohmann here, since it will never match a non-string
393e45d8c71SBrad Bishop // to a std::string
394e45d8c71SBrad Bishop return false;
395e45d8c71SBrad Bishop }
396e45d8c71SBrad Bishop };
397e45d8c71SBrad Bishop
398e45d8c71SBrad Bishop /// \brief Forwarding JSON/DBus matching Callable for std::variant (visitor)
399e45d8c71SBrad Bishop ///
400e45d8c71SBrad Bishop /// Forward calls to the correct template instantiation of MatchProbe
401e45d8c71SBrad Bishop struct MatchProbeForwarder
402e45d8c71SBrad Bishop {
MatchProbeForwarderMatchProbeForwarder403e45d8c71SBrad Bishop explicit MatchProbeForwarder(const nlohmann::json& probe) : probeRef(probe)
404e45d8c71SBrad Bishop {}
405e45d8c71SBrad Bishop const nlohmann::json& probeRef;
406e45d8c71SBrad Bishop
407e45d8c71SBrad Bishop template <typename T>
operator ()MatchProbeForwarder408e45d8c71SBrad Bishop bool operator()(const T& dbusValue) const
409e45d8c71SBrad Bishop {
410e45d8c71SBrad Bishop return MatchProbe<T>::match(probeRef, dbusValue);
411e45d8c71SBrad Bishop }
412e45d8c71SBrad Bishop };
413e45d8c71SBrad Bishop
matchProbe(const nlohmann::json & probe,const DBusValueVariant & dbusValue)414e45d8c71SBrad Bishop bool matchProbe(const nlohmann::json& probe, const DBusValueVariant& dbusValue)
415e45d8c71SBrad Bishop {
416e45d8c71SBrad Bishop return std::visit(MatchProbeForwarder(probe), dbusValue);
417e45d8c71SBrad Bishop }
418