KaliVeda  1.13/01
Heavy-Ion Analysis Toolkit
KVClassFactory.cpp
Go to the documentation of this file.
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  Error("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 
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 
252 
254 {
255  //Write pre-processor directives in file
256  //i.e. '#ifndef __TOTO_H' etc.
257  //If this class has inheritance, we add '#include "base_class.h"' for each of the base classes.
258  //and any other include files added using AddHeaderIncludeFile
259 
260  TString tmp = fClassName;
261  tmp.ToUpper();
262  tmp.Prepend("__");
263  tmp.Append("_H");
264  file << "#ifndef " << tmp.Data() << endl;
265  file << "#define " << tmp.Data() << "\n" << endl;
266  //base class(es) ?
267  if (fHasBaseClass) {
268  if (WithMultipleBaseClasses()) {
269  fBaseClassName.Begin(",");
270  while (!fBaseClassName.End())
271  file << "#include \"" << fBaseClassName.Next(kTRUE) << ".h\"" << endl;
272  file << endl;
273  }
274  else
275  file << "#include \"" << fBaseClassName.Data() << ".h\"\n" << endl;
276  }
277  if (fHeadInc.GetSize()) {
278  TIter next(&fHeadInc);
279  TObjString* str;
280  while ((str = (TObjString*)next())) {
281  file << "#include \"" << str->String().Data() << "\"\n" << endl;
282  }
283  }
284 }
285 
286 
287 
293 
295 {
296  // Write the class declaration in the header file
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()->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()->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()->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\n#endif" << endl; //don't forget to close the preprocessor #if !!!
461 }
462 
463 
464 
468 
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()->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 
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  Warning("GenerateCode", "Object is zombie. No code will be generated.");
738  return;
739  }
740 
742 
743  if (fWithTemplate) {
746  }
747  else {
749  AddDestructor();
754  if (fBaseClassTObject) {
755  // check for base class which inherits from TObject
756  // if so, we add a skeleton Copy(const TObject&) method
757  // and use it in the copy ctor
759  }
760  else if (!fHasBaseClass) {
761  // if a base class is defined, even if it does not inherit TObject,
762  // we assume that it functions correctly with the ROOT CLI.
763  // otherwise, we need to add #include "Rtypes.h" for definition of ClassDef and ClassImp
764  AddHeaderIncludeFile("Rtypes.h");
765  }
769 
771  WriteClassImp();
772  }
773 }
774 
775 
776 
780 
781 KVClassFactory::KVClassMember* KVClassFactory::AddMember(const Char_t* name, const Char_t* type, const Char_t* comment, const Char_t* access)
782 {
783  // Add a member variable to the class, with name 'f[name]' according to ROOT convention.
784  // The access type is by default "protected", in accordance with OO-encapsulation.
785 
786  KVClassMember* m = new KVClassMember(name, type, comment, access);
787  fMembers.Add(m);
788  return m;
789 }
790 
791 
792 
796 
798 {
799  // for each member variable we generate inlined Get/Set methods
800  // for boolean members we generate Is/SetIs methods
801 
803  TIter it(&fMembers);
804  KVClassMember* m;
805  while ((m = (KVClassMember*)it())) {
806  TString mem_name = m->GetRealName();
807  TString mem_type = m->GetType();
808  KVClassMethod* meth;
809  if (mem_type == "Bool_t") meth = AddMethod(Form("SetIs%s", mem_name.Data()), "void");
810  else meth = AddMethod(Form("Set%s", mem_name.Data()), "void");
811  meth->SetInline();
812  meth->AddArgument(mem_type);
813  meth->SetMethodComment(
814  Form("Set value of %s", m->GetName())
815  );
816  meth->SetMethodBody(
817  Form(" %s=arg1;", m->GetName())
818  );
819  if (mem_type == "Bool_t") meth = AddMethod(Form("Is%s", mem_name.Data()), mem_type, "public", kFALSE, kTRUE);
820  else meth = AddMethod(Form("Get%s", mem_name.Data()), mem_type, "public", kFALSE, kTRUE);
821  meth->SetInline();
822  meth->SetMethodComment(
823  Form("Get value of %s", m->GetName())
824  );
825  meth->SetMethodBody(
826  Form(" return %s;", m->GetName())
827  );
828  }
829  }
830 }
831 
832 
833 
837 
839 {
840  //Set date, time and user name based on current environment
841  //If available, we use the full name of the current user, otherwise we use the login name.
842 
843  UserGroup_t* user = gSystem->GetUserInfo();
844  fAuthor = user->fRealName;
845  if (fAuthor == "")
846  fAuthor = user->fUser;
847  // remove trailing commas (???)
848  if (fAuthor.EndsWith(",")) {
849  Ssiz_t len = fAuthor.Length() - 1;
850  do {
851  fAuthor.Remove(len);
852  --len;
853  }
854  while (fAuthor.EndsWith(","));
855  }
856  delete user;
857  fNow.Set();
858 }
859 
860 
861 
862 
869 
871 {
872  // Return position of beginning of next uncommented line in file starting
873  // from position beg (default = 0).
874  // An uncommented line is a line outside of a "/* ... */" block
875  // containing non-whitespace material before any '/*' or '//'.
876  // If no uncommented line is found we return -1.
877 
878  Ssiz_t pos = beg;
879  Ssiz_t beg_cur_line = beg;
880  Bool_t nonWS = kFALSE;
881 
882  while (pos < file.Length()) {
883 
884  if (file(pos) == ' ' || file(pos) == '\t') {
885  // skip whitespace & tab
886  pos++;
887  }
888  else if (file(pos) == '\n') {
889  // reached newline without seeing comment
890  // if there is non-whitespace stuff on line, this is OK
891  if (nonWS) return beg_cur_line;
892  pos++;
893  beg_cur_line = pos;
894  }
895  else if (file(pos) == '/') {
896 
897  if (file(pos + 1) == '*') {
898  // beginning of comment block
899  // was there non-whitespace stuff before this ?
900  if (nonWS) return beg_cur_line;
901  Ssiz_t len = file.Index("*/", pos + 2); // find end of comment
902  if (len > -1) pos = len + 2;
903  else {
904  // end of comment block not found in rest of file
905  // return -1
906  pos = -1;
907  break;
908  }
909  }
910  else if (file(pos + 1) == '/') {
911  // beginning of 1-line comment
912  // was there non-whitespace stuff before this ?
913  if (nonWS) return beg_cur_line;
914  Ssiz_t len = file.Index('\n', pos + 2); // find end of line
915  if (len > 0) {
916  pos = len + 1;
917  beg_cur_line = pos;
918  }
919  else {
920  // end of comment not found in rest of file
921  // return -1
922  pos = -1;
923  break;
924  }
925  }
926  }
927  else {
928  //non-whitespace stuff
929  nonWS = kTRUE;
930  pos++;
931  }
932  }
933  // no new line at end of first uncommented file which is also the last line in the file
934  if (nonWS && pos > -1) return beg_cur_line;
935  return pos;
936 }
937 
938 
939 
943 
945 {
946  //Writes the header file for a class using a template file.
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 = " ClassDef(";
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 << "\n#endif" << endl; //don't forget to close the preprocessor #if !!!
1026  file_h.close();
1027 
1028  cout << "<KVClassFactory::WriteClassWithTemplateHeader> : File " << GetHeaderFileName() << " generated." << endl;
1029 
1030 }
1031 
1032 
1033 
1036 
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 
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 
1145  if (!KVBase::SearchKVFile(filename, fTemplateH)) return kFALSE;
1146  }
1147  filename = fTemplateClassName + ".cpp";
1148  //same treatment for '.cpp' file
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);
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  Error("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  Error("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  Error("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 
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");
1460  body += "You should add here any member variables, for example:\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 
1497 
1499 {
1500  // Adds copy constructor if class has member variables
1501  // If class inherits from TObject, this just calls the Copy method
1502 
1503  if (!GetNumberOfMemberVariables()) return;
1504 
1505  KVClassConstructor* ctor = AddConstructor(Form("const %s&", fClassName.Data()), "obj");
1506  ctor->SetCopyCtor();
1507  ctor->SetMethodComment("Copy constructor");
1508  if (fBaseClassTObject) {
1509  ctor->SetMethodBody(" obj.Copy(*this);");
1510  }
1511 
1512 }
1513 
1514 
1515 
1524 
1526 {
1527  // For classes with member variables, add a constructor which initialises
1528  // the values of all member variables
1529  // If base_ctor is non-null, it is assumed to point to a constructor which has
1530  // been deduced from the base class' list of constructors; in this case we
1531  // add our class' members to the beginning of the list of arguments
1532  // so that if any of the base class ctor arguments have default values, they
1533  // will be at the end of the list
1534 
1535  if (!GetNumberOfMemberVariables()) return;
1536 
1537  TIter next(&fMembers);
1538  KVClassMember* memb = (KVClassMember*)next();
1539  KVClassConstructor* ctor;
1540  Bool_t adding_to_base = kFALSE;
1541  Int_t add_to_base(1);
1542  if (base_ctor) {
1543  ctor = base_ctor;
1544  adding_to_base = kTRUE;
1545  ctor->AddArgument(add_to_base, memb->GetType(), memb->GetRealName());
1546  ctor->SetMemberVariableNameForArgument(add_to_base, memb->GetName());
1547  }
1548  else {
1549  ctor = AddConstructor(memb->GetType(), memb->GetRealName());
1550  ctor->SetMemberVariableNameForArgument(1, memb->GetName());
1551  }
1552  int arg_num = 2;
1553  while ((memb = (KVClassMember*)next())) {
1554  if (adding_to_base) {
1555  ctor->AddArgument(++add_to_base, memb->GetType(), memb->GetRealName());
1556  ctor->SetMemberVariableNameForArgument(add_to_base, memb->GetName());
1557  }
1558  else {
1559  ctor->AddArgument(memb->GetType(), memb->GetRealName());
1560  ctor->SetMemberVariableNameForArgument(arg_num++, memb->GetName());
1561  }
1562  }
1563  ctor->SetMethodComment("Constructor with initial values for all member variables");
1564 }
1565 
1566 
1567 
1571 
1573 {
1574  // Add "ClassName& operator= (const ClassName&)" method if class
1575  // has member variables
1576 
1577  if (!GetNumberOfMemberVariables()) return;
1578 
1579  KVClassMethod* oper = AddMethod("operator=", Form("%s&", fClassName.Data()));
1580  oper->AddArgument(Form("const %s&", fClassName.Data()), "other");
1581  oper->SetMethodComment("Assignment operator");
1582  KVString body = " if(this != &other) { // check for self-assignment\n";
1583  if (fBaseClassTObject) {
1584  body += " other.Copy(*this);\n";
1585  }
1586  else {
1587  if (fMembers.GetEntries()) {
1588  TIter it(&fMembers);
1589  KVClassMember* m;
1590  while ((m = (KVClassMember*)it())) {
1591  body += " Set";
1592  body += m->GetRealName();
1593  body += "( other.Get";
1594  body += m->GetRealName();
1595  body += "() );\n";
1596  }
1597  }
1598  }
1599  body += " }\n";
1600  body += " return (*this);";
1601  oper->SetMethodBody(body);
1602 }
1603 
1604 
1605 
1606 
1610 //Helper classes for KVClassFactory
1611 
1612 
1613 
1617 void KVClassFactory::KVClassMethod::WriteDeclaration(KVString& decl)
1618 {
1619  //Write declaration in the KVString object
1620  //If method is inline write method body directly after declaration
1621 
1622  decl = " ";
1623  if (fVirtual) decl += "virtual ";
1624  if (IsNormalMethod()) {
1625  decl += GetReturnType();
1626  decl += " ";
1627  decl += GetName();
1628  }
1629  else {
1630  if (IsDestructor()) decl += "~";
1631  decl += GetClassName();
1632  }
1633  decl += "(";
1634  for (int i = 1; i <= fNargs; i++) {
1635  decl += fFields.GetStringValue(Form("Arg_%d", i));
1636  if (fFields.HasParameter(Form("Arg_%d_name", i))) {
1637  decl += " ";
1638  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1639  }
1640  else
1641  decl += Form(" arg%d", i);
1642  if (fFields.HasParameter(Form("Arg_%d_default", i))) {
1643  decl += " = ";
1644  decl += fFields.GetStringValue(Form("Arg_%d_default", i));
1645  }
1646  if (i < fNargs) decl += ", ";
1647  }
1648  decl += ")";
1649  if (fConst) decl += " const";
1650  if (!IsInline()) {
1651  decl += ";";
1652  return;
1653  }
1654  // write method body of inline function
1655  write_method_body(decl);
1656 }
1657 
1658 
1659 
1662 
1664 {
1665  //Write declaration in the KVString object
1666 
1667  decl = GetType();
1668  decl += " ";
1669  decl += GetName();
1670 
1671  decl += ";//";
1672  decl += GetComment();
1673 }
1674 
1675 
1676 
1678 
1680 {
1681  KVString indentation = "";
1682  if (IsInline()) indentation = " ";
1683  decl += "\n";
1684  decl += __add_indented_line("{", indentation);
1685  if (!strcmp(GetAccess(), "private")) decl += __add_indented_line(" // PRIVATE method", indentation);
1686  else if (!strcmp(GetAccess(), "protected")) decl += __add_indented_line(" // PROTECTED method", indentation);
1687  if (fFields.HasParameter("Body")) {
1688  //write body of method
1689  decl += __add_indented_line(fFields.GetStringValue("Body"), indentation);
1690  }
1691  else {
1692  if (fFields.HasParameter("ReturnType") && strcmp(fFields.GetStringValue("ReturnType"), "void")) {
1693  KVString return_dir = "return (";
1694  return_dir += GetReturnType();
1695  return_dir += ")0;";
1696  __add_indented_line(return_dir, indentation);
1697  }
1698  }
1699  decl += __add_indented_line("}", indentation, kFALSE);
1700 }
1701 
1702 
1703 
1705 
1707 {
1708  KVString indentation = "";
1709  if (IsInline()) indentation = " ";
1710  if ((fNargs && !IsCopyCtor()) ||
1711  ((IsCopyCtor() || IsDefaultCtor()) && fFields.HasParameter("BaseClass"))
1712  || (IsCopyCtor() && !fParentClass->IsBaseClassTObject())) {
1713  decl += "\n : ";
1714  if (fFields.HasParameter("BaseClass")) {
1715  // initialise base class
1716  decl += fFields.GetStringValue("BaseClass");
1717  decl += "(";
1718  if (!IsCopyCtor() && fNargs) {
1719  Int_t base_args = 0;
1720  for (int i = 1; i <= fNargs; i++) {
1721  if (fFields.HasParameter(Form("Arg_%d_baseclass", i))) {
1722  ++base_args;
1723  if (fFields.HasParameter(Form("Arg_%d_name", i))) {
1724  if (base_args > 1) decl += ", ";
1725  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1726  }
1727  else {
1728  if (base_args > 1) decl += ", ";
1729  decl += Form("arg%d", i);
1730  }
1731  }
1732  }
1733  }
1734  else if (IsCopyCtor() && !fParentClass->IsBaseClassTObject()) {
1735  // for a derived object not inheriting TObject we call the copy ctor of the parent class
1736  decl += fFields.GetStringValue("Arg_1_name");
1737  }
1738  decl += ")";
1739  if ((fNargs && !IsCopyCtor() && fParentClass->GetNumberOfMemberVariables())
1740  || (IsCopyCtor() && !fParentClass->IsBaseClassTObject() && fParentClass->GetNumberOfMemberVariables())) decl += ", ";
1741  }
1742  if (fParentClass->GetNumberOfMemberVariables()) {
1743  // initialise member variables
1744  if (!IsCopyCtor() && fNargs) {
1745  Int_t mem_vars = 0;
1746  for (int i = 1; i <= fNargs; i++) {
1747  if (fFields.HasStringParameter(Form("Arg_%d_memvar", i))) {
1748  if (mem_vars) decl += ", ";
1749  decl += fFields.GetStringValue(Form("Arg_%d_memvar", i));
1750  decl += "(";
1751  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1752  decl += ")";
1753  ++mem_vars;
1754  }
1755  }
1756  }
1757  else if ((IsCopyCtor() && !fParentClass->IsBaseClassTObject())) {
1758  TIter it(fParentClass->GetListOfMembers());
1759  KVClassMember* m;
1760  Int_t imem = 0;
1761  while ((m = (KVClassMember*)it())) {
1762  if (imem) decl += ", ";
1763  decl += m->GetName();
1764  decl += "( ";
1765  decl += fFields.GetStringValue("Arg_1_name");
1766  decl += ".Get";
1767  decl += m->GetRealName();
1768  decl += "() )";
1769  ++imem;
1770  }
1771  }
1772  }
1773  }
1774  decl += "\n";
1775  decl += __add_indented_line("{", indentation);
1776  if (!strcmp(GetAccess(), "private")) decl += __add_indented_line(" // PRIVATE constructor", indentation);
1777  else if (!strcmp(GetAccess(), "protected")) decl += __add_indented_line(" // PROTECTED constructor", indentation);
1778  if (fFields.HasParameter("Body")) {
1779  //write body of method
1780  decl += __add_indented_line(fFields.GetStringValue("Body"), indentation);
1781  }
1782  decl += __add_indented_line("}", indentation, kFALSE);
1783 }
1784 
1785 
1786 
1790 
1792 {
1793  //Write skeleton implementation in the KVString object
1794  //All constructors call the default ctor of the base class (if defined)
1795 
1796  decl = "";
1797  if (fFields.HasParameter("Comment")) {
1798  // Go through comment line by line adding doxygen comment markers
1799  KVString comment(fFields.GetStringValue("Comment"));
1800  comment.Begin("\n");
1801  // find longest line
1802  Ssiz_t longest = 0;
1803  while (!comment.End()) {
1804  KVString line = comment.Next();
1805  if (line.Length() > longest) longest = line.Length();
1806  }
1807  longest += 4; // remember to add "/// " at beginning of each comment line
1808  // write "////...." as long as longest line
1809  while (longest--) decl += "/";
1810  decl += "\n";
1811  comment.Begin("\n");
1812  while (!comment.End()) {
1813  KVString line = comment.Next();
1814  decl += "/// ";
1815  decl += line;
1816  decl += "\n";
1817  }
1818  decl += "\n";
1819  }
1820  decl += GetReturnType();
1821  if (IsNormalMethod()) {
1822  decl += " ";
1823  }
1824  decl += GetClassName();
1825  decl += "::";
1826  if (IsNormalMethod())
1827  decl += GetName();
1828  else {
1829  if (IsDestructor()) decl += "~";
1830  decl += GetClassName();
1831  }
1832  decl += "(";
1833  for (int i = 1; i <= fNargs; i++) {
1834  decl += fFields.GetStringValue(Form("Arg_%d", i));
1835  if (fFields.HasParameter(Form("Arg_%d_name", i))) {
1836  decl += " ";
1837  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1838  }
1839  else
1840  decl += Form(" arg%d", i);
1841  if (i < fNargs) decl += ", ";
1842  }
1843  decl += ")";
1844  if (fConst) decl += " const";
1845  write_method_body(decl);
1846  decl += "\n\n";
1847 
1848 }
1849 
1850 
1851 
1852 
1855 
1857 {
1858  //ctor par copie
1859  obj.Copy(*this);
1860 }
1861 
1862 
1863 
1864 
1867 
1869 {
1870  //ctor par copie
1871  obj.Copy(*this);
1872 }
1873 
1874 
1875 
1876 
1879 
1881 {
1882  //copy this to obj
1883  KVBase::Copy(obj);
1884  ((KVClassMember&)obj).SetComment(GetComment());
1885  ((KVClassMember&)obj).fRealName = GetRealName();
1886 }
1887 
1888 
1889 
1890 
1893 
1895 {
1896  //copy this to obj
1897  KVClassMember::Copy(obj);
1898  ((KVClassMethod&)obj).SetVirtual(IsVirtual());
1899  ((KVClassMethod&)obj).SetConst(IsConst());
1900  fFields.Copy(((KVClassMethod&)obj).fFields);
1901  ((KVClassMethod&)obj).SetNargs(GetNargs());
1902  ((KVClassMethod&)obj).SetInline(IsInline());
1903 }
1904 
1905 
1906 
1910 
1911 void KVClassFactory::KVClassMethod::AddArgument(Int_t i, const Char_t* type, const Char_t* argname, const Char_t* defaultvalue)
1912 {
1913  // Add an argument to the method, which will be in i-th position in the argument list
1914  // Any existing arguments with indices [i,fNargs] will first be moved to [i+1,fNargs+1]
1915 
1916  if (!(i > 0 && i <= fNargs + 1)) {
1917  Error("AddArgument(Int_t i, ...)", "Must be called with i>0 & i<=%d", fNargs + 1);
1918  return;
1919  }
1920 
1921  if (i == fNargs + 1) { // this is just same as call to AddArgument(type,argname,...)
1922  AddArgument(type, argname, defaultvalue);
1923  return;
1924  }
1925 
1926  for (int j = fNargs; j >= i; --j) {
1927  if (fFields.HasStringParameter(Form("Arg_%d", j))) {
1928  fFields.SetValue(Form("Arg_%d", j + 1), fFields.GetStringValue(Form("Arg_%d", j)));
1929  fFields.RemoveParameter(Form("Arg_%d", j));
1930  }
1931  if (fFields.HasStringParameter(Form("Arg_%d_name", j))) {
1932  fFields.SetValue(Form("Arg_%d_name", j + 1), fFields.GetStringValue(Form("Arg_%d_name", j)));
1933  fFields.RemoveParameter(Form("Arg_%d_name", j));
1934  }
1935  if (fFields.HasIntParameter(Form("Arg_%d_baseclass", j))) {
1936  fFields.SetValue(Form("Arg_%d_baseclass", j + 1), fFields.GetIntValue(Form("Arg_%d_baseclass", j)));
1937  fFields.RemoveParameter(Form("Arg_%d_baseclass", j));
1938  }
1939  if (fFields.HasStringParameter(Form("Arg_%d_default", j))) {
1940  fFields.SetValue(Form("Arg_%d_default", j + 1), fFields.GetStringValue(Form("Arg_%d_default", j)));
1941  fFields.RemoveParameter(Form("Arg_%d_default", j));
1942  }
1943  }
1944 
1945  KVString _type(type);
1946  fFields.SetValue(Form("Arg_%d", i), _type);
1947  if (strcmp(defaultvalue, "")) {
1948  KVString _s(defaultvalue);
1949  fFields.SetValue(Form("Arg_%d_default", i), _s);
1950  }
1951  if (strcmp(argname, "")) {
1952  KVString _s(argname);
1953  fFields.SetValue(Form("Arg_%d_name", i), _s);
1954  }
1955 
1956  ++fNargs;
1957 }
1958 
1959 
1960 
1963 
1965 {
1966  // print the KVClass method
1967  cout << "KVClassMethod object -----> " << GetName() << endl;
1968  fFields.Print();
1969  cout << "This method is " << GetAccess() << endl;
1970  if (fConst) cout << "This method is CONST" << endl;
1971  if (fVirtual) cout << "This method is VIRTUAL" << endl;
1972 }
1973 
1974 
1975 
1978 
1980 {
1981  // print the KVClass member
1982  cout << "KVClassMember object -----> " << GetType() << " " << GetName() << endl;
1983  cout << "This member is " << GetAccess() << endl;
1984 }
1985 
1986 
1987 
1988 
1994 
1996 {
1997  // Add constructors with the same signature as all base class constructors
1998  // (apart from the default ctor or any copy constructors, which are a special case)
1999  // If this class has its own member variables, we add them to the argument list
2000  // of each base class constructor.
2001 
2002  if (!fBaseClass) return;
2003 
2004  KVHashList clist;
2006  unique_ptr<KVSeqCollection> constructors(clist.GetSubListWithName(fBaseClassName));
2007  TIter next_ctor(constructors.get());
2008  TMethod* method;
2009  while ((method = (TMethod*)next_ctor())) {
2010  if (!method->GetNargs()) continue; // ignore default ctor
2011  TList* args = method->GetListOfMethodArgs();
2012  TMethodArg* arg = (TMethodArg*)args->First();
2013  TString typenam = arg->GetFullTypeName();
2014  if (typenam.Contains(fBaseClassName)) continue; // ignore copy ctor
2015  KVClassConstructor* ctor;
2016  if (arg->GetDefault()) ctor = AddConstructor(typenam, arg->GetName(), arg->GetDefault());
2017  else ctor = AddConstructor(typenam, arg->GetName());
2018  ctor->SetBaseClassArgument(1);
2019  for (int i = 1; i < method->GetNargs(); i++) {
2020  arg = (TMethodArg*)args->At(i);
2021  if (arg->GetDefault()) ctor->AddArgument(arg->GetFullTypeName(), arg->GetName(), arg->GetDefault());
2022  else ctor->AddArgument(arg->GetFullTypeName(), arg->GetName());
2023  ctor->SetBaseClassArgument(i + 1);
2024  }
2025  ctor->SetMethodComment(Form("Constructor inherited from %s", GetBaseClass()));
2027  }
2028 }
2029 
2030 
2031 
2034 
2036 {
2037  // Add default destructor to class
2038 
2039  if (!GetDestructor()) {
2041  d->SetClassName(fClassName);
2042  d->SetAccess(access);
2043  fMethods.Add(d);
2044  }
2045 }
2046 
2047 
2048 
2051 
2052 KVClassFactory::KVClassMember::KVClassMember(const Char_t* name, const Char_t* type, const Char_t* comment, const Char_t* access)
2053  : KVBase(Form("f%s", name), type), fComment(comment), fRealName(name)
2054 {
2055  // New class member variable
2056  SetAccess(access);
2057 }
2058 
2059 
int Int_t
#define str(s)
Definition: KVBase.cpp:57
KVString __add_indented_line(const KVString &line, const KVString &indent, Bool_t newline=kTRUE)
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define d(i)
int Ssiz_t
char Char_t
const Bool_t kFALSE
bool Bool_t
const Bool_t kTRUE
const char Option_t
int type
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
Base class for KaliVeda framework.
Definition: KVBase.h:141
virtual const Char_t * GetType() const
Definition: KVBase.h:176
static const Char_t * GetTEMPLATEDIRFilePath(const Char_t *namefile="")
Definition: KVBase.cpp:83
static Bool_t SearchKVFile(const Char_t *name, TString &fullpath, const Char_t *kvsubdir="")
Definition: KVBase.cpp:538
static Bool_t SearchAndOpenKVFile(const Char_t *name, KVSQLite::database &dbfile, const Char_t *kvsubdir="")
Definition: KVBase.cpp:649
virtual void Copy(TObject &) const
Make a copy of this object.
Definition: KVBase.cpp:394
Constructor for a class generated with KVClassFactory.
virtual void write_method_body(KVString &decl)
void SetMemberVariableNameForArgument(Int_t i, const Char_t *memvar)
Destructor for a class generated with KVClassFactory.
Member variable in a class generated with KVClassFactory.
virtual void WriteDeclaration(KVString &)
Write declaration in the KVString object.
void Print(Option_t *="") const
print the KVClass member
void SetAccess(const Char_t *acc="public")
set access type : public, protected or private
const Char_t * GetRealName() const
get short name without leading 'f'
const Char_t * GetComment() const
get access type : public, protected or private
void Copy(TObject &obj) const
copy this to obj
Method in a class generated with KVClassFactory.
virtual void write_method_body(KVString &decl)
void SetMethodComment(const KVString &com)
void Print(Option_t *="") const
print the KVClass method
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 Copy(TObject &obj) const
copy this to obj
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
Print infos on object.
Bool_t fInlineAllCtors
kTRUE if all ctor implementations written in header
void WriteWhoWhen(std::ofstream &)
const Char_t * GetClassDesc() const
Bool_t WithMultipleBaseClasses() const
void SetTemplate(Bool_t temp, const Char_t *temp_file)
KVList fMembers
list of member variables for class
Bool_t fInlineAllMethods
kTRUE if all (non-ctor) method implementations written in header
void AddMethodComment(const Char_t *method_name, const KVString &comment)
Set the comments for method 'method_name' added to the class using AddMethod.
void WriteClassWithTemplateImp()
Writes the implementation file for the class.
KVString fTemplateClassName
name of template dummy class
void GenerateGettersAndSetters()
KVList fMethods
list of methods added to class
void GenerateCode()
Generate header and implementation file for currently-defined class.
TDatime fNow
for dating files
Bool_t fHasBaseClass
kTRUE if class derived from another
void SetClassName(const Char_t *n)
const Char_t * GetImpFileName() const
KVString fTemplateCPP
full path to template .cpp
void AddMemberInitialiserConstructor(KVClassConstructor *=nullptr)
TClass * fBaseClass
description of base class
void WriteClassHeader()
Write the class header file.
KVString fClassDesc
class description
Bool_t fInheritAllCtors
kTRUE if all ctor from base class should be inherited
const Char_t * GetHeaderFileName() const
KVClassFactory()
Default ctor.
KVString fClassPath
directory in which to write source files, if not working directory
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 Copy(TObject &obj) const
Copy the state of this KVClassFactory to the one referenced by 'obj'.
void AddDestructor(const TString &access="public")
Add default destructor to class.
void WriteClassDec(std::ofstream &)
void AddImplIncludeFile(const Char_t *filename)
KVString fTemplateH
full path to template .h
KVString fBaseClassName
name of base class
Bool_t CheckTemplateFiles(const Char_t *base_class, const Char_t *templateFile)
void AddDefaultConstructor()
const Char_t * GetClassName() const
void SetClassDesc(const Char_t *d)
void WritePreProc(std::ofstream &)
Int_t GetNumberOfMemberVariables() const
void AddMethodBody(const Char_t *method_name, const KVString &body)
Ssiz_t FindNextUncommentedLine(TString &, Ssiz_t beg=0)
const Char_t * GetBaseClass() const
void WriteClassWithTemplateHeader()
void AddAssignmentOperator()
void InlineAllMethods(bool yes=true)
Bool_t fBaseClassTObject
kTRUE if class derived from TObject
KVList fHeadInc
list of 'includes' to be added to header file
KVString fTemplateBase
template base name passed to SetTemplate method
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)
KVString fClassName
name of class to generate
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...
Bool_t fWithTemplate
true if class has a template
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")
KVString fAuthor
user who called ClassFactory to generate class
KVList fImpInc
list of 'includes' to be added to implementation file
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:28
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
virtual Int_t GetSize() const
virtual void Add(TObject *obj)
virtual TObject * FindObjectByName(const Char_t *name) const
KVSeqCollection * GetSubListWithLabel(const Char_t *retvalue) const
virtual TObject * FindObject(const char *name) const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:72
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
virtual TObject * At(Int_t idx) const
virtual TObject * First() const
const char * GetFullTypeName() const
const char * GetDefault() const
virtual TList * GetListOfMethodArgs()
virtual const char * GetName() const
virtual void SetName(const char *name)
virtual const char * GetName() const
void SetBit(UInt_t f)
virtual void Warning(const char *method, const char *msgfmt,...) const
R__ALWAYS_INLINE Bool_t IsZombie() const
virtual void Copy(TObject &object) const
virtual void Error(const char *method, const char *msgfmt,...) 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
void ToUpper()
TString & Append(char c, Ssiz_t rep=1)
const char * Data() const
TString & Prepend(char c, Ssiz_t rep=1)
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)
const long double m
Definition: KVUnits.h:70
llvm::StringRef GetComment(const clang::Decl &decl, clang::SourceLocation *loc=0)
Type GetType(const std::string &Name)
TString fRealName
TString fUser