#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "TClassEdit.h"
#include <ctype.h>
#include "Rstrstream.h"
#include "cint/Api.h"
namespace std {} using namespace std;
int TClassEdit::STLKind(const char *type)
{
unsigned char offset = 0;
if (strncmp(type,"std::",5)==0) { offset = 5; }
static const char *stls[] =
{"any","vector","list","deque","map","multimap","set","multiset",0};
for(int k=1;stls[k];k++) {if (strcmp(type+offset,stls[k])==0) return k;}
return 0;
}
int TClassEdit::STLArgs(int kind)
{
static const char stln[] =
{ 1, 1, 1, 1, 3, 3, 2, 2 };
return stln[kind];
}
bool TClassEdit::IsDefAlloc(const char *allocname, const char *classname)
{
string a = CleanType(allocname);
string k = CleanType(classname);
if (a=="alloc") return true;
if (a=="__default_alloc_template<true,0>") return true;
if (a=="__malloc_alloc_template<0>") return true;
string ts("allocator<"); ts += k; ts+=">";
if (a==ts) return true;
ts = "allocator<"; ts += k; ts+=" >";
if (a==ts) return true;
return false;
}
bool TClassEdit::IsDefAlloc(const char *allocname,
const char *keyclassname,
const char *valueclassname)
{
if (IsDefAlloc(allocname,keyclassname)) return true;
string a = CleanType(allocname);
string k = CleanType(keyclassname);
string v = CleanType(valueclassname);
string stem("allocator<pair<");
stem += k;
stem += ",";
stem += v;
string ts(stem);
ts += "> >";
if (a==ts) return true;
ts = stem;
ts += " > >";
if (a==ts) return true;
stem = "allocator<pair<const ";
stem += k;
stem += ",";
stem += v;
ts = stem;
ts += "> >";
if (a==ts) return true;
ts = stem;
ts += " > >";
if (a==ts) return true;
if ( keyclassname[strlen(keyclassname)-1] == '*' ) {
stem = "allocator<pair<";
stem += k;
stem += "const";
stem += ",";
stem += v;
string tss(stem);
tss += "> >";
if (a==tss) return true;
tss = stem;
tss += " > >";
if (a==tss) return true;
stem = "allocator<pair<const ";
stem += k;
stem += "const";
stem += ",";
stem += v;
tss = stem;
tss += "> >";
if (a==tss) return true;
tss = stem;
tss += " > >";
if (a==tss) return true;
}
return false;
}
bool TClassEdit::IsDefComp(const char *compname, const char *classname)
{
string c = CleanType(compname);
string k = CleanType(classname);
string stdless("less<");
stdless += k;
if (stdless[stdless.size()-1]=='>') stdless += " >";
else stdless += ">";
if (stdless == c) return true;
stdless.insert(0,"std::");
if (stdless == c) return true;
return false;
}
string TClassEdit::GetLong64_Name(const string& original)
{
static const char* longlong_s = "long long";
static const char* ulonglong_s = "unsigned long long";
static const unsigned int longlong_len = strlen(longlong_s);
static const unsigned int ulonglong_len = strlen(ulonglong_s);
string result = original;
int pos = 0;
while( (pos = result.find(ulonglong_s,pos) ) >=0 ) {
result.replace(pos, ulonglong_len, "ULong64_t");
}
pos = 0;
while( (pos = result.find(longlong_s,pos) ) >=0 ) {
result.replace(pos, longlong_len, "Long64_t");
}
return result;
}
int TClassEdit::GetSplit(const char *type, vector<string>& output, int &nestedLoc)
{
int keepConst = 0;
int keepInnerConst = 1;
nestedLoc = 0;
output.clear();
if (strlen(type)==0) return 0;
string full = CleanType(type, keepInnerConst );
const char *t = full.c_str();
const char *c = strchr(t,'<');
string stars;
const char *starloc = t+strlen(t)-1;
if ( (*starloc)=='*' ) {
while( (*(starloc-1))=='*' ) { starloc--; }
stars = starloc;
full.replace(strlen(t)-strlen(starloc),strlen(starloc),1,'\0');
}
if (c) {
output.push_back(string(full,0,c-t));
} else {
output.push_back(string()); c=t-1;
}
do {
output.push_back(CleanType(c+1,keepConst,&c));
} while(*c!='>' && *c);
if (*c=='>') {
if (*(c+1)==':') {
nestedLoc = output.size();
output.push_back((c+1));
}
}
if (stars.length()) output.push_back(stars);
return output.size();
}
string TClassEdit::CleanType(const char *typeDesc, int mode, const char **tail)
{
static const char* remove[] = {"class","const","volatile",0};
string result;
result.reserve(strlen(typeDesc)*2);
int lev=0,kbl=1;
const char* c;
for(c=typeDesc;*c;c++) {
if (c[0]==' ') {
if (kbl) continue;
if (!isalnum(c[ 1]) && c[ 1] !='_') continue;
}
if (kbl && (mode>=2 || lev==0)) {
int done = 0;
int n = (mode) ? 999 : 1;
for (int k=0; k<n && remove[k]; k++) {
int rlen = strlen(remove[k]);
if (strncmp(remove[k],c,rlen)) continue;
if (isalnum(c[rlen]) || c[rlen]=='_' || c[rlen]=='$') continue;
c+=rlen-1; done = 1; break;
}
if (done) continue;
}
kbl = (!isalnum(c[ 0]) && c[ 0]!='_' && c[ 0]!='$' && c[0]!='[' && c[0]!=']');
if (*c == '<') lev++;
if (lev==0 && !isalnum(*c)) {
if (!strchr("*:_$ []",*c)) break;
}
if (c[0]=='>' && result.size() && result[result.size()-1]=='>') result+=" ";
result += c[0];
if (*c == '>') lev--;
}
if(tail) *tail=c;
return result;
}
string TClassEdit::ShortType(const char *typeDesc, int mode)
{
string full = CleanType(typeDesc, 1 );
string answ;
int tailLoc=0;
int nestedLoc=0;
vector<string> arglist;
int narg = GetSplit(full.c_str(),arglist,nestedLoc);
if (narg==0) return typeDesc;
if (arglist[narg-1].empty() == false && arglist[narg-1][0]=='*') {
if ((mode&1)==0) tailLoc = narg-1;
narg--;
}
mode &= (~1);
if (nestedLoc) narg--;
int kind = STLKind(arglist[0].c_str());
int iall = STLArgs(kind);
if (mode&(8|16)) {
while(narg-1>iall) {arglist.pop_back(); narg--;}
if (!arglist[0].empty() && tailLoc) {
tailLoc = 0;
}
arglist[0].erase(0,999);
mode&=(~8);
}
if (mode & kDropStlDefault) mode |= kDropDefaultAlloc;
if (kind) {
bool allocRemoved = false;
if ( mode & (kDropDefaultAlloc|kDropAlloc) ) {
if (narg-1 == iall+1) {
bool dropAlloc = false;
if (mode & kDropAlloc) {
dropAlloc = true;
} else if (mode & kDropDefaultAlloc) {
switch (kind) {
case kVector:
case kList:
case kDeque:
case kSet:
case kMultiSet:
dropAlloc = IsDefAlloc(arglist[iall+1].c_str(),arglist[1].c_str());
break;
case kMap:
case kMultiMap:
dropAlloc = IsDefAlloc(arglist[iall+1].c_str(),arglist[1].c_str(),arglist[2].c_str());
break;
default:
dropAlloc = false;
}
}
if (dropAlloc) {
narg--;
allocRemoved = true;
}
} else {
allocRemoved = true;
}
}
if ( allocRemoved && (mode & kDropStlDefault) && narg-1 == iall) {
if ( IsDefComp( arglist[iall].c_str(), arglist[1].c_str() ) ) {
narg--;
}
} else if ( mode & kDropComparator ) {
switch (kind) {
case kVector:
case kList:
case kDeque:
break;
case kSet:
case kMultiSet:
case kMap:
case kMultiMap:
if (!allocRemoved && narg-1 == iall+1) {
narg--;
allocRemoved = true;
}
if (narg-1 == iall) narg--;
break;
default:
break;
}
}
}
for (int i=1;i<narg; i++) {
if (strchr(arglist[i].c_str(),'<')==0) continue;
bool hasconst = 0==strncmp("const ",arglist[i].c_str(),6);
arglist[i] = ShortType(arglist[i].c_str(),mode);
if (hasconst) {
arglist[i] = "const " + arglist[i];
}
}
if (!arglist[0].empty()) {answ += arglist[0]; answ +="<";}
{ for (int i=1;i<narg-1; i++) { answ += arglist[i]; answ+=",";} }
if (narg>1) { answ += arglist[narg-1]; }
if (!arglist[0].empty()) {
if ( answ.at(answ.size()-1) == '>') {
answ += " >";
} else {
answ += '>';
}
}
if (nestedLoc) answ += arglist[nestedLoc];
if (tailLoc) answ += arglist[tailLoc];
return answ;
}
int TClassEdit::IsSTLCont(const char *type,int testAlloc)
{
if (strchr(type,'<')==0) return 0;
int mode = (testAlloc) ? 2 : 0;
string fullname = ShortType(type,mode);
vector<string> arglist;
int nestedLoc=0;
int numb = GetSplit(fullname.c_str(),arglist,nestedLoc);
if ( arglist[0].length()>0 && arglist[numb-1][0]=='*' ) numb--;
if ( nestedLoc ) {
return 0;
}
int kind = STLKind(arglist[0].c_str());
if (kind==kVector || kind==kList ) {
if (testAlloc && (numb-1 > STLArgs(kind)) ) {
kind = -kind;
} else {
int k = IsSTLCont(arglist[1].c_str(),testAlloc);
if (k<0) kind = -kind;
}
}
if(kind>2) kind = - kind;
return kind;
}
bool TClassEdit::IsStdClass(const char *classname)
{
if ( strncmp(classname,"std::",5)==0 ) classname += 5;
if ( strcmp(classname,"string")==0 ) return true;
if ( strncmp(classname,"pair<",strlen("pair<"))==0) return true;
if ( strcmp(classname,"allocator")==0) return true;
if ( strncmp(classname,"allocator<",strlen("allocator<"))==0) return true;
if ( strncmp(classname,"greater<",strlen("greater<"))==0) return true;
return IsSTLCont(classname) != 0;
}
bool TClassEdit::IsVectorBool(const char *name) {
int nestedLoc=0;
vector<string> splitName;
TClassEdit::GetSplit(name,splitName,nestedLoc);
return ( TClassEdit::STLKind( splitName[0].c_str() ) == TClassEdit::kVector)
&& ( splitName[1] == "bool" || splitName[1]=="Bool_t");
};
namespace {
static bool ShouldReplace(const char *name)
{
const char *excludelist [] = {"Char_t","Short_t","Int_t","Long_t","Float_t",
"Int_t","Double_t","Double32_t","Float16_t",
"UChar_t","UShort_t","UInt_t","ULong_t","UInt_t",
"Long64_t","ULong64_t","Bool_t"};
for (unsigned int i=0; i < sizeof(excludelist)/sizeof(excludelist[0]); ++i) {
if (strcmp(name,excludelist[i])==0) return false;
}
return true;
}
}
string TClassEdit::ResolveTypedef(const char *tname, bool resolveAll)
{
if ( tname==0 || tname[0]==0) return tname;
if ( strchr(tname,'<')==0 && (tname[strlen(tname)-1]!='*') ) {
if ( strchr(tname,':')!=0 ) {
int slen = strlen(tname);
for(int k=0;k<slen;++k) {
if (tname[k]==':') {
if (k+1>=slen || tname[k+1]!=':') {
return tname;
}
if (k) {
string base(tname, 0, k);
if (base=="std") {
tname += 5;
break;
} else {
G__ClassInfo info(base.c_str());
if (!info.IsLoaded()) {
return tname;
}
}
}
}
}
}
if (resolveAll || ShouldReplace(tname)) {
G__TypedefInfo t;
t.Init(tname);
if (t.IsValid()) return t.TrueName();
}
return tname;
}
int len = strlen(tname);
string input(tname);
#ifdef R__SSTREAM
stringstream answ;
#else
strstream answ;
#endif
int prev = 0;
for (int i=0; i<len; ++i) {
switch (tname[i]) {
case '<':
case '>':
case '*':
case ' ':
case '&':
case ',':
{
char keep = input[i];
string temp( input, prev,i-prev );
if ( (resolveAll&&(temp!="Double32_t")&&(temp!="Float16_t")) || ShouldReplace(temp.c_str())) {
answ << ResolveTypedef( temp.c_str(), resolveAll);
} else {
answ << temp;
}
answ << keep;
prev = i+1;
}
}
}
const char *last = &(input.c_str()[prev]);
if ((resolveAll&&(strcmp(last,"Double32_t")!=0)&&(strcmp(last,"Float16_t")!=0)) || ShouldReplace(last)) {
answ << ResolveTypedef( last, resolveAll);
} else {
answ << last;
}
#ifndef R__SSTREAM
answ << ends;
std::string ret = answ.str();
answ.freeze(false);
return ret;
#else
return answ.str();
#endif
}
Last change: Wed Jun 25 08:35:37 2008
Last generated: 2008-06-25 08:35
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.