32 static TClassEdit::TInterpreterLookupHelper *gInterpreterHelper = 0;
35 struct ShuttingDownSignaler :
public T {
38 ~ShuttingDownSignaler()
40 if (gInterpreterHelper)
41 gInterpreterHelper->ShuttingDownSignal();
46 namespace std {}
using namespace std;
52 static size_t StdLen(
const std::string_view name)
55 if (name.compare(0,5,
"std::")==0) {
60 if (gInterpreterHelper) {
61 for(
size_t i = 5; i < name.length(); ++i) {
62 if (name[i] ==
'<')
break;
65 std::string scope(name.data(),i);
66 std::string scoperesult;
69 static ShuttingDownSignaler<std::set<std::string>> gInlined;
71 if (gInlined.find(scope) != gInlined.end()) {
73 if (i+1<name.length() && name[i+1]==
':') {
77 if (!gInterpreterHelper->ExistingTypeCheck(scope, scoperesult)
78 && gInterpreterHelper->IsDeclaredScope(scope,isInlined)) {
80 gInlined.insert(scope);
82 if (i+1<name.length() && name[i+1]==
':') {
99 static void RemoveStd(std::string &name,
size_t pos = 0)
101 size_t len = StdLen({name.data()+pos,name.length()-pos});
111 static void RemoveStd(std::string_view &name)
113 size_t len = StdLen(name);
115 name.remove_prefix(len);
121 TClassEdit::EComplexType TClassEdit::GetComplexType(
const char* clName)
123 if (0 == strncmp(clName,
"complex<", 8)) {
124 const char *clNamePlus8 = clName + 8;
125 if (0 == strcmp(
"float>", clNamePlus8)) {
126 return EComplexType::kFloat;
128 if (0 == strcmp(
"double>", clNamePlus8)) {
129 return EComplexType::kDouble;
131 if (0 == strcmp(
"int>", clNamePlus8)) {
132 return EComplexType::kInt;
134 if (0 == strcmp(
"long>", clNamePlus8)) {
135 return EComplexType::kLong;
138 return EComplexType::kNone;
142 TClassEdit::TInterpreterLookupHelper::~TInterpreterLookupHelper()
149 if (
this == gInterpreterHelper)
150 gInterpreterHelper =
nullptr;
155 void TClassEdit::Init(TClassEdit::TInterpreterLookupHelper *helper)
157 gInterpreterHelper = helper;
163 TClassEdit::TSplitType::TSplitType(
const char *type2split, EModType mode) : fName(type2split), fNestedLocation(0)
165 TClassEdit::GetSplit(type2split, fElements, fNestedLocation, mode);
173 ROOT::ESTLType TClassEdit::TSplitType::IsInSTL()
const
175 if (fElements[0].empty())
return ROOT::kNotSTL;
176 return STLKind(fElements[0]);
190 int TClassEdit::TSplitType::IsSTLCont(
int testAlloc)
const
193 if (fElements[0].empty())
return 0;
194 int numb = fElements.size();
195 if (!fElements[numb-1].empty() && fElements[numb-1][0]==
'*') --numb;
197 if ( fNestedLocation ) {
203 int kind = STLKind(fElements[0]);
205 if (kind==ROOT::kSTLvector || kind==ROOT::kSTLlist || kind==ROOT::kSTLforwardlist) {
207 int nargs = STLArgs(kind);
208 if (testAlloc && (numb-1 > nargs) && !IsDefAlloc(fElements[numb-1].c_str(),fElements[1].c_str())) {
219 int k = TClassEdit::IsSTLCont(fElements[1].c_str(),testAlloc);
220 if (k<0) kind = -kind;
226 if(kind>2) kind = - kind;
234 void TClassEdit::TSplitType::ShortType(std::string &answ,
int mode)
246 int narg = fElements.size();
257 if (fElements[narg-1].empty() ==
false &&
258 (fElements[narg-1][0]==
'*'
259 || fElements[narg-1][0]==
'&'
260 || fElements[narg-1][0]==
'['
261 || 0 == fElements[narg-1].compare(0,6,
"const*")
262 || 0 == fElements[narg-1].compare(0,6,
"const&")
263 || 0 == fElements[narg-1].compare(0,6,
"const[")
264 || 0 == fElements[narg-1].compare(
"const")
267 if ((mode&1)==0) tailLoc = narg-1;
269 else { assert(fElements[narg-1].empty()); };
273 if (fNestedLocation) narg--;
278 const int kind = STLKind(fElements[0]);
279 const int iall = STLArgs(kind);
283 while(narg-1>iall) { fElements.pop_back(); narg--;}
284 if (!fElements[0].empty() && tailLoc) {
287 fElements[0].clear();
291 if (mode & kDropAllDefault) mode |= kDropStlDefault;
292 if (mode & kDropStlDefault) mode |= kDropDefaultAlloc;
295 bool allocRemoved =
false;
297 if ( mode & (kDropDefaultAlloc|kDropAlloc) ) {
301 if (narg-1 == iall+1) {
303 bool dropAlloc =
false;
304 if (mode & kDropAlloc) {
308 }
else if (mode & kDropDefaultAlloc) {
310 case ROOT::kSTLvector:
312 case ROOT::kSTLforwardlist:
313 case ROOT::kSTLdeque:
315 case ROOT::kSTLmultiset:
316 case ROOT::kSTLunorderedset:
317 case ROOT::kSTLunorderedmultiset:
318 dropAlloc = IsDefAlloc(fElements[iall+1].c_str(),fElements[1].c_str());
321 case ROOT::kSTLmultimap:
322 case ROOT::kSTLunorderedmap:
323 case ROOT::kSTLunorderedmultimap:
324 dropAlloc = IsDefAlloc(fElements[iall+1].c_str(),fElements[1].c_str(),fElements[2].c_str());
341 if ( allocRemoved && (mode & kDropStlDefault) && narg-1 == iall) {
342 if ( IsDefComp( fElements[iall].c_str(), fElements[1].c_str() ) ) {
345 }
else if ( mode & kDropComparator ) {
348 case ROOT::kSTLvector:
350 case ROOT::kSTLforwardlist:
351 case ROOT::kSTLdeque:
354 case ROOT::kSTLmultiset:
356 case ROOT::kSTLmultimap:
357 if (!allocRemoved && narg-1 == iall+1) {
361 if (narg-1 == iall) narg--;
382 if (kind == ROOT::kSTLunorderedset || kind == ROOT::kSTLunorderedmultiset || kind == ROOT::kSTLunorderedmap || kind == ROOT::kSTLunorderedmultimap){
384 bool predRemoved =
false;
386 if ( allocRemoved && (mode & kDropStlDefault) && narg-1 == iall) {
387 if ( IsDefPred( fElements[iall].c_str(), fElements[1].c_str() ) ) {
393 if ( predRemoved && (mode & kDropStlDefault) && narg == iall) {
394 if ( IsDefHash( fElements[iall-1].c_str(), fElements[1].c_str() ) ) {
401 if ( (mode & kDropStlDefault) && (narg >= 3)) {
402 unsigned int offset = (0==strncmp(
"const ",fElements[0].c_str(),6)) ? 6 : 0;
403 offset += (0==strncmp(
"std::",fElements[0].c_str()+offset,5)) ? 5 : 0;
404 if (0 == strcmp(fElements[0].c_str()+offset,
"__shared_ptr"))
406 #ifdef _CONCURRENCE_H
407 static const std::string sharedPtrDef = std::to_string(__gnu_cxx::__default_lock_policy);
409 static const std::string sharedPtrDef = std::to_string(2);
411 if (fElements[2] == sharedPtrDef) {
419 for (
int i=1;i<narg; i++) {
420 if (strchr(fElements[i].c_str(),
'<')==0) {
422 unsigned int offset = (0==strncmp(
"const ",fElements[i].c_str(),6)) ? 6 : 0;
423 RemoveStd( fElements[i], offset );
425 if (mode&kResolveTypedef) {
426 fElements[i] = ResolveTypedef(fElements[i].c_str(),
true);
430 fElements[i] = TClassEdit::ShortType(fElements[i].c_str(),mode | TClassEdit::kKeepOuterConst);
431 if (mode&kResolveTypedef) {
436 if (gInterpreterHelper &&
437 (gInterpreterHelper->ExistingTypeCheck(fElements[i], typeresult)
438 || gInterpreterHelper->GetPartiallyDesugaredNameWithScopeHandling(fElements[i], typeresult))) {
439 if (!typeresult.empty()) fElements[i] = typeresult;
444 unsigned int tailOffset = 0;
445 if (tailLoc && fElements[tailLoc].compare(0,5,
"const") == 0) {
446 if (mode & kKeepOuterConst) answ +=
"const ";
449 if (!fElements[0].empty()) {answ += fElements[0]; answ +=
"<";}
457 if (mode & kDropAllDefault) {
458 int nargNonDefault = 0;
459 std::string nonDefName = answ;
461 std::string nameSuperLong = fName;
462 if (gInterpreterHelper)
463 gInterpreterHelper->GetPartiallyDesugaredName(nameSuperLong);
464 while (++nargNonDefault < narg) {
467 const char* closeTemplate =
" >";
468 if (nonDefName[nonDefName.length() - 1] !=
'>')
470 string nondef = nonDefName + closeTemplate;
471 if (gInterpreterHelper &&
472 gInterpreterHelper->IsAlreadyPartiallyDesugaredName(nondef, nameSuperLong))
474 if (nargNonDefault>1) nonDefName +=
",";
475 nonDefName += fElements[nargNonDefault];
477 if (nargNonDefault < narg)
478 narg = nargNonDefault;
482 {
for (
int i=1;i<narg-1; i++) { answ += fElements[i]; answ+=
",";} }
483 if (narg>1) { answ += fElements[narg-1]; }
485 if (!fElements[0].empty()) {
486 if ( answ.at(answ.size()-1) ==
'>') {
492 if (fNestedLocation) {
494 fElements[fNestedLocation] = TClassEdit::ShortType(fElements[fNestedLocation].c_str(),mode);
495 answ += fElements[fNestedLocation];
498 if (tailLoc) answ += fElements[tailLoc].c_str()+tailOffset;
503 bool TClassEdit::TSplitType::IsTemplate()
505 return !fElements[0].empty();
512 ROOT::ESTLType TClassEdit::STLKind(std::string_view type)
515 if (type.compare(0,6,
"const ")==0) { offset += 6; }
516 offset += StdLen(type.substr(offset));
519 static const char *stls[] =
520 {
"any",
"vector",
"list",
"deque",
"map",
"multimap",
"set",
"multiset",
"bitset",
521 "forward_list",
"unordered_set",
"unordered_multiset",
"unordered_map",
"unordered_multimap", 0};
522 static const size_t stllen[] =
523 { 3, 6, 4, 5, 3, 8, 3, 8, 6,
524 12, 13, 18, 13, 18, 0};
525 static const ROOT::ESTLType values[] =
526 { ROOT::kNotSTL, ROOT::kSTLvector,
527 ROOT::kSTLlist, ROOT::kSTLdeque,
528 ROOT::kSTLmap, ROOT::kSTLmultimap,
529 ROOT::kSTLset, ROOT::kSTLmultiset,
532 ROOT::kSTLforwardlist,
533 ROOT::kSTLunorderedset, ROOT::kSTLunorderedmultiset,
534 ROOT::kSTLunorderedmap, ROOT::kSTLunorderedmultimap,
539 auto len = type.length();
542 for(
int k=1;stls[k];k++) {
543 if (len == stllen[k]) {
544 if (type.compare(offset,len,stls[k])==0)
return values[k];
548 for(
int k=1;stls[k];k++) {
if (type.compare(offset,len,stls[k])==0)
return values[k];}
550 return ROOT::kNotSTL;
556 int TClassEdit::STLArgs(
int kind)
558 static const char stln[] =
560 { 1, 1, 1, 1, 3, 3, 2, 2, 1,
569 static size_t findNameEnd(
const std::string_view full)
572 for(
size_t i = 0; i < full.length(); ++i) {
574 case '<': { ++level;
break; }
576 if (level == 0)
return i;
581 if (level == 0)
return i;
587 return full.length();
592 static size_t findNameEnd(
const std::string &full,
size_t pos)
594 return pos + findNameEnd( {full.data()+pos,full.length()-pos} );
601 bool TClassEdit::IsDefAlloc(
const char *allocname,
const char *classname)
603 string_view a( allocname );
606 if (a==
"alloc")
return true;
607 if (a==
"__default_alloc_template<true,0>")
return true;
608 if (a==
"__malloc_alloc_template<0>")
return true;
610 const static int alloclen = strlen(
"allocator<");
611 if (a.compare(0,alloclen,
"allocator<") != 0) {
614 a.remove_prefix(alloclen);
618 string_view k = classname;
621 if (a.compare(0,k.length(),k) != 0) {
623 size_t end = findNameEnd(a);
625 std::string valuepart;
626 GetNormalizedName(valuepart,std::string_view(a.data(),end));
628 std::string norm_value;
629 GetNormalizedName(norm_value,k);
631 if (valuepart != norm_value) {
634 a.remove_prefix(end);
636 a.remove_prefix(k.length());
639 if (a.compare(0,1,
">")!=0 && a.compare(0,2,
" >")!=0) {
650 bool TClassEdit::IsDefAlloc(
const char *allocname,
651 const char *keyclassname,
652 const char *valueclassname)
654 if (IsDefAlloc(allocname,keyclassname))
return true;
656 string_view a( allocname );
659 const static int alloclen = strlen(
"allocator<");
660 if (a.compare(0,alloclen,
"allocator<") != 0) {
663 a.remove_prefix(alloclen);
667 const static int pairlen = strlen(
"pair<");
668 if (a.compare(0,pairlen,
"pair<") != 0) {
671 a.remove_prefix(pairlen);
673 const static int constlen = strlen(
"const");
674 if (a.compare(0,constlen+1,
"const ") == 0) {
675 a.remove_prefix(constlen+1);
680 string_view k = keyclassname;
682 if (k.compare(0,constlen+1,
"const ") == 0) {
683 k.remove_prefix(constlen+1);
686 if (a.compare(0,k.length(),k) != 0) {
688 size_t end = findNameEnd(a);
690 std::string alloc_keypart;
691 GetNormalizedName(alloc_keypart,std::string_view(a.data(),end));
693 std::string norm_key;
694 GetNormalizedName(norm_key,k);
696 if (alloc_keypart != norm_key) {
697 if ( norm_key[norm_key.length()-1] ==
'*' ) {
701 norm_key +=
" const";
703 if (alloc_keypart != norm_key) {
707 a.remove_prefix(end);
709 size_t end = k.length();
710 if ( (a[end-1] ==
'*') || a[end]==
' ' ) {
711 size_t skipSpace = (a[end] ==
' ');
712 if (a.compare(end+skipSpace,constlen,
"const") == 0) {
713 end += constlen+skipSpace;
716 a.remove_prefix(end);
725 string_view v = valueclassname;
728 if (a.compare(0,v.length(),v) != 0) {
730 size_t end = findNameEnd(a);
732 std::string valuepart;
733 GetNormalizedName(valuepart,std::string_view(a.data(),end));
735 std::string norm_value;
736 GetNormalizedName(norm_value,v);
738 if (valuepart != norm_value) {
741 a.remove_prefix(end);
743 a.remove_prefix(v.length());
746 if (a.compare(0,1,
">")!=0 && a.compare(0,2,
" >")!=0) {
757 static bool IsDefElement(
const char *elementName,
const char* defaultElementName,
const char *classname)
759 string c = elementName;
761 size_t pos = StdLen(c);
763 const int elementlen = strlen(defaultElementName);
764 if (c.compare(pos,elementlen,defaultElementName) != 0) {
769 string k = classname;
770 if (c.compare(pos,k.length(),k) != 0) {
772 size_t end = findNameEnd(c,pos);
775 TClassEdit::GetNormalizedName(keypart,std::string_view(c.c_str()+pos,end-pos));
777 std::string norm_key;
778 TClassEdit::GetNormalizedName(norm_key,k);
780 if (keypart != norm_key) {
788 if (c.compare(pos,1,
">")!=0 && c.compare(pos,2,
" >")!=0) {
799 bool TClassEdit::IsDefComp(
const char *compname,
const char *classname)
801 return IsDefElement(compname,
"less<", classname);
808 bool TClassEdit::IsDefPred(
const char *predname,
const char *classname)
810 return IsDefElement(predname,
"equal_to<", classname);
817 bool TClassEdit::IsDefHash(
const char *hashname,
const char *classname)
819 return IsDefElement(hashname,
"hash<", classname);
832 void TClassEdit::GetNormalizedName(std::string &norm_name, std::string_view name)
834 norm_name = std::string(name);
837 TClassEdit::TSplitType splitname(norm_name.c_str(),(TClassEdit::EModType)(TClassEdit::kLong64 | TClassEdit::kDropStd | TClassEdit::kDropStlDefault | TClassEdit::kKeepOuterConst));
838 splitname.ShortType(norm_name,TClassEdit::kDropStd | TClassEdit::kDropStlDefault | TClassEdit::kResolveTypedef | TClassEdit::kKeepOuterConst);
843 if (norm_name.length()>2 && norm_name[0]==
':' && norm_name[1]==
':') {
844 norm_name.erase(0,2);
847 if (gInterpreterHelper) {
849 std::string typeresult;
850 if (gInterpreterHelper->ExistingTypeCheck(norm_name, typeresult)
851 || gInterpreterHelper->GetPartiallyDesugaredNameWithScopeHandling(norm_name, typeresult)) {
853 if (!typeresult.empty()) norm_name = typeresult;
861 string TClassEdit::GetLong64_Name(
const char* original)
866 return GetLong64_Name(
string(original));
872 string TClassEdit::GetLong64_Name(
const string& original)
874 static const char* longlong_s =
"long long";
875 static const char* ulonglong_s =
"unsigned long long";
876 static const unsigned int longlong_len = strlen(longlong_s);
877 static const unsigned int ulonglong_len = strlen(ulonglong_s);
879 string result = original;
882 while( (pos = result.find(ulonglong_s,pos) ) >=0 ) {
883 result.replace(pos, ulonglong_len,
"ULong64_t");
886 while( (pos = result.find(longlong_s,pos) ) >=0 ) {
887 result.replace(pos, longlong_len,
"Long64_t");
895 const char *TClassEdit::GetUnqualifiedName(
const char *original)
897 const char *lastPos = original;
900 for(
auto cursor = original; *cursor !=
'\0'; ++cursor) {
901 if ( *cursor ==
'<' || *cursor ==
'(') ++depth;
902 else if ( *cursor ==
'>' || *cursor ==
')' ) --depth;
903 else if ( *cursor ==
':' ) {
904 if (depth==0 && *(cursor+1) ==
':' && *(cursor+2) !=
'\0') {
915 static void R__FindTrailing(std::string &full,
919 const char *t = full.c_str();
920 const unsigned int tlen( full.size() );
922 const char *starloc = t + tlen - 1;
923 bool hasconst =
false;
925 && (starloc-t) > 4 && 0 == strncmp((starloc-4),
"const",5)
926 && ( (*(starloc-5)) ==
' ' || (*(starloc-5)) ==
'*' || (*(starloc-5)) ==
'&'
927 || (*(starloc-5)) ==
'>' || (*(starloc-5)) ==
']') ) {
930 if ((*starloc-1)==
' ') {
936 if ( hasconst || (*starloc)==
'*' || (*starloc)==
'&' || (*starloc)==
']' ) {
937 bool isArray = ( (*starloc)==
']' );
938 while( t<=(starloc-1) && ((*(starloc-1))==
'*' || (*(starloc-1))==
'&' || (*(starloc-1))==
't' || isArray)) {
941 isArray = ! ( (*starloc)==
'[' );
942 }
else if ( (*(starloc-1))==
't' ) {
943 if ( (starloc-1-t) > 5 && 0 == strncmp((starloc-5),
"const",5)
944 && ( (*(starloc-6)) ==
' ' || (*(starloc-6)) ==
'*' || (*(starloc-6)) ==
'&'
945 || (*(starloc-6)) ==
'>' || (*(starloc-6)) ==
']')) {
956 if ((*(starloc-1))==
' ') {
961 const unsigned int starlen = strlen(starloc);
962 full.erase(tlen-starlen,starlen);
963 }
else if (hasconst) {
965 const unsigned int starlen = strlen(starloc);
966 full.erase(tlen-starlen,starlen);
982 int TClassEdit::GetSplit(
const char *type, vector<string>& output,
int &nestedLoc, EModType mode)
986 if (strlen(type)==0)
return 0;
988 int cleantypeMode = 1 ;
989 if (mode & kKeepOuterConst) {
992 string full( mode & kLong64 ? TClassEdit::GetLong64_Name( CleanType(type, cleantypeMode) )
993 : CleanType(type, cleantypeMode) );
997 unsigned int const_offset = (0==strncmp(
"const ",full.c_str(),6)) ? 6 : 0;
998 bool isString =
false;
999 bool isStdString =
false;
1000 size_t std_offset = const_offset;
1001 static const char* basic_string_std =
"std::basic_string<char";
1002 static const unsigned int basic_string_std_len = strlen(basic_string_std);
1004 if (full.compare(const_offset,basic_string_std_len,basic_string_std) == 0
1005 && full.size() > basic_string_std_len) {
1009 }
else if (full.compare(const_offset,basic_string_std_len-5,basic_string_std+5) == 0
1010 && full.size() > (basic_string_std_len-5)) {
1013 }
else if (full.find(
"basic_string") != std::string::npos) {
1014 size_t len = StdLen(full.c_str() + const_offset);
1015 if (len && len != 5 && full.compare(const_offset + len, basic_string_std_len-5, basic_string_std+5) == 0) {
1022 size_t offset = basic_string_std_len - 5;
1023 offset += std_offset;
1024 if ( full[offset] ==
'>' ) {
1026 }
else if (full[offset] ==
',') {
1028 if (full.compare(offset, 5,
"std::") == 0) {
1031 static const char* char_traits_s =
"char_traits<char>";
1032 static const unsigned int char_traits_len = strlen(char_traits_s);
1033 if (full.compare(offset, char_traits_len, char_traits_s) == 0) {
1034 offset += char_traits_len;
1035 if ( full[offset] ==
'>') {
1037 }
else if (full[offset] ==
' ' && full[offset+1] ==
'>') {
1040 }
else if (full[offset] ==
',') {
1042 if (full.compare(offset, 5,
"std::") == 0) {
1045 static const char* allocator_s =
"allocator<char>";
1046 static const unsigned int allocator_len = strlen(allocator_s);
1047 if (full.compare(offset, allocator_len, allocator_s) == 0) {
1048 offset += allocator_len;
1049 if ( full[offset] ==
'>') {
1051 }
else if (full[offset] ==
' ' && full[offset+1] ==
'>') {
1072 output.push_back(
string());
1073 if (const_offset && (mode & kKeepOuterConst)) {
1074 if (isStdString && !(mode & kDropStd)) {
1075 output.push_back(
"const std::string");
1077 output.push_back(
"const string");
1080 if (isStdString && !(mode & kDropStd)) {
1081 output.push_back(
"std::string");
1083 output.push_back(
"string");
1086 if (offset < full.length()) {
1089 string right( full.substr(offset) );
1091 R__FindTrailing(right, stars);
1092 output.back().append(right.c_str()+1);
1093 output.push_back(stars);
1095 output.push_back(
"");
1097 return output.size();
1102 if ( mode & kDropStd) {
1103 unsigned int offset = (0==strncmp(
"const ",full.c_str(),6)) ? 6 : 0;
1104 RemoveStd( full, offset );
1108 if ( !full.empty() ) {
1109 R__FindTrailing(full, stars);
1112 const char *c = strchr(full.c_str(),
'<');
1115 output.push_back(
string(full,0,c - full.c_str()));
1119 for(cursor = c + 1; *cursor !=
'\0' && !(level==0 && *cursor ==
'>'); ++cursor) {
1121 case '<': ++level;
break;
1122 case '>': --level;
break;
1125 output.push_back(std::string(c+1,cursor));
1132 if (*(cursor-1) ==
' ') {
1133 output.push_back(std::string(c+1,cursor-1));
1135 output.push_back(std::string(c+1,cursor));
1138 if (*(cursor+1)==
':') {
1141 nestedLoc = output.size();
1142 output.push_back((cursor+1));
1144 }
else if (level >= 0) {
1146 output.push_back(std::string(c+1,cursor));
1150 output.push_back(
string());
1151 output.push_back(full);
1154 if (!output.empty()) output.push_back(stars);
1155 return output.size();
1175 string TClassEdit::CleanType(
const char *typeDesc,
int mode,
const char **tail)
1177 static const char*
remove[] = {
"class",
"const",
"volatile",0};
1178 static bool isinit =
false;
1179 static std::vector<size_t> lengths;
1181 for (
int k=0;
remove[k]; ++k) {
1182 lengths.push_back(strlen(
remove[k]));
1188 result.reserve(strlen(typeDesc)*2);
1192 for(c=typeDesc;*c;c++) {
1195 if (!isalnum(c[ 1]) && c[ 1] !=
'_')
continue;
1197 if (kbl && (mode>=2 || lev==0)) {
1199 int n = (mode) ? 999 : 1;
1202 for (
int k=0; k<n &&
remove[k]; k++) {
1203 int rlen = lengths[k];
1206 if (strncmp(
remove[k],c,rlen))
continue;
1209 if (isalnum(c[rlen]) || c[rlen]==
'_' || c[rlen]==
'$')
continue;
1211 c+=rlen-1; done = 1;
break;
1216 kbl = (!isalnum(c[ 0]) && c[ 0]!=
'_' && c[ 0]!=
'$' && c[0]!=
'[' && c[0]!=
']' && c[0]!=
'-' && c[0]!=
'@');
1220 if (*c ==
'<' || *c ==
'(') lev++;
1221 if (lev==0 && !isalnum(*c)) {
1222 if (!strchr(
"*&:._$ []-@",*c))
break;
1226 if (c[0]==
'>' && result.size() && result[result.size()-1]==
'>') result+=
" ";
1230 if (*c ==
'>' || *c ==
')') lev--;
1248 string TClassEdit::ShortType(
const char *typeDesc,
int mode)
1254 TSplitType arglist(typeDesc, (EModType) mode);
1255 arglist.ShortType(answer, mode);
1265 bool TClassEdit::IsInterpreterDetail(
const char *type)
1267 size_t len = strlen(type);
1268 if (len < 2 || strncmp(type+len-2,
"_t",2) != 0)
return false;
1270 unsigned char offset = 0;
1271 if (strncmp(type,
"const ",6)==0) { offset += 6; }
1272 static const char *names[] = {
"CallFunc_t",
"ClassInfo_t",
"BaseClassInfo_t",
1273 "DataMemberInfo_t",
"FuncTempInfo_t",
"MethodInfo_t",
"MethodArgInfo_t",
1274 "TypeInfo_t",
"TypedefInfo_t",0};
1276 for(
int k=1;names[k];k++) {
if (strcmp(type+offset,names[k])==0)
return true;}
1283 bool TClassEdit::IsSTLBitset(
const char *classname)
1285 size_t offset = StdLen(classname);
1286 if ( strncmp(classname+offset,
"bitset<",strlen(
"bitset<"))==0)
return true;
1302 ROOT::ESTLType TClassEdit::UnderlyingIsSTLCont(std::string_view type)
1304 if (type.compare(0,6,
"const ",6) == 0)
1305 type.remove_prefix(6);
1307 while(type[type.length()-1]==
'*' ||
1308 type[type.length()-1]==
'&' ||
1309 type[type.length()-1]==
' ') {
1310 type.remove_suffix(1);
1312 return IsSTLCont(type);
1321 ROOT::ESTLType TClassEdit::IsSTLCont(std::string_view type)
1323 auto pos = type.find(
'<');
1324 if (pos==std::string_view::npos)
return ROOT::kNotSTL;
1327 for (decltype(type.length()) level = 1; c < type.length(); ++c) {
1328 if (type[c] ==
'<') ++level;
1329 if (type[c] ==
'>') --level;
1330 if (level == 0)
break;
1332 if (c != (type.length()-1) ) {
1333 return ROOT::kNotSTL;
1336 return STLKind(type.substr(0,pos));
1350 int TClassEdit::IsSTLCont(
const char *type,
int testAlloc)
1352 if (strchr(type,
'<')==0)
return 0;
1354 TSplitType arglist( type );
1355 return arglist.IsSTLCont(testAlloc);
1361 bool TClassEdit::IsStdClass(
const char *classname)
1363 classname += StdLen( classname );
1364 if ( strcmp(classname,
"string")==0 )
return true;
1365 if ( strncmp(classname,
"bitset<",strlen(
"bitset<"))==0)
return true;
1366 if ( strncmp(classname,
"pair<",strlen(
"pair<"))==0)
return true;
1367 if ( strcmp(classname,
"allocator")==0)
return true;
1368 if ( strncmp(classname,
"allocator<",strlen(
"allocator<"))==0)
return true;
1369 if ( strncmp(classname,
"greater<",strlen(
"greater<"))==0)
return true;
1370 if ( strncmp(classname,
"less<",strlen(
"less<"))==0)
return true;
1371 if ( strncmp(classname,
"equal_to<",strlen(
"equal_to<"))==0)
return true;
1372 if ( strncmp(classname,
"hash<",strlen(
"hash<"))==0)
return true;
1373 if ( strncmp(classname,
"auto_ptr<",strlen(
"auto_ptr<"))==0)
return true;
1375 if ( strncmp(classname,
"vector<",strlen(
"vector<"))==0)
return true;
1376 if ( strncmp(classname,
"list<",strlen(
"list<"))==0)
return true;
1377 if ( strncmp(classname,
"forward_list<",strlen(
"forward_list<"))==0)
return true;
1378 if ( strncmp(classname,
"deque<",strlen(
"deque<"))==0)
return true;
1379 if ( strncmp(classname,
"map<",strlen(
"map<"))==0)
return true;
1380 if ( strncmp(classname,
"multimap<",strlen(
"multimap<"))==0)
return true;
1381 if ( strncmp(classname,
"set<",strlen(
"set<"))==0)
return true;
1382 if ( strncmp(classname,
"multiset<",strlen(
"multiset<"))==0)
return true;
1383 if ( strncmp(classname,
"unordered_set<",strlen(
"unordered_set<"))==0)
return true;
1384 if ( strncmp(classname,
"unordered_multiset<",strlen(
"unordered_multiset<"))==0)
return true;
1385 if ( strncmp(classname,
"unordered_map<",strlen(
"unordered_map<"))==0)
return true;
1386 if ( strncmp(classname,
"unordered_multimap<",strlen(
"unordered_multimap<"))==0)
return true;
1387 if ( strncmp(classname,
"bitset<",strlen(
"bitset<"))==0)
return true;
1395 bool TClassEdit::IsVectorBool(
const char *name) {
1396 TSplitType splitname( name );
1398 return ( TClassEdit::STLKind( splitname.fElements[0] ) == ROOT::kSTLvector)
1399 && ( splitname.fElements[1] ==
"bool" || splitname.fElements[1]==
"Bool_t");
1404 static void ResolveTypedefProcessType(
const char *tname,
1406 unsigned int cursor,
1408 unsigned int start_of_type,
1409 unsigned int end_of_type,
1410 unsigned int mod_start_of_type,
1412 std::string &result)
1414 std::string type(modified && (mod_start_of_type < result.length()) ?
1415 result.substr(mod_start_of_type, string::npos)
1416 : string(tname, start_of_type, end_of_type == 0 ? cursor - start_of_type : end_of_type - start_of_type));
1418 if (gInterpreterHelper->ExistingTypeCheck(type, typeresult)
1419 || gInterpreterHelper->GetPartiallyDesugaredNameWithScopeHandling(type, typeresult,
false)) {
1421 if (!typeresult.empty()) {
1424 result.replace(mod_start_of_type, string::npos,
1429 mod_start_of_type = start_of_type;
1430 result += string(tname,0,start_of_type);
1431 if (constprefix && typeresult.compare(0,6,
"const ",6) == 0) {
1432 result += typeresult.substr(6,string::npos);
1434 result += typeresult;
1437 }
else if (modified) {
1438 result.replace(mod_start_of_type, string::npos,
1442 if (end_of_type != 0 && end_of_type!=cursor) {
1443 result += std::string(tname,end_of_type,cursor-end_of_type);
1450 if (end_of_type != 0 && end_of_type!=cursor) {
1451 result += std::string(tname,end_of_type,cursor-end_of_type);
1459 static void ResolveTypedefImpl(
const char *tname,
1461 unsigned int &cursor,
1463 std::string &result)
1470 bool constprefix =
false;
1472 if (tname[cursor]==
' ') {
1475 result += string(tname,0,cursor);
1477 while (tname[cursor]==
' ') ++cursor;
1480 if (tname[cursor]==
'c' && (cursor+6<len)) {
1481 if (strncmp(tname+cursor,
"const ",6) == 0) {
1483 if (modified) result +=
"const ";
1489 if (len > 2 && strncmp(tname+cursor,
"::",2) == 0) {
1493 unsigned int start_of_type = cursor;
1494 unsigned int end_of_type = 0;
1495 unsigned int mod_start_of_type = result.length();
1496 unsigned int prevScope = cursor;
1497 for ( ; cursor<len; ++cursor) {
1498 switch (tname[cursor]) {
1500 if ((cursor+1)>=len || tname[cursor+1]!=
':') {
1502 if (modified) result += (tname+prevScope);
1507 scope = result.substr(mod_start_of_type, string::npos);
1508 scope += std::string(tname+prevScope,cursor-prevScope);
1510 scope = std::string(tname, start_of_type, cursor - start_of_type);
1512 std::string scoperesult;
1513 bool isInlined =
false;
1514 if (gInterpreterHelper->ExistingTypeCheck(scope, scoperesult)
1515 ||gInterpreterHelper->GetPartiallyDesugaredNameWithScopeHandling(scope, scoperesult)) {
1517 if (!scoperesult.empty()) {
1520 if (constprefix && scoperesult.compare(0,6,
"const ",6) != 0) mod_start_of_type -= 6;
1521 result.replace(mod_start_of_type, string::npos,
1526 mod_start_of_type = start_of_type;
1527 result += string(tname,0,start_of_type);
1529 result += scoperesult;
1532 }
else if (modified) {
1533 result += std::string(tname+prevScope,cursor+2-prevScope);
1535 }
else if (!gInterpreterHelper->IsDeclaredScope(scope,isInlined)) {
1537 if (modified) result += std::string(tname+prevScope,cursor+2-prevScope);
1538 }
else if (isInlined) {
1542 mod_start_of_type = start_of_type;
1543 result += string(tname,0,start_of_type);
1545 result += string(tname,start_of_type,prevScope - start_of_type);
1547 }
else if (modified) {
1548 result += std::string(tname+prevScope,cursor+2-prevScope);
1552 prevScope = cursor+1;
1558 result += std::string(tname+prevScope,cursor+1-prevScope);
1563 ResolveTypedefImpl(tname,len,cursor,modified,result);
1564 }
while( cursor<len && tname[cursor] ==
',' );
1566 while (cursor<len && tname[cursor+1]==
' ') ++cursor;
1571 if (cursor+2<len && tname[cursor+1]==
':' && tname[cursor+2]==
':') {
1572 if (modified) result +=
"::";
1574 prevScope = cursor+1;
1576 if ( (cursor+1)<len && tname[cursor+1] ==
',') {
1578 if (modified) result +=
',';
1581 if ( (cursor+1)<len && tname[cursor+1] ==
'>') {
1583 if (modified) result +=
" >";
1586 if ( (cursor+1) >= len) {
1589 if (tname[cursor] !=
' ')
break;
1590 if (modified) prevScope = cursor+1;
1597 end_of_type = cursor;
1599 while ((cursor+1)<len && tname[cursor+1] ==
' ') ++cursor;
1601 auto next = cursor+1;
1602 if (strncmp(tname+next,
"const",5) == 0 && ((next+5)==len || tname[next+5] ==
' ' || tname[next+5] ==
'*' || tname[next+5] ==
'&' || tname[next+5] ==
',' || tname[next+5] ==
'>' || tname[next+5] ==
']'))
1607 result += string(tname,0,start_of_type);
1609 mod_start_of_type = start_of_type + 6;
1610 result += string(tname,start_of_type,end_of_type-start_of_type);
1611 }
else if (mod_start_of_type < result.length()) {
1612 result.insert(mod_start_of_type,
"const ");
1613 mod_start_of_type += 6;
1616 mod_start_of_type += 6;
1617 result += string(tname,start_of_type,end_of_type-start_of_type);
1620 end_of_type = cursor+1;
1621 prevScope = end_of_type;
1622 if ((next+5)==len || tname[next+5] ==
',' || tname[next+5] ==
'>' || tname[next+5] ==
'[') {
1625 }
else if (next!=len && tname[next] !=
'*' && tname[next] !=
'&') {
1635 if (tname[cursor] !=
' ') end_of_type = cursor;
1637 auto next = cursor+1;
1638 if (strncmp(tname+next,
"const",5) == 0) {
1639 if ((next+5)==len || tname[next+5] ==
' ' || tname[next+5] ==
'*' || tname[next+5] ==
'&' || tname[next+5] ==
',' || tname[next+5] ==
'>' || tname[next+5] ==
'[') {
1644 (tname[next] ==
' ' || tname[next] ==
'*' || tname[next] ==
'&')) {
1647 if (strncmp(tname+next,
"const",5) == 0) {
1648 if ((next+5)==len || tname[next+5] ==
' ' || tname[next+5] ==
'*' || tname[next+5] ==
'&' || tname[next+5] ==
',' || tname[next+5] ==
'>' || tname[next+5] ==
'[') {
1660 if (modified && prevScope) {
1661 result += std::string(tname+prevScope,(end_of_type == 0 ? cursor : end_of_type)-prevScope);
1663 ResolveTypedefProcessType(tname,len,cursor,constprefix,start_of_type,end_of_type,mod_start_of_type,
1665 if (modified) result +=
',';
1669 if (modified && prevScope) {
1670 result += std::string(tname+prevScope,(end_of_type == 0 ? cursor : end_of_type)-prevScope);
1672 ResolveTypedefProcessType(tname,len,cursor,constprefix,start_of_type,end_of_type,mod_start_of_type,
1674 if (modified) result +=
'>';
1682 if (prevScope && modified) result += std::string(tname+prevScope,(end_of_type == 0 ? cursor : end_of_type)-prevScope);
1684 ResolveTypedefProcessType(tname,len,cursor,constprefix,start_of_type,end_of_type,mod_start_of_type,
1691 string TClassEdit::ResolveTypedef(
const char *tname,
bool )
1699 if (tname == 0 || tname[0] == 0)
1701 if (!gInterpreterHelper)
1708 if (gInterpreterHelper->ExistingTypeCheck(tname, result))
1710 if (result.empty())
return tname;
1714 unsigned int len = strlen(tname);
1716 unsigned int cursor = 0;
1717 bool modified =
false;
1718 ResolveTypedefImpl(tname,len,cursor,modified,result);
1720 if (!modified)
return tname;
1727 string TClassEdit::InsertStd(
const char *tname)
1734 static const char* sSTLtypes[] = {
1747 "basic_istringstream",
1750 "basic_ostringstream",
1754 "basic_stringstream",
1783 "istreambuf_iterator",
1792 "localedef utility",
1809 "moneypunct_byname",
1821 "ostreambuf_iterator",
1827 "pointer_to_binary_function",
1828 "pointer_to_unary_function",
1832 "raw_storage_iterator",
1851 "unordered_multimap",
1852 "unordered_multiset",
1858 static ShuttingDownSignaler<set<string>> sSetSTLtypes;
1860 if (tname==0 || tname[0]==0)
return "";
1862 if (sSetSTLtypes.empty()) {
1864 const size_t nSTLtypes =
sizeof(sSTLtypes) /
sizeof(
const char*);
1865 for (
size_t i = 0; i < nSTLtypes; ++i)
1866 sSetSTLtypes.insert(sSTLtypes[i]);
1870 size_t len = strlen(tname);
1872 ret.reserve(len + 20);
1876 bool precScope =
false;
1877 while (!(isalnum(tname[b]) || tname[b] ==
'_') && b < len) {
1878 precScope = (b < len - 2) && (tname[b] ==
':') && (tname[b + 1] ==
':');
1890 while (e < len && (isalnum(tname[e]) || tname[e] ==
'_'))
1894 set<string>::const_iterator iSTLtype = sSetSTLtypes.find(
id);
1895 if (iSTLtype != sSetSTLtypes.end())
1910 class NameCleanerForIO {
1912 std::vector<std::unique_ptr<NameCleanerForIO>> fArgumentNodes = {};
1913 NameCleanerForIO* fMother;
1914 bool fHasChanged =
false;
1915 bool AreAncestorsSTLContOrArray()
1917 NameCleanerForIO* mother = fMother;
1918 if (!mother)
return false;
1919 bool isSTLContOrArray =
true;
1920 while (
nullptr != mother){
1921 auto stlType = TClassEdit::IsSTLCont(mother->fName+
"<>");
1922 isSTLContOrArray &= ROOT::kNotSTL != stlType || TClassEdit::IsStdArray(mother->fName+
"<");
1923 mother = mother->fMother;
1926 return isSTLContOrArray;
1930 NameCleanerForIO(
const std::string& clName =
"",
1931 TClassEdit::EModType mode = TClassEdit::kNone,
1932 NameCleanerForIO* mother =
nullptr):fMother(mother)
1934 if (clName.back() !=
'>') {
1939 std::vector<std::string> v;
1941 TClassEdit::GetSplit(clName.c_str(), v, dummy, mode);
1944 auto argsEnd = v.end();
1945 auto argsBeginPlusOne = ++v.begin();
1946 auto argPos = std::find_if(argsBeginPlusOne, argsEnd,
1947 [](std::string& arg){
return (!arg.empty() && arg.front() ==
':');});
1948 if (argPos != argsEnd) {
1949 const int lenght = clName.size();
1950 int wedgeBalance = 0;
1951 int lastOpenWedge = 0;
1952 for (
int i=lenght-1;i>-1;i--) {
1953 auto& c = clName.at(i);
1957 }
else if (c ==
'>') {
1959 }
else if (c ==
':' && 0 == wedgeBalance) {
1961 auto nameToClean = clName.substr(0,i-1);
1962 NameCleanerForIO node(nameToClean, mode);
1963 auto cleanName = node.ToString();
1964 fHasChanged = node.HasChanged();
1970 cleanName += clName.substr(i+1,lastOpenWedge-i-1);
1973 auto lastTemplate = &clName.data()[i+1];
1976 TClassEdit::GetSplit(lastTemplate, v, dummy, mode);
1985 unsigned int nargs = v.size() - 2;
1986 for (
unsigned int i=0;i<nargs;++i) {
1987 fArgumentNodes.emplace_back(
new NameCleanerForIO(v[i+1],mode,
this));
1991 bool HasChanged()
const {
return fHasChanged;}
1993 std::string ToString()
1995 std::string name(fName);
1997 if (fArgumentNodes.empty())
return name;
2001 if (!fMother && TClassEdit::IsUniquePtr(fName+
"<")) {
2002 name = fArgumentNodes.front()->ToString();
2004 TClassEdit::TSplitType tst(name.c_str());
2005 tst.ShortType(name, 1);
2011 auto stlContType = AreAncestorsSTLContOrArray();
2012 if (stlContType != ROOT::kNotSTL && TClassEdit::IsUniquePtr(fName+
"<")) {
2013 name = fArgumentNodes.front()->ToString();
2020 for (
auto& node : fArgumentNodes) {
2021 name += node->ToString() +
",";
2022 fHasChanged |= node->HasChanged();
2025 name += name.back() ==
'>' ?
" >" :
">";
2029 const std::string& GetName() {
return fName;}
2030 const std::vector<std::unique_ptr<NameCleanerForIO>>* GetChildNodes()
const {
return &fArgumentNodes;}
2035 std::string TClassEdit::GetNameForIO(
const std::string& templateInstanceName,
2036 TClassEdit::EModType mode,
2046 NameCleanerForIO node(templateInstanceName, mode);
2047 auto nameForIO = node.ToString();
2049 *hasChanged = node.HasChanged();
2057 bool TClassEdit::GetStdArrayProperties(
const char* typeName,
2058 std::string& typeNameBuf,
2059 std::array<int, 5>& maxIndices,
2062 if (!IsStdArray(typeName))
return false;
2065 NameCleanerForIO node(typeName);
2068 auto childNodes = node.GetChildNodes();
2069 for (ndim = 1;ndim <=5 ; ndim++) {
2070 maxIndices[ndim-1] = std::atoi(childNodes->back()->GetName().c_str());
2071 auto& frontNode = childNodes->front();
2072 typeNameBuf = frontNode->GetName();
2073 if (! IsStdArray(typeNameBuf+
"<")) {
2074 typeNameBuf = frontNode->ToString();
2077 childNodes = frontNode->GetChildNodes();
2088 char* TClassEdit::DemangleTypeIdName(
const std::type_info& ti,
int& errorCode)
2090 const char* mangled_name = ti.name();
2091 return DemangleName(mangled_name, errorCode);
2096 struct FunctionSplitInfo {
2098 std::string fReturnType;
2101 std::string fScopeName;
2104 std::string fFunctionName;
2108 std::vector<std::string> fFunctionTemplateArguments;
2111 std::vector<std::string> fFunctionParameters;
2118 std::size_t FindNonNestedNeedles(std::string_view haystack, string_view needles)
2120 std::stack<char> expected;
2121 for (std::size_t pos = 0, end = haystack.length(); pos < end; ++pos) {
2122 char c = haystack[pos];
2123 if (expected.empty()) {
2124 if (needles.find(c) != std::string_view::npos)
2127 if (c == expected.top()) {
2133 case '<': expected.emplace(
'>');
break;
2134 case '(': expected.emplace(
')');
break;
2135 case '[': expected.emplace(
']');
break;
2138 return std::string_view::npos;
2142 std::size_t FindNonNestedDoubleColons(std::string_view haystack)
2144 std::size_t lenHaystack = haystack.length();
2145 std::size_t prevAfterColumn = 0;
2147 std::size_t posColumn = FindNonNestedNeedles(haystack.substr(prevAfterColumn),
":");
2148 if (posColumn == std::string_view::npos)
2149 return std::string_view::npos;
2150 prevAfterColumn += posColumn;
2152 if (prevAfterColumn + 1 >= lenHaystack)
2153 return std::string_view::npos;
2156 if (haystack[prevAfterColumn] ==
':')
2157 return prevAfterColumn - 1;
2161 return std::string_view::npos;
2164 std::string_view StripSurroundingSpace(std::string_view str)
2166 while (!str.empty() && std::isspace(str[0]))
2167 str.remove_prefix(1);
2168 while (!str.empty() && std::isspace(str.back()))
2169 str.remove_suffix(1);
2173 std::string ToString(std::string_view sv)
2177 return std::string(sv.data(), sv.length());
2182 bool TClassEdit::SplitFunction(std::string_view decl, TClassEdit::FunctionSplitInfo &result)
2190 std::size_t posArgs = FindNonNestedNeedles(decl,
"(");
2191 std::string_view declNoArgs = decl.substr(0, posArgs);
2193 std::size_t prevAfterWhiteSpace = 0;
2194 static const char whitespace[] =
" \t\n";
2195 while (declNoArgs.length() > prevAfterWhiteSpace) {
2196 std::size_t posWS = FindNonNestedNeedles(declNoArgs.substr(prevAfterWhiteSpace), whitespace);
2197 if (posWS == std::string_view::npos)
2199 prevAfterWhiteSpace += posWS + 1;
2200 while (declNoArgs.length() > prevAfterWhiteSpace
2201 && strchr(whitespace, declNoArgs[prevAfterWhiteSpace]))
2202 ++prevAfterWhiteSpace;
2206 std::size_t endReturn = prevAfterWhiteSpace;
2207 while (declNoArgs.length() > endReturn
2208 && strchr(
"&* \t \n", declNoArgs[endReturn]))
2211 result.fReturnType = ToString(StripSurroundingSpace(declNoArgs.substr(0, endReturn)));
2214 std::string_view scopeFunctionTmplt = declNoArgs.substr(endReturn);
2215 std::size_t prevAtScope = FindNonNestedDoubleColons(scopeFunctionTmplt);
2216 while (prevAtScope != std::string_view::npos
2217 && scopeFunctionTmplt.length() > prevAtScope + 2) {
2218 std::size_t posScope = FindNonNestedDoubleColons(scopeFunctionTmplt.substr(prevAtScope + 2));
2219 if (posScope == std::string_view::npos)
2221 prevAtScope += posScope + 2;
2224 std::size_t afterScope = prevAtScope + 2;
2225 if (prevAtScope == std::string_view::npos) {
2230 result.fScopeName = ToString(StripSurroundingSpace(scopeFunctionTmplt.substr(0, prevAtScope)));
2231 std::string_view funcNameTmplArgs = scopeFunctionTmplt.substr(afterScope);
2233 result.fFunctionTemplateArguments.clear();
2234 std::size_t posTmpltOpen = FindNonNestedNeedles(funcNameTmplArgs,
"<");
2235 if (posTmpltOpen != std::string_view::npos) {
2236 result.fFunctionName = ToString(StripSurroundingSpace(funcNameTmplArgs.substr(0, posTmpltOpen)));
2239 std::string_view tmpltArgs = funcNameTmplArgs.substr(posTmpltOpen + 1);
2240 std::size_t posTmpltClose = FindNonNestedNeedles(tmpltArgs,
">");
2241 if (posTmpltClose != std::string_view::npos) {
2242 tmpltArgs = tmpltArgs.substr(0, posTmpltClose);
2243 std::size_t prevAfterArg = 0;
2244 while (tmpltArgs.length() > prevAfterArg) {
2245 std::size_t posComma = FindNonNestedNeedles(tmpltArgs.substr(prevAfterArg),
",");
2246 if (posComma == std::string_view::npos) {
2249 result.fFunctionTemplateArguments.emplace_back(ToString(StripSurroundingSpace(tmpltArgs.substr(prevAfterArg, posComma))));
2250 prevAfterArg += posComma + 1;
2253 result.fFunctionTemplateArguments.emplace_back(ToString(StripSurroundingSpace(tmpltArgs.substr(prevAfterArg))));
2256 result.fFunctionName = ToString(StripSurroundingSpace(funcNameTmplArgs));
2259 result.fFunctionParameters.clear();
2260 if (posArgs != std::string_view::npos) {
2262 std::string_view params = decl.substr(posArgs + 1);
2263 std::size_t posEndArgs = FindNonNestedNeedles(params,
")");
2264 if (posEndArgs != std::string_view::npos) {
2265 params = params.substr(0, posEndArgs);
2266 std::size_t prevAfterArg = 0;
2267 while (params.length() > prevAfterArg) {
2268 std::size_t posComma = FindNonNestedNeedles(params.substr(prevAfterArg),
",");
2269 if (posComma == std::string_view::npos) {
2270 result.fFunctionParameters.emplace_back(ToString(StripSurroundingSpace(params.substr(prevAfterArg))));
2273 result.fFunctionParameters.emplace_back(ToString(StripSurroundingSpace(params.substr(prevAfterArg, posComma))));
2274 prevAfterArg += posComma + 1;