1 /* 2 // Copyright (c) 2017 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 /// \file utils.cpp 17 18 #include "utils.hpp" 19 20 #include <boost/algorithm/string/classification.hpp> 21 #include <boost/algorithm/string/find.hpp> 22 #include <boost/algorithm/string/predicate.hpp> 23 #include <boost/algorithm/string/replace.hpp> 24 #include <boost/algorithm/string/split.hpp> 25 #include <boost/container/flat_map.hpp> 26 #include <boost/lexical_cast.hpp> 27 #include <sdbusplus/bus/match.hpp> 28 29 #include <filesystem> 30 #include <iostream> 31 #include <map> 32 #include <regex> 33 34 namespace fs = std::filesystem; 35 36 bool findFiles(const fs::path& dirPath, const std::string& matchString, 37 std::vector<fs::path>& foundPaths) 38 { 39 if (!fs::exists(dirPath)) 40 { 41 return false; 42 } 43 44 std::regex search(matchString); 45 std::smatch match; 46 for (const auto& p : fs::directory_iterator(dirPath)) 47 { 48 std::string path = p.path().string(); 49 if (std::regex_search(path, match, search)) 50 { 51 foundPaths.emplace_back(p.path()); 52 } 53 } 54 return true; 55 } 56 57 bool findFiles(const std::vector<fs::path>&& dirPaths, 58 const std::string& matchString, 59 std::vector<fs::path>& foundPaths) 60 { 61 std::map<fs::path, fs::path> paths; 62 std::regex search(matchString); 63 std::smatch match; 64 for (const auto& dirPath : dirPaths) 65 { 66 if (!fs::exists(dirPath)) 67 { 68 continue; 69 } 70 71 for (const auto& p : fs::recursive_directory_iterator(dirPath)) 72 { 73 std::error_code ec; 74 if (p.is_directory(ec)) 75 { 76 continue; 77 } 78 79 std::string path = p.path().string(); 80 if (std::regex_search(path, match, search)) 81 { 82 paths[p.path().filename()] = p.path(); 83 } 84 } 85 } 86 87 for (const auto& [key, value] : paths) 88 { 89 foundPaths.emplace_back(value); 90 } 91 92 return !foundPaths.empty(); 93 } 94 95 bool getI2cDevicePaths(const fs::path& dirPath, 96 boost::container::flat_map<size_t, fs::path>& busPaths) 97 { 98 if (!fs::exists(dirPath)) 99 { 100 return false; 101 } 102 103 // Regex for matching the path 104 std::regex searchPath(std::string(R"(i2c-\d+$)")); 105 // Regex for matching the bus numbers 106 std::regex searchBus(std::string(R"(\w[^-]*$)")); 107 std::smatch matchPath; 108 std::smatch matchBus; 109 for (const auto& p : fs::directory_iterator(dirPath)) 110 { 111 std::string path = p.path().string(); 112 if (std::regex_search(path, matchPath, searchPath)) 113 { 114 if (std::regex_search(path, matchBus, searchBus)) 115 { 116 size_t bus = stoul(*matchBus.begin()); 117 busPaths.insert(std::pair<size_t, fs::path>(bus, p.path())); 118 } 119 } 120 } 121 122 return true; 123 } 124 125 /// \brief JSON/DBus matching Callable for std::variant (visitor) 126 /// 127 /// Default match JSON/DBus match implementation 128 /// \tparam T The concrete DBus value type from DBusValueVariant 129 template <typename T> 130 struct MatchProbe 131 { 132 /// \param probe the probe statement to match against 133 /// \param value the property 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 T& value) 136 { 137 return probe == value; 138 } 139 }; 140 141 /// \brief JSON/DBus matching Callable for std::variant (visitor) 142 /// 143 /// std::string specialization of MatchProbe enabling regex matching 144 template <> 145 struct MatchProbe<std::string> 146 { 147 /// \param probe the probe statement to match against 148 /// \param value the string value being matched to a probe 149 /// \return true if the dbusValue matched the probe otherwise false 150 static bool match(const nlohmann::json& probe, const std::string& value) 151 { 152 if (probe.is_string()) 153 { 154 try 155 { 156 std::regex search(probe); 157 std::smatch regMatch; 158 return std::regex_search(value, regMatch, search); 159 } 160 catch (const std::regex_error&) 161 { 162 std::cerr << "Syntax error in regular expression: " << probe 163 << " will never match"; 164 } 165 } 166 167 // Skip calling nlohmann here, since it will never match a non-string 168 // to a std::string 169 return false; 170 } 171 }; 172 173 /// \brief Forwarding JSON/DBus matching Callable for std::variant (visitor) 174 /// 175 /// Forward calls to the correct template instantiation of MatchProbe 176 struct MatchProbeForwarder 177 { 178 explicit MatchProbeForwarder(const nlohmann::json& probe) : probeRef(probe) 179 {} 180 const nlohmann::json& probeRef; 181 182 template <typename T> 183 bool operator()(const T& dbusValue) const 184 { 185 return MatchProbe<T>::match(probeRef, dbusValue); 186 } 187 }; 188 189 bool matchProbe(const nlohmann::json& probe, const DBusValueVariant& dbusValue) 190 { 191 return std::visit(MatchProbeForwarder(probe), dbusValue); 192 } 193