KaliVeda
Toolkit for HIC analysis
KVClassFactory.cpp
1 /*
2 $Id: KVClassFactory.cpp,v 1.19 2009/01/21 08:04:20 franklan Exp $
3 $Revision: 1.19 $
4 $Date: 2009/01/21 08:04:20 $
5 */
6 
7 #include "KVClassFactory.h"
8 #include "TSystem.h"
9 #include "TSystemDirectory.h"
10 #include "KVBase.h"
11 #include "TObjString.h"
12 #include "KVHashList.h"
13 #include "TClass.h"
14 #include "TMethod.h"
15 #include "TMethodArg.h"
16 
17 using namespace std;
18 
20 
21 
22 
24 KVString __add_indented_line(const KVString& line, const KVString& indent, Bool_t newline = kTRUE)
25 {
26  KVString output;
27  line.Begin("\n");
28  while (!line.End()) {
29  KVString _line = line.Next();
30  output += (indent + _line);
31  output += "\n";
32  }
33  if (!newline) output.Remove(output.Length() - 1);
34  return output;
35 }
36 
37 
38 
41 
43  : fBaseClass(nullptr), fHasBaseClass(kFALSE), fBaseClassTObject(kFALSE), fInlineAllMethods(kFALSE), fInlineAllCtors(kFALSE),
44  fInheritAllCtors(kTRUE)
45 {
46  // Default ctor
47 }
48 
49 
50 
80 
82  const Char_t* classdesc,
83  const Char_t* base_class,
84  Bool_t withTemplate,
85  const Char_t* templateFile)
86  : fBaseClass(nullptr), fHasBaseClass(kFALSE), fBaseClassTObject(kFALSE), fInlineAllMethods(kFALSE), fInlineAllCtors(kFALSE),
87  fInheritAllCtors(kTRUE)
88 {
89  //Create a new class with the following characteristics:
90  //
91  // classname = name of new class
92  // classdesc = short (one line) description of class
93  // base_class = name of base class(es)* (if creating a derived class)
94  // withTemplate = kTRUE if template files for the '.h' and '.cpp' are to be used
95  // templateFile = base name of template files
96  //
97  // *(if the class has several base classes, give a comma-separated list)
98  //
99  //Only classname and classdesc have to be given.
100  //By default we create a new base class without use of template files.
101  //
102  //If withTemplate=kTRUE, the base name for the template files must be given.
103  //We check that the template files exist. If they do not, an error message is
104  //printed and this object will be made a zombie (test IsZombie() after constructor).
105  //The template for the class structure is defined in a '.h' and a '.cpp' file,
106  //as follows:
107  //
108  // if templateFile="" (default), we expect base_class!="", and template files with names base_classTemplate.h and base_classTemplate.cpp
109  // must be present in either $TEMPLATEDIR, $HOME or $PWD directories.
110  // the dummy classname "base_classTemplate" will be replaced everywhere by 'classname'
111  //
112  // if templateFile="/absolute/path/classTemplate" we use classTemplate.h & classTemplate.cpp in the given directory.
113  // the dummy classname "classTemplate" will be replaced everywhere by 'classname'
114  //
115  // if templateFile="classTemplate" we look for classTemplate.h & classTemplate.cpp in $TEMPLATEDIR, $HOME or $PWD directories.
116  // the dummy classname "classTemplate" will be replaced everywhere by 'classname'
117 
118  fBaseClass = NULL;
119  SetClassName(classname);
120  SetClassDesc(classdesc);
121  SetBaseClass(base_class);
122  SetTemplate(withTemplate, templateFile);
123  SetWhoWhen();
124 
125  if (!withTemplate) {
126  // for untemplated classes we add default ctor & dtor straight away
128  AddDestructor();
129  }
130 }
131 
132 
133 
134 
150 
151 void KVClassFactory::SetTemplate(Bool_t temp, const Char_t* templateFile)
152 {
153  //If the class uses template files (temp=kTRUE), 'templateFile' is the base name used to find these files.
154  //The template for the class structure is defined in a '.h' and a '.cpp' file,
155  //as follows:
156  //
157  // if templateFile="" (default), we expect a base class to have been given,
158  // and template files with names base_classTemplate.h and base_classTemplate.cpp
159  // must be present in either $TEMPLATEDIR, $HOME or $PWD directories.
160  // the dummy classname "base_classTemplate" will be replaced everywhere by 'classname'
161  //
162  // if templateFile="/absolute/path/classTemplate" we use classTemplate.h & classTemplate.cpp in the given directory.
163  // the dummy classname "classTemplate" will be replaced everywhere by 'classname'
164  //
165  // if templateFile="classTemplate" we look for classTemplate.h & classTemplate.cpp in $TEMPLATEDIR, $HOME or $PWD directories.
166  // the dummy classname "classTemplate" will be replaced everywhere by 'classname'
167 
168  fWithTemplate = temp;
169  fTemplateBase = templateFile;
170 
171  if (temp) {
172  //if we want to use template files for the new class,
173  //we have to make sure they exist;
174  if (!CheckTemplateFiles(GetBaseClass(), templateFile)) {
175  //template files not found - cannot proceed
176  KVError::Error(this, "SetTemplate", "Cannot find template files %s. Object made a zombie.", templateFile);
178  }
179  }
180 }
181 
182 
183 
184 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
185 
188 
190 #else
191 void KVClassFactory::Copy(TObject& obj)
192 #endif
193 {
194  //Copy the state of this KVClassFactory to the one referenced by 'obj'
195  TObject::Copy(obj);
196  ((KVClassFactory&)obj).SetClassName(GetClassName());
197  ((KVClassFactory&)obj).SetClassDesc(GetClassDesc());
198  ((KVClassFactory&)obj).SetBaseClass(GetBaseClass());
199  ((KVClassFactory&)obj).SetTemplate(WithTemplate(), GetTemplateBase());
200  ((KVClassFactory&)obj).SetWhoWhen();
201  if (fMethods.GetEntries()) {
202  TIter next(&fMethods);
203  KVClassMethod* meth;
204  while ((meth = (KVClassMethod*)next()))((KVClassFactory&)obj).AddMethod(*meth);
205  }
206  if (fHeadInc.GetEntries()) fHeadInc.Copy(((KVClassFactory&)obj).fHeadInc);
207  if (fImpInc.GetEntries()) fImpInc.Copy(((KVClassFactory&)obj).fImpInc);
208  ((KVClassFactory&)obj).SetOutputPath(GetOutputPath());
209 }
210 
211 
212 
215 
217 {
218  //ctor par copie
219  fBaseClass = NULL;
220 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
221  obj.Copy(*this);
222 #else
223  ((KVClassFactory&)obj).Copy(*this);
224 #endif
225 }
226 
227 
228 
233 
234 void KVClassFactory::WriteWhoWhen(ofstream& file)
235 {
236  // Write a stub doxygen comment block to be used to document the file
237  // This will include
238  // class name, brief description, author name and date
239 
240  file << "/**\n \\class " << GetClassName() << "\n \\brief " << GetClassDesc() << "\n\n ";
241  file << "Write a detailed documentation for your class here, see doxygen manual for help.\n\n ";
242  file << "\\author " << fAuthor.Data() << "\n \\date " << fNow.AsString() << "\n*/\n\n";
243 }
244 
245 
246 
253 
254 void KVClassFactory::WritePreProc(ofstream& file)
255 {
256  //Write pre-processor directives in file
257  //i.e. '#pragma once' etc.
258  //
259  //If this class has inheritance, we add '#include "base_class.h"' for each of the base classes.
260  //and any other include files added using AddHeaderIncludeFile
261 
262  file << "#pragma once\n" << endl;
263 
264  //base class(es) ?
265  if (fHasBaseClass) {
266  if (WithMultipleBaseClasses()) {
267  fBaseClassName.Begin(",");
268  while (!fBaseClassName.End())
269  file << "#include \"" << fBaseClassName.Next(kTRUE) << ".h\"" << endl;
270  file << endl;
271  }
272  else
273  file << "#include \"" << fBaseClassName.Data() << ".h\"\n" << endl;
274  }
275  if (fHeadInc.GetSize()) {
276  TIter next(&fHeadInc);
277  TObjString* str;
278  while ((str = (TObjString*)next())) {
279  file << "#include \"" << str->String().Data() << "\"\n" << endl;
280  }
281  }
282 }
283 
284 
285 
292 
293 void KVClassFactory::WriteClassDec(ofstream& file)
294 {
295  // Write the class declaration in the header file
296  //
297  // This will include a default constructor & destructor and
298  // any methods added using AddMethod, sorted according to
299  // their access type.
300 
301  file << "class " << fClassName.Data();
302  if (fHasBaseClass) {
303  file << " : ";
304  if (WithMultipleBaseClasses()) {
305  fBaseClassName.Begin(",");
306  file << "public " << fBaseClassName.Next(kTRUE);
307  while (!fBaseClassName.End()) file << ", public " << fBaseClassName.Next(kTRUE);
308  }
309  else
310  file << "public " << fBaseClassName.Data();
311  }
312  file << "\n{" << endl;
313 
314  // private members
315  unique_ptr<KVSeqCollection> prem(fMembers.GetSubListWithMethod("private", "GetAccess"));
316  if (prem->GetEntries()) {
317  file << "\n" << endl;
318  KVString line;
319  TIter next(prem.get());
320  KVClassMember* meth;
321  while ((meth = (KVClassMember*)next())) {
322  meth->WriteDeclaration(line);
323  file << " " << line.Data() << endl;
324  }
325  }
326 
327  // private methods + constructors + destructor (if private)
328  unique_ptr<KVSeqCollection> priv(fMethods.GetSubListWithMethod("private", "GetAccess"));
329  unique_ptr<KVSeqCollection> ctor(priv->GetSubListWithMethod("1", "IsConstructor"));
330  if (ctor->GetEntries()) {
331  file << endl;
332  KVString line;
333  TIter next(ctor.get());
334  KVClassMethod* meth;
335  while ((meth = (KVClassMethod*)next())) {
336  meth->WriteDeclaration(line);
337  file << " " << line.Data() << endl;
338  }
339  }
340  if (priv->GetEntries()) {
341  file << endl;
342  KVString line;
343  TIter next(priv.get());
344  KVClassMethod* meth;
345  while ((meth = (KVClassMethod*)next())) {
346  if (meth->IsNormalMethod()) {
347  meth->WriteDeclaration(line);
348  file << " " << line.Data() << endl;
349  }
350  }
351  }
352  // private destructor
353  if (GetDestructor() && GetDestructor()->IsPrivate()) {
354  KVString line;
356  file << " " << line.Data() << endl;
357  }
358 
359  bool protected_written = kFALSE;
360 
361  // protected members
362  prem.reset(fMembers.GetSubListWithMethod("protected", "GetAccess"));
363  if (prem->GetEntries()) {
364  file << "\nprotected:" << endl;
365  protected_written = kTRUE;
366  KVString line;
367  TIter next(prem.get());
368  KVClassMember* meth;
369  while ((meth = (KVClassMember*)next())) {
370  meth->WriteDeclaration(line);
371  file << " " << line.Data() << endl;
372  }
373  }
374 
375  // protected methods + ctors + dtor (if protected)
376  unique_ptr<KVSeqCollection> prot(fMethods.GetSubListWithMethod("protected", "GetAccess"));
377  ctor.reset(prot->GetSubListWithMethod("1", "IsConstructor"));
378  if (ctor->GetEntries()) {
379  if (!protected_written) {
380  file << "\nprotected:" << endl;
381  protected_written = kTRUE;
382  }
383  else
384  file << endl;
385  KVString line;
386  TIter next(ctor.get());
387  KVClassMethod* meth;
388  while ((meth = (KVClassMethod*)next())) {
389  meth->WriteDeclaration(line);
390  file << " " << line.Data() << endl;
391  }
392  }
393  if (prot->GetEntries()) {
394  if (!protected_written) {
395  file << "\nprotected:" << endl;
396  protected_written = kTRUE;
397  }
398  else
399  file << endl;
400  KVString line;
401  TIter next(prot.get());
402  KVClassMethod* meth;
403  while ((meth = (KVClassMethod*)next())) {
404  if (meth->IsNormalMethod()) {
405  meth->WriteDeclaration(line);
406  file << " " << line.Data() << endl;
407  }
408  }
409  }
410  // protected destructor
411  if (GetDestructor() && GetDestructor()->IsProtected()) {
412  if (!protected_written) {
413  file << "\nprotected:" << endl;
414  protected_written = kTRUE;
415  }
416  else
417  file << endl;
418  KVString line;
420  file << " " << line.Data() << endl;
421  }
422 
423  //public methods
424  file << "public:" << endl;
425  //list of public ctors
426  unique_ptr<KVSeqCollection> pub(fMethods.GetSubListWithMethod("public", "GetAccess"));
427  ctor.reset(pub->GetSubListWithMethod("1", "IsConstructor"));
428  unique_ptr<KVSeqCollection> pubnor(pub->GetSubListWithMethod("1", "IsNormalMethod"));
429  if (ctor->GetEntries()) {
430  KVString line;
431  TIter next(ctor.get());
432  KVClassMethod* meth;
433  while ((meth = (KVClassMethod*)next())) {
434  meth->WriteDeclaration(line);
435  file << line.Data() << endl;
436  }
437  }
438  // public destructor
439  if (GetDestructor() && GetDestructor()->IsPublic()) {
440  file << endl;
441  KVString line;
443  file << line.Data() << endl;
444  if (pubnor->GetEntries()) file << endl;
445  }
446 
447  // public methods
448  if (pubnor->GetEntries()) {
449  KVString line;
450  TIter next(pubnor.get());
451  KVClassMethod* meth;
452  while ((meth = (KVClassMethod*)next())) {
453  meth->WriteDeclaration(line);
454  file << line.Data() << endl;
455  }
456  }
457 
458  file << "\n ClassDef(" << fClassName.Data() << ",1)//";
459  file << fClassDesc.Data() << endl;
460  file << "};\n" << endl;
461 }
462 
463 
464 
468 
469 void KVClassFactory::WriteClassImp()
470 {
471  //Write the class implementation file
472  //This includes a class description in pure HTML
473 
474  ofstream file_cpp;
475 
476  // make sure any required directories exist
477  if (fClassPath != "") gSystem->mkdir(fClassPath, kTRUE);
478  file_cpp.open(GetImpFileName());
479 
480  file_cpp << "#include \"" << fClassName.Data() << ".h\"" << endl;
481  if (fImpInc.GetSize()) {
482  TIter next(&fImpInc);
483  TObjString* str;
484  while ((str = (TObjString*)next())) {
485  file_cpp << "#include \"" << str->String().Data() << "\"" << endl;
486  }
487  }
488  file_cpp << endl << "ClassImp(" << fClassName.Data() << ")\n" << endl << endl;
489 
490  // list of constructors
491  unique_ptr<KVSeqCollection> ctor(fMethods.GetSubListWithMethod("1", "IsConstructor"));
492  if (ctor->GetEntries()) {
493  KVString line;
494  TIter next(ctor.get());
495  KVClassMethod* meth;
496  while ((meth = (KVClassMethod*)next())) {
497  if (!meth->IsInline()) {
498  meth->WriteImplementation(line);
499  file_cpp << line.Data() << endl;
500  }
501  }
502  }
503 
504  // write destructor
505  if (GetDestructor() && !GetDestructor()->IsInline()) {
506  KVString line;
508  file_cpp << line.Data() << endl;
509  }
510 
511  //write implementations of added methods
512  unique_ptr<KVSeqCollection> normeth(fMethods.GetSubListWithMethod("1", "IsNormalMethod"));
513  if (normeth->GetEntries()) {
514  KVString line;
515  TIter next(normeth.get());
516  KVClassMethod* meth;
517  while ((meth = (KVClassMethod*)next())) {
518  if (!meth->IsInline()) {
519  meth->WriteImplementation(line);
520  file_cpp << line.Data() << endl << endl;
521  }
522  }
523  }
524 
525  file_cpp.close();
526 
527  cout << "<KVClassFactory::WriteClassImp> : File " << GetImpFileName() << " generated." << endl;
528 }
529 
530 
531 
534 
535 void KVClassFactory::WriteClassHeader()
536 {
537  //Write the class header file
538 
539  ofstream file_h;
540 
541  // make sure any required directories exist
542  if (fClassPath != "") gSystem->mkdir(fClassPath, kTRUE);
543  file_h.open(GetHeaderFileName());
544 
545  WritePreProc(file_h);
546  WriteWhoWhen(file_h);
547  WriteClassDec(file_h);
548 
549  file_h.close();
550 
551  cout << "<KVClassFactory::WriteClassHeader> : File " << GetHeaderFileName() << " generated." << endl;
552 }
553 
554 
555 
630 
631 void KVClassFactory::MakeClass(const Char_t* classname,
632  const Char_t* classdesc,
633  const Char_t* base_class,
634  Bool_t withTemplate,
635  const Char_t* templateFile)
636 {
637  //Static method for generating skeleton header and implementation files for a new class.
638  //
639  //Give a name for the class and a short description, used for HTML doc.
640  //
641  //The optional string 'base_class' gives the name(s) of the parent class(es)*, in case of inheritance;
642  //if not given, the new class will be a base class.
643  // *(in case of several base classes, give a comma-separated list)
644  //
645  //if withTemplate=kTRUE, we use a template for the class structure, defined in a '.h' and a '.cpp' file,
646  //as follows:
647  //
648  // - if templateFile="" (default), we expect base_class!="", and template files with names base_classTemplate.h and base_classTemplate.cpp
649  // must be present in either $KVROOT/KVFiles, $HOME or $PWD directories.
650  // the dummy classname "base_classTemplate" will be replaced everywhere by 'classname'
651  //
652  // - if templateFile="/absolute/path/classTemplate" we use classTemplate.h & classTemplate.cpp in the given directory.
653  // the dummy classname "classTemplate" will be replaced everywhere by 'classname'
654  //
655  // - if templateFile="classTemplate" we look for classTemplate.h & classTemplate.cpp in $KVROOT/KVFiles, $HOME or $PWD directories.
656  // the dummy classname "classTemplate" will be replaced everywhere by 'classname'
657  //
658  //Example of use:
659  //~~~~~{.cpp}
660  // KVClassFactory::MakeClass("MyClass", "A brand new class", "TObject")
661  //~~~~~
662  //will generate the following MyClass.h and MyClass.cpp files:
663  //~~~~{.cpp}
664 //MyClass.h ======================================>>>>
665 // //Created by KVClassFactory on Fri Mar 24 23:52:54 2006 (<-------creation date)
666 // //Author: John Frankland (<----- full name of user who calls MakeClass method)
667 //
668 // #ifndef __MYCLASS_H
669 // #define __MYCLASS_H
670 //
671 // #include <TObject.h> (<----- header file for parent class, if necessary)
672 //
673 // class MyClass : public TObject
674 // {
675 // public:
676 //
677 // MyClass();
678 // virtual ~MyClass();
679 //
680 // ClassDef(MyClass,1)//A brand new class (<------- class description)
681 // };
682 //
683 // #endif
684 //<<<<<<<===========================================
685 //
686  //~~~~
687  //~~~~{.cpp}
688 //MyClass.cpp=================================>>>>>>>
689 // //Created by KVClassFactory on Fri Mar 24 23:52:54 2006
690 // //Author: John Frankland (<----- full name of user who calls MakeClass method)
691 //
692 // #include "MyClass.h"
693 //
694 // ClassImp(MyClass)
695 //
696 // ////////////////////////////////////////////////////////////////////////////////
697 // // A brand new class (<------- class description)
698 // ////////////////////////////////////////////////////////////////////////////////
699 //
700 // MyClass::MyClass()
701 // {
702 // //Default constructor
703 // }
704 //
705 // MyClass::~MyClass()
706 // {
707 // //Destructor
708 // }
709  //~~~~
710 
711  KVClassFactory cf(classname, classdesc, base_class, withTemplate, templateFile);
712  if (!cf.IsZombie()) cf.GenerateCode();
713 }
714 
715 
716 
718 
720 {
721  if (!GetDefaultCtor()) {
722  KVClassConstructor* ctor(AddConstructor());// add default ctor
723  ctor->SetMethodComment("Default constructor");
724  }
725 }
726 
727 
728 
731 
733 {
734  // Generate header and implementation file for currently-defined class
735 
736  if (IsZombie()) {
737  KVError::Warning(this, "GenerateCode", "Object is zombie. No code will be generated.");
738  return;
739  }
740 
741  if (fWithTemplate) {
742  WriteClassWithTemplateHeader();
743  WriteClassWithTemplateImp();
744  }
745  else {
747  AddDestructor();
748  if (fInheritAllCtors) AddAllBaseConstructors();
749  AddCopyConstructor();
750  AddMemberInitialiserConstructor();
751  AddAssignmentOperator();
752  if (fBaseClassTObject) {
753  // check for base class which inherits from TObject
754  // if so, we add a skeleton Copy(const TObject&) method
755  // and use it in the copy ctor
756  AddTObjectCopyMethod();
757  }
758  else if (!fHasBaseClass) {
759  // if a base class is defined, even if it does not inherit TObject,
760  // we assume that it functions correctly with the ROOT CLI.
761  // otherwise, we need to add #include "Rtypes.h" for definition of ClassDef and ClassImp
762  AddHeaderIncludeFile("Rtypes.h");
763  }
764  GenerateGettersAndSetters();
765  if (fInlineAllMethods) InlineAllMethods();
766  if (fInlineAllCtors) InlineAllConstructors();
767 
768  WriteClassHeader();
769  WriteClassImp();
770  }
771 }
772 
773 
774 
778 
779 KVClassFactory::KVClassMember* KVClassFactory::AddMember(const Char_t* name, const Char_t* type, const Char_t* comment, const Char_t* access)
780 {
781  // Add a member variable to the class, with name 'f[name]' according to ROOT convention.
782  // The access type is by default "protected", in accordance with OO-encapsulation.
783 
784  KVClassMember* m = new KVClassMember(name, type, comment, access);
785  fMembers.Add(m);
786  return m;
787 }
788 
789 
790 
794 
795 void KVClassFactory::GenerateGettersAndSetters()
796 {
797  // for each member variable we generate inlined Get/Set methods
798  // for boolean members we generate Is/SetIs methods
799 
801  TIter it(&fMembers);
802  KVClassMember* m;
803  while ((m = (KVClassMember*)it())) {
804  TString mem_name = m->GetRealName();
805  TString mem_type = m->GetType();
806  KVClassMethod* meth;
807  if (mem_type == "Bool_t") meth = AddMethod(Form("SetIs%s", mem_name.Data()), "void");
808  else meth = AddMethod(Form("Set%s", mem_name.Data()), "void");
809  meth->SetInline();
810  meth->AddArgument(mem_type);
811  meth->SetMethodComment(
812  Form("Set value of %s", m->GetName())
813  );
814  meth->SetMethodBody(
815  Form(" %s=arg1;", m->GetName())
816  );
817  if (mem_type == "Bool_t") meth = AddMethod(Form("Is%s", mem_name.Data()), mem_type, "public", kFALSE, kTRUE);
818  else meth = AddMethod(Form("Get%s", mem_name.Data()), mem_type, "public", kFALSE, kTRUE);
819  meth->SetInline();
820  meth->SetMethodComment(
821  Form("Get value of %s", m->GetName())
822  );
823  meth->SetMethodBody(
824  Form(" return %s;", m->GetName())
825  );
826  }
827  }
828 }
829 
830 
831 
835 
836 void KVClassFactory::SetWhoWhen()
837 {
838  //Set date, time and user name based on current environment
839  //If available, we use the full name of the current user, otherwise we use the login name.
840 
841  UserGroup_t* user = gSystem->GetUserInfo();
842  fAuthor = user->fRealName;
843  if (fAuthor == "")
844  fAuthor = user->fUser;
845  // remove trailing commas (???)
846  if (fAuthor.EndsWith(",")) {
847  Ssiz_t len = fAuthor.Length() - 1;
848  do {
849  fAuthor.Remove(len);
850  --len;
851  }
852  while (fAuthor.EndsWith(","));
853  }
854  delete user;
855  fNow.Set();
856 }
857 
858 
859 
860 
867 
868 Ssiz_t KVClassFactory::FindNextUncommentedLine(TString& file, Ssiz_t beg)
869 {
870  // Return position of beginning of next uncommented line in file starting
871  // from position beg (default = 0).
872  // An uncommented line is a line outside of a "/* ... */" block
873  // containing non-whitespace material before any '/*' or '//'.
874  // If no uncommented line is found we return -1.
875 
876  Ssiz_t pos = beg;
877  Ssiz_t beg_cur_line = beg;
878  Bool_t nonWS = kFALSE;
879 
880  while (pos < file.Length()) {
881 
882  if (file(pos) == ' ' || file(pos) == '\t') {
883  // skip whitespace & tab
884  pos++;
885  }
886  else if (file(pos) == '\n') {
887  // reached newline without seeing comment
888  // if there is non-whitespace stuff on line, this is OK
889  if (nonWS) return beg_cur_line;
890  pos++;
891  beg_cur_line = pos;
892  }
893  else if (file(pos) == '/') {
894 
895  if (file(pos + 1) == '*') {
896  // beginning of comment block
897  // was there non-whitespace stuff before this ?
898  if (nonWS) return beg_cur_line;
899  Ssiz_t len = file.Index("*/", pos + 2); // find end of comment
900  if (len > -1) pos = len + 2;
901  else {
902  // end of comment block not found in rest of file
903  // return -1
904  pos = -1;
905  break;
906  }
907  }
908  else if (file(pos + 1) == '/') {
909  // beginning of 1-line comment
910  // was there non-whitespace stuff before this ?
911  if (nonWS) return beg_cur_line;
912  Ssiz_t len = file.Index('\n', pos + 2); // find end of line
913  if (len > 0) {
914  pos = len + 1;
915  beg_cur_line = pos;
916  }
917  else {
918  // end of comment not found in rest of file
919  // return -1
920  pos = -1;
921  break;
922  }
923  }
924  }
925  else {
926  //non-whitespace stuff
927  nonWS = kTRUE;
928  pos++;
929  }
930  }
931  // no new line at end of first uncommented file which is also the last line in the file
932  if (nonWS && pos > -1) return beg_cur_line;
933  return pos;
934 }
935 
936 
937 
942 
943 void KVClassFactory::WriteClassWithTemplateHeader()
944 {
945  //Writes the header file for a class using a template file.
946  //
947  //The ClassDef line in the template file will be replaced with one corresponding to the new class.
948 
949  ofstream file_h;
950 
951  // make sure any required directories exist
952  if (fClassPath != "") gSystem->mkdir(fClassPath, kTRUE);
953  file_h.open(GetHeaderFileName());
954 
955  WritePreProc(file_h);
956  WriteWhoWhen(file_h);
957 
958  ifstream file_h_template;
959 
960  //open file whose full path was stored in fTemplateH
961  if (!KVBase::SearchAndOpenKVFile(fTemplateH.Data(), file_h_template)) {
962  //this should never happen!
963  cout <<
964  "<KVClassFactory::WriteClassWithTemplateHeader>: cannot open " <<
965  fTemplateH.Data() << endl;
966  return;
967  }
968 
969  TString headFile;
970  headFile.ReadFile(file_h_template);
971  file_h_template.close();
972 
973  //find ClassDef
974  Ssiz_t class_ind;
975  if ((class_ind = headFile.Index("ClassDef")) > -1) {
976 
977  // find end of line just before ClassDef
978  Ssiz_t end_of_line = class_ind;
979  while (headFile(--end_of_line) != '\n') ;
980  //cut file into two parts: before ClassDef line, after ClassDef line
981  TString part1 = headFile(0, end_of_line + 1);
982  //keep part of file from "ClassDef" onwards.
983  TString subs = headFile(class_ind, headFile.Length() - 1);
984  //find next newline character i.e. the end of ClassDef line
985  Ssiz_t nl = subs.Index("\n");
986  TString part3 = subs(nl + 1, subs.Length() - 1);
987  //write ClassDef line
988  TString part2 = " ClassDefOverride(";
989  part2 += fClassName;
990  part2 += ",1)//";
991  part2 += fClassDesc;
992  part2 += "\n";
993 
994  KVString part_add;
995  //write declarations of added methods
996  // group by access type
997  if (fMethods.GetSize()) {
998  KVString line;
999  KVString acc_types[] = {"private", "protected", "public", "-"};
1000  int iac = 0;
1001  while (acc_types[iac] != "-") {
1002  std::unique_ptr<KVSeqCollection> sublist(fMethods.GetSubListWithLabel(acc_types[iac]));
1003  if (sublist->GetEntries()) {
1004  part_add += acc_types[iac];
1005  part_add += ":\n";
1006  TIter next(sublist.get());
1007  KVClassMethod* meth;
1008  while ((meth = (KVClassMethod*)next())) {
1009  meth->WriteDeclaration(line);
1010  part_add += line;
1011  part_add += "\n";
1012  }
1013  part_add += "\n";
1014  }
1015  ++iac;
1016  }
1017  }
1018 
1019  //stick all parts together
1020  headFile = part1 + part_add + part2 + part3;
1021  }
1022 
1023  file_h << headFile.ReplaceAll(fTemplateClassName.Data(),
1024  fClassName.Data());
1025  file_h << endl;
1026  file_h.close();
1027 
1028  cout << "<KVClassFactory::WriteClassWithTemplateHeader> : File " << GetHeaderFileName() << " generated." << endl;
1029 
1030 }
1031 
1032 
1033 
1036 
1037 void KVClassFactory::WriteClassWithTemplateImp()
1038 {
1039  // Writes the implementation file for the class
1040 
1041  ofstream file_cpp;
1042 
1043  // make sure any required directories exist
1044  if (fClassPath != "") gSystem->mkdir(fClassPath, kTRUE);
1045  file_cpp.open(GetImpFileName());
1046 
1047  file_cpp << "#include \"" << fClassName.Data() << ".h\"" << endl;
1048  if (fImpInc.GetSize()) {
1049  TIter next(&fImpInc);
1050  TObjString* str;
1051  while ((str = (TObjString*)next())) {
1052  file_cpp << "#include \"" << str->String().Data() << "\"" << endl;
1053  }
1054  }
1055  file_cpp << endl << "ClassImp(" << fClassName.Data() << ")\n" << endl;
1056 
1057  TString cppFile;
1058  ifstream file_cpp_template;
1059 
1060  //open file whose full path was stored in fTemplateCPP
1061  if (!KVBase::
1062  SearchAndOpenKVFile(fTemplateCPP.Data(), file_cpp_template)) {
1063  //this should never happen!
1064  cout << "<KVClassFactory::WriteClassWithTemplateImp>: cannot open "
1065  << fTemplateCPP.Data() << endl;
1066  return;
1067  }
1068 
1069  cppFile.ReadFile(file_cpp_template);
1070  file_cpp_template.close();
1071  file_cpp << cppFile.ReplaceAll(fTemplateClassName.Data(),
1072  fClassName.Data());
1073 
1074  //write implementations of added methods
1075  if (fMethods.GetSize()) {
1076  KVString line;
1077  TIter next(&fMethods);
1078  KVClassMethod* meth;
1079  while ((meth = (KVClassMethod*)next())) {
1080  meth->WriteImplementation(line);
1081  file_cpp << line.Data();
1082  }
1083  }
1084  file_cpp.close();
1085 
1086  cout << "<KVClassFactory::WriteClassWithTemplateImp> : File " << GetImpFileName() << " generated." << endl;
1087 }
1088 
1089 
1090 
1091 
1108 
1109 Bool_t KVClassFactory::CheckTemplateFiles(const Char_t* base_class,
1110  const Char_t* templateFile)
1111 {
1112  //Check that we have the necessary template files to generate the new class.
1113  //
1114  // if templateFile="" (default), we expect base_class!="", and template files with names base_classTemplate.h and base_classTemplate.cpp
1115  // must be present in either $TEMPLATEDIR, $HOME or $PWD directories.
1116  // the dummy classname "base_classTemplate" will be replaced everywhere by the new class name
1117  //
1118  // if templateFile="/absolute/path/classTemplate" we use classTemplate.h & classTemplate.cpp in the given directory.
1119  // the dummy classname "classTemplate" will be replaced everywhere by the new class name
1120  //
1121  // if templateFile="classTemplate" we look for classTemplate.h & classTemplate.cpp in $TEMPLATEDIR, $HOME or $PWD directories.
1122  // the dummy classname "classTemplate" will be replaced everywhere by the new class name
1123  //
1124  //if all goes well, this method returns kTRUE and fTemplateClassName contains the dummy class name
1125  //which should be replaced in the template files with the name of the new class, while fTemplateH and fTemplateCPP
1126  //contain the full paths to the template files.
1127 
1128  if (strcmp(base_class, "")) {
1129  //we have a base class name.
1130  //the dummy class name is base_classTemplate and we look for base_classTemplate.h and base_classTemplate.cpp
1131  fTemplateClassName = base_class;
1132  fTemplateClassName += "Template";
1133  }
1134  else {
1135  //no base class. we look for templateFile.h and templateFile.cpp
1136  fTemplateClassName = gSystem->BaseName(templateFile);
1137  }
1138 
1139  TString filename = fTemplateClassName + ".h";
1140  //we look for the template .h file in $TEMPLATEDIR, in $HOME and in $PWD
1141  //if found, fTemplateH contains the full path to the file.
1142  //if not found, we return kFALSE as we cannot proceed with the class generation.
1143 
1144  if (!KVBase::SearchKVFile(KVBase::GetTEMPLATEDIRFilePath(filename), fTemplateH)) {
1145  if (!KVBase::SearchKVFile(filename, fTemplateH)) return kFALSE;
1146  }
1147  filename = fTemplateClassName + ".cpp";
1148  //same treatment for '.cpp' file
1149  if (!KVBase::SearchKVFile(KVBase::GetTEMPLATEDIRFilePath(filename), fTemplateCPP)) {
1150  if (!KVBase::SearchKVFile(filename.Data(), fTemplateCPP)) return kFALSE;
1151  }
1152 
1153  return kTRUE;
1154 }
1155 
1156 
1157 
1158 
1162 
1164 {
1165  //A new KVClassMethod object will be created and added to the class,
1166  //copying the informations held in kvcm
1167 
1168  KVClassMethod* meth = new KVClassMethod(kvcm);
1169  fMethods.Add(meth);
1170 }
1171 
1172 
1173 
1174 
1185 
1186 KVClassFactory::KVClassMethod* KVClassFactory::AddMethod(const Char_t* name, const Char_t* return_type, const Char_t* access,
1187  Bool_t isVirtual, Bool_t isConst)
1188 {
1189  // Add a method to the class.
1190  // User must give return type and name of method.
1191  // Optional arguments determine access type (public, protected or private)
1192  // and if the method is 'virtual' and/or 'const'
1193  //
1194  // If another method with the same name already exists, user should keep the returned
1195  // pointer to the new KVClassMethod object and use KVClassMethod::AddArgument(),
1196  // KVClassMethod::SetMethodBody() in order to define arguments, method body, etc.
1197  // instead of using the AddMethodArgument, AddMethodBody methods
1198 
1199  KVClassMethod* meth = new KVClassMethod;
1200  fMethods.Add(meth);
1201  meth->SetName(name);
1202  meth->SetClassName(fClassName);
1203  meth->SetReturnType(return_type);
1204  meth->SetAccess(access);
1205  meth->SetVirtual(isVirtual);
1206  meth->SetConst(isConst);
1207  return meth;
1208 }
1209 
1210 
1211 
1212 
1224 
1226  const Char_t* argument_name, const Char_t* default_value, const Char_t* access)
1227 {
1228  // Add a constructor with or without arguments to the class.
1229  // If no arguments are given, adds a default constructor (no arguments).
1230  //
1231  // Optional argument 'access' determines access type (public, protected or private) [default: "public"]
1232  //
1233  // If more than one argument is needed, user should keep the returned pointer
1234  // to the new object and use KVClassMethod::AddArgument() in order to add further arguments.
1235  //
1236  // In order to define the implementation of the ctor method, user should keep the returned pointer
1237  // to the new object and use KVClassMethod::SetMethodBody(KVString&).
1238 
1239  KVClassConstructor* meth = new KVClassConstructor(this);
1240  fMethods.Add(meth);
1241  if (strcmp(argument_type, "")) {
1242  // use type of first argument as name of ctor method
1243  meth->SetName(argument_type);
1244  meth->AddArgument(argument_type, argument_name, default_value);
1245  }
1246  else {
1247  // default constructor
1248  meth->SetName("default_ctor");
1249  }
1250  meth->SetClassName(fClassName);
1251  if (fHasBaseClass) meth->SetBaseClass(fBaseClassName);
1252  meth->SetAccess(access);
1253  return meth;
1254 }
1255 
1256 
1257 
1258 
1264 
1265 void KVClassFactory::AddMethodArgument(const Char_t* method_name, const Char_t* argument_type,
1266  const Char_t* argument_name, const Char_t* default_value)
1267 {
1268  //Add an argument to the method 'method_name' added to the class using AddMethod.
1269  //User must give type of argument.
1270  //Optional argument argument_name gives name of argument (will be used in implementation declaration).
1271  //Optional argument default_value gives default value.
1272 
1273  KVClassMethod* meth = (KVClassMethod*)fMethods.FindObjectByName(method_name);
1274  if (!meth) {
1275  KVError::Error(this, "AddMethodArgument",
1276  "Method %s not found.", method_name);
1277  return;
1278  }
1279  meth->AddArgument(argument_type, argument_name, default_value);
1280 }
1281 
1282 
1283 
1284 
1288 
1289 void KVClassFactory::AddMethodBody(const Char_t* method_name, const KVString& body)
1290 {
1291  //Set the body of the code for method 'method_name' added to the class using AddMethod.
1292  //N.B. does not work for implementing constructors, see AddConstructor
1293 
1294  KVClassMethod* meth = (KVClassMethod*)fMethods.FindObjectByName(method_name);
1295  if (!meth) {
1296  KVError::Error(this, "AddMethodBody",
1297  "Method %s not found.", method_name);
1298  return;
1299  }
1300  meth->SetMethodBody(body);
1301 }
1302 
1303 
1304 
1307 
1308 void KVClassFactory::AddMethodComment(const Char_t* method_name, const KVString& comment)
1309 {
1310  //Set the comments for method 'method_name' added to the class using AddMethod.
1311 
1312  KVClassMethod* meth = (KVClassMethod*)fMethods.FindObjectByName(method_name);
1313  if (!meth) {
1314  KVError::Error(this, "AddMethodComment",
1315  "Method %s not found.", method_name);
1316  return;
1317  }
1318  meth->SetMethodComment(comment);
1319 }
1320 
1321 
1322 
1323 
1329 
1331 {
1332  //Add a file which will appear in the 'includes' list of the '.h' file
1333  //i.e. we will add a line
1334  // #include "filename"
1335  //to the .h file
1336  fHeadInc.Add(new TObjString(filename));
1337 }
1338 
1339 
1340 
1341 
1347 
1349 {
1350  //Add a file which will appear in the 'includes' list of the '.cpp' file
1351  //i.e. we will add a line
1352  // #include "filename"
1353  //to the .cpp file
1354  fImpInc.Add(new TObjString(filename));
1355 // Info("AddImplIncludeFile", "Called for %s %#x. List now contains %d filenames.",
1356 // ClassName(), (long)this, fImpInc.GetEntries());
1357 }
1358 
1359 
1360 
1361 
1364 
1366 {
1367  //Print infos on object
1368  Info("Print", "object name = %s, address = %p", GetName(), this);
1369  cout << " * fClassName = " << fClassName.Data() << endl;
1370  cout << " * fClassDesc = " << fClassDesc.Data() << endl;
1371  cout << " * fBaseClass = " << fBaseClassName.Data() << endl;
1372  cout << " * fTemplateBase = " << fTemplateBase.Data() << endl;
1373  cout << "---------> Methods" << endl;
1374  fMethods.Print();
1375  cout << "---------> Header Includes" << endl;
1376  fHeadInc.Print();
1377  cout << "---------> Implementation Includes" << endl;
1378  fImpInc.Print();
1379 }
1380 
1381 
1382 
1385 
1387 {
1388  // For each named parameter in the list, we add protected member variables with the name and type of the parameter.
1389 
1390  int npars = nvl.GetNpar();
1391  for (int i = 0; i < npars; i++) {
1392  KVNamedParameter* par = nvl.GetParameter(i);
1393  if (par->IsString()) {
1394  AddMember(par->GetName(), "TString", "member automatically generated by KVClassFactory::AddGetSetMethods");
1395  // make sure #include "TString.h" appears in header file
1396  if (! fHeadInc.FindObject("TString.h")) AddHeaderIncludeFile("TString.h");
1397  }
1398  else if (par->IsInt()) {
1399  AddMember(par->GetName(), "Int_t", "member automatically generated by KVClassFactory::AddGetSetMethods");
1400  }
1401  else if (par->IsDouble()) {
1402  AddMember(par->GetName(), "Double_t", "member automatically generated by KVClassFactory::AddGetSetMethods");
1403  }
1404  else if (par->IsBool()) {
1405  AddMember(par->GetName(), "Bool_t", "member automatically generated by KVClassFactory::AddGetSetMethods");
1406  }
1407  }
1408 }
1409 
1410 
1411 
1414 
1416 {
1417  // \param yes =true: Write implementation of all non-ctor/non-dtor methods in the header file of the class
1418 
1419  TIter it(&fMethods);
1420  KVClassMethod* m;
1421  while ((m = (KVClassMethod*)it())) {
1422  if (!m->IsConstructor() && !m->IsDestructor()) m->SetInline(yes);
1423  }
1424  fInlineAllMethods = yes;
1425 }
1426 
1427 
1428 
1431 
1433 {
1434  // \param yes =true: Write implementation of all constructors & the destructor in the header file of the class.
1435 
1436  unique_ptr<KVSeqCollection> ctors(fMethods.GetSubListWithMethod("1", "IsConstructor"));
1437  ctors->R__FOR_EACH(KVClassConstructor, SetInline)(yes);
1438  fInlineAllCtors = yes;
1439  KVClassDestructor* dtor = fMethods.get_object<KVClassDestructor>("destructor");
1440  if (dtor) dtor->SetInline(yes);
1441 }
1442 
1443 
1444 
1445 
1449 
1450 void KVClassFactory::AddTObjectCopyMethod()
1451 {
1452  // Adds skeleton standard ROOT Copy method if class has
1453  // member variables
1454 
1455  if (!GetNumberOfMemberVariables()) return;
1456 
1457  AddMethod("Copy", "void", "public", kFALSE, kTRUE);
1458  AddMethodArgument("Copy", "TObject&", "obj");
1459  KVString body("This method copies the current state of 'this' object into 'obj'\n\n");
1460  body += "You should add here any member variables, for example:\n\n";
1461  body += "(supposing a member variable ";
1462  body += fClassName;
1463  body += "::fToto)\n";
1464  body += " CastedObj.fToto = fToto;\n";
1465  body += "or\n";
1466  body += " CastedObj.SetToto( GetToto() );";
1467  AddMethodComment("Copy", body);
1468  // call Copy method for base class
1469  body = "\n\n ";
1470  body += fBaseClassName;
1471  body += "::Copy(obj);\n";
1472  if (!fMembers.GetEntries()) body += " //";
1473  else body += " ";
1474  body += fClassName;
1475  body += "& CastedObj = (";
1476  body += fClassName;
1477  body += "&)obj;\n";
1478  if (fMembers.GetEntries()) {
1479  TIter it(&fMembers);
1480  KVClassMember* m;
1481  while ((m = (KVClassMember*)it())) {
1482  body += " CastedObj.Set";
1483  body += m->GetRealName();
1484  body += "( Get";
1485  body += m->GetRealName();
1486  body += "() );\n";
1487  }
1488  }
1489  AddMethodBody("Copy", body);
1490 }
1491 
1492 
1493 
1498 
1499 void KVClassFactory::AddCopyConstructor()
1500 {
1501  // Adds copy constructor if class has member variables
1502  //
1503  // If class inherits from TObject, this just calls the Copy method
1504 
1505  if (!GetNumberOfMemberVariables()) return;
1506 
1507  KVClassConstructor* ctor = AddConstructor(Form("const %s&", fClassName.Data()), "obj");
1508  ctor->SetCopyCtor();
1509  ctor->SetMethodComment("Copy constructor");
1510  if (fBaseClassTObject) {
1511  ctor->SetMethodBody(" obj.Copy(*this);");
1512  }
1513 
1514 }
1515 
1516 
1517 
1527 
1528 void KVClassFactory::AddMemberInitialiserConstructor(KVClassConstructor* base_ctor)
1529 {
1530  // For classes with member variables, add a constructor which initialises
1531  // the values of all member variables
1532  //
1533  // If base_ctor is non-null, it is assumed to point to a constructor which has
1534  // been deduced from the base class' list of constructors; in this case we
1535  // add our class' members to the beginning of the list of arguments
1536  // so that if any of the base class ctor arguments have default values, they
1537  // will be at the end of the list
1538 
1539  if (!GetNumberOfMemberVariables()) return;
1540 
1541  TIter next(&fMembers);
1542  KVClassMember* memb = (KVClassMember*)next();
1543  KVClassConstructor* ctor;
1544  Bool_t adding_to_base = kFALSE;
1545  Int_t add_to_base(1);
1546  if (base_ctor) {
1547  ctor = base_ctor;
1548  adding_to_base = kTRUE;
1549  ctor->AddArgument(add_to_base, memb->GetType(), memb->GetRealName());
1550  ctor->SetMemberVariableNameForArgument(add_to_base, memb->GetName());
1551  }
1552  else {
1553  ctor = AddConstructor(memb->GetType(), memb->GetRealName());
1554  ctor->SetMemberVariableNameForArgument(1, memb->GetName());
1555  }
1556  int arg_num = 2;
1557  while ((memb = (KVClassMember*)next())) {
1558  if (adding_to_base) {
1559  ctor->AddArgument(++add_to_base, memb->GetType(), memb->GetRealName());
1560  ctor->SetMemberVariableNameForArgument(add_to_base, memb->GetName());
1561  }
1562  else {
1563  ctor->AddArgument(memb->GetType(), memb->GetRealName());
1564  ctor->SetMemberVariableNameForArgument(arg_num++, memb->GetName());
1565  }
1566  }
1567  ctor->SetMethodComment("Constructor with initial values for all member variables");
1568 }
1569 
1570 
1571 
1574 
1575 void KVClassFactory::AddAssignmentOperator()
1576 {
1577  // Add "ClassName& operator= (ClassName)" method and move constructor using copy & swap idiom if class has member variables
1578 
1579  if (!GetNumberOfMemberVariables()) return;
1580 
1581  auto swap_method = AddMethod("swap", "friend void");
1582  swap_method->AddArgument(Form("%s&",fClassName.Data()), "a");
1583  swap_method->AddArgument(Form("%s&",fClassName.Data()), "b");
1584  swap_method->SetInline();
1585  swap_method->SetMethodComment("Exception-safe swap method (copy & swap idiom)");
1586  KVString body = " using std::swap;\n";
1587  TIter it(&fMembers);
1588  KVClassMember* m;
1589  while ((m = (KVClassMember*)it())) {
1590  body += " swap(a.";
1591  body += m->GetName();
1592  body += ",b.";
1593  body += m->GetName();
1594  body += ");\n";
1595  }
1596  // if class is derived from another, we have to call swap also for the base class
1597  if(fHasBaseClass)
1598  body += Form(" swap(static_cast<%s&>(a),static_cast<%s&>(b));\n", fBaseClassName.Data(), fBaseClassName.Data());
1599  swap_method->SetMethodBody(body);
1600  auto oper = AddMethod("operator=", Form("%s&", fClassName.Data()));
1601  oper->AddArgument(fClassName, "other");
1602  oper->SetMethodComment("Assignment/move operator (copy & swap idiom)");
1603  body = " swap(*this,other);\n";
1604  body += " return (*this);";
1605  oper->SetMethodBody(body);
1606  auto move_con = AddConstructor(Form("%s&&",fClassName.Data()), "other");
1607  move_con->SetMoveCtor();
1608  move_con->SetMethodComment("Move constructor (copy & swap idiom)");
1609  move_con->SetNoExcept();
1610  body = " swap(*this,other);";
1611  move_con->SetMethodBody(body);
1612 }
1613 
1614 
1615 
1616 
1620 //Helper classes for KVClassFactory
1621 
1622 
1623 
1628 void KVClassFactory::KVClassMethod::WriteDeclaration(KVString& decl)
1629 {
1630  //Write declaration in the KVString object
1631  //
1632  //If method is inline write method body directly after declaration
1633 
1634  if(IsInline())
1635  write_doxygen_format_method_comments(decl);
1636  decl = " ";
1637  if (fVirtual) decl += "virtual ";
1638  if (IsNormalMethod()) {
1639  decl += GetReturnType();
1640  decl += " ";
1641  decl += GetName();
1642  }
1643  else {
1644  if (IsDestructor()) decl += "~";
1645  decl += GetClassName();
1646  }
1647  decl += "(";
1648  for (int i = 1; i <= fNargs; i++) {
1649  decl += fFields.GetStringValue(Form("Arg_%d", i));
1650  if (fFields.HasParameter(Form("Arg_%d_name", i))) {
1651  decl += " ";
1652  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1653  }
1654  else
1655  decl += Form(" arg%d", i);
1656  if (fFields.HasParameter(Form("Arg_%d_default", i))) {
1657  decl += " = ";
1658  decl += fFields.GetStringValue(Form("Arg_%d_default", i));
1659  }
1660  if (i < fNargs) decl += ", ";
1661  }
1662  decl += ")";
1663  if (fConst) decl += " const";
1664  if (fNoexcept) decl += " noexcept";
1665  if (!IsInline()) {
1666  decl += ";";
1667  return;
1668  }
1669  // write method body of inline function
1670  write_method_body(decl);
1671 }
1672 
1673 
1674 
1679 
1681 {
1682  // Write declaration in the KVString object
1683  //
1684  // All fundamental types and pointers are default-initialised (=0)
1685 
1686  decl = GetType();
1687  decl += " ";
1688  decl += GetName();
1689  if(IsFundamental() || IsPointer())
1690  decl += " = {}";
1691  decl += ";//";
1692  decl += GetComment();
1693 }
1694 
1695 
1696 
1698 
1699 void KVClassFactory::KVClassMethod::write_method_body(KVString& decl)
1700 {
1701  KVString indentation = "";
1702  if (IsInline()) indentation = " ";
1703  decl += "\n";
1704  decl += __add_indented_line("{", indentation);
1705  if (!strcmp(GetAccess(), "private")) decl += __add_indented_line(" // PRIVATE method", indentation);
1706  else if (!strcmp(GetAccess(), "protected")) decl += __add_indented_line(" // PROTECTED method", indentation);
1707  if (fFields.HasParameter("Body")) {
1708  //write body of method
1709  decl += __add_indented_line(fFields.GetStringValue("Body"), indentation);
1710  }
1711  else {
1712  if (fFields.HasParameter("ReturnType") && strcmp(fFields.GetStringValue("ReturnType"), "void")) {
1713  KVString return_dir = "return (";
1714  return_dir += GetReturnType();
1715  return_dir += ")0;";
1716  __add_indented_line(return_dir, indentation);
1717  }
1718  }
1719  decl += __add_indented_line("}", indentation, kFALSE);
1720 }
1721 
1722 
1723 
1725 
1726 void KVClassFactory::KVClassConstructor::write_method_body(KVString& decl)
1727 {
1728  KVString indentation = "";
1729  if (IsInline()) indentation = " ";
1730  if ((fNargs && !IsCopyCtor()) ||
1731  ((IsCopyCtor() || IsDefaultCtor()) && fFields.HasParameter("BaseClass"))
1732  || (IsCopyCtor() && !fParentClass->IsBaseClassTObject())
1733  || IsMoveCtor()) {
1734  decl += "\n : ";
1735  if (IsMoveCtor())
1736  {
1737  decl += Form("%s()", GetClassName());// move ctor delegates to default ctor - copy & swap idiom
1738  }
1739  else if (fFields.HasParameter("BaseClass")) {
1740  // initialise base class
1741  decl += fFields.GetStringValue("BaseClass");
1742  decl += "(";
1743  if (!IsCopyCtor() && fNargs) {
1744  Int_t base_args = 0;
1745  for (int i = 1; i <= fNargs; i++) {
1746  if (fFields.HasParameter(Form("Arg_%d_baseclass", i))) {
1747  ++base_args;
1748  if (fFields.HasParameter(Form("Arg_%d_name", i))) {
1749  if (base_args > 1) decl += ", ";
1750  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1751  }
1752  else {
1753  if (base_args > 1) decl += ", ";
1754  decl += Form("arg%d", i);
1755  }
1756  }
1757  }
1758  }
1759  else if (IsCopyCtor() && !fParentClass->IsBaseClassTObject()) {
1760  // for a derived object not inheriting TObject we call the copy ctor of the parent class
1761  decl += fFields.GetStringValue("Arg_1_name");
1762  }
1763  decl += ")";
1764  if ((fNargs && !IsCopyCtor() && fParentClass->GetNumberOfMemberVariables())
1765  || (IsCopyCtor() && !fParentClass->IsBaseClassTObject() && fParentClass->GetNumberOfMemberVariables())) decl += ", ";
1766  }
1767  if (fParentClass->GetNumberOfMemberVariables()) {
1768  // initialise member variables
1769  if (!IsCopyCtor() && fNargs) {
1770  Int_t mem_vars = 0;
1771  for (int i = 1; i <= fNargs; i++) {
1772  if (fFields.HasStringParameter(Form("Arg_%d_memvar", i))) {
1773  if (mem_vars) decl += ", ";
1774  decl += fFields.GetStringValue(Form("Arg_%d_memvar", i));
1775  decl += "(";
1776  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1777  decl += ")";
1778  ++mem_vars;
1779  }
1780  }
1781  }
1782  else if ((IsCopyCtor() && !fParentClass->IsBaseClassTObject())) {
1783  TIter it(fParentClass->GetListOfMembers());
1784  KVClassMember* m;
1785  Int_t imem = 0;
1786  while ((m = (KVClassMember*)it())) {
1787  if (imem) decl += ", ";
1788  decl += m->GetName();
1789  decl += "( ";
1790  decl += fFields.GetStringValue("Arg_1_name");
1791  decl += ".Get";
1792  decl += m->GetRealName();
1793  decl += "() )";
1794  ++imem;
1795  }
1796  }
1797  }
1798  }
1799  decl += "\n";
1800  decl += __add_indented_line("{", indentation);
1801  if (!strcmp(GetAccess(), "private")) decl += __add_indented_line(" // PRIVATE constructor", indentation);
1802  else if (!strcmp(GetAccess(), "protected")) decl += __add_indented_line(" // PROTECTED constructor", indentation);
1803  if (fFields.HasParameter("Body")) {
1804  //write body of method
1805  decl += __add_indented_line(fFields.GetStringValue("Body"), indentation);
1806  }
1807  decl += __add_indented_line("}", indentation, kFALSE);
1808 }
1809 
1810 
1811 
1813 
1814 void KVClassFactory::KVClassMethod::write_doxygen_format_method_comments(KVString& decl)
1815 {
1816  if (fFields.HasParameter("Comment")) {
1817  // Go through comment line by line adding doxygen comment markers
1818  KVString comment(fFields.GetStringValue("Comment"));
1819  comment.Begin("\n");
1820  // find longest line
1821  Ssiz_t longest = 0;
1822  while (!comment.End()) {
1823  KVString line = comment.Next();
1824  if (line.Length() > longest) longest = line.Length();
1825  }
1826  longest += 4; // remember to add "/// " at beginning of each comment line
1827  // write "////...." as long as longest line
1828  while (longest--) decl += "/";
1829  decl += "\n";
1830  comment.Begin("\n");
1831  while (!comment.End()) {
1832  KVString line = comment.Next();
1833  decl += "/// ";
1834  decl += line;
1835  decl += "\n";
1836  }
1837  decl += "\n";
1838  }
1839 }
1840 
1841 
1842 
1846 
1848 {
1849  //Write skeleton implementation in the KVString object
1850  //All constructors call the default ctor of the base class (if defined)
1851 
1852  decl = "";
1853  write_doxygen_format_method_comments(decl);
1854  decl += GetReturnType();
1855  if (IsNormalMethod()) {
1856  decl += " ";
1857  }
1858  decl += GetClassName();
1859  decl += "::";
1860  if (IsNormalMethod())
1861  decl += GetName();
1862  else {
1863  if (IsDestructor()) decl += "~";
1864  decl += GetClassName();
1865  }
1866  decl += "(";
1867  for (int i = 1; i <= fNargs; i++) {
1868  decl += fFields.GetStringValue(Form("Arg_%d", i));
1869  if (fFields.HasParameter(Form("Arg_%d_name", i))) {
1870  decl += " ";
1871  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1872  }
1873  else
1874  decl += Form(" arg%d", i);
1875  if (i < fNargs) decl += ", ";
1876  }
1877  decl += ")";
1878  if (fConst) decl += " const";
1879  if (fNoexcept) decl += " noexcept";
1880  write_method_body(decl);
1881  decl += "\n\n";
1882 
1883 }
1884 
1885 
1886 
1887 
1890 
1892 {
1893  //ctor par copie
1894  obj.Copy(*this);
1895 }
1896 
1897 
1898 
1899 
1902 
1904 {
1905  //ctor par copie
1906  obj.Copy(*this);
1907 }
1908 
1909 
1910 
1911 
1914 
1916 {
1917  //copy this to obj
1918  KVBase::Copy(obj);
1919  ((KVClassMember&)obj).SetComment(GetComment());
1920  ((KVClassMember&)obj).fRealName = GetRealName();
1921 }
1922 
1923 
1924 
1925 
1928 
1930 {
1931  //copy this to obj
1932  KVClassMember::Copy(obj);
1933  ((KVClassMethod&)obj).SetVirtual(IsVirtual());
1934  ((KVClassMethod&)obj).SetConst(IsConst());
1935  fFields.Copy(((KVClassMethod&)obj).fFields);
1936  ((KVClassMethod&)obj).SetNargs(GetNargs());
1937  ((KVClassMethod&)obj).SetInline(IsInline());
1938 }
1939 
1940 
1941 
1945 
1946 void KVClassFactory::KVClassMethod::AddArgument(Int_t i, const Char_t* type, const Char_t* argname, const Char_t* defaultvalue)
1947 {
1948  // Add an argument to the method, which will be in i-th position in the argument list
1949  // Any existing arguments with indices [i,fNargs] will first be moved to [i+1,fNargs+1]
1950 
1951  if (!(i > 0 && i <= fNargs + 1)) {
1952  KVError::Error(this, "AddArgument(Int_t i, ...)", "Must be called with i>0 & i<=%d", fNargs + 1);
1953  return;
1954  }
1955 
1956  if (i == fNargs + 1) { // this is just same as call to AddArgument(type,argname,...)
1957  AddArgument(type, argname, defaultvalue);
1958  return;
1959  }
1960 
1961  for (int j = fNargs; j >= i; --j) {
1962  if (fFields.HasStringParameter(Form("Arg_%d", j))) {
1963  fFields.SetValue(Form("Arg_%d", j + 1), fFields.GetStringValue(Form("Arg_%d", j)));
1964  fFields.RemoveParameter(Form("Arg_%d", j));
1965  }
1966  if (fFields.HasStringParameter(Form("Arg_%d_name", j))) {
1967  fFields.SetValue(Form("Arg_%d_name", j + 1), fFields.GetStringValue(Form("Arg_%d_name", j)));
1968  fFields.RemoveParameter(Form("Arg_%d_name", j));
1969  }
1970  if (fFields.HasIntParameter(Form("Arg_%d_baseclass", j))) {
1971  fFields.SetValue(Form("Arg_%d_baseclass", j + 1), fFields.GetIntValue(Form("Arg_%d_baseclass", j)));
1972  fFields.RemoveParameter(Form("Arg_%d_baseclass", j));
1973  }
1974  if (fFields.HasStringParameter(Form("Arg_%d_default", j))) {
1975  fFields.SetValue(Form("Arg_%d_default", j + 1), fFields.GetStringValue(Form("Arg_%d_default", j)));
1976  fFields.RemoveParameter(Form("Arg_%d_default", j));
1977  }
1978  }
1979 
1980  KVString _type(type);
1981  fFields.SetValue(Form("Arg_%d", i), _type);
1982  if (strcmp(defaultvalue, "")) {
1983  KVString _s(defaultvalue);
1984  fFields.SetValue(Form("Arg_%d_default", i), _s);
1985  }
1986  if (strcmp(argname, "")) {
1987  KVString _s(argname);
1988  fFields.SetValue(Form("Arg_%d_name", i), _s);
1989  }
1990 
1991  ++fNargs;
1992 }
1993 
1994 
1995 
1998 
2000 {
2001  // print the KVClass method
2002  cout << "KVClassMethod object -----> " << GetName() << endl;
2003  fFields.Print();
2004  cout << "This method is " << GetAccess() << endl;
2005  if (fConst) cout << "This method is CONST" << endl;
2006  if (fVirtual) cout << "This method is VIRTUAL" << endl;
2007 }
2008 
2009 
2010 
2013 
2015 {
2016  // print the KVClass member
2017  cout << "KVClassMember object -----> " << GetType() << " " << GetName() << endl;
2018  cout << "This member is " << GetAccess() << endl;
2019 }
2020 
2021 
2022 
2023 
2029 
2031 {
2032  // Add constructors with the same signature as all base class constructors
2033  // (apart from the default ctor or any copy constructors, which are a special case)
2034  // If this class has its own member variables, we add them to the argument list
2035  // of each base class constructor.
2036 
2037  if (!fBaseClass) return;
2038 
2039  KVHashList clist;
2040  clist.AddAll(fBaseClass->GetListOfMethods());
2041  unique_ptr<KVSeqCollection> constructors(clist.GetSubListWithName(fBaseClassName));
2042  TIter next_ctor(constructors.get());
2043  TMethod* method;
2044  while ((method = (TMethod*)next_ctor())) {
2045  if (!method->GetNargs()) continue; // ignore default ctor
2046  TList* args = method->GetListOfMethodArgs();
2047  TMethodArg* arg = (TMethodArg*)args->First();
2048  TString typenam = arg->GetFullTypeName();
2049  if (typenam.Contains(fBaseClassName)) continue; // ignore copy ctor
2050  KVClassConstructor* ctor;
2051  if (arg->GetDefault()) ctor = AddConstructor(typenam, arg->GetName(), arg->GetDefault());
2052  else ctor = AddConstructor(typenam, arg->GetName());
2053  ctor->SetBaseClassArgument(1);
2054  for (int i = 1; i < method->GetNargs(); i++) {
2055  arg = (TMethodArg*)args->At(i);
2056  if (arg->GetDefault()) ctor->AddArgument(arg->GetFullTypeName(), arg->GetName(), arg->GetDefault());
2057  else ctor->AddArgument(arg->GetFullTypeName(), arg->GetName());
2058  ctor->SetBaseClassArgument(i + 1);
2059  }
2060  ctor->SetMethodComment(Form("Constructor inherited from %s", GetBaseClass()));
2061  AddMemberInitialiserConstructor(ctor);
2062  }
2063 }
2064 
2065 
2066 
2071 
2073 {
2074  // If this is a base class with virtual methods, it must have a virtual destructor
2075  //
2076  // Otherwise, there is no need to add one
2077 
2078  if(!fHasBaseClass && HasVirtualMethods())
2079  {
2080  if (!GetDestructor()) {
2082  d->SetClassName(fClassName);
2083  d->SetAccess(access);
2084  d->SetVirtual();
2085  fMethods.Add(d);
2086  }
2087  }
2088 }
2089 
2090 
2091 
2094 
2095 KVClassFactory::KVClassMember::KVClassMember(const Char_t* name, const Char_t* type, const Char_t* comment, const Char_t* access)
2096  : KVBase(Form("f%s", name), type), fComment(comment), fRealName(name)
2097 {
2098  // New class member variable
2099  SetAccess(access);
2100  fIsFundamental = (bool)gInterpreter->ProcessLine(Form("std::is_fundamental_v<%s>",type));
2101  fIsPointer = (bool)gInterpreter->ProcessLine(Form("std::is_pointer_v<%s>",type));
2102 }
2103 
2104 
int Int_t
#define d(i)
bool Bool_t
int Ssiz_t
char Char_t
constexpr Bool_t kFALSE
constexpr Bool_t kTRUE
const char Option_t
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t len
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
#define gInterpreter
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
Base class for KaliVeda framework.
Definition: KVBase.h:140
virtual const Char_t * GetType() const
Definition: KVBase.h:177
static const Char_t * GetTEMPLATEDIRFilePath(const Char_t *namefile="")
Definition: KVBase.cpp:76
void Copy(TObject &) const override
Make a copy of this object.
Definition: KVBase.cpp:396
static Bool_t SearchKVFile(const Char_t *name, TString &fullpath, const Char_t *kvsubdir="")
Definition: KVBase.cpp:540
static Bool_t SearchAndOpenKVFile(const Char_t *name, KVSQLite::database &dbfile, const Char_t *kvsubdir="")
Definition: KVBase.cpp:651
Constructor for a class generated with KVClassFactory.
Destructor for a class generated with KVClassFactory.
Member variable in a class generated with KVClassFactory.
virtual void WriteDeclaration(KVString &)
void Print(Option_t *="") const override
print the KVClass member
void SetAccess(const Char_t *acc="public")
set access type : public, protected or private
void Copy(TObject &obj) const override
copy this to obj
const Char_t * GetComment() const
get access type : public, protected or private
Method in a class generated with KVClassFactory.
void SetMethodComment(const KVString &com)
void Copy(TObject &obj) const override
copy this to obj
void WriteDeclaration(KVString &) override
KVClassMethod(Bool_t Virtual=kFALSE, Bool_t Const=kFALSE, Bool_t Inline=kFALSE)
void SetConst(Bool_t c=kTRUE)
void WriteImplementation(KVString &decl)
void SetBaseClass(const Char_t *name)
void Print(Option_t *="") const override
print the KVClass method
void AddArgument(const Char_t *type, const Char_t *argname="", const Char_t *defaultvalue="")
void SetReturnType(const Char_t *type)
void SetClassName(const Char_t *name)
void SetVirtual(Bool_t c=kTRUE)
void SetInline(Bool_t yes=kTRUE)
void SetMethodBody(const KVString &body)
Factory class for generating skeleton files for new classes.
void Print(Option_t *opt="") const override
Print infos on object.
void Copy(TObject &obj) const override
Copy the state of this KVClassFactory to the one referenced by 'obj'.
const Char_t * GetClassDesc() const
Bool_t HasVirtualMethods() const
Bool_t WithMultipleBaseClasses() const
void SetTemplate(Bool_t temp, const Char_t *temp_file)
void AddMethodComment(const Char_t *method_name, const KVString &comment)
Set the comments for method 'method_name' added to the class using AddMethod.
void GenerateCode()
Generate header and implementation file for currently-defined class.
void SetClassName(const Char_t *n)
const Char_t * GetImpFileName() const
const Char_t * GetHeaderFileName() const
KVClassFactory()
Default ctor.
KVClassConstructor * GetDefaultCtor() const
static void MakeClass(const Char_t *classname, const Char_t *classdesc, const Char_t *base_class="", Bool_t withTemplate=kFALSE, const Char_t *templateFile="")
void AddHeaderIncludeFile(const Char_t *filename)
void AddDestructor(const TString &access="public")
void AddImplIncludeFile(const Char_t *filename)
void AddDefaultConstructor()
const Char_t * GetClassName() const
void SetClassDesc(const Char_t *d)
Int_t GetNumberOfMemberVariables() const
void AddMethodBody(const Char_t *method_name, const KVString &body)
const Char_t * GetBaseClass() const
void InlineAllMethods(bool yes=true)
void AddMethodArgument(const Char_t *method_name, const Char_t *argument_type, const Char_t *argument_name="", const Char_t *default_value="")
void InlineAllConstructors(bool yes=true)
KVClassDestructor * GetDestructor() const
void SetBaseClass(const Char_t *b)
void AddGetSetMethods(const KVNameValueList &)
For each named parameter in the list, we add protected member variables with the name and type of the...
KVClassConstructor * AddConstructor(const Char_t *argument_type="", const Char_t *argument_name="", const Char_t *default_value="", const Char_t *access="public")
KVClassMember * AddMember(const Char_t *name, const Char_t *type, const Char_t *comment, const Char_t *access="protected")
void AddAllBaseConstructors()
KVClassMethod * AddMethod(const Char_t *name, const Char_t *return_type, const Char_t *access="public", Bool_t isVirtual=kFALSE, Bool_t isConst=kFALSE)
Extended version of ROOT THashList.
Definition: KVHashList.h:29
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
KVNamedParameter * GetParameter(Int_t idx) const
return the parameter object with index idx
Int_t GetNpar() const
return the number of stored parameters
A generic named parameter storing values of different types.
Bool_t IsDouble() const
Bool_t IsInt() const
Bool_t IsBool() const
Bool_t IsString() const
KVSeqCollection * GetSubListWithName(const Char_t *retvalue) const
KVSeqCollection * GetSubListWithMethod(const Char_t *retvalue, const Char_t *method) const
T * get_object(const TString &name) const
void Add(TObject *obj) override
TObject * FindObject(const char *name) const override
Int_t GetSize() const override
virtual TObject * FindObjectByName(const Char_t *name) const
KVSeqCollection * GetSubListWithLabel(const Char_t *retvalue) const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:73
void Begin(TString delim) const
Definition: KVString.cpp:565
Bool_t End() const
Definition: KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:695
TList * GetListOfMethods(Bool_t load=kTRUE)
virtual void Print(Option_t *option, const char *wildcard, Int_t recurse=1) const
virtual void AddAll(const TCollection *col)
virtual Int_t GetEntries() const
void Set()
const char * AsString() const
Int_t GetNargs() const
TObject * First() const override
TObject * At(Int_t idx) const override
const char * GetFullTypeName() const
const char * GetDefault() const
virtual TList * GetListOfMethodArgs()
const char * GetName() const override
virtual void SetName(const char *name)
TString & String()
virtual const char * GetName() const
void SetBit(UInt_t f)
R__ALWAYS_INLINE Bool_t IsZombie() const
virtual void Copy(TObject &object) const
virtual void Info(const char *method, const char *msgfmt,...) const
Ssiz_t Length() const
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
const char * Data() const
std::istream & ReadFile(std::istream &str)
TString & Remove(EStripType s, char c)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
TString & ReplaceAll(const char *s1, const char *s2)
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
virtual UserGroup_t * GetUserInfo(const char *user=nullptr)
virtual const char * BaseName(const char *pathname)
TLine * line
RPY_EXPORTED bool IsDestructor(TCppMethod_t method)
void Error(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:116
void Warning(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:125
llvm::StringRef GetComment(const clang::Decl &decl, clang::SourceLocation *loc=nullptr)
Type GetType(const std::string &Name)
TString fRealName
TString fUser
TMarker m
ClassImp(TPyArg)