ATLAS Offline Software
Loading...
Searching...
No Matches
CxxUtils::ClassName Class Reference

Recursively separate out template arguments in a C++ class name. More...

#include <ClassName.h>

Collaboration diagram for CxxUtils::ClassName:

Classes

class  ExcBadClassName
 Exception to signal a malformed class name. More...
class  ExcMissingVariable
 Exception to signal a missing variable. More...
class  Rules
 A set of transformation rules to use with ClassName. More...

Public Types

typedef std::map< std::string, ClassNamematch_t
 Map used to hold variable assignments from matching.

Public Member Functions

 ClassName ()
 Default constructor.
 ClassName (const char *name)
 Parse a class name into component parts.
 ClassName (const std::string &name)
 Parse a class name into component parts.
 ClassName (const std::string &name, std::string::size_type &pos)
 Parse a class name into component parts.
void swap (ClassName &other)
 Swap this expression with another one.
bool isConst () const
 Get the const flag for this expression.
void setConst ()
 Set the const flag for this expression.
const std::string & name () const
 Return the root name of the expression.
std::string qualifiedName () const
 Return the namespace-qualified name of the expression.
std::string fullName () const
 Return the full name of the expression.
size_t ntargs () const
 Return number of template arguments.
const ClassNametarg (size_t i) const
 Return one template argument.
bool operator== (const ClassName &other) const
 Test two expressions for equality.
bool operator!= (const ClassName &other) const
 Test two expressions for inequality.
bool match (const ClassName &pattern, match_t &matches) const
 Match this expression against a pattern.
void subst (const match_t &matches)
 Substitute variables into this expression.
ClassName substCopy (const match_t &matches) const
 Return a copy of this expression with variables substituted.
void applyRules (const Rules &rules)
 Apply a set of transformation rules to this object.

Static Public Member Functions

static std::string applyRules (const std::string &name, const Rules &rules)
 Apply a set of transformation rules a class name.

Private Member Functions

void parse (const std::string &name, std::string::size_type &pos)
 Parse a string into a ClassName.
std::string parsePrimary (const std::string &name, std::string::size_type &pos)
 Parse a primary part of the class name.
void parseNamespace (const std::string &name, std::string::size_type &pos)
 Parse a namespace qualification.
void parseTemplateArgs (const std::string &name, std::string::size_type &pos)
 Parse the template part of a name.
void skipSpaces (const std::string &name, std::string::size_type &pos)
 Skip past spaces in a string.
bool match1 (const ClassName &pattern, bool topLevel, match_t &matches) const
 Match this expression against a pattern.
bool applyRules1 (const Rules &rules)
 Apply a set of transformation rules to this object.

Private Attributes

bool m_const
 Is this expression const?
std::vector< ClassNamem_namespace
 The containing namespace.
std::string m_name
 The primary name part of this expression.
std::vector< ClassNamem_targs
 The template arguments for this name.

Detailed Description

Recursively separate out template arguments in a C++ class name.

This class allows making some simple transformations of C++ class names. For example, given these rules:

rules.add ("std::vector<$T, std::allocator<$T> >",
"std::vector<$T>");
rules.add ("std::map<$K,$V, std::less<$K>, std::allocator<std::pair<const $K,$V> > >",
"std::map<$K,$V>");
rules.add ("DataVector<$T, $B>", "DataVector<$T>");
rules.add ("std::__1", "std");
A set of transformation rules to use with ClassName.
void add(const ClassName &pattern, const ClassName &replacement)
Add a new transformation rule.

then rules.apply can make transformations like this:

std::__1::vector<std::__1::vector<int, std::__1::allocator<int> >, std::__1::allocator<std::__1::vector<int, std::__1::allocator<int> > > >
-> std::vector<std::vector<int> >
std::map<int, float, std::less<int>, std::allocator<std::pair<const int, float> > >
-> std::map<int, float>
Derived DataVector<T>.
Definition DataVector.h:795

In slightly more detail: this class analyzes C++ class names. A name like

A::B<int, double>

is broken down like this:

  • Name: B.
  • Namespace: A.
  • Template arguments: int and double.

This is done recursively; both the namespace and template argument pieces can be further broken down like this. A name can also be marked as ‘const’, but no other parsing of C-like declarators is done.

Parsed names can be matched against simple patterns like this:

A::B<$T>

