CMS 3D CMS Logo

TriggerSelector.cc
Go to the documentation of this file.
1 #include "TriggerSelector.h"
2 
9 
10 #include <iostream>
11 #include <algorithm>
12 
13 #include <boost/regex.hpp>
14 
15 namespace dqmservices {
16 
17  // compatibility constructor
18 
19  TriggerSelector::TriggerSelector(Strings const& pathspecs, Strings const& triggernames) : useOld_(true) {
20  acceptAll_ = false;
21  eventSelector_.reset(new edm::EventSelector(pathspecs, triggernames));
22  }
23 
24  TriggerSelector::TriggerSelector(std::string const& expression, Strings const& triggernames) : useOld_(false) {
25  init(trim(expression), triggernames);
26  }
27 
28  void TriggerSelector::init(std::string const& expression, Strings const& triggernames) {
29  // debug_ = true;
30  if (expression.empty()) {
31  acceptAll_ = true;
32  return;
33  }
34  if (expression.size() == 1 && expression.at(0) == '*')
35  acceptAll_ = true;
36  else
37  acceptAll_ = false;
38 
39  // replace all possible alternate operators (.AND. and .OR.)
40  {
41  using namespace boost;
43  temp = regex_replace(expression, regex(".AND."), "&&");
44  expression_ = regex_replace(temp, regex(".and."), "&&");
45  temp = regex_replace(expression_, regex(".OR."), "||");
46  expression_ = regex_replace(temp, regex(".or."), "||");
47  }
48 
49  // build decision tree
50  masterElement_.reset(new TreeElement(expression_, triggernames));
51  }
52 
54  if (useOld_) {
55  return eventSelector_->acceptEvent(tr);
56  }
57 
58  if (acceptAll_)
59  return true;
60 
61  return masterElement_->returnStatus(tr);
62  }
63 
64  bool TriggerSelector::acceptEvent(unsigned char const* array_of_trigger_results, int number_of_trigger_paths) const {
65  if (useOld_)
66  return eventSelector_->acceptEvent(array_of_trigger_results, number_of_trigger_paths);
67 
68  if (acceptAll_)
69  return true;
70 
71  // Form HLTGlobalStatus object to represent the array_of_trigger_results
72  edm::HLTGlobalStatus tr(number_of_trigger_paths);
73  int byteIndex = 0;
74  int subIndex = 0;
75  for (int pathIndex = 0; pathIndex < number_of_trigger_paths; ++pathIndex) {
76  int state = array_of_trigger_results[byteIndex] >> (subIndex * 2);
77  state &= 0x3;
78  edm::HLTPathStatus pathStatus(static_cast<edm::hlt::HLTState>(state));
79  tr[pathIndex] = pathStatus;
80  ++subIndex;
81  if (subIndex == 4) {
82  ++byteIndex;
83  subIndex = 0;
84  }
85  }
86  // Now make the decision, based on the HLTGlobalStatus tr,
87  // which we have created from the supplied array of results
88  masterElement_->returnStatus(tr);
89  return masterElement_->returnStatus(tr);
90  }
91 
93  Strings const& tr,
94  TreeElement* parentElement)
95  : op_(NonInit), trigBit_(-1) {
96  std::string str_ = trim(inputString);
97  children_.clear();
98  parent_ = parentElement;
99 
100  size_t offset_ = 0;
101  bool occurrences_ = false;
102 
103  if (str_.empty())
104  throw edm::Exception(edm::errors::Configuration) << "Syntax Error (empty element)";
105 
106  static const size_t bopsSize_ = 2;
107  static const std::string binaryOperators_[bopsSize_] = {"||", "&&"};
108 
109  for (size_t opr = 0; opr < bopsSize_; opr++) {
110  bool exitloop_ = false;
111  while (!exitloop_) {
112  size_t t_end_;
113 
114  std::string tmpStr = str_.substr(offset_);
115  t_end_ = tmpStr.find(binaryOperators_[opr]);
116  if (debug_)
117  std::cout << "offset: " << offset_ << " length: " << t_end_ << " string: " << tmpStr << std::endl;
118 
119  if (t_end_ == std::string::npos) {
120  // right side element
121  if (occurrences_)
122  children_.push_back(new TreeElement(tmpStr, tr, this));
123  break;
124  }
125  t_end_ += offset_;
126  if (t_end_ == 0 || t_end_ + 2 >= str_.size())
127  throw edm::Exception(edm::errors::Configuration) << "Syntax Error (operator is not unary)\n";
128  else {
129  // count bracket in preceeding part
130  size_t brackets_ = 0;
131  for (size_t k = offset_; k < t_end_; k++) {
132  if (str_.at(k) == '(') {
133  brackets_++;
134  } else if (str_.at(k) == ')') {
135  if (brackets_ == 0) {
136  throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
137  } else {
138  brackets_--;
139  }
140  }
141  }
142  if (brackets_ == 0) {
143  std::string next = str_.substr(offset_, t_end_ - offset_);
144  children_.push_back(new TreeElement(next, tr, this));
145  occurrences_ = true;
146  offset_ = t_end_ + 2;
147  } else {
148  // operator is inside brackets, find another
149  int bracketcnt_ = 0;
150  for (size_t k = offset_; true; k++) {
151  if (k >= str_.size()) {
152  if (bracketcnt_ != 0)
153  throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
154  exitloop_ = true;
155  if (occurrences_) {
156  children_.push_back(new TreeElement(str_.substr(offset_), tr, this));
157  }
158  break;
159  }
160  // look for another operator
161  if (k >= t_end_ + 2 && bracketcnt_ == 0) {
162  std::string temp = str_.substr(k);
163  size_t pos = temp.find(binaryOperators_[opr]);
164  if (pos == std::string::npos) {
165  exitloop_ = true;
166  if (occurrences_) {
167  children_.push_back(new TreeElement(str_.substr(offset_), tr, this));
168  }
169  break;
170  } else {
171  int brcount_ = 0;
172  for (size_t s = 0; s < pos; s++) {
173  // counting check of brackets from last position to operator
174  if (temp.at(pos) == '(') {
175  brcount_++;
176  } else if (temp.at(pos) == ')') {
177  if (brcount_ == 0) {
178  throw edm::Exception(edm::errors::Configuration) << "Syntax error (brackets)\n";
179  } else {
180  brcount_--;
181  }
182  }
183  }
184  if (brcount_ != 0)
185  throw edm::Exception(edm::errors::Configuration) << "Syntax error (brackets)\n";
186 
187  children_.push_back(new TreeElement(str_.substr(offset_, pos + k), tr, this));
188  offset_ = k + pos + 2;
189  occurrences_ = true;
190  if (offset_ >= str_.size())
191  throw edm::Exception(edm::errors::Configuration) << "Syntax Error (operator is not unary)\n";
192  break;
193  }
194  }
195 
196  if (str_.at(k) == '(')
197  bracketcnt_++;
198  if (str_.at(k) == ')')
199  bracketcnt_--;
200  }
201  }
202  }
203  }
204  if (occurrences_) {
205  if (opr == 0)
206  op_ = OR;
207  else
208  op_ = AND;
209  return;
210  }
211  }
212 
213  if (str_.empty()) {
214  op_ = AND;
215  if (debug_)
216  std::cout << "warning: empty element (will return true)" << std::endl;
217  return;
218  }
219 
220  if (str_.at(0) == '!') {
221  op_ = NOT;
222  std::string next = str_.substr(1);
223  children_.push_back(new TreeElement(next, tr, this));
224  return;
225  }
226  size_t beginBlock_ = str_.find('(');
227  size_t endBlock_ = str_.rfind(')');
228  bool found_lbracket = (beginBlock_ != std::string::npos);
229  bool found_rbracket = (endBlock_ != std::string::npos);
230 
231  if (found_lbracket != found_rbracket) {
232  throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
233  } else if (found_lbracket && found_rbracket) {
234  if (beginBlock_ >= endBlock_) {
235  throw edm::Exception(edm::errors::Configuration) << "Syntax Error (brackets)\n";
236  }
237  if (beginBlock_ != 0 || endBlock_ != str_.size() - 1)
238  throw edm::Exception(edm::errors::Configuration) << "Syntax Error (invalid character)\n";
239 
240  std::string next = str_.substr(beginBlock_ + 1, endBlock_ - beginBlock_ - 1);
241 
242  children_.push_back(new TreeElement(next, tr, this));
243  op_ = BR; // a bracket
244  return;
245  } else if (!found_lbracket && !found_rbracket) // assume single trigger or wildcard (parsing)
246  {
247  bool ignore_if_missing = true;
248  size_t chr_pos = str_.find('@');
249  if (chr_pos != std::string::npos) {
250  ignore_if_missing = false;
251  str_ = str_.substr(0, chr_pos);
252  }
253 
254  std::vector<Strings::const_iterator> matches = edm::regexMatch(tr, str_);
255  if (matches.empty()) {
256  if (!ignore_if_missing) // && !edm::is_glob(str_))
257  throw edm::Exception(edm::errors::Configuration) << "Trigger name (or match) not present";
258  else {
259  if (debug_)
260  std::cout << "TriggerSelector: Couldn't match any triggers from: " << str_ << std::endl
261  << " Node will not be added " << std::endl;
262  op_ = OR;
263  return;
264  }
265  }
266  if (matches.size() == 1) {
267  // Single Trigger match
268  trigBit_ = distance(tr.begin(), matches[0]);
269  if (debug_)
270  std::cout << "added trigger path: " << trigBit_ << std::endl;
271  return;
272  }
273  if (matches.size() > 1) {
274  op_ = OR;
275  for (size_t l = 0; l < matches.size(); l++)
276  children_.push_back(new TreeElement(*(matches[l]), tr, this));
277  }
278  }
279  }
280 
282  if (!input.empty()) {
283  std::string::size_type pos = input.find_first_not_of(' ');
284  if (pos != std::string::npos)
285  input.erase(0, pos);
286 
287  pos = input.find_last_not_of(' ');
288  if (pos != std::string::npos)
289  input.erase(pos + 1);
290  }
291  return input;
292  }
293 
296  if (!input.empty()) {
297  for (size_t pos = 0; pos < input.size(); pos++) {
298  char ch = input.at(pos);
299  if (ch == '&')
300  output.append("&amp;");
301  else
302  output.append(1, ch);
303  }
304  }
305  return output;
306  }
307 
309  if (children_.empty()) {
310  if (op_ == OR || op_ == NOT)
311  return false;
312  if (op_ == AND || op_ == BR)
313  return true;
314 
315  if (trigBit_ < 0 || (unsigned int)trigBit_ >= trStatus.size())
316  throw edm::Exception(edm::errors::Configuration) << "Internal Error: array out of bounds.";
317 
318  if ((trStatus[trigBit_]).state() == edm::hlt::Pass)
319  return true;
320  // else if ((trStatus[trigBit]).state() == edm::hlt::Fail) return false;
321 
322  return false;
323  }
324  if (op_ == NOT) { // NEGATION
325  return !children_[0]->returnStatus(trStatus);
326  }
327  if (op_ == BR) { // BRACKET
328  return children_[0]->returnStatus(trStatus);
329  }
330  if (op_ == AND) { // AND
331  bool status = true;
332  for (size_t i = 0; i < children_.size(); i++)
333  status = status && children_[i]->returnStatus(trStatus);
334  return status;
335  } else if (op_ == OR) { // OR
336  bool status = false;
337  for (size_t i = 0; i < children_.size(); i++)
338  status = status || children_[i]->returnStatus(trStatus);
339  return status;
340  }
342  << "Internal error: reached end of returnStatus(...), op:state = " << op_;
343  return false;
344  }
345 
347  for (std::vector<TreeElement*>::iterator it = children_.begin(); it != children_.end(); it++)
348  delete *it;
349  children_.clear();
350  }
351 } // namespace dqmservices
Definition: CLHEP.h:16
static std::string trim(std::string input)
uint16_t size_type
static std::string const input
Definition: EdmProvDump.cc:50
static std::string makeXMLString(std::string const &input)
unsigned int size() const
Get number of paths stored.
bool returnStatus(edm::HLTGlobalStatus const &trStatus) const
accept
Definition: HLTenums.h:18
TriggerSelector(Strings const &pathspecs, Strings const &names)
std::shared_ptr< TreeElement > masterElement_
TreeElement(std::string const &inputString, Strings const &tr, TreeElement *parentElement=nullptr)
void init(std::string const &path, Strings const &triggernames)
std::vector< std::vector< std::string >::const_iterator > regexMatch(std::vector< std::string > const &strings, std::regex const &regexp)
Definition: RegexMatch.cc:26
bool returnStatus(edm::HLTGlobalStatus const &trStatus) const
bool acceptEvent(edm::TriggerResults const &) const
std::shared_ptr< edm::EventSelector > eventSelector_
std::vector< TreeElement * > children_
std::vector< std::string > Strings