ATLAS Offline Software
Loading...
Searching...
No Matches
Trigger/TrigConfiguration/TrigConfL1Data/Root/HelperFunctions.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5
10#include <boost/algorithm/string/trim.hpp>
11#include "boost/algorithm/string.hpp"
12#include <iostream>
13#include <sstream>
14#include <cassert>
15#include <cstdlib>
16#include <algorithm>
17#include <string>
18#include <string_view>
19#include <charconv>
20#include <stdexcept>
21using namespace std;
22using namespace TrigConf;
23
24
25
26std::vector<std::string>
27TrigConf::split(const std::string& line, const std::string& del) {
28 std::vector<std::string> res;
29 boost::split(res, line, boost::is_any_of(del));
30 return res;
31}
32
33// helper method: removing all spaces at beginning and end of a string
34void
35TrigConf::strip(std::string& str) {
36 boost::algorithm::trim(str);
37}
38
39// helper method: replace tabs by single space
40void TrigConf::replaceTabs(std::string& str) {
41 std::replace(str.begin(), str.end(), '\t', ' ');
42}
43
44
45// helper function: all chars to lower chars
46void
47TrigConf::toLower(std::string& s) {
48 for(size_t i=0; i<s.size(); i++) s[i] += (s[i]>='A'&&s[i]<='Z')?'a'-'A':0;
49}
50
51
52
53namespace {
54
56 parseToken(const std::string& givenlogic,
57 std::string::size_type& pos,
58 const std::vector<std::string>& conditions,
59 const std::vector<TrigConf::TriggerThreshold*>& thrs);
60
61
63 parseExpr(const std::string& expr,
64 const std::vector<std::string>& conditions,
65 const std::vector<TrigConf::TriggerThreshold*>& thrs)
66 {
67
68
69 std::string::size_type pos = 0;
70 std::string::size_type last = expr.size();
71
72 TrigConf::TriggerItemNode * newNode = 0;
73
74 while(pos!=last) {
75
76 TrigConf::TriggerItemNode * nodeForToken = parseToken(expr, pos, conditions, thrs);
77
78 // deal with the end of the expression
79 if(pos == last) {
80 if(newNode==0)
81 return nodeForToken; // single token
82 newNode->addChild(nodeForToken);
83 return newNode;
84 }
85
86
87 // determine the &/| type from the next character
88 TriggerItemNode::NodeType typeFromChar;
89 if(expr[pos]=='&' || expr[pos]=='|') {
90 typeFromChar = TriggerItemNode::typeFromChar(expr[pos]);
91 } else {
92 throw std::logic_error(string("Unexpected character '") + expr[pos] + "' in expression '" + expr
93 + "' at position" + std::to_string(pos) + " [b]");
94 }
95
96
97 if(newNode==0) {
98 // create Node upon first encounter of & or |
99 newNode = new TriggerItemNode(typeFromChar);
100 } else {
101 // check that current character matches the type of the node
102 if(newNode->type() != typeFromChar) {
103 throw std::logic_error(string("Unexpected character '") + expr[pos] + "' in expression '" + expr
104 + "' at position" + std::to_string(pos) + " [c] Expected "
105 + TriggerItemNode::typeAsString(newNode->type()) );
106 }
107 }
108
109 newNode->addChild(nodeForToken);
110 pos++; // move beyond the &/|
111 }
112
113 return newNode;
114 }
115
116 std::string getSubExpr(const std::string &exp, const std::string::size_type begin) {
117 std::string::size_type pos = begin;
118 std::string::size_type last = exp.size();
119
120 int openBrackets = 0;
121 while(pos!=last) {
122 char cc = exp[pos];
123 if(cc=='(') openBrackets++;
124 if(cc==')') openBrackets--;
125 if(openBrackets==0 && (cc=='&' or cc=='|') ) break;
126 pos++;
127 }
128 if (openBrackets>0) {
129 std::cout << "ERROR: No matching closing bracket in '" << exp << "'" << std::endl;
130 assert(0);
131 }
132 std::string se(exp, begin, pos-begin);
133 // std::cout << "Subexp of '" << exp << "'[" << begin<<"] returns " << se << std::endl;
134 return se;
135 }
136
137
139 parseToken(const std::string& logic,
140 std::string::size_type& pos,
141 const std::vector<std::string>& conditions,
142 const std::vector<TrigConf::TriggerThreshold*>& thrs) {
143
144 // logic should be the definition of a node
145 //
146 // this means it needs to start with a number, '(', or '!'
147
148 //std::cout << "parse '" << givenlogic << "'" << std::endl;
149 //for(uint32_t i =0; i<conditions.size(); i++) std::cout << conditions[i] << std::endl;
150 //std::cout << thrs.size() << ")" << std::endl;
151
152
153 //std::string::size_type last = logic.size();
154
155 TriggerItemNode* thisNode(0);
156 // tokenize
157
158 // need three tokens to build a TriggerItemNode
159 char cur = logic[pos];
160 switch(cur) {
161 case '!':
162 {
163 pos++;
165 std::string se = getSubExpr(logic,pos);
166 thisNode->addChild( parse(se,conditions,thrs) );
167 pos += se.size();
168 break;
169 }
170 case '(':
171 {
172 std::string se = getSubExpr(logic,pos);
173 pos += se.size();
174 // should have outer parentheses (...)
175 std::string senop(se, 1, se.size()-2);
176 thisNode = parse(senop,conditions,thrs);
177 break;
178 }
179 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
180 {
181 std::string se = getSubExpr(logic,pos);
182 pos += se.size();
183 uint32_t condIdx = static_cast<uint32_t>(std::stoul(se));
184 thisNode = buildObjNode(condIdx, conditions, thrs);
185 break;
186 }
187 default:
188 {
189 std::string errMsg = "Unexpected character '";
190 errMsg += logic[pos];
191 errMsg += "' in expression '" + logic + "' at position" + std::to_string(pos) + " [a]";
192 throw std::logic_error(errMsg);
193 }
194 break;
195 }
196
197
198 return thisNode;
199 }
200}
201
202
203
205TrigConf::buildObjNode(uint32_t condIdx,
206 const vector<string>& conditions,
207 const vector<TrigConf::TriggerThreshold*>& thrs) {
208
210
211 try {
212 vector<string> condDef = split(conditions[condIdx-1], ",");
213
214 if(condDef.size()==1) { // internal trigger (condDef contains internal trigger name)
215
216 newNode->setInternalTrigger( condDef[0] );
217
218 } else { // threshold (condDef contains multiplicity, condName, and threshold name)
219 // set multiplicity
220 newNode->setMultiplicity(std::stoi(condDef[0]));
221 // find trigger threshold in list of all thresholds and set it in the TriggerItemNode
222 std::string& name = condDef[2];
223 if(thrs.size()>0) {
224 std::vector<TrigConf::TriggerThreshold*>::const_iterator thrIt = thrs.begin();
225 for(;thrIt!=thrs.end(); ++thrIt ) {
226 if((*thrIt)->name()==name) {
227 newNode->setTriggerThreshold(*thrIt);
228 break;
229 }
230 }
231 } else {
232 newNode->setThresholdName(name);
233 }
234 }
235 }
236 catch(const std::exception& e) {
237 std::cout << "Exeption caught in buildObjNode for " << conditions[condIdx-1] << ": " << e.what() << std::endl;
238 throw;
239 }
240 return newNode;
241}
242
243
245TrigConf::parse(const std::string& givenlogic,
246 const std::vector<std::string>& conditions,
247 const std::vector<TrigConf::TriggerThreshold*>& thrs) {
248
249 // balance expression
250 std::string expr = insertParenthesis(givenlogic);
251
252 // parse
253 TriggerItemNode* topNode = parseExpr(expr, conditions, thrs);
254
255 // wrap in an AND
256 if( topNode->type() != TriggerItemNode::AND) {
258 newNode->addChild(topNode);
259 topNode = newNode;
260 }
261
262 return topNode;
263}
264
265
266
267
268
269
270// pos: position of the current opening bracket
271std::string::size_type
272TrigConf::findClosingBracket(std::string::size_type pos,
273 const std::string& logic) {
274
275 pos++;
276 uint32_t openBrackets = 1;
277 std::string::size_type last = logic.size();
278 while(openBrackets>0 && pos!=last) {
279 if(logic[pos]==')') openBrackets--;
280 if(logic[pos]=='(') openBrackets++;
281 pos++;
282 }
283 if (openBrackets>0) {
284 std::string errMsg = "No matching closing bracket in '";
285 errMsg += logic;
286 errMsg += "'";
287 throw std::logic_error(errMsg);
288 }
289 return pos-1;
290}
291
292std::string
293TrigConf::insertParenthesis(const std::string& givenlogic) {
294 std::string logicWithPars(givenlogic);
295 size_t last = givenlogic.size()-1;
296 bool leadingAnd(false);
297 for(size_t pos = 0;pos<last;pos++) {
298 char c = logicWithPars[pos];
299 if(c=='(') { pos=findClosingBracket(pos,givenlogic); continue; }
300 if(c=='&') leadingAnd=true;
301 if(c=='|') {
302 if(leadingAnd) {
303 logicWithPars.insert(pos,")");
304 logicWithPars.insert(0,"(");
305 }
306 break;
307 }
308 }
309 return logicWithPars;
310}
311
312
313uint32_t
314TrigConf::bin2uint(const std::string& binary){
315 uint32_t value = 0;
316 auto [ptr, ec] = std::from_chars(binary.data(),
317 binary.data() + binary.size(), value, 2);
318 if (ec != std::errc{} || ptr != binary.data() + binary.size()) {
319 throw std::invalid_argument("Invalid binary string");
320 }
321 return value;
322}
323
324
325std::string
326TrigConf::uint2bin(uint32_t value, uint16_t width){
327 std::string s(width, '0');
328 for (uint16_t i = 0; i < width; ++i) {
329 s[width - 1 - i] = '0' + ((value >> i) & 1);
330 }
331 return s;
332}
std::pair< std::vector< unsigned int >, bool > res
const double width
static NodeType typeFromChar(const char &c)
static std::string typeAsString(NodeType)
void setInternalTrigger(L1DataDef::TriggerType x, unsigned int thresholdNumber)
void addChild(TriggerItemNode *node)
void setTriggerThreshold(TriggerThreshold *thr)
void setThresholdName(const std::string &thrname)
Forward iterator to traverse the main components of the trigger configuration.
Definition Config.h:22
std::string uint2bin(uint32_t uinteger, uint16_t width)
std::string insertParenthesis(const std::string &givenlogic)
std::string::size_type findClosingBracket(std::string::size_type pos, const std::string &logic)
std::vector< std::string > split(const std::string &line, const std::string &del=" ")
TrigConf::TriggerItemNode * buildObjNode(uint32_t condIdx, const std::vector< std::string > &conditions, const std::vector< TrigConf::TriggerThreshold * > &thrs)
std::vector< std::string > parse(std::string names)
STL namespace.
setEventNumber uint32_t