and the variable T gets set to the corresponding piece of the type being matched. For example, given the above pattern,

  • A::C<int> matches with T set to int.
  • A::C<const Foo<Bar> > matches with T set to const Foo<Bar>.

If the pattern were A::B<const $T>, then A::B<const int> would match with T set to int, but A::B<int> would not match.

However, the root name of a pattern may not be a variable; for example, you can't use A::$T<int> as a pattern.

You can also substitute variables back into a pattern; for example,

  • T=int into A::B<$T> gives A::B<int>.
  • T=const int into A::B<$T> gives A::B<const int>.
  • T=const int into A::B<const int> gives A::B<const int>.

Definition at line 100 of file CxxUtils/CxxUtils/ClassName.h.

Member Typedef Documentation

◆ match_t

typedef std::map<std::string, ClassName> CxxUtils::ClassName::match_t

Map used to hold variable assignments from matching.

Definition at line 200 of file CxxUtils/CxxUtils/ClassName.h.

Constructor & Destructor Documentation

◆ ClassName() [1/4]

Default constructor.

Needed for STL compatibility.

Definition at line 138 of file CxxUtils/Root/ClassName.cxx.

139 : m_const(false)
140{
141}
bool m_const
Is this expression const?

◆ ClassName() [2/4]

ClassName< T >::ClassName ( const char * name)

Parse a class name into component parts.

Parameters
nameThe name to parse.

Raises a BadClassName exception if the name isn't completely parsed.

Parameters
nameThe name to parse.

Raises a ExcBadClassName exception if the name isn't completely parsed.

Definition at line 150 of file CxxUtils/Root/ClassName.cxx.

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}
Exception to signal a malformed class name.
void skipSpaces(const std::string &name, std::string::size_type &pos)
Skip past spaces in a string.
const std::string & name() const
Return the root name of the expression.
void parse(const std::string &name, std::string::size_type &pos)
Parse a string into a ClassName.

◆ ClassName() [3/4]

ClassName< T >::ClassName ( const std::string & name)

Parse a class name into component parts.

Parameters
nameThe name to parse.

Raises a BadClassName exception if the name isn't completely parsed.

Parameters
nameThe name to parse.

Raises a ExcBadClassName exception if the name isn't completely parsed.

Definition at line 168 of file CxxUtils/Root/ClassName.cxx.

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}

◆ ClassName() [4/4]

ClassName< T >::ClassName ( const std::string & name,
std::string::size_type & pos )

Parse a class name into component parts.

Parameters
nameString containing the name to parse.
posPosition in the string at which parsing should start.

pos is updated to point to past the point where parsing stopped.

Definition at line 186 of file CxxUtils/Root/ClassName.cxx.

187 : m_const (false)
188{
189 parse (name, pos);
190}

Member Function Documentation

◆ applyRules() [1/2]

void ClassName< T >::applyRules ( const Rules & rules)

Apply a set of transformation rules to this object.

Parameters
rulesThe set of rules to apply.

Recursively walk this expression, trying to apply the transformation rules in rules. If any matches are found, this expression is modified in-place and the walk is repeated. This function terminates when no further matches are found.

Warning: An infinite loop is possible if the replacement for a pattern can always be matched by another pattern.

Definition at line 410 of file CxxUtils/Root/ClassName.cxx.

411{
412 while (applyRules1 (rules))
413 ;
414}
bool applyRules1(const Rules &rules)
Apply a set of transformation rules to this object.

◆ applyRules() [2/2]

std::string ClassName< T >::applyRules ( const std::string & name,
const Rules & rules )
static

Apply a set of transformation rules a class name.

param The name of the class to transform.

Parameters
rulesThe set of rules to apply.

This is just shorthand for

cn.applyRules (rules);
return cn.fullName();
ClassName()
Default constructor.

Definition at line 430 of file CxxUtils/Root/ClassName.cxx.

432{
433 ClassName cn (name);
434 cn.applyRules (rules);
435 return cn.fullName();
436}

◆ applyRules1()

bool ClassName< T >::applyRules1 ( const Rules & rules)
private

Apply a set of transformation rules to this object.

Parameters
rulesThe set of rules to apply.

Recursively walk this expression, trying to apply the transformation rules in rules. If any matches are found, this expression is modified in-place.

Returns true if any matches were found.

