Move mapper methods to free functions
As a design pattern, free functions are preferable to lambdas because
they reduce scopes, and produce better stack traces which include the
name of the function when things go wrong. This commit moves them.
Unfortunately, because of the interface_map capture, we still need the
lambda to be able to capture that reference, but that still seems much
better than leaving everything in a lambda.
In theory, this also makes them easier to unit test, although that
pattern isn't shown directly in this patchset.
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: Ib3ade71ab4572378461a62e233738776578de2f1
diff --git a/src/main.cpp b/src/main.cpp
index d4709b4..53b36d5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -452,6 +452,202 @@
}
}
+std::vector<interface_map_type::value_type>
+ getAncestors(const interface_map_type& interface_map, std::string req_path,
+ std::vector<std::string>& interfaces)
+{
+ // Interfaces need to be sorted for intersect to function
+ std::sort(interfaces.begin(), interfaces.end());
+
+ if (boost::ends_with(req_path, "/"))
+ {
+ req_path.pop_back();
+ }
+ if (req_path.size() && interface_map.find(req_path) == interface_map.end())
+ {
+ throw NotFoundException();
+ }
+
+ std::vector<interface_map_type::value_type> ret;
+ for (auto& object_path : interface_map)
+ {
+ auto& this_path = object_path.first;
+ if (boost::starts_with(req_path, this_path) && (req_path != this_path))
+ {
+ if (interfaces.empty())
+ {
+ ret.emplace_back(object_path);
+ }
+ else
+ {
+ for (auto& interface_map : object_path.second)
+ {
+
+ if (intersect(interfaces.begin(), interfaces.end(),
+ interface_map.second.begin(),
+ interface_map.second.end()))
+ {
+ addObjectMapResult(ret, this_path, interface_map);
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+boost::container::flat_map<std::string, boost::container::flat_set<std::string>>
+ getObject(const interface_map_type& interface_map, const std::string& path,
+ std::vector<std::string>& interfaces)
+{
+ boost::container::flat_map<std::string,
+ boost::container::flat_set<std::string>>
+ results;
+
+ // Interfaces need to be sorted for intersect to function
+ std::sort(interfaces.begin(), interfaces.end());
+ auto path_ref = interface_map.find(path);
+ if (path_ref == interface_map.end())
+ {
+ throw NotFoundException();
+ }
+ if (interfaces.empty())
+ {
+ return path_ref->second;
+ }
+ for (auto& interface_map : path_ref->second)
+ {
+ if (intersect(interfaces.begin(), interfaces.end(),
+ interface_map.second.begin(), interface_map.second.end()))
+ {
+ results.emplace(interface_map.first, interface_map.second);
+ }
+ }
+
+ if (results.empty())
+ {
+ throw NotFoundException();
+ }
+
+ return results;
+}
+
+std::vector<interface_map_type::value_type>
+ getSubTree(const interface_map_type& interface_map, std::string req_path,
+ int32_t depth, std::vector<std::string>& interfaces)
+{
+ if (depth <= 0)
+ {
+ depth = std::numeric_limits<int32_t>::max();
+ }
+ // Interfaces need to be sorted for intersect to function
+ std::sort(interfaces.begin(), interfaces.end());
+ std::vector<interface_map_type::value_type> ret;
+
+ if (boost::ends_with(req_path, "/"))
+ {
+ req_path.pop_back();
+ }
+ if (req_path.size() && interface_map.find(req_path) == interface_map.end())
+ {
+ throw NotFoundException();
+ }
+
+ for (auto& object_path : interface_map)
+ {
+ auto& this_path = object_path.first;
+
+ if (this_path == req_path)
+ {
+ continue;
+ }
+
+ if (boost::starts_with(this_path, req_path))
+ {
+ // count the number of slashes past the search term
+ int32_t this_depth = std::count(this_path.begin() + req_path.size(),
+ this_path.end(), '/');
+ if (this_depth <= depth)
+ {
+ for (auto& interface_map : object_path.second)
+ {
+ if (intersect(interfaces.begin(), interfaces.end(),
+ interface_map.second.begin(),
+ interface_map.second.end()) ||
+ interfaces.empty())
+ {
+ addObjectMapResult(ret, this_path, interface_map);
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+std::vector<std::string>
+ getSubTreePaths(const interface_map_type& interface_map,
+ std::string req_path, int32_t depth,
+ std::vector<std::string>& interfaces)
+{
+ if (depth <= 0)
+ {
+ depth = std::numeric_limits<int32_t>::max();
+ }
+ // Interfaces need to be sorted for intersect to function
+ std::sort(interfaces.begin(), interfaces.end());
+ std::vector<std::string> ret;
+
+ if (boost::ends_with(req_path, "/"))
+ {
+ req_path.pop_back();
+ }
+ if (req_path.size() && interface_map.find(req_path) == interface_map.end())
+ {
+ throw NotFoundException();
+ }
+
+ for (auto& object_path : interface_map)
+ {
+ auto& this_path = object_path.first;
+
+ if (this_path == req_path)
+ {
+ continue;
+ }
+
+ if (boost::starts_with(this_path, req_path))
+ {
+ // count the number of slashes past the search term
+ int this_depth = std::count(this_path.begin() + req_path.size(),
+ this_path.end(), '/');
+ if (this_depth <= depth)
+ {
+ bool add = interfaces.empty();
+ for (auto& interface_map : object_path.second)
+ {
+ if (intersect(interfaces.begin(), interfaces.end(),
+ interface_map.second.begin(),
+ interface_map.second.end()))
+ {
+ add = true;
+ break;
+ }
+ }
+ if (add)
+ {
+ // TODO(ed) this is a copy
+ ret.emplace_back(this_path);
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
int main(int argc, char** argv)
{
auto options = ArgumentParser(argc, argv);
@@ -651,202 +847,26 @@
iface->register_method(
"GetAncestors", [&interface_map](std::string& req_path,
std::vector<std::string>& interfaces) {
- // Interfaces need to be sorted for intersect to function
- std::sort(interfaces.begin(), interfaces.end());
-
- if (boost::ends_with(req_path, "/"))
- {
- req_path.pop_back();
- }
- if (req_path.size() &&
- interface_map.find(req_path) == interface_map.end())
- {
- throw NotFoundException();
- }
-
- std::vector<interface_map_type::value_type> ret;
- for (auto& object_path : interface_map)
- {
- auto& this_path = object_path.first;
- if (boost::starts_with(req_path, this_path) &&
- (req_path != this_path))
- {
- if (interfaces.empty())
- {
- ret.emplace_back(object_path);
- }
- else
- {
- for (auto& interface_map : object_path.second)
- {
-
- if (intersect(interfaces.begin(), interfaces.end(),
- interface_map.second.begin(),
- interface_map.second.end()))
- {
- addObjectMapResult(ret, this_path,
- interface_map);
- }
- }
- }
- }
- }
-
- return ret;
+ return getAncestors(interface_map, req_path, interfaces);
});
iface->register_method(
"GetObject", [&interface_map](const std::string& path,
std::vector<std::string>& interfaces) {
- boost::container::flat_map<std::string,
- boost::container::flat_set<std::string>>
- results;
-
- // Interfaces need to be sorted for intersect to function
- std::sort(interfaces.begin(), interfaces.end());
- auto path_ref = interface_map.find(path);
- if (path_ref == interface_map.end())
- {
- throw NotFoundException();
- }
- if (interfaces.empty())
- {
- return path_ref->second;
- }
- for (auto& interface_map : path_ref->second)
- {
- if (intersect(interfaces.begin(), interfaces.end(),
- interface_map.second.begin(),
- interface_map.second.end()))
- {
- results.emplace(interface_map.first, interface_map.second);
- }
- }
-
- if (results.empty())
- {
- throw NotFoundException();
- }
-
- return results;
+ return getObject(interface_map, path, interfaces);
});
iface->register_method(
"GetSubTree", [&interface_map](std::string& req_path, int32_t depth,
std::vector<std::string>& interfaces) {
- if (depth <= 0)
- {
- depth = std::numeric_limits<int32_t>::max();
- }
- // Interfaces need to be sorted for intersect to function
- std::sort(interfaces.begin(), interfaces.end());
- std::vector<interface_map_type::value_type> ret;
-
- if (boost::ends_with(req_path, "/"))
- {
- req_path.pop_back();
- }
- if (req_path.size() &&
- interface_map.find(req_path) == interface_map.end())
- {
- throw NotFoundException();
- }
-
- for (auto& object_path : interface_map)
- {
- auto& this_path = object_path.first;
-
- if (this_path == req_path)
- {
- continue;
- }
-
- if (boost::starts_with(this_path, req_path))
- {
- // count the number of slashes past the search term
- int32_t this_depth =
- std::count(this_path.begin() + req_path.size(),
- this_path.end(), '/');
- if (this_depth <= depth)
- {
- for (auto& interface_map : object_path.second)
- {
- if (intersect(interfaces.begin(), interfaces.end(),
- interface_map.second.begin(),
- interface_map.second.end()) ||
- interfaces.empty())
- {
- addObjectMapResult(ret, this_path,
- interface_map);
- }
- }
- }
- }
- }
-
- return ret;
+ return getSubTree(interface_map, req_path, depth, interfaces);
});
iface->register_method(
"GetSubTreePaths",
[&interface_map](std::string& req_path, int32_t depth,
std::vector<std::string>& interfaces) {
- if (depth <= 0)
- {
- depth = std::numeric_limits<int32_t>::max();
- }
- // Interfaces need to be sorted for intersect to function
- std::sort(interfaces.begin(), interfaces.end());
- std::vector<std::string> ret;
-
- if (boost::ends_with(req_path, "/"))
- {
- req_path.pop_back();
- }
- if (req_path.size() &&
- interface_map.find(req_path) == interface_map.end())
- {
- throw NotFoundException();
- }
-
- for (auto& object_path : interface_map)
- {
- auto& this_path = object_path.first;
-
- if (this_path == req_path)
- {
- continue;
- }
-
- if (boost::starts_with(this_path, req_path))
- {
- // count the number of slashes past the search term
- int this_depth =
- std::count(this_path.begin() + req_path.size(),
- this_path.end(), '/');
- if (this_depth <= depth)
- {
- bool add = interfaces.empty();
- for (auto& interface_map : object_path.second)
- {
- if (intersect(interfaces.begin(), interfaces.end(),
- interface_map.second.begin(),
- interface_map.second.end()))
- {
- add = true;
- break;
- }
- }
- if (add)
- {
- // TODO(ed) this is a copy
- ret.emplace_back(this_path);
- }
- }
- }
- }
-
- return ret;
+ return getSubTreePaths(interface_map, req_path, depth, interfaces);
});
iface->initialize();