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