Definition at line 674 of file CxxUtils/Root/ClassName.cxx.

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}
std::vector< ClassName > m_namespace
The containing namespace.
std::vector< ClassName > m_targs
The template arguments for this name.

◆ fullName()

std::string ClassName< T >::fullName ( ) const

Return the full name of the expression.

Definition at line 252 of file CxxUtils/Root/ClassName.cxx.

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}
std::string qualifiedName() const
Return the namespace-qualified name of the expression.

◆ isConst()

bool ClassName< T >::isConst ( ) const

Get the const flag for this expression.

Definition at line 209 of file CxxUtils/Root/ClassName.cxx.

210{
211 return m_const;
212}

◆ match()

bool ClassName< T >::match ( const ClassName & pattern,
match_t & matches ) const

Match this expression against a pattern.

Parameters
patternThe pattern to match.
[out]matchesDictionary of pattern substitutions.

Return true if pattern matches the current expression. pattern may contain dummy variables of the form $T. On a successful return, the map matches contains the variable assignments needed for the match.

Definition at line 339 of file CxxUtils/Root/ClassName.cxx.

340{
341 matches.clear();
342 return match1 (pattern, true, matches);
343}
bool match1(const ClassName &pattern, bool topLevel, match_t &matches) const
Match this expression against a pattern.

◆ match1()

bool ClassName< T >::match1 ( const ClassName & pattern,
bool topLevel,
match_t & matches ) const
private

Match this expression against a pattern.

Parameters
patternThe pattern to match.
topLevelTrue if this is the outermost level of matching.
[out]matchesDictionary of pattern substitutions.

Return true if pattern matches the current expression. pattern may contain dummy variables of the form $T. On a successful return, the map matches contains the variable assignments needed for the match.

Definition at line 603 of file CxxUtils/Root/ClassName.cxx.

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}
std::string m_name
The primary name part of this expression.

◆ name()

const std::string & ClassName< T >::name ( ) const

Return the root name of the expression.

In A::B<C>, the root name is B.

Definition at line 229 of file CxxUtils/Root/ClassName.cxx.

230{
231 return m_name;
232}

◆ ntargs()

size_t ClassName< T >::ntargs ( ) const

Return number of template arguments.

Definition at line 275 of file CxxUtils/Root/ClassName.cxx.

276{
277 return m_targs.size();
278}

◆ operator!=()

bool ClassName< T >::operator!= ( const ClassName & other) const

Test two expressions for inequality.

Definition at line 323 of file CxxUtils/Root/ClassName.cxx.

324{
325 return !(*this==other);
326}

◆ operator==()

bool ClassName< T >::operator== ( const ClassName & other) const

Test two expressions for equality.

Definition at line 294 of file CxxUtils/Root/ClassName.cxx.

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}

◆ parse()

void ClassName< T >::parse ( const std::string & name,
std::string::size_type & pos )
private

Parse a string into a ClassName.

Parameters
nameThe string containing the name.
posPosition in the string to start parsing.

On return, pos will be updated to point just past the last character consumed.

Definition at line 447 of file CxxUtils/Root/ClassName.cxx.

448{
449 m_name = parsePrimary (name, pos);
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] == '<')
462 parseTemplateArgs (name, pos);
463 else if (name[pos] == ':' && pos+1 < name.size() && name[pos+1] == ':')
464 parseNamespace (name, pos);
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}
std::string parsePrimary(const std::string &name, std::string::size_type &pos)
Parse a primary part of the class name.
void parseNamespace(const std::string &name, std::string::size_type &pos)
Parse a namespace qualification.
void parseTemplateArgs(const std::string &name, std::string::size_type &pos)
Parse the template part of a name.

◆ parseNamespace()

void ClassName< T >::parseNamespace ( const std::string & name,
std::string::size_type & pos )
private

Parse a namespace qualification.

Parameters
nameThe string containing the name.
posPosition in the string to start parsing.

When this is called, the namespace part has already been parsed, and the next two characters in name are ::. This reads in the remainder of the string as a ClassName, and then moves it inside the namespace given by the current object.

On return, pos will be updated to point just past the last character consumed.

Definition at line 522 of file CxxUtils/Root/ClassName.cxx.

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}
void setConst()
Set the const flag for this expression.

◆ parsePrimary()

std::string ClassName< T >::parsePrimary ( const std::string & name,
std::string::size_type & pos )
private

Parse a primary part of the class name.

