EntityManager: Split out PerformProbe
Continue breaking down the code so regular people can comprehend it.
Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: Ic4458054df7426d579cb99dd21f3578d1265711d
diff --git a/src/EntityManager.cpp b/src/EntityManager.cpp
index 725f2bf..8bd97fd 100644
--- a/src/EntityManager.cpp
+++ b/src/EntityManager.cpp
@@ -109,222 +109,6 @@
return ptr;
}
-// probes dbus interface dictionary for a key with a value that matches a regex
-// When an interface passes a probe, also save its D-Bus path with it.
-bool probeDbus(const std::string& interface,
- const std::map<std::string, nlohmann::json>& matches,
- FoundDeviceT& devices, const std::shared_ptr<PerformScan>& scan,
- bool& foundProbe)
-{
- bool foundMatch = false;
- foundProbe = false;
-
- for (const auto& [path, interfaces] : scan->dbusProbeObjects)
- {
- auto it = interfaces.find(interface);
- if (it == interfaces.end())
- {
- continue;
- }
-
- foundProbe = true;
-
- bool deviceMatches = true;
- const boost::container::flat_map<std::string, BasicVariantType>&
- properties = it->second;
-
- for (const auto& [matchProp, matchJSON] : matches)
- {
- auto deviceValue = properties.find(matchProp);
- if (deviceValue != properties.end())
- {
- deviceMatches =
- deviceMatches && matchProbe(matchJSON, deviceValue->second);
- }
- else
- {
- // Move on to the next DBus path
- deviceMatches = false;
- break;
- }
- }
- if (deviceMatches)
- {
- if constexpr (debug)
- {
- std::cerr << "probeDBus: Found probe match on " << path << " "
- << interface << "\n";
- }
- devices.emplace_back(properties, path);
- foundMatch = true;
- }
- }
- return foundMatch;
-}
-
-// default probe entry point, iterates a list looking for specific types to
-// call specific probe functions
-bool probe(const std::vector<std::string>& probeCommand,
- const std::shared_ptr<PerformScan>& scan, FoundDeviceT& foundDevs)
-{
- const static std::regex command(R"(\((.*)\))");
- std::smatch match;
- bool ret = false;
- bool matchOne = false;
- bool cur = true;
- probe_type_codes lastCommand = probe_type_codes::FALSE_T;
- bool first = true;
-
- for (auto& probe : probeCommand)
- {
- bool foundProbe = false;
- boost::container::flat_map<const char*, probe_type_codes,
- CmpStr>::const_iterator probeType;
-
- for (probeType = probeTypes.begin(); probeType != probeTypes.end();
- ++probeType)
- {
- if (probe.find(probeType->first) != std::string::npos)
- {
- foundProbe = true;
- break;
- }
- }
- if (foundProbe)
- {
- switch (probeType->second)
- {
- case probe_type_codes::FALSE_T:
- {
- cur = false;
- break;
- }
- case probe_type_codes::TRUE_T:
- {
- cur = true;
- break;
- }
- case probe_type_codes::MATCH_ONE:
- {
- // set current value to last, this probe type shouldn't
- // affect the outcome
- cur = ret;
- matchOne = true;
- break;
- }
- /*case probe_type_codes::AND:
- break;
- case probe_type_codes::OR:
- break;
- // these are no-ops until the last command switch
- */
- case probe_type_codes::FOUND:
- {
- if (!std::regex_search(probe, match, command))
- {
- std::cerr << "found probe syntax error " << probe
- << "\n";
- return false;
- }
- std::string commandStr = *(match.begin() + 1);
- boost::replace_all(commandStr, "'", "");
- cur = (std::find(scan->passedProbes.begin(),
- scan->passedProbes.end(),
- commandStr) != scan->passedProbes.end());
- break;
- }
- default:
- {
- break;
- }
- }
- }
- // look on dbus for object
- else
- {
- if (!std::regex_search(probe, match, command))
- {
- std::cerr << "dbus probe syntax error " << probe << "\n";
- return false;
- }
- std::string commandStr = *(match.begin() + 1);
- // convert single ticks and single slashes into legal json
- boost::replace_all(commandStr, "'", "\"");
- boost::replace_all(commandStr, R"(\)", R"(\\)");
- auto json = nlohmann::json::parse(commandStr, nullptr, false);
- if (json.is_discarded())
- {
- std::cerr << "dbus command syntax error " << commandStr << "\n";
- return false;
- }
- // we can match any (string, variant) property. (string, string)
- // does a regex
- std::map<std::string, nlohmann::json> dbusProbeMap =
- json.get<std::map<std::string, nlohmann::json>>();
- auto findStart = probe.find('(');
- if (findStart == std::string::npos)
- {
- return false;
- }
- std::string probeInterface = probe.substr(0, findStart);
- cur = probeDbus(probeInterface, dbusProbeMap, foundDevs, scan,
- foundProbe);
- }
-
- // some functions like AND and OR only take affect after the
- // fact
- if (lastCommand == probe_type_codes::AND)
- {
- ret = cur && ret;
- }
- else if (lastCommand == probe_type_codes::OR)
- {
- ret = cur || ret;
- }
-
- if (first)
- {
- ret = cur;
- first = false;
- }
- lastCommand = probeType != probeTypes.end() ? probeType->second
- : probe_type_codes::FALSE_T;
- }
-
- // probe passed, but empty device
- if (ret && foundDevs.size() == 0)
- {
- foundDevs.emplace_back(
- boost::container::flat_map<std::string, BasicVariantType>{},
- std::string{});
- }
- if (matchOne && ret)
- {
- // match the last one
- auto last = foundDevs.back();
- foundDevs.clear();
-
- foundDevs.emplace_back(std::move(last));
- }
- return ret;
-}
-
-PerformProbe::PerformProbe(
- const std::vector<std::string>& probeCommand,
- std::shared_ptr<PerformScan>& scanPtr,
- std::function<void(FoundDeviceT&, const DBusProbeObjectT&)>&& callback) :
- _probeCommand(probeCommand),
- scan(scanPtr), _callback(std::move(callback))
-{}
-PerformProbe::~PerformProbe()
-{
- FoundDeviceT foundDevs;
- if (probe(_probeCommand, scan, foundDevs))
- {
- _callback(foundDevs, scan->dbusProbeObjects);
- }
-}
-
// writes output files to persist data
bool writeJsonFiles(const nlohmann::json& systemConfiguration)
{
diff --git a/src/PerformProbe.cpp b/src/PerformProbe.cpp
new file mode 100644
index 0000000..7024e47
--- /dev/null
+++ b/src/PerformProbe.cpp
@@ -0,0 +1,248 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+/// \file PerformProbe.cpp
+#include "EntityManager.hpp"
+
+#include <boost/algorithm/string/replace.hpp>
+
+#include <regex>
+
+constexpr const bool debug = false;
+
+/* Keep this in sync with EntityManager.cpp */
+static const boost::container::flat_map<const char*, probe_type_codes, CmpStr>
+ probeTypes{{{"FALSE", probe_type_codes::FALSE_T},
+ {"TRUE", probe_type_codes::TRUE_T},
+ {"AND", probe_type_codes::AND},
+ {"OR", probe_type_codes::OR},
+ {"FOUND", probe_type_codes::FOUND},
+ {"MATCH_ONE", probe_type_codes::MATCH_ONE}}};
+
+// probes dbus interface dictionary for a key with a value that matches a regex
+// When an interface passes a probe, also save its D-Bus path with it.
+bool probeDbus(const std::string& interface,
+ const std::map<std::string, nlohmann::json>& matches,
+ FoundDeviceT& devices, const std::shared_ptr<PerformScan>& scan,
+ bool& foundProbe)
+{
+ bool foundMatch = false;
+ foundProbe = false;
+
+ for (const auto& [path, interfaces] : scan->dbusProbeObjects)
+ {
+ auto it = interfaces.find(interface);
+ if (it == interfaces.end())
+ {
+ continue;
+ }
+
+ foundProbe = true;
+
+ bool deviceMatches = true;
+ const boost::container::flat_map<std::string, BasicVariantType>&
+ properties = it->second;
+
+ for (const auto& [matchProp, matchJSON] : matches)
+ {
+ auto deviceValue = properties.find(matchProp);
+ if (deviceValue != properties.end())
+ {
+ deviceMatches =
+ deviceMatches && matchProbe(matchJSON, deviceValue->second);
+ }
+ else
+ {
+ // Move on to the next DBus path
+ deviceMatches = false;
+ break;
+ }
+ }
+ if (deviceMatches)
+ {
+ if constexpr (debug)
+ {
+ std::cerr << "probeDBus: Found probe match on " << path << " "
+ << interface << "\n";
+ }
+ devices.emplace_back(properties, path);
+ foundMatch = true;
+ }
+ }
+ return foundMatch;
+}
+
+// default probe entry point, iterates a list looking for specific types to
+// call specific probe functions
+bool probe(const std::vector<std::string>& probeCommand,
+ const std::shared_ptr<PerformScan>& scan, FoundDeviceT& foundDevs)
+{
+ const static std::regex command(R"(\((.*)\))");
+ std::smatch match;
+ bool ret = false;
+ bool matchOne = false;
+ bool cur = true;
+ probe_type_codes lastCommand = probe_type_codes::FALSE_T;
+ bool first = true;
+
+ for (auto& probe : probeCommand)
+ {
+ bool foundProbe = false;
+ boost::container::flat_map<const char*, probe_type_codes,
+ CmpStr>::const_iterator probeType;
+
+ for (probeType = probeTypes.begin(); probeType != probeTypes.end();
+ ++probeType)
+ {
+ if (probe.find(probeType->first) != std::string::npos)
+ {
+ foundProbe = true;
+ break;
+ }
+ }
+ if (foundProbe)
+ {
+ switch (probeType->second)
+ {
+ case probe_type_codes::FALSE_T:
+ {
+ cur = false;
+ break;
+ }
+ case probe_type_codes::TRUE_T:
+ {
+ cur = true;
+ break;
+ }
+ case probe_type_codes::MATCH_ONE:
+ {
+ // set current value to last, this probe type shouldn't
+ // affect the outcome
+ cur = ret;
+ matchOne = true;
+ break;
+ }
+ /*case probe_type_codes::AND:
+ break;
+ case probe_type_codes::OR:
+ break;
+ // these are no-ops until the last command switch
+ */
+ case probe_type_codes::FOUND:
+ {
+ if (!std::regex_search(probe, match, command))
+ {
+ std::cerr << "found probe syntax error " << probe
+ << "\n";
+ return false;
+ }
+ std::string commandStr = *(match.begin() + 1);
+ boost::replace_all(commandStr, "'", "");
+ cur = (std::find(scan->passedProbes.begin(),
+ scan->passedProbes.end(),
+ commandStr) != scan->passedProbes.end());
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+ }
+ // look on dbus for object
+ else
+ {
+ if (!std::regex_search(probe, match, command))
+ {
+ std::cerr << "dbus probe syntax error " << probe << "\n";
+ return false;
+ }
+ std::string commandStr = *(match.begin() + 1);
+ // convert single ticks and single slashes into legal json
+ boost::replace_all(commandStr, "'", "\"");
+ boost::replace_all(commandStr, R"(\)", R"(\\)");
+ auto json = nlohmann::json::parse(commandStr, nullptr, false);
+ if (json.is_discarded())
+ {
+ std::cerr << "dbus command syntax error " << commandStr << "\n";
+ return false;
+ }
+ // we can match any (string, variant) property. (string, string)
+ // does a regex
+ std::map<std::string, nlohmann::json> dbusProbeMap =
+ json.get<std::map<std::string, nlohmann::json>>();
+ auto findStart = probe.find('(');
+ if (findStart == std::string::npos)
+ {
+ return false;
+ }
+ std::string probeInterface = probe.substr(0, findStart);
+ cur = probeDbus(probeInterface, dbusProbeMap, foundDevs, scan,
+ foundProbe);
+ }
+
+ // some functions like AND and OR only take affect after the
+ // fact
+ if (lastCommand == probe_type_codes::AND)
+ {
+ ret = cur && ret;
+ }
+ else if (lastCommand == probe_type_codes::OR)
+ {
+ ret = cur || ret;
+ }
+
+ if (first)
+ {
+ ret = cur;
+ first = false;
+ }
+ lastCommand = probeType != probeTypes.end() ? probeType->second
+ : probe_type_codes::FALSE_T;
+ }
+
+ // probe passed, but empty device
+ if (ret && foundDevs.size() == 0)
+ {
+ foundDevs.emplace_back(
+ boost::container::flat_map<std::string, BasicVariantType>{},
+ std::string{});
+ }
+ if (matchOne && ret)
+ {
+ // match the last one
+ auto last = foundDevs.back();
+ foundDevs.clear();
+
+ foundDevs.emplace_back(std::move(last));
+ }
+ return ret;
+}
+
+PerformProbe::PerformProbe(
+ const std::vector<std::string>& probeCommand,
+ std::shared_ptr<PerformScan>& scanPtr,
+ std::function<void(FoundDeviceT&, const DBusProbeObjectT&)>&& callback) :
+ _probeCommand(probeCommand),
+ scan(scanPtr), _callback(std::move(callback))
+{}
+PerformProbe::~PerformProbe()
+{
+ FoundDeviceT foundDevs;
+ if (probe(_probeCommand, scan, foundDevs))
+ {
+ _callback(foundDevs, scan->dbusProbeObjects);
+ }
+}
diff --git a/src/meson.build b/src/meson.build
index bab416c..5add400 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -4,6 +4,7 @@
'entity-manager',
'EntityManager.cpp',
'PerformScan.cpp',
+ 'PerformProbe.cpp',
'Overlay.cpp',
'Utils.cpp',
cpp_args: cpp_args + ['-DBOOST_ASIO_DISABLE_THREADS'],