LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
GroupSelectorRules.cc
Go to the documentation of this file.
2 
4 #include "boost/algorithm/string.hpp"
7 #include "cetlib/container_algorithms.h"
8 
9 #include <algorithm>
10 #include <cctype>
11 #include <ostream>
12 #include <regex>
13 #include <string>
14 
15 using namespace art;
16 using namespace cet;
17 using namespace fhicl;
18 using namespace std;
19 
20 using VCBDMP = vector<BranchDescription const*>;
21 
22 namespace {
23 
24  // The partial_match() functions are helpers for Rule(). They
25  // ascertain matches between criterion and candidate value for
26  // components of the branch description, with appropriate wildcard
27  // rules.
28  inline bool
29  partial_match(string const& regularExpression, string const& branchstring)
30  {
31  return regularExpression.empty() ?
32  branchstring == "" :
33  std::regex_match(branchstring, std::regex(regularExpression));
34  }
35 
36  inline bool
37  partial_match(art::BranchType wanted, art::BranchType candidate)
38  {
39  bool result = (wanted == art::NumBranchTypes) || (wanted == candidate);
40  return result;
41  }
42 
43  using namespace std::string_literals;
44  static auto const branchTypeString =
45  "[Ii]n(?:(Event)|(SubRun)|(Run)|(Results))"s;
46  static std::regex const branchTypeRE(branchTypeString);
47 
48  static std::string const rulesMsg =
49  "Syntax: keep|drop <spec> [<branchtype]>\n"
50  "where <spec> is EITHER \"*\" OR:\n"
51  "<friendly-type>_<module-label>_<instance-name>_<process-name>\n"
52  "Wildcards are permissible within each field: * (any number of "
53  "characters), or\n"
54  "? (any single permissible character).\n"
55  "Permissible non-wildcard characters in all fields: [A-Za-z0-9].\n"
56  "Additionally, \"::\" is permissible in friendly type names, and\n"
57  "\"#\" is permissible in module labels.\n";
58 
60  parseComponents(std::string s,
61  std::string const& parameterName,
62  std::string const& owner,
63  bool& selectflag)
64  {
65  BranchKey components;
66  std::smatch ruleMatch;
67  static std::regex const re("(keep|drop)\\s+(\\*|(?:[^_]*)_(?:[^_]*)_(?:[^_]"
68  "*)_(?:[^_\\s]*))(?:\\s+(.*))?");
69  boost::trim(s); // Removing leading / trailing whitespace.
70  if (!std::regex_match(s, ruleMatch, re)) { // Failed preliminary check.
72  << "Illegal product selection rule \"" << s
73  << "\" failed initial checks in " << owner << '.' << parameterName
74  << ".\n"
75  << rulesMsg;
76  }
77  selectflag = (ruleMatch[1].str() == "keep");
78  if (ruleMatch[2].str() == "*") { // special case for wildcard
79  components.friendlyClassName_ = ".*";
80  components.moduleLabel_ = ".*";
81  components.productInstanceName_ = ".*";
82  components.processName_ = ".*";
83  } else {
84  std::string errMsg;
85 
86  components = art::detail::splitToComponents(ruleMatch[2], errMsg);
87 
88  if (!errMsg.empty()) {
90  << errMsg << "Error occurred in " << owner << '.' << parameterName
91  << " (exactly four components required if not \"*\").\n"
92  << rulesMsg;
93  }
94 
95  bool good = art::detail::checkBranchNameSelector(components, errMsg);
96 
97  if (!good) {
99  << errMsg << "Error occurred in " << owner << '.' << parameterName
100  << ".\n"
101  << rulesMsg;
102  }
103  boost::replace_all(components.friendlyClassName_, "*", ".*");
104  boost::replace_all(components.friendlyClassName_, "?", ".");
105  boost::replace_all(components.moduleLabel_, "*", ".*");
106  boost::replace_all(components.moduleLabel_, "?", ".");
107  boost::replace_all(components.productInstanceName_, "*", ".*");
108  boost::replace_all(components.productInstanceName_, "?", ".");
109  boost::replace_all(components.processName_, "*", ".*");
110  boost::replace_all(components.processName_, "?", ".");
111  }
112  if ((ruleMatch[3].length() > 0) && // Have a BranchType specification.
113  (ruleMatch[3] != "*")) { // Wildcard is NOP, here.
114  std::smatch btMatch;
115  auto const foundBT = ruleMatch[3].str();
116  if (std::regex_match(foundBT, btMatch, branchTypeRE)) {
117  // Should be true by construction.
118  assert(btMatch.size() ==
119  static_cast<size_t>(art::NumBranchTypes) + 1ul);
120  auto itFirstMatch = btMatch.begin();
121  ++itFirstMatch;
122  auto it = std::find_if(itFirstMatch, btMatch.end(), [](auto& s) {
123  return (s.length() > 0);
124  });
125  assert(it != btMatch.end()); // Should be true by construction.
126  components.branchType_ = std::distance(itFirstMatch, it);
127  } else {
129  << "Invalid branch type specification \"" << ruleMatch[3] << "\" in "
130  << owner << " parameter named '" << parameterName
131  << "'\n"
132  "If the optional branch type is specified, it must satisfy the "
133  "following regex: \"^"
134  << branchTypeString << "$\".\n"
135  << rulesMsg;
136  }
137  }
138  return components;
139  }
140 }
141 
143  string const& parameterName,
144  string const& owner)
145  : components_{parseComponents(s, parameterName, owner, selectflag_)}
146 {}
147 
148 void
150  vector<BranchSelectState>& branchstates) const
151 {
152  for (auto& state : branchstates)
153  applyToOne(state.desc, state.selectMe);
154 }
155 
156 void
157 GroupSelectorRules::applyToAll(vector<BranchSelectState>& branchstates) const
158 {
159  for (auto const& rule : rules_)
160  rule.applyToAll(branchstates);
161 }
162 
163 void
165  bool& result) const
166 {
167  if (this->appliesTo(branch))
168  result = selectflag_;
169 }
170 
171 bool
173 {
174  return partial_match(components_.friendlyClassName_,
175  branch->friendlyClassName()) &&
176  partial_match(components_.moduleLabel_, branch->moduleLabel()) &&
177  partial_match(components_.productInstanceName_,
178  branch->productInstanceName()) &&
179  partial_match(components_.processName_, branch->processName()) &&
180  partial_match(static_cast<BranchType>(components_.branchType_),
181  branch->branchType());
182 }
183 
184 GroupSelectorRules::GroupSelectorRules(vector<string> const& commands,
185  string const& parameterName,
186  string const& parameterOwnerName)
187 {
188  rules_.reserve(commands.size());
189  for (auto const& cmd : commands) {
190  rules_.emplace_back(cmd, parameterName, parameterOwnerName);
191  }
192  keepAll_ = commands.size() == 1 && commands[0] == "keep *";
193 }
194 
195 // ======================================================================
Float_t s
Definition: plot.C:23
bool appliesTo(BranchDescription const *branch) const
bool checkBranchNameSelector(std::string const &branchNameSelector, std::string &errMsg)
GroupSelectorRules(std::vector< std::string > const &commands, std::string const &parameterName, std::string const &parameterOwnerName)
STL namespace.
BranchKey splitToComponents(std::string const &branchName, std::string &errMsg)
vector< BranchDescription const * > VCBDMP
std::string productInstanceName_
Definition: BranchKey.h:44
void applyToAll(std::vector< BranchSelectState > &branchstates) const
std::string friendlyClassName_
Definition: BranchKey.h:42
void applyToAll(std::vector< BranchSelectState > &branchstates) const
parameter set interface
std::string const & moduleLabel() const
BranchType branchType() const
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::string processName_
Definition: BranchKey.h:45
std::string const & productInstanceName() const
BranchType
Definition: BranchType.h:18
std::vector< Rule > rules_
HLT enums.
void applyToOne(BranchDescription const *branch, bool &result) const
std::string const & processName() const
std::string moduleLabel_
Definition: BranchKey.h:43
std::string const & friendlyClassName() const
Rule(std::string const &s, std::string const &parameterName, std::string const &owner)