Parameters
nameThe string containing the name.
posPosition in the string to start parsing.

The primary part of the class name is a string without namespace and template delimiters.

On return, pos will be updated to point just past the last character consumed.

Definition at line 488 of file CxxUtils/Root/ClassName.cxx.

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}

◆ parseTemplateArgs()

void ClassName< T >::parseTemplateArgs ( const std::string & name,
std::string::size_type & pos )
private

Parse the template part of a name.

Parameters
nameThe string containing the name.
posPosition in the string to start parsing.

When this is called, the qualified name part of the name has already been parsed, and the next character in name is ::. This reads in template arguments from name.

On return, pos will be updated to point just past the last character consumed.

Definition at line 554 of file CxxUtils/Root/ClassName.cxx.

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}

◆ qualifiedName()

std::string ClassName< T >::qualifiedName ( ) const

Return the namespace-qualified name of the expression.

Return the root name of the expression.

In A::B<C>, this is A::B.

In A::B<C>, the root name is B.

Definition at line 240 of file CxxUtils/Root/ClassName.cxx.

241{
242 std::string nsname;
243 if (m_namespace.size() > 0)
244 nsname = m_namespace[0].fullName() + "::";
245 return nsname + m_name;
246}

◆ setConst()

void ClassName< T >::setConst ( )

Set the const flag for this expression.

Definition at line 218 of file CxxUtils/Root/ClassName.cxx.

219{
220 m_const = true;
221}

◆ skipSpaces()

void ClassName< T >::skipSpaces ( const std::string & name,
std::string::size_type & pos )
private

Skip past spaces in a string.

Parameters
nameThe string containing the name.
posPosition in the string to start skipping.

On return, pos will be updated to point just past the last character consumed.

Definition at line 584 of file CxxUtils/Root/ClassName.cxx.

586{
587 while (pos < name.size() && name[pos] == ' ')
588 ++pos;
589}

◆ subst()

void ClassName< T >::subst ( const match_t & matches)

Substitute variables into this expression.

Parameters
Thedictionary of variables to substitute.

If this expression contains variables like $T, they are replaced with the corresponding values from matches. If a variable is present in the expression but is not in matches, ExcMissingVariable is thrown.

The substitutions are made in-place.

Definition at line 357 of file CxxUtils/Root/ClassName.cxx.

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}
Exception to signal a missing variable.

◆ substCopy()

ClassName ClassName< T >::substCopy ( const match_t & matches) const

Return a copy of this expression with variables substituted.

Parameters
Thedictionary of variables to substitute.

If this expression contains variables like $T, they are replaced with the corresponding values from matches. If a variable is present in the expression but is not in matches, ExcMissingVariable is thrown.

The substitutions are made in a copy of the expression, which is returned.

Definition at line 390 of file CxxUtils/Root/ClassName.cxx.

391{
392 ClassName cn (*this);
393 cn.subst (matches);
394 return cn;
395}

◆ swap()

void ClassName< T >::swap ( ClassName & other)

Swap this expression with another one.

Parameters
otherThe other expression with which to swap.

Definition at line 197 of file CxxUtils/Root/ClassName.cxx.

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}
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)

◆ targ()

const ClassName & ClassName< T >::targ ( size_t i) const

Return one template argument.

Parameters
iIndex of the argument to return.

Definition at line 285 of file CxxUtils/Root/ClassName.cxx.

286{
287 return m_targs.at (i);
288}

Member Data Documentation

◆ m_const

bool CxxUtils::ClassName::m_const
private

Is this expression const?

Definition at line 477 of file CxxUtils/CxxUtils/ClassName.h.

◆ m_name

std::string CxxUtils::ClassName::m_name
private

The primary name part of this expression.

Definition at line 486 of file CxxUtils/CxxUtils/ClassName.h.

◆ m_namespace

std::vector<ClassName> CxxUtils::ClassName::m_namespace
private

The containing namespace.

This vector is always either 0 or 1 elements long; this is a way of getting something sort of like a pointer but with completely automatic management.

Definition at line 483 of file CxxUtils/CxxUtils/ClassName.h.

◆ m_targs

std::vector<ClassName> CxxUtils::ClassName::m_targs
private

The template arguments for this name.

Definition at line 489 of file CxxUtils/CxxUtils/ClassName.h.


The documentation for this class was generated from the following files: