ATLAS Offline Software
ClassName.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
12 #include "CxxUtils/ClassName.h"
13 #include <cassert>
14 
15 
16 namespace CxxUtils {
17 
18 
19 
24  : std::runtime_error ("ExcBadClassName: Malformed class name: `" +
25  name + "'")
26 {
27 }
28 
29 
34  : std::runtime_error ("ExcMissingVariable: Variable `" + var +
35  "' referenced in substitution but not present "
36  "in matches map.")
37 {
38 }
39 
40 
44 size_t ClassName::Rules::size() const
45 {
46  return m_rules.size();
47 }
48 
49 
61  const ClassName& replacement)
62 {
63  m_rules.insert (std::make_pair (pattern.name(),
64  std::make_pair (pattern, replacement)));
65 }
66 
67 
79  ClassName&& replacement)
80 {
81  std::string name = pattern.name();
82  m_rules.insert (std::make_pair (name,
83  std::make_pair (std::move(pattern),
84  std::move(replacement))));
85 }
86 
87 
100 {
101  bool ret = false;
102  rulemap_t::const_iterator it = m_rules.find (cn.name());
103  while (it != m_rules.end() && it->first == cn.name()) {
104  ClassName::match_t matches;
105  if (cn.match (it->second.first, matches)) {
106  bool const_save = cn.isConst();
107  cn = it->second.second.substCopy (matches);
108  if (const_save) {
109  cn.setConst();
110  }
111  ret = true;
112  }
113  ++it;
114  }
115  return ret;
116 }
117 
118 
127 std::string ClassName::Rules::apply (const std::string& name) const
128 {
129  return ClassName::applyRules (name, *this);
130 }
131 
132 
139  : m_const(false)
140 {
141 }
142 
143 
151  : m_const(false)
152 {
153  std::string sname = name;
154  std::string::size_type pos = 0;
155  parse (sname, pos);
156  skipSpaces (sname, pos);
157  if (pos != sname.size())
158  throw ExcBadClassName (sname);
159 }
160 
161 
168 ClassName::ClassName (const std::string& name)
169  : m_const(false)
170 {
171  std::string::size_type pos = 0;
172  parse (name, pos);
173  skipSpaces (name, pos);
174  if (pos != name.size())
175  throw ExcBadClassName (name);
176 }
177 
178 
186 ClassName::ClassName (const std::string& name, std::string::size_type& pos)
187  : m_const (false)
188 {
189  parse (name, pos);
190 }
191 
192 
198 {
199  std::swap (m_const, other.m_const);
200  std::swap (m_namespace, other.m_namespace);
201  std::swap (m_name, other.m_name);
202  m_targs.swap (other.m_targs);
203 }
204 
205 
209 bool ClassName::isConst() const
210 {
211  return m_const;
212 }
213 
214 
219 {
220  m_const = true;
221 }
222 
223 
229 const std::string& ClassName::name() const
230 {
231  return m_name;
232 }
233 
234 
240 std::string ClassName::qualifiedName() const
241 {
242  std::string nsname;
243  if (m_namespace.size() > 0)
244  nsname = m_namespace[0].fullName() + "::";
245  return nsname + m_name;
246 }
247 
248 
252 std::string ClassName::fullName() const
253 {
254  std::string name = qualifiedName();
255  if (m_const)
256  name = "const " + name;
257  if (m_targs.size() > 0) {
258  name += '<';
259  for (const ClassName& cn : m_targs) {
260  if (name[name.size()-1] != '<')
261  name += ',';
262  name += cn.fullName();
263  }
264  if (name[name.size()-1] == '>')
265  name += ' ';
266  name += '>';
267  }
268  return name;
269 }
270 
271 
275 size_t ClassName::ntargs() const
276 {
277  return m_targs.size();
278 }
279 
280 
285 const ClassName& ClassName::targ (size_t i) const
286 {
287  return m_targs.at (i);
288 }
289 
290 
295 {
296  if (m_name != other.m_name)
297  return false;
298 
299  if (m_const != other.m_const)
300  return false;
301 
302  if (m_namespace.size() != other.m_namespace.size())
303  return false;
304 
305  if (m_targs.size() != other.m_targs.size())
306  return false;
307 
308  if (m_namespace.size() > 0 && m_namespace[0] != other.m_namespace[0])
309  return false;
310 
311  for (size_t i = 0; i < m_targs.size(); ++i) {
312  if (m_targs[i] != other.m_targs[i])
313  return false;
314  }
315 
316  return true;
317 }
318 
319 
324 {
325  return !(*this==other);
326 }
327 
328 
339 bool ClassName::match (const ClassName& pattern, match_t& matches) const
340 {
341  matches.clear();
342  return match1 (pattern, true, matches);
343 }
344 
345 
357 void ClassName::subst (const match_t& matches)
358 {
359  if (m_name[0] == '$') {
360  std::string var = m_name.substr (1, std::string::npos);
361  match_t::const_iterator it = matches.find (var);
362  if (it != matches.end()) {
363  bool const_save = m_const;
364  *this = it->second;
365  m_const |= const_save;
366  }
367  else {
368  throw ExcMissingVariable (var);
369  }
370  }
371 
372  for (ClassName& c : m_namespace)
373  c.subst (matches);
374  for (ClassName& c : m_targs)
375  c.subst (matches);
376 }
377 
378 
390 ClassName ClassName::substCopy (const match_t& matches) const
391 {
392  ClassName cn (*this);
393  cn.subst (matches);
394  return cn;
395 }
396 
397 
410 void ClassName::applyRules (const Rules& rules)
411 {
412  while (applyRules1 (rules))
413  ;
414 }
415 
416 
430 std::string ClassName::applyRules (const std::string& name,
431  const Rules& rules)
432 {
433  ClassName cn (name);
434  cn.applyRules (rules);
435  return cn.fullName();
436 }
437 
438 
447 void ClassName::parse (const std::string& name, std::string::size_type& pos)
448 {
450  if (m_name.compare (0, 6, "const ") ==0) {
451  m_const = true;
452  m_name.erase (0, 6);
453  }
454  if (m_name.size() >= 6 && m_name.compare (m_name.size()-6, 6, " const") ==0) {
455  m_const = true;
456  m_name.erase (m_name.size()-6, 6);
457  }
458 
459  skipSpaces (name, pos);
460  while (pos < name.size()) {
461  if (name[pos] == '<')
463  else if (name[pos] == ':' && pos+1 < name.size() && name[pos+1] == ':')
465  else
466  break;
467  }
468  skipSpaces (name, pos);
469  if (name.compare (pos, 5, "const")==0) {
470  m_const = true;
471  pos += 5;
472  }
473 }
474 
475 
487 std::string
488 ClassName::parsePrimary (const std::string& name, std::string::size_type& pos)
489 {
490  skipSpaces (name, pos);
491  std::string out;
492  size_t nest = 0;
493  while (pos < name.size()) {
494  char c = name[pos];
495  if (c == '(')
496  ++nest;
497  else if (c == ')' && nest > 0)
498  --nest;
499  else if (nest == 0 && (c == '<' || c == '>' || c == ',' || c == ':'))
500  break;
501 
502  out += c;
503  ++pos;
504  }
505  return out;
506 }
507 
508 
522 void ClassName::parseNamespace (const std::string& name,
523  std::string::size_type& pos)
524 {
525  assert (pos+1 < name.size() && name[pos] == ':' && name[pos+1] == ':');
526  pos += 2;
527  skipSpaces (name, pos);
528 
529  ClassName ns (name, pos);
530  ns.swap (*this);
531  if (ns.isConst()) {
532  this->setConst();
533  ns.m_const = false;
534  }
535  ClassName* p = this;
536  while (p->m_namespace.size() > 0)
537  p = &p->m_namespace[0];
538  p->m_namespace.push_back (std::move(ns));
539 }
540 
541 
554 void ClassName::parseTemplateArgs (const std::string& name,
555  std::string::size_type& pos)
556 {
557  assert (pos < name.size() && name[pos] == '<');
558  ++pos;
559  while (true) {
560  skipSpaces (name, pos);
561  m_targs.emplace_back (name, pos);
562  skipSpaces (name, pos);
563  if (pos == name.size()) break;
564  if (name[pos] == '>') {
565  ++pos;
566  break;
567  }
568  else if (name[pos] == ',')
569  ++pos;
570  else
571  break;
572  }
573 }
574 
575 
584 void ClassName::skipSpaces (const std::string& name,
585  std::string::size_type& pos)
586 {
587  while (pos < name.size() && name[pos] == ' ')
588  ++pos;
589 }
590 
591 
604  bool topLevel,
605  match_t& matches) const
606 {
607  if (pattern.m_name[0] == '$') {
608  std::string var = pattern.m_name.substr (1, std::string::npos);
609  match_t::iterator it = matches.find (var);
610  if (it != matches.end()) {
611  if (pattern.m_const && !it->second.m_const) {
612  ClassName cn (it->second);
613  cn.setConst();
614  return *this == cn;
615  }
616  return *this == it->second;
617  }
618 
619  matches[var] = *this;
620  if (pattern.m_const) {
621  if (m_const)
622  matches[var].m_const = false;
623  else
624  return false;
625  }
626  return true;
627  }
628 
629  // Require that const qualifiers match.
630  // However, if this is the top level, we allow a pattern with no explicit
631  // const to match something that is const. Otherwise, we'd need to repeat
632  // all patterns for the const case.
633  if (topLevel) {
634  if (pattern.m_const && !m_const)
635  return false;
636  }
637  else if (m_const != pattern.m_const) {
638  return false;
639  }
640 
641  if (m_name != pattern.m_name)
642  return false;
643 
644  if (m_namespace.size() != pattern.m_namespace.size())
645  return false;
646 
647  if (m_targs.size() != pattern.m_targs.size())
648  return false;
649 
650  if (m_namespace.size() > 0) {
651  if (!m_namespace[0].match1 (pattern.m_namespace[0], false, matches))
652  return false;
653  }
654 
655  for (size_t i = 0; i < m_targs.size(); i++) {
656  if (!m_targs[i].match1 (pattern.m_targs[i], false, matches))
657  return false;
658  }
659 
660  return true;
661 }
662 
663 
674 bool ClassName::applyRules1 (const Rules& rules)
675 {
676  bool ret = rules.applyTo (*this);
677 
678  if (m_namespace.size() > 0)
679  ret |= m_namespace[0].applyRules1 (rules);
680 
681  for (size_t i = 0; i < m_targs.size(); i++)
682  ret |= m_targs[i].applyRules1 (rules);
683 
684  return ret;
685 }
686 
687 
688 } // namespace CxxUtils
689 
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
mergePhysValFiles.pattern
pattern
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:26
beamspotnt.var
var
Definition: bin/beamspotnt.py:1394
ClassName.h
Recursively separate out template arguments in a C++ class name.
CxxUtils::ClassName::Rules::add
void add(const ClassName &pattern, const ClassName &replacement)
Add a new transformation rule.
Definition: ClassName.cxx:60
CxxUtils::ClassName::Rules::size
size_t size() const
Return the number of defined rules.
Definition: ClassName.cxx:44
CxxUtils::ClassName::isConst
bool isConst() const
Get the const flag for this expression.
Definition: ClassName.cxx:209
CxxUtils::ClassName::name
const std::string & name() const
Return the root name of the expression.
Definition: ClassName.cxx:229
CxxUtils::ClassName::subst
void subst(const match_t &matches)
Substitute variables into this expression.
Definition: ClassName.cxx:357
CxxUtils::ClassName::swap
void swap(ClassName &other)
Swap this expression with another one.
Definition: ClassName.cxx:197
CxxUtils::ClassName::ExcBadClassName::ExcBadClassName
ExcBadClassName(const std::string &name)
Exception to signal a malformed class name.
Definition: ClassName.cxx:23
CxxUtils::ClassName::setConst
void setConst()
Set the const flag for this expression.
Definition: ClassName.cxx:218
CxxUtils::ClassName::ExcMissingVariable
Exception to signal a missing variable.
Definition: CxxUtils/CxxUtils/ClassName.h:120
skel.it
it
Definition: skel.GENtoEVGEN.py:396
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:71
CxxUtils::ClassName::ExcMissingVariable::ExcMissingVariable
ExcMissingVariable(const std::string &var)
Exception to signal a missing variable.
Definition: ClassName.cxx:33
CxxUtils::ClassName::parse
void parse(const std::string &name, std::string::size_type &pos)
Parse a string into a ClassName.
Definition: ClassName.cxx:447
CxxUtils::ClassName::m_const
bool m_const
Is this expression const?
Definition: CxxUtils/CxxUtils/ClassName.h:477
CxxUtils::ClassName::parseNamespace
void parseNamespace(const std::string &name, std::string::size_type &pos)
Parse a namespace qualification.
Definition: ClassName.cxx:522
CxxUtils::ClassName::Rules::applyTo
bool applyTo(ClassName &cn) const
Apply the set of transformation rules to a class name object.
Definition: ClassName.cxx:99
CxxUtils::ClassName::skipSpaces
void skipSpaces(const std::string &name, std::string::size_type &pos)
Skip past spaces in a string.
Definition: ClassName.cxx:584
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
CxxUtils::ClassName::ntargs
size_t ntargs() const
Return number of template arguments.
Definition: ClassName.cxx:275
CxxUtils::ClassName
Recursively separate out template arguments in a C++ class name.
Definition: CxxUtils/CxxUtils/ClassName.h:101
lumiFormat.i
int i
Definition: lumiFormat.py:85
CxxUtils::ClassName::operator!=
bool operator!=(const ClassName &other) const
Test two expressions for inequality.
Definition: ClassName.cxx:323
CxxUtils::ClassName::m_namespace
std::vector< ClassName > m_namespace
The containing namespace.
Definition: CxxUtils/CxxUtils/ClassName.h:483
CxxUtils::ClassName::m_targs
std::vector< ClassName > m_targs
The template arguments for this name.
Definition: CxxUtils/CxxUtils/ClassName.h:489
CxxUtils::ClassName::operator==
bool operator==(const ClassName &other) const
Test two expressions for equality.
Definition: ClassName.cxx:294
CxxUtils::ClassName::parseTemplateArgs
void parseTemplateArgs(const std::string &name, std::string::size_type &pos)
Parse the template part of a name.
Definition: ClassName.cxx:554
CxxUtils
Definition: aligned_vector.h:29
CxxUtils::ClassName::fullName
std::string fullName() const
Return the full name of the expression.
Definition: ClassName.cxx:252
CxxUtils::ClassName::Rules::apply
std::string apply(const std::string &name) const
Apply transformations to a class name.
Definition: ClassName.cxx:127
CxxUtils::ClassName::Rules
A set of transformation rules to use with ClassName.
Definition: CxxUtils/CxxUtils/ClassName.h:130
WriteCalibToCool.swap
swap
Definition: WriteCalibToCool.py:94
CxxUtils::ClassName::targ
const ClassName & targ(size_t i) const
Return one template argument.
Definition: ClassName.cxx:285
CxxUtils::ClassName::match1
bool match1(const ClassName &pattern, bool topLevel, match_t &matches) const
Match this expression against a pattern.
Definition: ClassName.cxx:603
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
CxxUtils::ClassName::applyRules1
bool applyRules1(const Rules &rules)
Apply a set of transformation rules to this object.
Definition: ClassName.cxx:674
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
CxxUtils::ClassName::applyRules
void applyRules(const Rules &rules)
Apply a set of transformation rules to this object.
Definition: ClassName.cxx:410
CxxUtils::ClassName::ExcBadClassName
Exception to signal a malformed class name.
Definition: CxxUtils/CxxUtils/ClassName.h:109
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
CxxUtils::ClassName::match_t
std::map< std::string, ClassName > match_t
Map used to hold variable assignments from matching.
Definition: CxxUtils/CxxUtils/ClassName.h:200
python.SystemOfUnits.ns
int ns
Definition: SystemOfUnits.py:130
CxxUtils::ClassName::ClassName
ClassName()
Default constructor.
Definition: ClassName.cxx:138
CxxUtils::ClassName::parsePrimary
std::string parsePrimary(const std::string &name, std::string::size_type &pos)
Parse a primary part of the class name.
Definition: ClassName.cxx:488
CxxUtils::ClassName::substCopy
ClassName substCopy(const match_t &matches) const
Return a copy of this expression with variables substituted.
Definition: ClassName.cxx:390
python.compressB64.c
def c
Definition: compressB64.py:93
CxxUtils::ClassName::m_name
std::string m_name
The primary name part of this expression.
Definition: CxxUtils/CxxUtils/ClassName.h:486
CxxUtils::ClassName::qualifiedName
std::string qualifiedName() const
Return the namespace-qualified name of the expression.
Definition: ClassName.cxx:240
CxxUtils::ClassName::match
bool match(const ClassName &pattern, match_t &matches) const
Match this expression against a pattern.
Definition: ClassName.cxx:339