KaliVeda  1.12/06
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.
1144  if (!KVBase::SearchKVFile(filename, fTemplateH)) return kFALSE;
1145  }
1146  filename = fTemplateClassName + ".cpp";
1147  //same treatment for '.cpp' file
1149  if (!KVBase::SearchKVFile(filename.Data(), fTemplateCPP)) return kFALSE;
1150  }
1151  return kTRUE;
1152 }
1153 
1154 
1155 
1156 
1160 
1162 {
1163  //A new KVClassMethod object will be created and added to the class,
1164  //copying the informations held in kvcm
1165 
1166  KVClassMethod* meth = new KVClassMethod(kvcm);
1167  fMethods.Add(meth);
1168 }
1169 
1170 
1171 
1172 
1183 
1184 KVClassFactory::KVClassMethod* KVClassFactory::AddMethod(const Char_t* name, const Char_t* return_type, const Char_t* access,
1185  Bool_t isVirtual, Bool_t isConst)
1186 {
1187  // Add a method to the class.
1188  // User must give return type and name of method.
1189  // Optional arguments determine access type (public, protected or private)
1190  // and if the method is 'virtual' and/or 'const'
1191  //
1192  // If another method with the same name already exists, user should keep the returned
1193  // pointer to the new KVClassMethod object and use KVClassMethod::AddArgument(),
1194  // KVClassMethod::SetMethodBody() in order to define arguments, method body, etc.
1195  // instead of using the AddMethodArgument, AddMethodBody methods
1196 
1197  KVClassMethod* meth = new KVClassMethod;
1198  fMethods.Add(meth);
1199  meth->SetName(name);
1200  meth->SetClassName(fClassName);
1201  meth->SetReturnType(return_type);
1202  meth->SetAccess(access);
1203  meth->SetVirtual(isVirtual);
1204  meth->SetConst(isConst);
1205  return meth;
1206 }
1207 
1208 
1209 
1210 
1222 
1224  const Char_t* argument_name, const Char_t* default_value, const Char_t* access)
1225 {
1226  // Add a constructor with or without arguments to the class.
1227  // If no arguments are given, adds a default constructor (no arguments).
1228  //
1229  // Optional argument 'access' determines access type (public, protected or private) [default: "public"]
1230  //
1231  // If more than one argument is needed, user should keep the returned pointer
1232  // to the new object and use KVClassMethod::AddArgument() in order to add further arguments.
1233  //
1234  // In order to define the implementation of the ctor method, user should keep the returned pointer
1235  // to the new object and use KVClassMethod::SetMethodBody(KVString&).
1236 
1237  KVClassConstructor* meth = new KVClassConstructor(this);
1238  fMethods.Add(meth);
1239  if (strcmp(argument_type, "")) {
1240  // use type of first argument as name of ctor method
1241  meth->SetName(argument_type);
1242  meth->AddArgument(argument_type, argument_name, default_value);
1243  }
1244  else {
1245  // default constructor
1246  meth->SetName("default_ctor");
1247  }
1248  meth->SetClassName(fClassName);
1250  meth->SetAccess(access);
1251  return meth;
1252 }
1253 
1254 
1255 
1256 
1262 
1263 void KVClassFactory::AddMethodArgument(const Char_t* method_name, const Char_t* argument_type,
1264  const Char_t* argument_name, const Char_t* default_value)
1265 {
1266  //Add an argument to the method 'method_name' added to the class using AddMethod.
1267  //User must give type of argument.
1268  //Optional argument argument_name gives name of argument (will be used in implementation declaration).
1269  //Optional argument default_value gives default value.
1270 
1271  KVClassMethod* meth = (KVClassMethod*)fMethods.FindObjectByName(method_name);
1272  if (!meth) {
1273  Error("AddMethodArgument",
1274  "Method %s not found.", method_name);
1275  return;
1276  }
1277  meth->AddArgument(argument_type, argument_name, default_value);
1278 }
1279 
1280 
1281 
1282 
1286 
1287 void KVClassFactory::AddMethodBody(const Char_t* method_name, const KVString& body)
1288 {
1289  //Set the body of the code for method 'method_name' added to the class using AddMethod.
1290  //N.B. does not work for implementing constructors, see AddConstructor
1291 
1292  KVClassMethod* meth = (KVClassMethod*)fMethods.FindObjectByName(method_name);
1293  if (!meth) {
1294  Error("AddMethodBody",
1295  "Method %s not found.", method_name);
1296  return;
1297  }
1298  meth->SetMethodBody(body);
1299 }
1300 
1301 
1302 
1305 
1306 void KVClassFactory::AddMethodComment(const Char_t* method_name, const KVString& comment)
1307 {
1308  //Set the comments for method 'method_name' added to the class using AddMethod.
1309 
1310  KVClassMethod* meth = (KVClassMethod*)fMethods.FindObjectByName(method_name);
1311  if (!meth) {
1312  Error("AddMethodComment",
1313  "Method %s not found.", method_name);
1314  return;
1315  }
1316  meth->SetMethodComment(comment);
1317 }
1318 
1319 
1320 
1321 
1327 
1329 {
1330  //Add a file which will appear in the 'includes' list of the '.h' file
1331  //i.e. we will add a line
1332  // #include "filename"
1333  //to the .h file
1334  fHeadInc.Add(new TObjString(filename));
1335 }
1336 
1337 
1338 
1339 
1345 
1347 {
1348  //Add a file which will appear in the 'includes' list of the '.cpp' file
1349  //i.e. we will add a line
1350  // #include "filename"
1351  //to the .cpp file
1352  fImpInc.Add(new TObjString(filename));
1353 // Info("AddImplIncludeFile", "Called for %s %#x. List now contains %d filenames.",
1354 // ClassName(), (long)this, fImpInc.GetEntries());
1355 }
1356 
1357 
1358 
1359 
1362 
1364 {
1365  //Print infos on object
1366  Info("Print", "object name = %s, address = %p", GetName(), this);
1367  cout << " * fClassName = " << fClassName.Data() << endl;
1368  cout << " * fClassDesc = " << fClassDesc.Data() << endl;
1369  cout << " * fBaseClass = " << fBaseClassName.Data() << endl;
1370  cout << " * fTemplateBase = " << fTemplateBase.Data() << endl;
1371  cout << "---------> Methods" << endl;
1372  fMethods.Print();
1373  cout << "---------> Header Includes" << endl;
1374  fHeadInc.Print();
1375  cout << "---------> Implementation Includes" << endl;
1376  fImpInc.Print();
1377 }
1378 
1379 
1380 
1383 
1385 {
1386  // For each named parameter in the list, we add protected member variables with the name and type of the parameter.
1387 
1388  int npars = nvl.GetNpar();
1389  for (int i = 0; i < npars; i++) {
1390  KVNamedParameter* par = nvl.GetParameter(i);
1391  if (par->IsString()) {
1392  AddMember(par->GetName(), "TString", "member automatically generated by KVClassFactory::AddGetSetMethods");
1393  // make sure #include "TString.h" appears in header file
1394  if (! fHeadInc.FindObject("TString.h")) AddHeaderIncludeFile("TString.h");
1395  }
1396  else if (par->IsInt()) {
1397  AddMember(par->GetName(), "Int_t", "member automatically generated by KVClassFactory::AddGetSetMethods");
1398  }
1399  else if (par->IsDouble()) {
1400  AddMember(par->GetName(), "Double_t", "member automatically generated by KVClassFactory::AddGetSetMethods");
1401  }
1402  else if (par->IsBool()) {
1403  AddMember(par->GetName(), "Bool_t", "member automatically generated by KVClassFactory::AddGetSetMethods");
1404  }
1405  }
1406 }
1407 
1408 
1409 
1412 
1414 {
1415  // \param yes =true: Write implementation of all non-ctor/non-dtor methods in the header file of the class
1416 
1417  TIter it(&fMethods);
1418  KVClassMethod* m;
1419  while ((m = (KVClassMethod*)it())) {
1420  if (!m->IsConstructor() && !m->IsDestructor()) m->SetInline(yes);
1421  }
1422  fInlineAllMethods = yes;
1423 }
1424 
1425 
1426 
1429 
1431 {
1432  // \param yes =true: Write implementation of all constructors & the destructor in the header file of the class.
1433 
1434  unique_ptr<KVSeqCollection> ctors(fMethods.GetSubListWithMethod("1", "IsConstructor"));
1435  ctors->R__FOR_EACH(KVClassConstructor, SetInline)(yes);
1436  fInlineAllCtors = yes;
1437  KVClassDestructor* dtor = fMethods.get_object<KVClassDestructor>("destructor");
1438  if (dtor) dtor->SetInline(yes);
1439 }
1440 
1441 
1442 
1443 
1447 
1449 {
1450  // Adds skeleton standard ROOT Copy method if class has
1451  // member variables
1452 
1453  if (!GetNumberOfMemberVariables()) return;
1454 
1455  AddMethod("Copy", "void", "public", kFALSE, kTRUE);
1456  AddMethodArgument("Copy", "TObject&", "obj");
1457  KVString body("This method copies the current state of 'this' object into 'obj'\n");
1458  body += "You should add here any member variables, for example:\n";
1459  body += "(supposing a member variable ";
1460  body += fClassName;
1461  body += "::fToto)\n";
1462  body += " CastedObj.fToto = fToto;\n";
1463  body += "or\n";
1464  body += " CastedObj.SetToto( GetToto() );";
1465  AddMethodComment("Copy", body);
1466  // call Copy method for base class
1467  body = "\n\n ";
1468  body += fBaseClassName;
1469  body += "::Copy(obj);\n";
1470  if (!fMembers.GetEntries()) body += " //";
1471  else body += " ";
1472  body += fClassName;
1473  body += "& CastedObj = (";
1474  body += fClassName;
1475  body += "&)obj;\n";
1476  if (fMembers.GetEntries()) {
1477  TIter it(&fMembers);
1478  KVClassMember* m;
1479  while ((m = (KVClassMember*)it())) {
1480  body += " CastedObj.Set";
1481  body += m->GetRealName();
1482  body += "( Get";
1483  body += m->GetRealName();
1484  body += "() );\n";
1485  }
1486  }
1487  AddMethodBody("Copy", body);
1488 }
1489 
1490 
1491 
1495 
1497 {
1498  // Adds copy constructor if class has member variables
1499  // If class inherits from TObject, this just calls the Copy method
1500 
1501  if (!GetNumberOfMemberVariables()) return;
1502 
1503  KVClassConstructor* ctor = AddConstructor(Form("const %s&", fClassName.Data()), "obj");
1504  ctor->SetCopyCtor();
1505  ctor->SetMethodComment("Copy constructor");
1506  if (fBaseClassTObject) {
1507  ctor->SetMethodBody(" obj.Copy(*this);");
1508  }
1509 
1510 }
1511 
1512 
1513 
1522 
1524 {
1525  // For classes with member variables, add a constructor which initialises
1526  // the values of all member variables
1527  // If base_ctor is non-null, it is assumed to point to a constructor which has
1528  // been deduced from the base class' list of constructors; in this case we
1529  // add our class' members to the beginning of the list of arguments
1530  // so that if any of the base class ctor arguments have default values, they
1531  // will be at the end of the list
1532 
1533  if (!GetNumberOfMemberVariables()) return;
1534 
1535  TIter next(&fMembers);
1536  KVClassMember* memb = (KVClassMember*)next();
1537  KVClassConstructor* ctor;
1538  Bool_t adding_to_base = kFALSE;
1539  Int_t add_to_base(1);
1540  if (base_ctor) {
1541  ctor = base_ctor;
1542  adding_to_base = kTRUE;
1543  ctor->AddArgument(add_to_base, memb->GetType(), memb->GetRealName());
1544  ctor->SetMemberVariableNameForArgument(add_to_base, memb->GetName());
1545  }
1546  else {
1547  ctor = AddConstructor(memb->GetType(), memb->GetRealName());
1548  ctor->SetMemberVariableNameForArgument(1, memb->GetName());
1549  }
1550  int arg_num = 2;
1551  while ((memb = (KVClassMember*)next())) {
1552  if (adding_to_base) {
1553  ctor->AddArgument(++add_to_base, memb->GetType(), memb->GetRealName());
1554  ctor->SetMemberVariableNameForArgument(add_to_base, memb->GetName());
1555  }
1556  else {
1557  ctor->AddArgument(memb->GetType(), memb->GetRealName());
1558  ctor->SetMemberVariableNameForArgument(arg_num++, memb->GetName());
1559  }
1560  }
1561  ctor->SetMethodComment("Constructor with initial values for all member variables");
1562 }
1563 
1564 
1565 
1569 
1571 {
1572  // Add "ClassName& operator= (const ClassName&)" method if class
1573  // has member variables
1574 
1575  if (!GetNumberOfMemberVariables()) return;
1576 
1577  KVClassMethod* oper = AddMethod("operator=", Form("%s&", fClassName.Data()));
1578  oper->AddArgument(Form("const %s&", fClassName.Data()), "other");
1579  oper->SetMethodComment("Assignment operator");
1580  KVString body = " if(this != &other) { // check for self-assignment\n";
1581  if (fBaseClassTObject) {
1582  body += " other.Copy(*this);\n";
1583  }
1584  else {
1585  if (fMembers.GetEntries()) {
1586  TIter it(&fMembers);
1587  KVClassMember* m;
1588  while ((m = (KVClassMember*)it())) {
1589  body += " Set";
1590  body += m->GetRealName();
1591  body += "( other.Get";
1592  body += m->GetRealName();
1593  body += "() );\n";
1594  }
1595  }
1596  }
1597  body += " }\n";
1598  body += " return (*this);";
1599  oper->SetMethodBody(body);
1600 }
1601 
1602 
1603 
1604 
1608 //Helper classes for KVClassFactory
1609 
1610 
1611 
1615 void KVClassFactory::KVClassMethod::WriteDeclaration(KVString& decl)
1616 {
1617  //Write declaration in the KVString object
1618  //If method is inline write method body directly after declaration
1619 
1620  decl = " ";
1621  if (fVirtual) decl += "virtual ";
1622  if (IsNormalMethod()) {
1623  decl += GetReturnType();
1624  decl += " ";
1625  decl += GetName();
1626  }
1627  else {
1628  if (IsDestructor()) decl += "~";
1629  decl += GetClassName();
1630  }
1631  decl += "(";
1632  for (int i = 1; i <= fNargs; i++) {
1633  decl += fFields.GetStringValue(Form("Arg_%d", i));
1634  if (fFields.HasParameter(Form("Arg_%d_name", i))) {
1635  decl += " ";
1636  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1637  }
1638  else
1639  decl += Form(" arg%d", i);
1640  if (fFields.HasParameter(Form("Arg_%d_default", i))) {
1641  decl += " = ";
1642  decl += fFields.GetStringValue(Form("Arg_%d_default", i));
1643  }
1644  if (i < fNargs) decl += ", ";
1645  }
1646  decl += ")";
1647  if (fConst) decl += " const";
1648  if (!IsInline()) {
1649  decl += ";";
1650  return;
1651  }
1652  // write method body of inline function
1653  write_method_body(decl);
1654 }
1655 
1656 
1657 
1660 
1662 {
1663  //Write declaration in the KVString object
1664 
1665  decl = GetType();
1666  decl += " ";
1667  decl += GetName();
1668 
1669  decl += ";//";
1670  decl += GetComment();
1671 }
1672 
1673 
1674 
1676 
1678 {
1679  KVString indentation = "";
1680  if (IsInline()) indentation = " ";
1681  decl += "\n";
1682  decl += __add_indented_line("{", indentation);
1683  if (!strcmp(GetAccess(), "private")) decl += __add_indented_line(" // PRIVATE method", indentation);
1684  else if (!strcmp(GetAccess(), "protected")) decl += __add_indented_line(" // PROTECTED method", indentation);
1685  if (fFields.HasParameter("Body")) {
1686  //write body of method
1687  decl += __add_indented_line(fFields.GetStringValue("Body"), indentation);
1688  }
1689  else {
1690  if (fFields.HasParameter("ReturnType") && strcmp(fFields.GetStringValue("ReturnType"), "void")) {
1691  KVString return_dir = "return (";
1692  return_dir += GetReturnType();
1693  return_dir += ")0;";
1694  __add_indented_line(return_dir, indentation);
1695  }
1696  }
1697  decl += __add_indented_line("}", indentation, kFALSE);
1698 }
1699 
1700 
1701 
1703 
1705 {
1706  KVString indentation = "";
1707  if (IsInline()) indentation = " ";
1708  if ((fNargs && !IsCopyCtor()) ||
1709  ((IsCopyCtor() || IsDefaultCtor()) && fFields.HasParameter("BaseClass"))
1710  || (IsCopyCtor() && !fParentClass->IsBaseClassTObject())) {
1711  decl += "\n : ";
1712  if (fFields.HasParameter("BaseClass")) {
1713  // initialise base class
1714  decl += fFields.GetStringValue("BaseClass");
1715  decl += "(";
1716  if (!IsCopyCtor() && fNargs) {
1717  Int_t base_args = 0;
1718  for (int i = 1; i <= fNargs; i++) {
1719  if (fFields.HasParameter(Form("Arg_%d_baseclass", i))) {
1720  ++base_args;
1721  if (fFields.HasParameter(Form("Arg_%d_name", i))) {
1722  if (base_args > 1) decl += ", ";
1723  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1724  }
1725  else {
1726  if (base_args > 1) decl += ", ";
1727  decl += Form("arg%d", i);
1728  }
1729  }
1730  }
1731  }
1732  else if (IsCopyCtor() && !fParentClass->IsBaseClassTObject()) {
1733  // for a derived object not inheriting TObject we call the copy ctor of the parent class
1734  decl += fFields.GetStringValue("Arg_1_name");
1735  }
1736  decl += ")";
1737  if ((fNargs && !IsCopyCtor() && fParentClass->GetNumberOfMemberVariables())
1738  || (IsCopyCtor() && !fParentClass->IsBaseClassTObject() && fParentClass->GetNumberOfMemberVariables())) decl += ", ";
1739  }
1740  if (fParentClass->GetNumberOfMemberVariables()) {
1741  // initialise member variables
1742  if (!IsCopyCtor() && fNargs) {
1743  Int_t mem_vars = 0;
1744  for (int i = 1; i <= fNargs; i++) {
1745  if (fFields.HasStringParameter(Form("Arg_%d_memvar", i))) {
1746  if (mem_vars) decl += ", ";
1747  decl += fFields.GetStringValue(Form("Arg_%d_memvar", i));
1748  decl += "(";
1749  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1750  decl += ")";
1751  ++mem_vars;
1752  }
1753  }
1754  }
1755  else if ((IsCopyCtor() && !fParentClass->IsBaseClassTObject())) {
1756  TIter it(fParentClass->GetListOfMembers());
1757  KVClassMember* m;
1758  Int_t imem = 0;
1759  while ((m = (KVClassMember*)it())) {
1760  if (imem) decl += ", ";
1761  decl += m->GetName();
1762  decl += "( ";
1763  decl += fFields.GetStringValue("Arg_1_name");
1764  decl += ".Get";
1765  decl += m->GetRealName();
1766  decl += "() )";
1767  ++imem;
1768  }
1769  }
1770  }
1771  }
1772  decl += "\n";
1773  decl += __add_indented_line("{", indentation);
1774  if (!strcmp(GetAccess(), "private")) decl += __add_indented_line(" // PRIVATE constructor", indentation);
1775  else if (!strcmp(GetAccess(), "protected")) decl += __add_indented_line(" // PROTECTED constructor", indentation);
1776  if (fFields.HasParameter("Body")) {
1777  //write body of method
1778  decl += __add_indented_line(fFields.GetStringValue("Body"), indentation);
1779  }
1780  decl += __add_indented_line("}", indentation, kFALSE);
1781 }
1782 
1783 
1784 
1788 
1790 {
1791  //Write skeleton implementation in the KVString object
1792  //All constructors call the default ctor of the base class (if defined)
1793 
1794  decl = "";
1795  if (fFields.HasParameter("Comment")) {
1796  // Go through comment line by line adding doxygen comment markers
1797  KVString comment(fFields.GetStringValue("Comment"));
1798  comment.Begin("\n");
1799  // find longest line
1800  Ssiz_t longest = 0;
1801  while (!comment.End()) {
1802  KVString line = comment.Next();
1803  if (line.Length() > longest) longest = line.Length();
1804  }
1805  longest += 4; // remember to add "/// " at beginning of each comment line
1806  // write "////...." as long as longest line
1807  while (longest--) decl += "/";
1808  decl += "\n";
1809  comment.Begin("\n");
1810  while (!comment.End()) {
1811  KVString line = comment.Next();
1812  decl += "/// ";
1813  decl += line;
1814  decl += "\n";
1815  }
1816  decl += "\n";
1817  }
1818  decl += GetReturnType();
1819  if (IsNormalMethod()) {
1820  decl += " ";
1821  }
1822  decl += GetClassName();
1823  decl += "::";
1824  if (IsNormalMethod())
1825  decl += GetName();
1826  else {
1827  if (IsDestructor()) decl += "~";
1828  decl += GetClassName();
1829  }
1830  decl += "(";
1831  for (int i = 1; i <= fNargs; i++) {
1832  decl += fFields.GetStringValue(Form("Arg_%d", i));
1833  if (fFields.HasParameter(Form("Arg_%d_name", i))) {
1834  decl += " ";
1835  decl += fFields.GetStringValue(Form("Arg_%d_name", i));
1836  }
1837  else
1838  decl += Form(" arg%d", i);
1839  if (i < fNargs) decl += ", ";
1840  }
1841  decl += ")";
1842  if (fConst) decl += " const";
1843  write_method_body(decl);
1844  decl += "\n\n";
1845 
1846 }
1847 
1848 
1849 
1850 
1853 
1855 {
1856  //ctor par copie
1857  obj.Copy(*this);
1858 }
1859 
1860 
1861 
1862 
1865 
1867 {
1868  //ctor par copie
1869  obj.Copy(*this);
1870 }
1871 
1872 
1873 
1874 
1877 
1879 {
1880  //copy this to obj
1881  KVBase::Copy(obj);
1882  ((KVClassMember&)obj).SetComment(GetComment());
1883  ((KVClassMember&)obj).fRealName = GetRealName();
1884 }
1885 
1886 
1887 
1888 
1891 
1893 {
1894  //copy this to obj
1895  KVClassMember::Copy(obj);
1896  ((KVClassMethod&)obj).SetVirtual(IsVirtual());
1897  ((KVClassMethod&)obj).SetConst(IsConst());
1898  fFields.Copy(((KVClassMethod&)obj).fFields);
1899  ((KVClassMethod&)obj).SetNargs(GetNargs());
1900  ((KVClassMethod&)obj).SetInline(IsInline());
1901 }
1902 
1903 
1904 
1908 
1909 void KVClassFactory::KVClassMethod::AddArgument(Int_t i, const Char_t* type, const Char_t* argname, const Char_t* defaultvalue)
1910 {
1911  // Add an argument to the method, which will be in i-th position in the argument list
1912  // Any existing arguments with indices [i,fNargs] will first be moved to [i+1,fNargs+1]
1913 
1914  if (!(i > 0 && i <= fNargs + 1)) {
1915  Error("AddArgument(Int_t i, ...)", "Must be called with i>0 & i<=%d", fNargs + 1);
1916  return;
1917  }
1918 
1919  if (i == fNargs + 1) { // this is just same as call to AddArgument(type,argname,...)
1920  AddArgument(type, argname, defaultvalue);
1921  return;
1922  }
1923 
1924  for (int j = fNargs; j >= i; --j) {
1925  if (fFields.HasStringParameter(Form("Arg_%d", j))) {
1926  fFields.SetValue(Form("Arg_%d", j + 1), fFields.GetStringValue(Form("Arg_%d", j)));
1927  fFields.RemoveParameter(Form("Arg_%d", j));
1928  }
1929  if (fFields.HasStringParameter(Form("Arg_%d_name", j))) {
1930  fFields.SetValue(Form("Arg_%d_name", j + 1), fFields.GetStringValue(Form("Arg_%d_name", j)));
1931  fFields.RemoveParameter(Form("Arg_%d_name", j));
1932  }
1933  if (fFields.HasIntParameter(Form("Arg_%d_baseclass", j))) {
1934  fFields.SetValue(Form("Arg_%d_baseclass", j + 1), fFields.GetIntValue(Form("Arg_%d_baseclass", j)));
1935  fFields.RemoveParameter(Form("Arg_%d_baseclass", j));
1936  }
1937  if (fFields.HasStringParameter(Form("Arg_%d_default", j))) {
1938  fFields.SetValue(Form("Arg_%d_default", j + 1), fFields.GetStringValue(Form("Arg_%d_default", j)));
1939  fFields.RemoveParameter(Form("Arg_%d_default", j));
1940  }
1941  }
1942 
1943  KVString _type(type);
1944  fFields.SetValue(Form("Arg_%d", i), _type);
1945  if (strcmp(defaultvalue, "")) {
1946  KVString _s(defaultvalue);
1947  fFields.SetValue(Form("Arg_%d_default", i), _s);
1948  }
1949  if (strcmp(argname, "")) {
1950  KVString _s(argname);
1951  fFields.SetValue(Form("Arg_%d_name", i), _s);
1952  }
1953 
1954  ++fNargs;
1955 }
1956 
1957 
1958 
1961 
1963 {
1964  // print the KVClass method
1965  cout << "KVClassMethod object -----> " << GetName() << endl;
1966  fFields.Print();
1967  cout << "This method is " << GetAccess() << endl;
1968  if (fConst) cout << "This method is CONST" << endl;
1969  if (fVirtual) cout << "This method is VIRTUAL" << endl;
1970 }
1971 
1972 
1973 
1976 
1978 {
1979  // print the KVClass member
1980  cout << "KVClassMember object -----> " << GetType() << " " << GetName() << endl;
1981  cout << "This member is " << GetAccess() << endl;
1982 }
1983 
1984 
1985 
1986 
1992 
1994 {
1995  // Add constructors with the same signature as all base class constructors
1996  // (apart from the default ctor or any copy constructors, which are a special case)
1997  // If this class has its own member variables, we add them to the argument list
1998  // of each base class constructor.
1999 
2000  if (!fBaseClass) return;
2001 
2002  KVHashList clist;
2004  unique_ptr<KVSeqCollection> constructors(clist.GetSubListWithName(fBaseClassName));
2005  TIter next_ctor(constructors.get());
2006  TMethod* method;
2007  while ((method = (TMethod*)next_ctor())) {
2008  if (!method->GetNargs()) continue; // ignore default ctor
2009  TList* args = method->GetListOfMethodArgs();
2010  TMethodArg* arg = (TMethodArg*)args->First();
2011  TString typenam = arg->GetFullTypeName();
2012  if (typenam.Contains(fBaseClassName)) continue; // ignore copy ctor
2013  KVClassConstructor* ctor;
2014  if (arg->GetDefault()) ctor = AddConstructor(typenam, arg->GetName(), arg->GetDefault());
2015  else ctor = AddConstructor(typenam, arg->GetName());
2016  ctor->SetBaseClassArgument(1);
2017  for (int i = 1; i < method->GetNargs(); i++) {
2018  arg = (TMethodArg*)args->At(i);
2019  if (arg->GetDefault()) ctor->AddArgument(arg->GetFullTypeName(), arg->GetName(), arg->GetDefault());
2020  else ctor->AddArgument(arg->GetFullTypeName(), arg->GetName());
2021  ctor->SetBaseClassArgument(i + 1);
2022  }
2023  ctor->SetMethodComment(Form("Constructor inherited from %s", GetBaseClass()));
2025  }
2026 }
2027 
2028 
2029 
2032 
2034 {
2035  // Add default destructor to class
2036 
2037  if (!GetDestructor()) {
2039  d->SetClassName(fClassName);
2040  d->SetAccess(access);
2041  fMethods.Add(d);
2042  }
2043 }
2044 
2045 
2046 
2049 
2050 KVClassFactory::KVClassMember::KVClassMember(const Char_t* name, const Char_t* type, const Char_t* comment, const Char_t* access)
2051  : KVBase(Form("f%s", name), type), fComment(comment), fRealName(name)
2052 {
2053  // New class member variable
2054  SetAccess(access);
2055 }
2056 
2057 
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:135
const Char_t * GetType() const
Definition: KVBase.h:170
static const Char_t * GetTEMPLATEDIRFilePath(const Char_t *namefile="")
Definition: KVBase.cpp:83
static Bool_t SearchAndOpenKVFile(const Char_t *name, std::ifstream &file, const Char_t *kvsubdir="", KVLockfile *locks=0)
Definition: KVBase.cpp:601
static Bool_t SearchKVFile(const Char_t *name, TString &fullpath, const Char_t *kvsubdir="")
Definition: KVBase.cpp:541
virtual void Copy(TObject &) const
Make a copy of this object.
Definition: KVBase.cpp:397
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
virtual Int_t GetSize() const
T * get_object(const char *name) 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:562
Bool_t End() const
Definition: KVString.cpp:625
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:675
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