| Alexander Hansen | 4e1142d | 2025-07-25 17:07:27 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: Apache-2.0 | 
 | 2 | // SPDX-FileCopyrightText: Copyright 2017 Intel Corporation | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 3 |  | 
| Brad Bishop | e45d8c7 | 2022-05-25 15:12:53 -0400 | [diff] [blame] | 4 | #include "utils.hpp" | 
| James Feist | 481c5d5 | 2019-08-13 14:40:40 -0700 | [diff] [blame] | 5 |  | 
| James Feist | 481c5d5 | 2019-08-13 14:40:40 -0700 | [diff] [blame] | 6 | #include <boost/algorithm/string/classification.hpp> | 
 | 7 | #include <boost/algorithm/string/find.hpp> | 
| James Feist | 481c5d5 | 2019-08-13 14:40:40 -0700 | [diff] [blame] | 8 | #include <boost/algorithm/string/replace.hpp> | 
 | 9 | #include <boost/algorithm/string/split.hpp> | 
 | 10 | #include <boost/container/flat_map.hpp> | 
 | 11 | #include <boost/lexical_cast.hpp> | 
| James Feist | 1df06a4 | 2019-04-11 14:23:04 -0700 | [diff] [blame] | 12 | #include <sdbusplus/bus/match.hpp> | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 13 |  | 
| James Feist | 8c505da | 2020-05-28 10:06:33 -0700 | [diff] [blame] | 14 | #include <filesystem> | 
| Christopher Meis | 59ef1e7 | 2025-04-16 08:53:25 +0200 | [diff] [blame] | 15 | #include <iostream> | 
| Andrew Jeffery | a9c5892 | 2021-06-01 09:28:59 +0930 | [diff] [blame] | 16 | #include <map> | 
| James Feist | 8c505da | 2020-05-28 10:06:33 -0700 | [diff] [blame] | 17 | #include <regex> | 
 | 18 |  | 
| Ed Tanous | 072e25d | 2018-12-16 21:45:20 -0800 | [diff] [blame] | 19 | namespace fs = std::filesystem; | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 20 |  | 
| James Feist | a465ccc | 2019-02-08 12:51:01 -0800 | [diff] [blame] | 21 | bool findFiles(const fs::path& dirPath, const std::string& matchString, | 
 | 22 |                std::vector<fs::path>& foundPaths) | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 23 | { | 
| James Feist | a3c180a | 2018-08-09 16:06:04 -0700 | [diff] [blame] | 24 |     if (!fs::exists(dirPath)) | 
| Ed Tanous | 07d467b | 2021-02-23 14:48:37 -0800 | [diff] [blame] | 25 |     { | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 26 |         return false; | 
| Ed Tanous | 07d467b | 2021-02-23 14:48:37 -0800 | [diff] [blame] | 27 |     } | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 28 |  | 
| James Feist | a3c180a | 2018-08-09 16:06:04 -0700 | [diff] [blame] | 29 |     std::regex search(matchString); | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 30 |     std::smatch match; | 
| James Feist | a465ccc | 2019-02-08 12:51:01 -0800 | [diff] [blame] | 31 |     for (const auto& p : fs::directory_iterator(dirPath)) | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 32 |     { | 
 | 33 |         std::string path = p.path().string(); | 
| James Feist | c95cb14 | 2018-02-26 10:41:42 -0800 | [diff] [blame] | 34 |         if (std::regex_search(path, match, search)) | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 35 |         { | 
| James Feist | a3c180a | 2018-08-09 16:06:04 -0700 | [diff] [blame] | 36 |             foundPaths.emplace_back(p.path()); | 
| James Feist | 3cb5fec | 2018-01-23 14:41:51 -0800 | [diff] [blame] | 37 |         } | 
 | 38 |     } | 
 | 39 |     return true; | 
| James Feist | b4383f4 | 2018-08-06 16:54:10 -0700 | [diff] [blame] | 40 | } | 
 | 41 |  | 
