#ifndef REFLEX_BUILD
#define REFLEX_BUILD
#endif
#include "Reflex/Tools.h"
#include "Reflex/Kernel.h"
#include "Reflex/Type.h"
#include "Reflex/internal/OwnedMember.h"
#include <cstring>
#if defined(__GNUC__)
#include <cxxabi.h>
#elif defined(__SUNPRO_CC)
#include <demangle.h>
#endif
using namespace Reflex;
namespace FTypes {
static const std::type_info & Char() { static const std::type_info & t = Type::ByName("char").TypeInfo(); return t; }
static const std::type_info & SigChar() { static const std::type_info & t = Type::ByName("signed char").TypeInfo(); return t; }
static const std::type_info & ShoInt() { static const std::type_info & t = Type::ByName("short int").TypeInfo(); return t; }
static const std::type_info & Int() { static const std::type_info & t = Type::ByName("int").TypeInfo(); return t; }
static const std::type_info & LonInt() { static const std::type_info & t = Type::ByName("long int").TypeInfo(); return t; }
static const std::type_info & UnsChar() { static const std::type_info & t = Type::ByName("unsigned char").TypeInfo(); return t; }
static const std::type_info & UnsShoInt() { static const std::type_info & t = Type::ByName("unsigned short int").TypeInfo(); return t; }
static const std::type_info & UnsInt() { static const std::type_info & t = Type::ByName("unsigned int").TypeInfo(); return t; }
static const std::type_info & UnsLonInt() { static const std::type_info & t = Type::ByName("unsigned long int").TypeInfo(); return t; }
static const std::type_info & Bool() { static const std::type_info & t = Type::ByName("bool").TypeInfo(); return t; }
static const std::type_info & Float() { static const std::type_info & t = Type::ByName("float").TypeInfo(); return t; }
static const std::type_info & Double() { static const std::type_info & t = Type::ByName("double").TypeInfo(); return t; }
static const std::type_info & LonDouble() { static const std::type_info & t = Type::ByName("long double").TypeInfo(); return t; }
static const std::type_info & Void() { static const std::type_info & t = Type::ByName("void").TypeInfo(); return t; }
static const std::type_info & LonLong() { static const std::type_info & t = Type::ByName("long long").TypeInfo(); return t; }
static const std::type_info & UnsLonLong() { static const std::type_info & t = Type::ByName("unsigned long long").TypeInfo(); return t; }
}
static std::string splitScopedName( const std::string & nam,
bool returnScope,
bool startFromLeft = false ) {
size_t pos = 0;
if ( startFromLeft ) pos = Tools::GetFirstScopePosition( nam );
else pos = Tools::GetBasePosition( nam );
if ( pos != 0 ) {
if ( returnScope ) return nam.substr(0,pos-2);
else return nam.substr(pos);
}
else {
if ( returnScope ) return "";
else return nam;
}
}
EFUNDAMENTALTYPE Tools::FundamentalType( const Type & typ ) {
const std::type_info & tid = typ.FinalType().TypeInfo();
if ( tid == FTypes::Char() ) return kCHAR;
if ( tid == FTypes::SigChar() ) return kSIGNED_CHAR;
if ( tid == FTypes::ShoInt() ) return kSHORT_INT;
if ( tid == FTypes::Int() ) return kINT;
if ( tid == FTypes::LonInt() ) return kLONG_INT;
if ( tid == FTypes::UnsChar() ) return kUNSIGNED_CHAR;
if ( tid == FTypes::UnsShoInt() ) return kUNSIGNED_SHORT_INT;
if ( tid == FTypes::UnsInt() ) return kUNSIGNED_INT;
if ( tid == FTypes::UnsLonInt() ) return kUNSIGNED_LONG_INT;
if ( tid == FTypes::Bool() ) return kBOOL;
if ( tid == FTypes::Float() ) return kFLOAT;
if ( tid == FTypes::Double() ) return kDOUBLE;
if ( tid == FTypes::LonDouble() ) return kLONG_DOUBLE;
if ( tid == FTypes::Void() ) return kVOID;
if ( tid == FTypes::LonLong() ) return kLONGLONG;
if ( tid == FTypes::UnsLonLong() ) return kULONGLONG;
return kNOTFUNDAMENTAL;
}
std::string Tools::BuildTypeName( Type & t,
unsigned int ) {
std::string mod = "";
if ( t.IsConstVolatile()) mod = "const volatile";
else if ( t.IsConst()) mod = "const";
else if ( t.IsVolatile()) mod = "volatile";
std::string name = t.Name();
if (t.IsPointer() || t.IsPointerToMember()) name += " " + mod;
else name = mod + " " + name;
if ( t.IsReference()) name += "&";
return name;
}
std::vector<std::string> Tools::GenTemplateArgVec( const std::string & Name ) {
std::vector<std::string> vec;
std::string tname;
GetTemplateComponents( Name, tname, vec);
return vec;
}
void Tools::GetTemplateComponents( const std::string & Name, std::string &templatename, std::vector<std::string> &args) {
size_t basepos = Tools::GetBasePosition( Name );
const char *argpos = strstr( Name.c_str()+basepos, "<" );
if (!argpos) return;
size_t pos1 = argpos - Name.c_str();
templatename = Name.substr(0, pos1);
size_t pos2 = Name.rfind(">");
if ( pos2 == std::string::npos ) return;
std::string tpl = Name.substr(pos1+1, pos2-pos1-1);
if (tpl[tpl.size()-1] == ' ') {
tpl = tpl.substr(0,tpl.size()-1);
}
unsigned int par = 0;
std::string argName;
char c = 0;
for (std::string::size_type i = 0; i < tpl.length(); ++i) {
c = tpl[i];
if ( c == ',' ) {
if ( ! par ) {
StringStrip(argName);
args.push_back(argName);
argName = "";
}
else {
argName += c;
}
}
else {
argName += c;
if ( c == '<' ) ++par;
else if ( c == '>' ) --par;
}
}
if ( argName.length() ) {
StringStrip(argName);
args.push_back(argName);
}
return;
}
size_t Tools::GetBasePosition(const std::string& name) {
int ab = 0;
int rb = 0;
size_t pos = 0;
for (int i = name.size() - 1; (i >= 0) && !pos; --i) {
switch (name[i]) {
case '>':
{
int j = i - 1;
if (j > -1) {
if ((name[j] == '-') || (name[j] == '>')) {
--j;
}
}
for ( ; (j > -1) && (name[j] == ' '); --j) {}
if ((j > -1) && (name[j] == 'r') && ((j - 7) > -1)) {
if (name.substr(j - 7, 8) == "operator") {
i = j - 8;
break;
}
}
ab++;
}
break;
case '<':
{
int j = i - 1;
if (j > -1) {
if (name[j] == '<') {
--j;
}
}
for ( ; (j > -1) && (name[j] == ' '); --j) {}
if ((j > -1) && (name[j] == 'r') && ((j - 7) > -1)) {
if (name.substr(j - 7, 8) == "operator") {
i = j - 8;
break;
}
}
}
ab--;
break;
case ')':
{
int j = i - 1;
for ( ; (j > -1) && (name[j] == ' '); --j) {}
if (j > -1) {
if (name[j] == '(') {
--j;
for ( ; (j > -1) && (name[j] == ' '); --j) {}
if ((j > -1) && (name[j] == 'r') && ((j - 7) > -1)) {
if (name.substr(j - 7, 8) == "operator") {
i = j - 8;
break;
}
}
}
}
}
rb++;
break;
case '(':
{
int j = i - 1;
for ( ; (j > -1) && (name[j] == ' '); --j) {}
if ((j > -1) && (name[j] == 'r') && ((j - 7) > -1)) {
if (name.substr(j - 7, 8) == "operator") {
i = j - 8;
break;
}
}
}
rb--;
break;
case ':':
if (!ab && !rb && i && (name[i-1] == ':')) {
pos = i + 1;
}
break;
}
}
return pos;
}
size_t Tools::GetFirstScopePosition( const std::string & name ) {
int b = 0;
size_t pos = 0;
unsigned int i = 0;
for ( i = 0; i < name.size(); ++i ) {
switch (name[i]) {
case '<':
case '(':
b++; break;
case '>':
case ')':
b--; break;
case ':':
if ( b == 0 && name[i+1] == ':' ) {
pos = i + 2;
break;
}
default: continue;
}
if ( pos ) break;
}
return pos;
}
std::string Tools::GetScopeName( const std::string & name,
bool startFromLeft ){
return splitScopedName( name, true, startFromLeft );
}
std::string Tools::GetBaseName( const std::string & name,
bool startFromLeft ) {
return splitScopedName( name, false, startFromLeft );
}
bool Tools::IsTemplated(const char * name ) {
unsigned int paraLevel = 0;
size_t len = strlen(name);
if (len==0) return false;
for (size_t i = len - 1; i > 0; --i) {
if (name[i] == ')')
++paraLevel;
else if (name[i] == '(') {
if (paraLevel)
--paraLevel;
else
std::cerr << "Reflex::Tool::IsTemplated(): ERROR: level of parantheses < 0 for "
<< name << std::endl;
} else if (!paraLevel) {
if (name[i] == ':' && name[i - 1] == ':')
return false;
if (name[i] == '>') {
if (i > 7) {
int j = i;
if (name[i - 1] == '>' || name[i - 1] == '-') --j;
while (j && isspace(name[j]))
--j;
if (j > 7 && !strncmp(name + j - 8, "operator", 8))
return false;
}
return true;
}
}
}
return false;
}
void Tools::StringSplit( std::vector < std::string > & splitValues,
const std::string & str,
const std::string & delim ) {
if (!str.size()) {
return;
}
std::string str2 = str;
size_t pos = 0;
while (( pos = str2.find_first_of( delim )) != std::string::npos ) {
std::string s = str2.substr(0, pos);
StringStrip( s );
splitValues.push_back( s );
str2 = str2.substr( pos + delim.length());
}
StringStrip( str2 );
splitValues.push_back( str2 );
}
std::string Tools::StringVec2String( const std::vector<std::string> & vec ) {
std::string s = "";
StdString_Iterator lastbutone = vec.end()-1;
for( StdString_Iterator it = vec.begin(); it != vec.end(); ++it) {
s += *it;
if (it != lastbutone ) s += ", ";
}
return s;
}
std::string Tools::Demangle( const std::type_info & ti ) {
#if defined(_WIN32)
static std::vector<std::string> keywords;
if ( 0 == keywords.size() ) {
keywords.push_back("class ");
keywords.push_back("struct ");
keywords.push_back("enum ");
keywords.push_back("union ");
keywords.push_back("__cdecl");
}
std::string r = ti.name();
for ( size_t i = 0; i < keywords.size(); i ++ ) {
while (r.find(keywords[i]) != std::string::npos)
r = r.replace(r.find(keywords[i]), keywords[i].size(), "");
while (r.find(" *") != std::string::npos)
r = r.replace(r.find(" *"), 2, "*");
while (r.find(" &") != std::string::npos)
r = r.replace(r.find(" &"), 2, "&");
}
return r;
#elif defined(__GNUC__)
int status = 0;
bool remove_additional_pointer = false;
std::string mangled = ti.name();
if ( mangled == "Ss" ) return "std::basic_string<char>";
#if __GNUC__ <= 3 && __GNUC_MINOR__ <= 3
if ( mangled[0] == 'F' ) {
mangled.insert(0,"P");
remove_additional_pointer = true;
}
#elif __GNUC__ >= 4
if (mangled.length() == 1) {
switch ( mangled[0] ) {
case 'a': return "signed char"; break;
case 'b': return "bool"; break;
case 'c': return "char"; break;
case 'd': return "double"; break;
case 'e': return "long double"; break;
case 'f': return "float"; break;
case 'g': return "__float128"; break;
case 'h': return "unsigned char"; break;
case 'i': return "int"; break;
case 'j': return "unsigned int"; break;
case 'l': return "long"; break;
case 'm': return "unsigned long"; break;
case 'n': return "__int128"; break;
case 'o': return "unsigned __int128"; break;
case 's': return "short"; break;
case 't': return "unsigned short"; break;
case 'v': return "void"; break;
case 'w': return "wchar_t"; break;
case 'x': return "long long"; break;
case 'y': return "unsigned long long"; break;
case 'z': return "..."; break;
default: break;
}
}
#endif
char * c_demangled = abi::__cxa_demangle( mangled.c_str(), 0, 0, & status );
if ( status == -1 ) {
throw RuntimeError("Memory allocation failure while demangling ");
}
else if ( status == -2 ) {
throw RuntimeError( std::string(mangled) + " is not a valid Name under the C++ ABI");
}
else if ( status == -3 ) {
throw RuntimeError( std::string("Failure while demangling ") + mangled +
". One of the arguments is invalid ");
}
else {
std::string demangled = c_demangled;
free( c_demangled );
if ( remove_additional_pointer ) {
demangled = demangled.replace(demangled.find("(*)"), 3, "");
}
while ( demangled.find(", ") != std::string::npos ) {
demangled = demangled.replace(demangled.find(", "), 2, ",");
}
return demangled;
}
#elif defined(__SUNPRO_CC)
const char* mangled = ti.name();
size_t buffer = 1024;
char * c_demangled = new char[buffer];
int ret = cplus_demangle( mangled, c_demangled, buffer);
while ( ret == -1 ) {
buffer = buffer*2;
delete[] c_demangled;
c_demangled = new char[buffer];
ret = cplus_demangle( mangled, c_demangled, buffer);
}
if ( ret == 1 ) {
throw RuntimeError(std::string("Symbol ") + mangled + " not mangled correctly");
}
else {
std::string demangled = Tools::NormalizeName(c_demangled);
delete[] c_demangled;
return demangled;
}
#elif defined(__IBMCPP__)
return Tools::NormalizeName(ti.name());
#endif
return "";
}
void Tools::StringSplitPair( std::string & val1,
std::string & val2,
const std::string & str,
const std::string & delim ) {
std::string str2 = str;
size_t pos = str2.rfind( delim );
if ( pos != std::string::npos ) {
val1 = str2.substr( 0, pos );
val2 = str2.substr( pos + delim.length());
}
else {
val1 = str2;
}
StringStrip( val1 );
StringStrip( val2 );
}
void Tools::StringStrip( std::string & str ) {
size_t sPos = 0;
size_t ePos = str.length();
while ( str[sPos] == ' ' ) { ++sPos; }
while ( str[ePos] == ' ' ) { --ePos; }
str = str.substr( sPos, ePos - sPos );
}
std::string Tools::GetTemplateArguments( const char * name ) {
std::string baseName = GetBaseName(name);
return baseName.substr(baseName.find('<'));
}
std::string Tools::GetTemplateName( const char * name ) {
std::string scopeName = GetScopeName( name );
std::string baseName = GetBaseName( name );
std::string templateName = baseName.substr(0, baseName.find('<'));
if ( scopeName.length()) return scopeName + "::" + templateName;
return templateName;
}
bool isalphanum(int i) {
return isalpha(i) || isdigit(i);
}
std::string Tools::NormalizeName( const char * nam ) {
std::string norm_name;
char prev = 0;
for (size_t i = 0; nam[i] != 0; i++) {
char curr = nam[i];
if (curr == ' ') {
char next = 0;
while (nam[i] != 0 && (next = nam[i + 1]) == ' ') {
++i;
}
if (!isalphanum(prev) || !isalpha(next)) {
continue;
}
} else if ((curr == '>' && prev == '>') || (curr == '(' && prev != ')')) {
norm_name += ' ';
}
norm_name += (prev = curr);
}
return norm_name;
}
std::string Tools::NormalizeName( const std::string & nam ) {
return Tools::NormalizeName(nam.c_str());
}
Last change: Wed Jun 25 08:31:19 2008
Last generated: 2008-06-25 08:31
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.