| Andrew Jeffery | a9c5892 | 2021-06-01 09:28:59 +0930 | [diff] [blame] | 42 | bool findFiles(const std::vector<fs::path>&& dirPaths, | 
 | 43 |                const std::string& matchString, | 
 | 44 |                std::vector<fs::path>& foundPaths) | 
 | 45 | { | 
 | 46 |     std::map<fs::path, fs::path> paths; | 
 | 47 |     std::regex search(matchString); | 
 | 48 |     std::smatch match; | 
 | 49 |     for (const auto& dirPath : dirPaths) | 
 | 50 |     { | 
 | 51 |         if (!fs::exists(dirPath)) | 
| Bruce Mitchell | a6d4733 | 2021-12-13 10:18:03 -0600 | [diff] [blame] | 52 |         { | 
| Andrew Jeffery | a9c5892 | 2021-06-01 09:28:59 +0930 | [diff] [blame] | 53 |             continue; | 
| Bruce Mitchell | a6d4733 | 2021-12-13 10:18:03 -0600 | [diff] [blame] | 54 |         } | 
| Andrew Jeffery | a9c5892 | 2021-06-01 09:28:59 +0930 | [diff] [blame] | 55 |  | 
| Alexander Hansen | d8e8603 | 2025-04-25 14:49:15 +0200 | [diff] [blame] | 56 |         for (const auto& p : fs::recursive_directory_iterator(dirPath)) | 
| Andrew Jeffery | a9c5892 | 2021-06-01 09:28:59 +0930 | [diff] [blame] | 57 |         { | 
| Alexander Hansen | d8e8603 | 2025-04-25 14:49:15 +0200 | [diff] [blame] | 58 |             std::error_code ec; | 
 | 59 |             if (p.is_directory(ec)) | 
 | 60 |             { | 
 | 61 |                 continue; | 
 | 62 |             } | 
 | 63 |  | 
| Andrew Jeffery | a9c5892 | 2021-06-01 09:28:59 +0930 | [diff] [blame] | 64 |             std::string path = p.path().string(); | 
 | 65 |             if (std::regex_search(path, match, search)) | 
 | 66 |             { | 
 | 67 |                 paths[p.path().filename()] = p.path(); | 
 | 68 |             } | 
 | 69 |         } | 
 | 70 |     } | 
 | 71 |  | 
 | 72 |     for (const auto& [key, value] : paths) | 
 | 73 |     { | 
 | 74 |         foundPaths.emplace_back(value); | 
 | 75 |     } | 
 | 76 |  | 
 | 77 |     return !foundPaths.empty(); | 
 | 78 | } | 
 | 79 |  | 
| Nikhil Potade | d8884f1 | 2019-03-27 13:27:13 -0700 | [diff] [blame] | 80 | bool getI2cDevicePaths(const fs::path& dirPath, | 
 | 81 |                        boost::container::flat_map<size_t, fs::path>& busPaths) | 
 | 82 | { | 
 | 83 |     if (!fs::exists(dirPath)) | 
 | 84 |     { | 
 | 85 |         return false; | 
 | 86 |     } | 
 | 87 |  | 
 | 88 |     // Regex for matching the path | 
 | 89 |     std::regex searchPath(std::string(R"(i2c-\d+$)")); | 
 | 90 |     // Regex for matching the bus numbers | 
 | 91 |     std::regex searchBus(std::string(R"(\w[^-]*$)")); | 
 | 92 |     std::smatch matchPath; | 
 | 93 |     std::smatch matchBus; | 
 | 94 |     for (const auto& p : fs::directory_iterator(dirPath)) | 
 | 95 |     { | 
 | 96 |         std::string path = p.path().string(); | 
 | 97 |         if (std::regex_search(path, matchPath, searchPath)) | 
 | 98 |         { | 
 | 99 |             if (std::regex_search(path, matchBus, searchBus)) | 
 | 100 |             { | 
 | 101 |                 size_t bus = stoul(*matchBus.begin()); | 
 | 102 |                 busPaths.insert(std::pair<size_t, fs::path>(bus, p.path())); | 
 | 103 |             } | 
 | 104 |         } | 
 | 105 |     } | 
 | 106 |  | 
 | 107 |     return true; | 
 | 108 | } | 
 | 109 |  | 
| Brad Bishop | 5d52541 | 2020-08-26 08:50:50 -0400 | [diff] [blame] | 110 | /// \brief JSON/DBus matching Callable for std::variant (visitor) | 
 | 111 | /// | 
 | 112 | /// Default match JSON/DBus match implementation | 
| Andrew Jeffery | eab4929 | 2022-04-05 14:42:20 +0930 | [diff] [blame] | 113 | /// \tparam T The concrete DBus value type from DBusValueVariant | 
| Brad Bishop | 5d52541 | 2020-08-26 08:50:50 -0400 | [diff] [blame] | 114 | template <typename T> | 
 | 115 | struct MatchProbe | 
 | 116 | { | 
 | 117 |     /// \param probe the probe statement to match against | 
 | 118 |     /// \param value the property value being matched to a probe | 
 | 119 |     /// \return true if the dbusValue matched the probe otherwise false | 
 | 120 |     static bool match(const nlohmann::json& probe, const T& value) | 
 | 121 |     { | 
 | 122 |         return probe == value; | 
 | 123 |     } | 
 | 124 | }; | 
 | 125 |  | 
 | 126 | /// \brief JSON/DBus matching Callable for std::variant (visitor) | 
 | 127 | /// | 
 | 128 | /// std::string specialization of MatchProbe enabling regex matching | 
 | 129 | template <> | 
 | 130 | struct MatchProbe<std::string> | 
 | 131 | { | 
 | 132 |     /// \param probe the probe statement to match against | 
 | 133 |     /// \param value the string value being matched to a probe | 
 | 134 |     /// \return true if the dbusValue matched the probe otherwise false | 
 | 135 |     static bool match(const nlohmann::json& probe, const std::string& value) | 
 | 136 |     { | 
 | 137 |         if (probe.is_string()) | 
 | 138 |         { | 
 | 139 |             try | 
 | 140 |             { | 
 | 141 |                 std::regex search(probe); | 
 | 142 |                 std::smatch regMatch; | 
 | 143 |                 return std::regex_search(value, regMatch, search); | 
 | 144 |             } | 
 | 145 |             catch (const std::regex_error&) | 
 | 146 |             { | 
 | 147 |                 std::cerr << "Syntax error in regular expression: " << probe | 
 | 148 |                           << " will never match"; | 
 | 149 |             } | 
 | 150 |         } | 
 | 151 |  | 
 | 152 |         // Skip calling nlohmann here, since it will never match a non-string | 
 | 153 |         // to a std::string | 
 | 154 |         return false; | 
 | 155 |     } | 
 | 156 | }; | 
 | 157 |  | 
 | 158 | /// \brief Forwarding JSON/DBus matching Callable for std::variant (visitor) | 
 | 159 | /// | 
 | 160 | /// Forward calls to the correct template instantiation of MatchProbe | 
 | 161 | struct MatchProbeForwarder | 
 | 162 | { | 
 | 163 |     explicit MatchProbeForwarder(const nlohmann::json& probe) : probeRef(probe) | 
 | 164 |     {} | 
 | 165 |     const nlohmann::json& probeRef; | 
 | 166 |  | 
 | 167 |     template <typename T> | 
 | 168 |     bool operator()(const T& dbusValue) const | 
 | 169 |     { | 
 | 170 |         return MatchProbe<T>::match(probeRef, dbusValue); | 
 | 171 |     } | 
 | 172 | }; | 
 | 173 |  | 
| Andrew Jeffery | eab4929 | 2022-04-05 14:42:20 +0930 | [diff] [blame] | 174 | bool matchProbe(const nlohmann::json& probe, const DBusValueVariant& dbusValue) | 
| Brad Bishop | 3cb8a60 | 2020-08-25 17:40:54 -0400 | [diff] [blame] | 175 | { | 
| Brad Bishop | 5d52541 | 2020-08-26 08:50:50 -0400 | [diff] [blame] | 176 |     return std::visit(MatchProbeForwarder(probe), dbusValue); | 
 | 177 | } |