ATLAS Offline Software
Loading...
Searching...
No Matches
CodeGenerator_v2.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6// System include(s):
7#include <ctime>
8#include <locale>
9#include <sys/stat.h>
10
11// STL include(s):
12#include <fstream>
13#include <sstream>
14#include <algorithm>
15
16
17// Gaudi/Athena include(s):
18#include "GaudiKernel/System.h"
20
21// D3PD include(s):
23
24// Local include(s):
25#include "CodeGenerator_v2.h"
27#include "isPrimitive.h"
28
30static const char* const CODE_COMMENT =
31 "// Dear emacs, this is -*- c++ -*-\n"
32 "// -------------------------------------------------------------\n"
33 "// Code produced by D3PDMakerReader\n"
34 "//\n"
35 "// author: Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch>\n"
36 "// -------------------------------------------------------------";
37
39#define FOR_ALL_EVENT_VARIABLES(EXP) { \
40 std::set< ObjectMetadata >::const_iterator meta_itr = \
41 metadata.begin(); \
42 std::set< ObjectMetadata >::const_iterator meta_end = \
43 metadata.end(); \
44 std::set< std::string > varnames; \
45 for( ; meta_itr != meta_end; ++meta_itr ) { \
46 const std::string varname = \
47 eventVariableName( meta_itr->prefix(), \
48 meta_itr->name(), \
49 varnames ); \
50 varnames.insert( varname ); \
51 EXP; \
52 } \
53 } while( 0 )
54
55namespace {
56
58
71 std::string vectorTemplateArgument( const std::string& type,
72 bool& ok ) {
73
74 //
75 // Check that the type declaration begins with "std::vector<" or
76 // "vector<":
77 //
78 ok = true;
79 std::string result = type;
80 if( result.starts_with( "std::vector<" ) ) {
81 result.replace( 0, 12, "" );
82 } else if( result.starts_with( "vector<" ) ) {
83 result.replace( 0, 7, "" );
84 } else {
85 ok = false;
86 return "";
87 }
88
89 //
90 // Now go through the characters one-by-one, and try to find the closing
91 // bracket of the template argument. Remember that the template argument
92 // can itself be a templated type (vector of a vector for instance), so
93 // the code has to remember how many brackets were opened and closed.
94 //
95 int brackets = 0;
96 for( size_t i = 0; i < result.size(); ++i ) {
97
98 switch( result[ i ] ) {
99 case ',':
100 if( ! brackets ) {
101 return result.substr( 0, i );
102 }
103 break;
104 case '<':
105 ++brackets;
106 break;
107 case '>':
108 if( ! brackets ) {
109 // This is for the case when the vector's template argument is
110 // itself a template type:
111 if( result[ i - 1 ] == ' ' ) {
112 return result.substr( 0, i - 1 );
113 } else {
114 return result.substr( 0, i );
115 }
116 }
117 --brackets;
118 break;
119 default:
120 break;
121 }
122 }
123
124 ok = false;
125 return "";
126 }
127
129
137 void addSTLHeader( std::ostream& out, const char* name,
138 const D3PD::ObjectMetadata& metadata ) {
139
140 // Check if the STL name appears in the variable type names:
141 bool header_needed = false;
142 std::set< D3PD::ObjectMetadata::Variable >::const_iterator itr =
143 metadata.variables().begin();
144 std::set< D3PD::ObjectMetadata::Variable >::const_iterator end =
145 metadata.variables().end();
146 for( ; itr != end; ++itr ) {
147 if( itr->type().find( name ) != std::string::npos ) {
148 header_needed = true;
149 break;
150 }
151 }
152
153 // If it does, let's include it:
154 if( header_needed ) {
155 out << "#include <" << name << ">" << std::endl;
156 // This statement is here to make sure that ROOT's type names such as
157 // "vector<float>" will be compilable as well:
158 out << "using std::" << name << ";" << std::endl;
159 }
160
161 return;
162 }
163
165
173 std::string variableName( const std::string& varname ) {
174
175 std::string result = varname;
176
177 // Exchange the non C++-compilant characters:
178 std::string::size_type i = 0;
179 while( ( i = result.find( ":" ) ) != std::string::npos ) {
180 result[ i ] = '_';
181 }
182 while( ( i = result.find( " " ) ) != std::string::npos ) {
183 result[ i ] = '_';
184 }
185
186 // If the first character is a number, preceed it with the
187 // letter 'x':
188 if( isdigit( result[ 0 ] ) ) {
189 result = "x" + result;
190 }
191
192 return result;
193 }
194
196
212 std::string eventVariableName( const std::string& prefix,
213 const std::string& objectName,
214 const std::set< std::string >& varnames ) {
215
216 // The resulting string:
217 std::string result;
218
219 // If we have a prefix, use that as the variable name:
220 if( prefix.size() ) {
221 result = prefix;
222 // Remove a possible trailing underscore from the name:
223 if( result[ result.size() - 1 ] == '_' ) {
224 result.resize( prefix.size() - 1 );
225 }
226 // Return this variable name if it's not been used yet:
227 if( varnames.find( result ) == varnames.end() ) {
228 return result;
229 }
230 // Try to extend the variable name until it becomes unique:
231 for( int i = 0; ; ++i ) {
232 std::ostringstream name;
233 name << result << "_" << static_cast< char >( 'a' + i );
234 if( varnames.find( name.str() ) == varnames.end() ) {
235 return name.str();
236 }
237 }
238 }
239
240 // If we don't have a prefix, let's use the object name:
241 result = objectName;
242 // Remove a posible "D3PDObject" from the name:
243 if( result.find( "D3PDObject" ) == result.size() - 10 ) {
244 result.resize( result.size() - 10 );
245 }
246 // Turn the string into all lower case:
247 std::transform(result.begin(), result.end(), result.begin(),[](unsigned char c){ return std::tolower(c); });
248 return result;
249 }
250
251} // private namespace
252
253namespace D3PD {
254
255 namespace Version2 {
256
265 StatusCode writeD3PDObjectBase( const std::string& dir ) {
266
267 // Construct the file names as they will be needed in a few places:
268 const std::string headerName = dir + "/" + D3PDOBJECTBASE_HEADER_NAME;
269
270 // Only create the header if it doesn't exist:
271 struct stat fileInfo;
272 if( stat( headerName.c_str(), &fileInfo ) ) {
273
274 // Let everyone know what we're doing:
276 "Version2::writeD3PDObjectBase" )
277 << "Generating file: " << headerName;
278
279 // Open the header file (overwriting a possibly existing file):
280 std::ofstream header( headerName.c_str() );
281
282 // Write the header file:
283 header << D3PDOBJECTBASE_HEADER << std::endl;
284 header.close();
285 }
286
287 return StatusCode::SUCCESS;
288 }
289
298 StatusCode writeVarHandle( const std::string& dir ) {
299
300 // Construct the file names as they will be needed in a few places:
301 const std::string headerName = dir + "/" + VARHANDLE_HEADER_NAME;
302 const std::string implName = dir + "/" + VARHANDLE_IMPL_NAME;
303 const std::string sourceName = dir + "/" + VARHANDLE_CXX_NAME;
304
305 // Only create the header if it doesn't exist:
306 struct stat fileInfo;
307 if( stat( headerName.c_str(), &fileInfo ) ) {
308
309 // Let everyone know what we're doing:
311 "Version2::writeVarHandle" )
312 << "Generating file: " << headerName;
313
314 // Open the header file (overwriting a possibly existing file):
315 std::ofstream header( headerName.c_str() );
316
317 // Write the header file:
318 header << VARHANDLE_HEADER << std::endl;
319 header.close();
320 }
321
322 // Only create the implementation if it doesn't exist:
323 if( stat( implName.c_str(), &fileInfo ) ) {
324
325 // Let everyone know what we're doing:
326 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeVarHandle" )
327 << "Generating file: " << implName;
328
329 // Open the header file (overwriting a possibly existing file):
330 std::ofstream impl( implName.c_str() );
331
332 // Write the header file:
333 impl << VARHANDLE_IMPL << std::endl;
334 impl.close();
335 }
336
337 // Only create the source if it doesn't exist:
338 if( stat( sourceName.c_str(), &fileInfo ) ) {
339
340 // Let everyone know what we're doing:
341 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeVarHandle" )
342 << "Generating file: " << sourceName;
343
344 // Open the header file (overwriting a possibly existing file):
345 std::ofstream source( sourceName.c_str() );
346
347 // Write the header file:
348 source << VARHANDLE_CXX << std::endl;
349 source.close();
350 }
351
352 return StatusCode::SUCCESS;
353 }
354
363 StatusCode writeVarProxy( const std::string& dir ) {
364
365 // Construct the file names as they will be needed in a few places:
366 const std::string headerName = dir + "/" + VARPROXY_HEADER_NAME;
367 const std::string implName = dir + "/" + VARPROXY_IMPL_NAME;
368
369 // Only create the header if it doesn't exist:
370 struct stat fileInfo;
371 if( stat( headerName.c_str(), &fileInfo ) ) {
372
373 // Let everyone know what we're doing:
374 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeVarProxy" )
375 << "Generating file: " << headerName;
376
377 // Open the header file (overwriting a possibly existing file):
378 std::ofstream header( headerName.c_str() );
379
380 // Write the header file:
381 header << VARPROXY_HEADER << std::endl;
382 header.close();
383 }
384
385 // Only create the implementation if it doesn't exist:
386 if( stat( implName.c_str(), &fileInfo ) ) {
387
388 // Let everyone know what we're doing:
389 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeVarProxy" )
390 << "Generating file: " << implName;
391
392 // Open the header file (overwriting a possibly existing file):
393 std::ofstream impl( implName.c_str() );
394
395 // Write the header file:
396 impl << VARPROXY_IMPL << std::endl;
397 impl.close();
398 }
399
400 return StatusCode::SUCCESS;
401 }
402
411 StatusCode writeUserD3PDObject( const std::string& dir ) {
412
413 // Construct the file names as they will be needed in a few places:
414 const std::string headerName = dir + "/" + USERD3PDOBJECT_HEADER_NAME;
415 const std::string implName = dir + "/" + USERD3PDOBJECT_IMPL_NAME;
416 const std::string sourceName = dir + "/" + USERD3PDOBJECT_CXX_NAME;
417
418 // Only create the header if it doesn't exist:
419 struct stat fileInfo;
420 if( stat( headerName.c_str(), &fileInfo ) ) {
421
422 // Let everyone know what we're doing:
424 "Version2::writeUserD3PDObject" )
425 << "Generating file: " << headerName;
426
427 // Open the header file (overwriting a possibly existing file):
428 std::ofstream header( headerName.c_str() );
429
430 // Write the header file:
431 header << USERD3PDOBJECT_HEADER << std::endl;
432 header.close();
433 }
434
435 // Only create the implementation if it doesn't exist:
436 if( stat( implName.c_str(), &fileInfo ) ) {
437
438 // Let everyone know what we're doing:
440 "Version2::writeUserD3PDObject" )
441 << "Generating file: " << implName;
442
443 // Open the header file (overwriting a possibly existing file):
444 std::ofstream impl( implName.c_str() );
445
446 // Write the header file:
447 impl << USERD3PDOBJECT_IMPL << std::endl;
448 impl.close();
449 }
450
451 // Only create the source if it doesn't exist:
452 if( stat( sourceName.c_str(), &fileInfo ) ) {
453
454 // Let everyone know what we're doing:
456 "Version2::writeUserD3PDObject" )
457 << "Generating file: " << sourceName;
458
459 // Open the header file (overwriting a possibly existing file):
460 std::ofstream source( sourceName.c_str() );
461
462 // Write the header file:
463 source << USERD3PDOBJECT_CXX << std::endl;
464 source.close();
465 }
466
467 return StatusCode::SUCCESS;
468 }
469
478 StatusCode writeD3PDReadStats( const std::string& dir ) {
479
480 // Construct the file names as they will be needed in a few places:
481 const std::string headerName = dir + "/" + D3PDREADSTATS_HEADER_NAME;
482 const std::string cxxName = dir + "/" + D3PDREADSTATS_CXX_NAME;
483
484 // Only create the header if it doesn't exist:
485 struct stat fileInfo;
486 if( stat( headerName.c_str(), &fileInfo ) ) {
487
488 // Let everyone know what we're doing:
490 "Version2::writeD3PDReadStats" )
491 << "Generating file: " << headerName;
492
493 // Open the header file (overwriting a possibly existing file):
494 std::ofstream header( headerName.c_str() );
495
496 // Write the header file:
497 header << D3PDREADSTATS_HEADER << std::endl;
498 header.close();
499 }
500
501 // Only create the implementation if it doesn't exist:
502 if( stat( cxxName.c_str(), &fileInfo ) ) {
503
504 // Let everyone know what we're doing:
506 "Version2::writeD3PDReadStats" )
507 << "Generating file: " << cxxName;
508
509 // Open the header file (overwriting a possibly existing file):
510 std::ofstream impl( cxxName.c_str() );
511
512 // Write the header file:
513 impl << D3PDREADSTATS_CXX << std::endl;
514 impl.close();
515 }
516
517 return StatusCode::SUCCESS;
518 }
519
528 StatusCode writeD3PDPerfStats( const std::string& dir ) {
529
530 // Construct the file names as they will be needed in a few places:
531 const std::string headerName = dir + "/" + D3PDPERFSTATS_HEADER_NAME;
532 const std::string cxxName = dir + "/" + D3PDPERFSTATS_CXX_NAME;
533
534 // Only create the header if it doesn't exist:
535 struct stat fileInfo;
536 if( stat( headerName.c_str(), &fileInfo ) ) {
537
538 // Let everyone know what we're doing:
540 "Version2::writeD3PDPerfStats" )
541 << "Generating file: " << headerName;
542
543 // Open the header file (overwriting a possibly existing file):
544 std::ofstream header( headerName.c_str() );
545
546 // Write the header file:
547 header << D3PDPERFSTATS_HEADER << std::endl;
548 header.close();
549 }
550
551 // Only create the implementation if it doesn't exist:
552 if( stat( cxxName.c_str(), &fileInfo ) ) {
553
554 // Let everyone know what we're doing:
556 "Version2::writeD3PDPerfStats" )
557 << "Generating file: " << cxxName;
558
559 // Open the header file (overwriting a possibly existing file):
560 std::ofstream impl( cxxName.c_str() );
561
562 // Write the header file:
563 impl << D3PDPERFSTATS_CXX << std::endl;
564 impl.close();
565 }
566
567 return StatusCode::SUCCESS;
568 }
569
577 StatusCode writeUtils( const std::string& dir ) {
578
579 // Construct the file names as they will be needed in a few places:
580 const std::string headerName = dir + "/" + UTILS_HEADER_NAME;
581 const std::string cxxName = dir + "/" + UTILS_CXX_NAME;
582
583 // Only create the header if it doesn't exist:
584 struct stat fileInfo;
585 if( stat( headerName.c_str(), &fileInfo ) ) {
586
587 // Let everyone know what we're doing:
588 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeUtils" )
589 << "Generating file: " << headerName;
590
591 // Open the header file (overwriting a possibly existing file):
592 std::ofstream header( headerName.c_str() );
593
594 // Write the header file:
595 header << UTILS_HEADER << std::endl;
596 header.close();
597 }
598
599 // Only create the implementation if it doesn't exist:
600 if( stat( cxxName.c_str(), &fileInfo ) ) {
601
602 // Let everyone know what we're doing:
603 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeUtils" )
604 << "Generating file: " << cxxName;
605
606 // Open the header file (overwriting a possibly existing file):
607 std::ofstream impl( cxxName.c_str() );
608
609 // Write the header file:
610 impl << UTILS_CXX << std::endl;
611 impl.close();
612 }
613
614 return StatusCode::SUCCESS;
615 }
616
632 StatusCode writeHeader( const std::string& classname,
633 const std::string& dir,
634 const ObjectMetadata& metadata ) {
635
636 // Construct the file name:
637 const std::string fileName = dir + "/" + classname + ".h";
638
639 // If the file already exists, let's not overwrite it:
640 struct stat fileInfo;
641 if( ! stat( fileName.c_str(), &fileInfo ) ) return StatusCode::SUCCESS;
642
643 // Let everyone know what we're doing:
644 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeHeader" )
645 << "Generating file: " << fileName;
646
647 // Open the header file (overwriting a possibly existing file):
648 std::ofstream header( fileName.c_str() );
649
650 // Write a header for the file:
651 header << CODE_COMMENT << std::endl;
652 header << "#ifndef D3PDREADER_" << classname << "_H" << std::endl;
653 header << "#define D3PDREADER_" << classname << "_H" << std::endl
654 << std::endl;
655
656 // The STL map is always needed:
657 header << "// STL include(s):" << std::endl;
658 header << "#include <map>" << std::endl;
659
660 // Include some other STL headers if they're needed:
661 addSTLHeader( header, "vector", metadata );
662 addSTLHeader( header, "string", metadata );
663 header << std::endl;
664
665 // ROOT include(s):
666 header << "// ROOT include(s):" << std::endl;
667 header << "#include <TObject.h>" << std::endl;
668 header << "#include <TString.h>" << std::endl << std::endl;
669
670 // Local include(s):
671 header << "#include \"" << D3PDOBJECTBASE_HEADER_NAME << "\""
672 << std::endl;
673 header << "#include \"" << D3PDREADSTATS_HEADER_NAME << "\""
674 << std::endl;
675 header << "#include \"" << VARHANDLE_HEADER_NAME << "\"" << std::endl;
676 if( metadata.container() ) {
677 header << "#include \"" << VARPROXY_HEADER_NAME << "\""
678 << std::endl;
679 }
680 header << "#include \"" << USERD3PDOBJECT_HEADER_NAME << "\""
681 << std::endl;
682 header << std::endl;
683
684 // Forward declaration(s):
685 header << "class TTree;" << std::endl << std::endl;
686
687 // Declare the namespace:
688 header << "namespace D3PDReader {" << std::endl << std::endl;
689
690 //
691 // Declare the proxy class:
692 //
693 if( metadata.container() ) {
694
695 // Forward declare the reader class:
696 header << " // Forward declaration(s):" << std::endl;
697 header << " class " << classname << ";" << std::endl << std::endl;
698
699 // Declare the proxy class:
700 header << " /**" << std::endl;
701 header << " * Code generated by CodeGenerator_v2 on:"
702 << std::endl;
703 header << " * host = " << System::hostName() << std::endl;
704 header << " * OS = " << System::osName() << " / "
705 << System::osVersion() << std::endl;
706 header << " * user = " << System::accountName() << std::endl;
707 const time_t rawtime = time( NULL );
708 char buf[26];
709 header << " * time = " << ctime_r( &rawtime, buf );
710 header << " */" << std::endl;
711 header << " class " << classname << "Element : "
712 << "public UserD3PDObjectElement {" << std::endl
713 << std::endl;
714 header << " friend class " << classname << ";" << std::endl
715 << std::endl;
716 header << " protected:" << std::endl;
717
718 // Create the constructor:
719 header << " /// Constructor only visible to " << classname
720 << std::endl;
721 header << " " << classname << "Element( size_t index, const "
722 << classname << "& parent );" << std::endl << std::endl;
723
724 // Create the copy constructor:
725 header << " public:" << std::endl;
726 header << " /// Copy constructor" << std::endl;
727 header << " " << classname << "Element( const " << classname
728 << "Element& parent );" << std::endl << std::endl;
729
730 // Create the generic accessor functions:
731 header << " /// Parent object of this proxy object"
732 << std::endl;
733 header << " const " << classname << "* GetParent() const;"
734 << std::endl;
735 header << " /// Index of the object inside its container"
736 << std::endl;
737 header << " size_t GetIndex() const;" << std::endl
738 << std::endl;
739
740 // Create the member variable(s):
741 std::map< std::string, int > variableCounter;
742 std::set< ObjectMetadata::Variable >::const_iterator itr =
743 metadata.variables().begin();
744 std::set< ObjectMetadata::Variable >::const_iterator end =
745 metadata.variables().end();
746 for( ; itr != end; ++itr ) {
747 // Ignore the container size variable:
748 if( ( itr->name() == "n" ) || ( itr->name() == "N" ) ) continue;
749
750 bool ok = true;
751 const std::string type =
752 vectorTemplateArgument( itr->type(), ok );
753 if( ! ok ) {
754 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR,
755 "Version2::writeHeader" )
756 << "Unexpected variable type encountered for "
757 << "container dumper: " << itr->type();
758 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR,
759 "Version2::writeHeader" )
760 << "Variable name: " << itr->name();
761 return StatusCode::FAILURE;
762 }
763 if( itr->doc() != "" ) {
764 header << " /// " << itr->doc() << std::endl;
765 }
766 if( variableCounter.find( itr->name() ) ==
767 variableCounter.end() ) {
768 header << " VarProxy< " << type << " > "
769 << variableName( itr->name() ) << ";" << std::endl;
770 variableCounter[ itr->name() ] = 1;
771 } else {
772 header << " VarProxy< " << type << " > "
773 << variableName( itr->name() )
774 << variableCounter[ itr->name() ] << ";" << std::endl;
775 variableCounter[ itr->name() ]++;
776 }
777 }
778 header << std::endl;
779
780 // Create the private variable(s):
781 header << " private:" << std::endl;
782 header << " /// Reference to the parent of this object"
783 << std::endl;
784 header << " const " << classname << "* fParent;" << std::endl;
785 header << " /// The index of this object inside the parent "
786 << "container" << std::endl;
787 header << " size_t fIndex;" << std::endl << std::endl;
788
789 // Close the class definition:
790 header << " ClassDef( " << classname << "Element, 0 )"
791 << std::endl
792 << std::endl;
793 header << " }; // class " << classname << "Element" << std::endl
794 << std::endl;
795 }
796
797 //
798 // Declare the reader class itself:
799 //
800 header << " /**" << std::endl;
801 header << " * Code generated by CodeGenerator_v2 on:" << std::endl;
802 header << " * host = " << System::hostName() << std::endl;
803 header << " * OS = " << System::osName() << " / "
804 << System::osVersion() << std::endl;
805 header << " * user = " << System::accountName() << std::endl;
806 const time_t rawtime = time( NULL );
807 char buf[26];
808 header << " * time = " << ctime_r( &rawtime, buf );
809 header << " */" << std::endl;
810 header << " class " << classname << " : "
811 << "public UserD3PDObject {" << std::endl << std::endl;
812 header << " public:" << std::endl;
813
814 //
815 // Declare the constructor(s)/destructor:
816 //
817 header << " /// Constructor used when reading from a TTree"
818 << std::endl;
819 header << " " << classname
820 << "( const ::Long64_t& master, const char* prefix = \""
821 << metadata.prefix() << "\" );" << std::endl;
822 header << " /// Constructor when the object is only used for "
823 << "writing data out" << std::endl;
824 header << " " << classname << "( const char* prefix = \""
825 << metadata.prefix() << "\" );" << std::endl;
826 if( metadata.container() ) {
827 header << " /// Destructor" << std::endl;
828 header << " ~" << classname << "();" << std::endl;
829 }
830 header << std::endl;
831
832 //
833 // Declare some functions:
834 //
835 header << " /// Get the currently configured prefix value"
836 << std::endl;
837 header << " virtual const char* GetPrefix() const;" << std::endl;
838 header << " /// Set the prefix for the variables" << std::endl;
839 header << " virtual void SetPrefix( const char* prefix );"
840 << std::endl << std::endl;
841
842 header << " /// Connect the object to an input TTree"
843 << std::endl;
844 header << " virtual void ReadFrom( ::TTree* tree );" << std::endl;
845 header << " /// Connect the object to an output TTree"
846 << std::endl;
847 header << " virtual void WriteTo( ::TTree* tree );" << std::endl
848 << std::endl;
849
850 header << " /// Turn (selected) branches either on or off"
851 << std::endl;
852 header << " virtual void SetActive( ::Bool_t active = kTRUE,"
853 << std::endl;
854 header << " const ::TString& pattern = "
855 << "\".*\" );" << std::endl;
856 header << " /// Read in all the variables that we need to write "
857 << "out as well" << std::endl;
858 header << " virtual void ReadAllActive();" << std::endl
859 << std::endl;
860
861 header << " /// Get the D3PD reading statistics" << std::endl;
862 header << " virtual D3PDReadStats GetStatistics() const;"
863 << std::endl << std::endl;
864
865 header << " /// Set the contents of the object according to "
866 << "another object" << std::endl;
867 header << " " << classname << "& Set( const " << classname
868 << "& parent );" << std::endl << std::endl;
869
870 if( metadata.container() ) {
871 header << " /// Clear the container. Useful when writing new "
872 << "branches." << std::endl;
873 header << " void Clear( Option_t* option = \"\" );"
874 << std::endl;
875 header << " /// Add one element to an output collection"
876 << std::endl;
877 header << " " << classname << "& Add( const " << classname
878 << "Element& el );" << std::endl << std::endl;
879 header << " /// Access a proxy class describing one element of"
880 << " the container" << std::endl;
881 header << " " << classname << "Element& operator[]( size_t "
882 << "index );" << std::endl;
883 header << " /// Access a proxy class describing one element of"
884 << " the container (constant version)" << std::endl;
885 header << " const " << classname << "Element& operator[]( "
886 << "size_t index ) const;" << std::endl;
887 header << " /// Add one element to an output collection"
888 << std::endl;
889 header << " " << classname << "& operator+=( const "
890 << classname << "Element& el );" << std::endl << std::endl;
891 }
892
893 //
894 // Declare each variable responsible for reading a branch:
895 //
896 std::map< std::string, int > variableCounter;
897 std::set< ObjectMetadata::Variable >::const_iterator itr =
898 metadata.variables().begin();
899 std::set< ObjectMetadata::Variable >::const_iterator end =
900 metadata.variables().end();
901 for( ; itr != end; ++itr ) {
902 if( itr->doc() != "" ) {
903 header << " /// " << itr->doc() << std::endl;
904 }
905 if( variableCounter.find( itr->name() ) == variableCounter.end() ) {
906 header << " VarHandle< " << itr->type()
907 << ( itr->primitive() ? "" : "*" ) << " > "
908 << variableName( itr->name() ) << ";" << std::endl;
909 variableCounter[ itr->name() ] = 1;
910 } else {
911 header << " VarHandle< " << itr->type()
912 << ( itr->primitive() ? "" : "*" ) << " > "
913 << variableName( itr->name() )
914 << variableCounter[ itr->name() ] << ";" << std::endl;
915 variableCounter[ itr->name() ]++;
916 }
917 }
918
919 // Declare the private functions/members:
920 header << std::endl << " private:" << std::endl;
921 header << " /// Function used internally to access the variables"
922 << std::endl;
923 header << " VarHandleBase* GetVarHandle( const char* name );"
924 << std::endl;
925 header << " /// Function setting up all the VarHandle members"
926 << std::endl;
927 header << " void SetVarHandles( const ::Long64_t* master );"
928 << std::endl << std::endl;
929
930 // Declare the additional member variable(s):
931 if( metadata.container() ) {
932 header << " mutable std::vector< " << classname << "Element* >"
933 << " fProxies; ///< Internal list of proxy objects"
934 << std::endl;
935 }
936 header << " std::map< ::TString, VarHandleBase* > fHandles; "
937 << "///< Book-keeper of the VarHandle members" << std::endl;
938 header << " const ::Bool_t fFromInput; "
939 << "///< Flag specifying if object is used for D3PD reading"
940 << std::endl;
941 header << " ::TString fPrefix; ///< Prefix to the branch names"
942 << std::endl << std::endl;
943
944 // Close the class definition:
945 header << " ClassDef( " << classname << ", 0 )" << std::endl
946 << std::endl;
947 header << " }; // class " << classname << std::endl << std::endl;
948 header << "} // namespace D3PDReader" << std::endl << std::endl;
949 header << "#endif // D3PDREADER_" << classname << "_H" << std::endl;
950
951 header.close();
952
953 return StatusCode::SUCCESS;
954 }
955
967 StatusCode writeSource( const std::string& classname,
968 const std::string& dir,
969 const ObjectMetadata& metadata ) {
970
971 // Construct the file name:
972 const std::string fileName = dir + "/" + classname + ".cxx";
973
974 // If the file already exists, let's not overwrite it:
975 struct stat fileInfo;
976 if( ! stat( fileName.c_str(), &fileInfo ) ) return StatusCode::SUCCESS;
977
978 // Let everyone know what we're doing:
979 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeSource" )
980 << "Generating file: " << fileName;
981
982 // Open the header file (overwriting a possibly existing file):
983 std::ofstream source( fileName.c_str() );
984
985 // Add the common header to the file:
986 source << CODE_COMMENT << std::endl << std::endl;
987
988 if( metadata.container() ) {
989 source << "#include <limits>" << std::endl;
990 source << "#include <stdexcept>" << std::endl << std::endl;
991 }
992
993 // Extra ROOT include(s):
994 source << "#include <TPRegexp.h>" << std::endl;
995 source << "#include <TList.h>" << std::endl;
996 source << "#include <TDataMember.h>" << std::endl << std::endl;
997
998 // Include the class's header:
999 source << "#include \"" << classname << ".h\"" << std::endl
1000 << std::endl;
1001
1002 if( metadata.container() ) {
1003 source << "ClassImp( D3PDReader::" << classname << "Element )"
1004 << std::endl;
1005 }
1006 source << "ClassImp( D3PDReader::" << classname << " )" << std::endl
1007 << std::endl;
1008
1009 source << "namespace D3PDReader {" << std::endl << std::endl;
1010
1011 if( metadata.container() ) {
1012 //
1013 // Produce the constructor of the proxy class:
1014 //
1015 const std::string spacer( ( 2 * classname.size() ) + 21, ' ' );
1016 source << " /**" << std::endl;
1017 source << " * This constructor can be used to create new proxy "
1018 << "objects from scratch." << std::endl;
1019 source << " * Since the constructor of such an object is quite "
1020 << "complicated and" << std::endl;
1021 source << " * error prone, it is only visible to the parent "
1022 << "class " << classname << "." << std::endl;
1023 source << " */" << std::endl;
1024 source << " " << classname << "Element::" << classname
1025 << "Element( size_t index, const " << classname
1026 << "& parent )" << std::endl;
1027 source << " : UserD3PDObjectElement( index, parent )";
1028 std::map< std::string, int > variableCounter;
1029 std::set< ObjectMetadata::Variable >::const_iterator itr =
1030 metadata.variables().begin();
1031 std::set< ObjectMetadata::Variable >::const_iterator end =
1032 metadata.variables().end();
1033 for( ; itr != end; ++itr ) {
1034 // Ignore the container size variable:
1035 if( ( itr->name() == "n" ) || ( itr->name() == "N" ) ) continue;
1036
1037 source << "," << std::endl;
1038 if( variableCounter.find( itr->name() ) ==
1039 variableCounter.end() ) {
1040 source << " " << variableName( itr->name() )
1041 << "( parent." << variableName( itr->name() )
1042 << ", index )";
1043 variableCounter[ itr->name() ] = 1;
1044 } else {
1045 source << " " << variableName( itr->name() )
1046 << variableCounter[ itr->name() ]
1047 << "( parent." << variableName( itr->name() )
1048 << variableCounter[ itr->name() ] << ", index )";
1049 variableCounter[ itr->name() ]++;
1050 }
1051 }
1052 source << "," << std::endl;
1053 source << " fParent( &parent ), fIndex( index ) {"
1054 << std::endl << std::endl;
1055 source << " }" << std::endl << std::endl;
1056
1057 //
1058 // Produce the copy-constructor of the proxy class:
1059 //
1060 source << " /**" << std::endl;
1061 source << " * This constructor is useful for creating copies of "
1062 << "proxy objects." << std::endl;
1063 source << " * Such objects are fairly cheap to copy, so the user"
1064 << " is allowed to have" << std::endl;
1065 source << " * his/her containers of them inside an analysis "
1066 << "code. (To select and" << std::endl;
1067 source << " * sort objects according to some criteria for "
1068 << "instance.)" << std::endl;
1069 source << " *" << std::endl;
1070 source << " * @param parent The proxy object that should be "
1071 << "copied" << std::endl;
1072 source << " */" << std::endl;
1073 source << " " << classname << "Element::" << classname
1074 << "Element( const " << classname << "Element& parent )"
1075 << std::endl;
1076 source << " : UserD3PDObjectElement( parent )";
1077 variableCounter.clear();
1078 itr = metadata.variables().begin();
1079 end = metadata.variables().end();
1080 for( ; itr != end; ++itr ) {
1081 // Ignore the container size variable:
1082 if( ( itr->name() == "n" ) || ( itr->name() == "N" ) ) continue;
1083
1084 source << "," << std::endl;
1085 if( variableCounter.find( itr->name() ) ==
1086 variableCounter.end() ) {
1087 source << " " << variableName( itr->name() )
1088 << "( parent." << variableName( itr->name() )
1089 << " )";
1090 variableCounter[ itr->name() ] = 1;
1091 } else {
1092 source << " " << variableName( itr->name() )
1093 << variableCounter[ itr->name() ]
1094 << "( parent." << variableName( itr->name() )
1095 << variableCounter[ itr->name() ] << " )";
1096 variableCounter[ itr->name() ]++;
1097 }
1098 }
1099 source << "," << std::endl;
1100 source << " fParent( parent.fParent ), "
1101 << "fIndex( parent.fIndex ) {" << std::endl << std::endl;
1102 source << " }" << std::endl << std::endl;
1103
1104 //
1105 // Produce the GetParent() function of the proxy class:
1106 //
1107 source << " /**" << std::endl;
1108 source << " * This function can be used to access the parent "
1109 << "object of this" << std::endl;
1110 source << " * proxy object. It can come in handy when optimizing"
1111 << " an analysis code." << std::endl;
1112 source << " *" << std::endl;
1113 source << " * @returns A reference to this object's parent"
1114 << std::endl;
1115 source << " */" << std::endl;
1116 source << " const " << classname << "* " << classname
1117 << "Element::GetParent() const {" << std::endl << std::endl;
1118 source << " return fParent;" << std::endl;
1119 source << " }" << std::endl << std::endl;
1120
1121 //
1122 // Produce the GetIndex() function of the proxy class:
1123 //
1124 source << " /**" << std::endl;
1125 source << " * This function can be used to access the index of "
1126 << "this proxy object" << std::endl;
1127 source << " * inside the parent container. It can come in handy "
1128 << "when optimizing an" << std::endl;
1129 source << " * analysis code." << std::endl;
1130 source << " *" << std::endl;
1131 source << " * @returns The index of the proxy in the object's "
1132 << "parent" << std::endl;
1133 source << " */" << std::endl;
1134 source << " size_t " << classname << "Element::GetIndex() const {"
1135 << std::endl << std::endl;
1136 source << " return fIndex;" << std::endl;
1137 source << " }" << std::endl << std::endl;
1138 }
1139
1140 //
1141 // Produce the (input) constructor:
1142 //
1143 source << " /**" << std::endl;
1144 source << " * This constructor should be used when the object will "
1145 << "be used to read" << std::endl;
1146 source << " * variables from an existing ntuple. The object will "
1147 << "also be able to" << std::endl;
1148 source << " * output variables, but it will also need to read them "
1149 << "from somewhere." << std::endl;
1150 source << " *" << std::endl;
1151 source << " * @param master Reference to the variable holding the "
1152 << "current " << "event number" << std::endl;
1153 source << " * @param prefix Prefix of the variables in the D3PD"
1154 << std::endl;
1155 source << " */" << std::endl;
1156 source << " " << classname << "::" << classname
1157 << "( const ::Long64_t& master, const char* prefix )"
1158 << std::endl;
1159 source << " : UserD3PDObject( master, prefix ),"
1160 << std::endl;
1161 source << " fHandles()," << std::endl;
1162 source << " fFromInput( kTRUE )," << std::endl;
1163 source << " fPrefix( prefix ) {" << std::endl << std::endl;
1164 source << " SetVarHandles( &master );" << std::endl;
1165 source << " }" << std::endl << std::endl;
1166
1167 //
1168 // Produce the (output) constructor:
1169 //
1170 source << " /**" << std::endl;
1171 source << " * This constructor can be used when the object will "
1172 << "only have to output" << std::endl;
1173 source << " * (and temporarily store) new information into an "
1174 << "output ntuple. For" << std::endl;
1175 source << " * instance when one wants to create a selected/modified"
1176 << " list of information." << std::endl;
1177 source << " *" << std::endl;
1178 source << " * @param prefix Prefix of the variables in the D3PD"
1179 << std::endl;
1180 source << " */" << std::endl;
1181 source << " " << classname << "::" << classname
1182 << "( const char* prefix )" << std::endl;
1183 source << " : UserD3PDObject( prefix ),"
1184 << std::endl;
1185 source << " fHandles()," << std::endl;
1186 source << " fFromInput( kFALSE )," << std::endl;
1187 source << " fPrefix( prefix ) {" << std::endl << std::endl;
1188 source << " SetVarHandles( 0 );" << std::endl;
1189 source << " }" << std::endl << std::endl;
1190
1191 //
1192 // Produce the destructor:
1193 //
1194 if( metadata.container() ) {
1195 source << " /**" << std::endl;
1196 source << " * The destructor needs to delete all the allocated "
1197 << "objects." << std::endl;
1198 source << " */" << std::endl;
1199 source << " " << classname << "::~" << classname << "() {"
1200 << std::endl
1201 << std::endl;
1202 source << " for( size_t i = 0; i < fProxies.size(); ++i ) {"
1203 << std::endl;
1204 source << " delete fProxies[ i ];" << std::endl;
1205 source << " }" << std::endl;
1206 source << " }" << std::endl << std::endl;
1207 }
1208
1209 //
1210 // Produce the prefix handling function(s):
1211 //
1212 source << " /**" << std::endl;
1213 source << " * @returns The branch name prefix used by the object"
1214 << std::endl;
1215 source << " */" << std::endl;
1216 source << " const char* " << classname << "::GetPrefix() const {"
1217 << std::endl << std::endl;
1218 source << " return fPrefix;" << std::endl;
1219 source << " }" << std::endl << std::endl;
1220
1221 source << " /**" << std::endl;
1222 source << " * @param prefix The prefix that should be used for the "
1223 << "variables" << std::endl;
1224 source << " */" << std::endl;
1225 source << " void " << classname << "::SetPrefix( const char* prefix "
1226 << ") {" << std::endl << std::endl;
1227 source << " // Call the base class's function:" << std::endl;
1228 source << " UserD3PDObject::SetPrefix( prefix );" << std::endl
1229 << std::endl;
1230 source << " // Remember the prefix:" << std::endl;
1231 source << " fPrefix = prefix;" << std::endl << std::endl;
1232 source << " // Set all the variable names:" << std::endl;
1233 source << " std::map< TString, VarHandleBase* >::const_iterator "
1234 << "itr = fHandles.begin();" << std::endl;
1235 source << " std::map< TString, VarHandleBase* >::const_iterator "
1236 << "end = fHandles.end();" << std::endl;
1237 source << " for( ; itr != end; ++itr ) {" << std::endl;
1238 source << " itr->second->SetName( ::TString( prefix ) + "
1239 << "itr->first );" << std::endl;
1240 source << " }" << std::endl << std::endl;
1241 source << " return;" << std::endl;
1242 source << " }" << std::endl << std::endl;
1243
1244 //
1245 // Produce the ReadFrom(...) function:
1246 //
1247 source << " /**" << std::endl;
1248 source << " * This function should be called every time a new TFile"
1249 << " is opened" << std::endl;
1250 source << " * by your analysis code." << std::endl;
1251 source << " *" << std::endl;
1252 source << " * @param tree Pointer to the TTree with the variables"
1253 << std::endl;
1254 source << " */" << std::endl;
1255 source << " void " << classname << "::ReadFrom( TTree* tree ) {"
1256 << std::endl << std::endl;
1257 source << " // Check if the object will be able to read from the "
1258 << "TTree:" << std::endl;
1259 source << " if( ! fFromInput ) {" << std::endl;
1260 source << " Error( \"ReadFrom\", \"The object was not created "
1261 << "with the correct\" );" << std::endl;
1262 source << " Error( \"ReadFrom\", \"constructor to read data "
1263 << "from a D3PD!\" );" << std::endl;
1264 source << " return;" << std::endl;
1265 source << " }" << std::endl << std::endl;
1266 source << " // Call the base class's function:" << std::endl;
1267 source << " UserD3PDObject::ReadFrom( tree );" << std::endl
1268 << std::endl;
1269 source << " // Call ReadFrom(...) on all the variables:"
1270 << std::endl;
1271 source << " std::map< TString, VarHandleBase* >::const_iterator "
1272 << "itr = fHandles.begin();" << std::endl;
1273 source << " std::map< TString, VarHandleBase* >::const_iterator "
1274 << "end = fHandles.end();" << std::endl;
1275 source << " for( ; itr != end; ++itr ) {" << std::endl;
1276 source << " itr->second->ReadFrom( tree );" << std::endl;
1277 source << " }" << std::endl << std::endl;
1278 source << " return;" << std::endl;
1279 source << " }" << std::endl << std::endl;
1280
1281 //
1282 // Produce the WriteTo(...) function:
1283 //
1284 source << " /**" << std::endl;
1285 source << " * This function can be called to connect the active "
1286 << "variables of the object" << std::endl;
1287 source << " * to an output TTree. It can be called multiple times, "
1288 << "then the variables" << std::endl;
1289 source << " * will be written to multiple TTrees." << std::endl;
1290 source << " *" << std::endl;
1291 source << " * @param tree Pointer to the TTree where the variables "
1292 << "should be written" << std::endl;
1293 source << " */" << std::endl;
1294 source << " void " << classname << "::WriteTo( TTree* tree ) {"
1295 << std::endl << std::endl;
1296 source << " // Call the base class's function:" << std::endl;
1297 source << " UserD3PDObject::WriteTo( tree );" << std::endl
1298 << std::endl;
1299 source << " // Call WriteTo(...) on all the variables:"
1300 << std::endl;
1301 source << " std::map< TString, VarHandleBase* >::const_iterator "
1302 << "itr = fHandles.begin();" << std::endl;
1303 source << " std::map< TString, VarHandleBase* >::const_iterator "
1304 << "end = fHandles.end();" << std::endl;
1305 source << " for( ; itr != end; ++itr ) {" << std::endl;
1306 source << " itr->second->WriteTo( tree );" << std::endl;
1307 source << " }" << std::endl << std::endl;
1308 source << " return;" << std::endl;
1309 source << " }" << std::endl << std::endl;
1310
1311 //
1312 // Produce the SetActive(...) function:
1313 //
1314 source << " /**" << std::endl;
1315 source << " * This is a convenience function for turning the "
1316 << "branches active or" << std::endl;
1317 source << " * inactive conveniently. If the parameter is set to "
1318 << "<code>kTRUE</code>" << std::endl;
1319 source << " * then the branches available from the input which "
1320 << "match the given" << std::endl;
1321 source << " * pattern are turned active."
1322 << std::endl;
1323 source << " * When it's set to <code>kFALSE</code> then all the "
1324 << "variables matching" << std::endl;
1325 source << " * the pattern are turned inactive." << std::endl;
1326 source << " *" << std::endl;
1327 source << " * @param active Flag behaving as explained above"
1328 << std::endl;
1329 source << " * @param pattern Regular expression specifying which "
1330 << "branches to modify" << std::endl;
1331 source << " */" << std::endl;
1332 source << " void " << classname << "::SetActive( ::Bool_t active, "
1333 << "const ::TString& pattern ) {" << std::endl
1334 << std::endl;
1335 source << " // Call the base class's function:" << std::endl;
1336 source << " UserD3PDObject::SetActive( active, pattern );"
1337 << std::endl << std::endl;
1338 source << " ::TPRegexp re( pattern );" << std::endl << std::endl;
1339 source << " std::map< TString, VarHandleBase* >::const_iterator "
1340 << "itr = fHandles.begin();" << std::endl;
1341 source << " std::map< TString, VarHandleBase* >::const_iterator "
1342 << "end = fHandles.end();" << std::endl;
1343 source << " for( ; itr != end; ++itr ) {" << std::endl;
1344 source << " if( ! re.Match( fPrefix + itr->first ) ) continue;"
1345 << std::endl;
1346 source << " if( active ) {" << std::endl;
1347 source << " if( itr->second->IsAvailable() ) "
1348 << "itr->second->SetActive( active );" << std::endl;
1349 source << " } else {" << std::endl;
1350 source << " itr->second->SetActive( active );" << std::endl;
1351 source << " }" << std::endl;
1352 source << " }" << std::endl << std::endl;
1353 source << " return;" << std::endl;
1354 source << " }" << std::endl << std::endl;
1355
1356 //
1357 // Produce the ReadAllActive(...) function:
1358 //
1359 source << " /**" << std::endl;
1360 source << " * This function can be used to read in all the branches"
1361 << " from the input" << std::endl;
1362 source << " * TTree which are set active for writing out. This can "
1363 << "simplify writing" << std::endl;
1364 source << " * event selector codes immensely. Remember to set the "
1365 << "desired variable" << std::endl;
1366 source << " * active before calling this function." << std::endl;
1367 source << " */" << std::endl;
1368 source << " void " << classname << "::ReadAllActive() {" << std::endl
1369 << std::endl;
1370 source << " // Check if it makes sense to call this function:"
1371 << std::endl;
1372 source << " if( ! fFromInput ) {" << std::endl;
1373 source << " static ::Bool_t wPrinted = kFALSE;" << std::endl;
1374 source << " if( ! wPrinted ) {" << std::endl;
1375 source << " Warning( \"ReadAllActive\", "
1376 << "\"Function only meaningful when used on objects\" );"
1377 << std::endl;
1378 source << " Warning( \"ReadAllActive\", "
1379 << "\"which are used to read information from a D3PD\" );"
1380 << std::endl;
1381 source << " wPrinted = kTRUE;" << std::endl;
1382 source << " }" << std::endl;
1383 source << " }" << std::endl << std::endl;
1384 source << " // Call the base class's function:" << std::endl;
1385 source << " UserD3PDObject::ReadAllActive();" << std::endl
1386 << std::endl;
1387 source << " // Read in the current entry for each active "
1388 << "variable:" << std::endl;
1389 source << " std::map< TString, VarHandleBase* >::const_iterator "
1390 << "itr = fHandles.begin();" << std::endl;
1391 source << " std::map< TString, VarHandleBase* >::const_iterator "
1392 << "end = fHandles.end();" << std::endl;
1393 source << " for( ; itr != end; ++itr ) {" << std::endl;
1394 source << " if( ! itr->second->IsActive() ) continue;"
1395 << std::endl;
1396 source << " itr->second->ReadCurrentEntry();" << std::endl;
1397 source << " }" << std::endl << std::endl;
1398 source << " return;" << std::endl;
1399 source << " }" << std::endl << std::endl;
1400
1401 //
1402 // Produce the GetStatistics() function:
1403 //
1404 source << " /**" << std::endl;
1405 source << " * This function can be used to get information about "
1406 << "the access" << std::endl;
1407 source << " * pattern/statistics of the job. It should be called "
1408 << "at the end of" << std::endl;
1409 source << " * an analysis job to get the information about the "
1410 << "performance of the" << std::endl;
1411 source << " * analysis." << std::endl;
1412 source << " *" << std::endl;
1413 source << " * @returns An object describing the D3PD access "
1414 << "statistics" << std::endl;
1415 source << " */" << std::endl;
1416 source << " D3PDReadStats " << classname
1417 << "::GetStatistics() const {" << std::endl << std::endl;
1418 source << " // The result object:" << std::endl;
1419 source << " D3PDReadStats result = "
1420 << "UserD3PDObject::GetStatistics();" << std::endl << std::endl;
1421 source << " // Add the statistics from each variable to the "
1422 << "result:" << std::endl;
1423 source << " std::map< ::TString, VarHandleBase* >::const_iterator"
1424 << " itr = fHandles.begin();" << std::endl;
1425 source << " std::map< ::TString, VarHandleBase* >::const_iterator"
1426 << " end = fHandles.end();" << std::endl;
1427 source << " for( ; itr != end; ++itr ) {" << std::endl;
1428 source << " result.AddVariable( itr->second->GetStatistics() );"
1429 << std::endl;
1430 source << " }" << std::endl << std::endl;
1431 source << " return result;" << std::endl;
1432 source << " }" << std::endl << std::endl;
1433
1434 //
1435 // Produce the Set function:
1436 //
1437 source << " /**" << std::endl;
1438 source << " * This function can be used to copy the contents of the"
1439 << " entire object" << std::endl;
1440 source << " * for a given event. This can be useful for instance "
1441 << "when the user" << std::endl;
1442 source << " * wants to copy all information to an output file, and "
1443 << "modify it a bit," << std::endl;
1444 source << " * and only then write it out." << std::endl;
1445 source << " *" << std::endl;
1446 source << " * @param parent The object to copy the information from"
1447 << std::endl;
1448 source << " * @returns This same object, for convenience reasons"
1449 << std::endl;
1450 source << " */" << std::endl;
1451 source << " " << classname << "& " << classname << "::Set( const "
1452 << classname << "& parent ) {" << std::endl << std::endl;
1453 source << " // Check if this function can be used on the object:"
1454 << std::endl;
1455 source << " if( fFromInput ) {" << std::endl;
1456 source << " Error( \"Set\", "
1457 << "\"Objects used for reading a D3PD can't be modified!\" );"
1458 << std::endl;
1459 source << " return *this;" << std::endl;
1460 source << " }" << std::endl << std::endl;
1461 source << " // Call the base class's function:" << std::endl;
1462 source << " UserD3PDObject::Set( parent );" << std::endl
1463 << std::endl;
1464 std::map< std::string, int > variableCounter;
1465 std::set< ObjectMetadata::Variable >::const_iterator itr =
1466 metadata.variables().begin();
1467 std::set< ObjectMetadata::Variable >::const_iterator end =
1468 metadata.variables().end();
1469 for( ; itr != end; ++itr ) {
1470 std::string postfix = "";
1471 if( variableCounter.find( itr->name() ) == variableCounter.end() ) {
1472 variableCounter[ itr->name() ] = 1;
1473 } else {
1474 postfix =
1475 std::to_string( variableCounter[ itr->name() ] );
1476 variableCounter[ itr->name() ]++;
1477 }
1478 source << " if( parent." << variableName( itr->name() )
1479 << postfix << ".IsAvailable() && "
1480 << variableName( itr->name() ) << postfix
1481 << ".IsActive() ) {" << std::endl;
1482 if( itr->primitive() ) {
1483 source << " " << variableName( itr->name() ) << postfix
1484 << "() = parent." << variableName( itr->name() )
1485 << postfix << "();" << std::endl;
1486 } else {
1487 source << " *( " << variableName( itr->name() )
1488 << postfix << "() ) = *( parent."
1489 << variableName( itr->name() ) << postfix
1490 << "() );" << std::endl;
1491 }
1492 source << " } else {" << std::endl;
1493 if( itr->primitive() ) {
1494 source << " " << variableName( itr->name() )
1495 << postfix << "() = 0;" << std::endl;
1496 } else {
1497 source << " " << variableName( itr->name() )
1498 << postfix << "()->clear();" << std::endl;
1499 }
1500 source << " }" << std::endl;
1501 }
1502 source << std::endl << " return *this;" << std::endl;
1503 source << " }" << std::endl << std::endl;
1504
1505 if( metadata.container() ) {
1506 //
1507 // Produce the Clear function:
1508 //
1509 source << " /**" << std::endl;
1510 source << " * This function makes it easier to clear out the "
1511 << "object completely." << std::endl;
1512 source << " * It cleares all the vector variables, and sets the "
1513 << "element number" << std::endl;
1514 source << " * variable to 0. Very useful when performing object "
1515 << "selection." << std::endl;
1516 source << " * The option argument is not used at the moment for "
1517 << "anything." << std::endl;
1518 source << " * It's only there because the <code>Clear</code> "
1519 << "function defined in" << std::endl;
1520 source << " * TObject has this parameter as well." << std::endl;
1521 source << " *" << std::endl;
1522 source << " * @param option Ignored at the moment" << std::endl;
1523 source << " */" << std::endl;
1524 source << " void " << classname << "::Clear( Option_t* opt ) {"
1525 << std::endl << std::endl;
1526 source << " // Check if this function can be used on the "
1527 << "object:" << std::endl;
1528 source << " if( fFromInput ) {" << std::endl;
1529 source << " Error( \"Clear\", "
1530 << "\"Objects used for reading a D3PD can't be cleared!\" );"
1531 << std::endl;
1532 source << " return;" << std::endl;
1533 source << " }" << std::endl << std::endl;
1534 source << " // Call the base class's function:" << std::endl;
1535 source << " UserD3PDObject::Clear( opt );" << std::endl
1536 << std::endl;
1537 source << " // Clear each variable:" << std::endl;
1538 source << " std::map< ::TString, VarHandleBase* >::const_iterator"
1539 << " itr = fHandles.begin();" << std::endl;
1540 source << " std::map< ::TString, VarHandleBase* >::const_iterator"
1541 << " end = fHandles.end();" << std::endl;
1542 source << " for( ; itr != end; ++itr ) {" << std::endl;
1543 source << " itr->second->Clear();" << std::endl;
1544 source << " }" << std::endl << std::endl;
1545 source << " return;" << std::endl;
1546 source << " }" << std::endl << std::endl;
1547
1548 //
1549 // Produce the Add function:
1550 //
1551 source << " /**" << std::endl;
1552 source << " * This function can be used to easily add an "
1553 << "'element' describing one" << std::endl;
1554 source << " * object to an output collection. Comes in very "
1555 << "handy when performing" << std::endl;
1556 source << " * object selection." << std::endl;
1557 source << " *" << std::endl;
1558 source << " * Note that variables which are not available from "
1559 << "the input, will be" << std::endl;
1560 source << " * filled with dummy values." << std::endl;
1561 source << " *" << std::endl;
1562 source << " * @param el The 'element' that should be added to "
1563 << "the collection" << std::endl;
1564 source << " */" << std::endl;
1565 source << " " << classname << "& " << classname << "::Add( const "
1566 << classname << "Element& el ) {" << std::endl << std::endl;
1567 source << " // Check if this function can be used on the "
1568 << "object:" << std::endl;
1569 source << " if( fFromInput ) {" << std::endl;
1570 source << " Error( \"Add\", \"Objects used for reading a "
1571 << "D3PD can't be modified!\" );" << std::endl;
1572 source << " return *this;" << std::endl;
1573 source << " }" << std::endl << std::endl;
1574 source << " // Call the base class's function:" << std::endl;
1575 source << " UserD3PDObject::Add( el );" << std::endl
1576 << std::endl;
1577 variableCounter.clear();
1578 itr = metadata.variables().begin();
1579 end = metadata.variables().end();
1580 for( ; itr != end; ++itr ) {
1581 // Treat the size variable in a special way:
1582 if( itr->name() == "n" ) {
1583 source << " ++( n() );" << std::endl;
1584 continue;
1585 }
1586 if( itr->name() == "N" ) {
1587 source << " ++( N() );" << std::endl;
1588 continue;
1589 }
1590
1591 // Construct a possible post-fix for the variable name:
1592 std::string postfix = "";
1593 if( variableCounter.find( itr->name() ) ==
1594 variableCounter.end() ) {
1595 variableCounter[ itr->name() ] = 1;
1596 } else {
1597 postfix =
1598 std::to_string( variableCounter[ itr->name() ] );
1599 variableCounter[ itr->name() ]++;
1600 }
1601
1602 source << " if( el." << variableName( itr->name() )
1603 << postfix << ".IsAvailable() && "
1604 << variableName( itr->name() ) << postfix
1605 << ".IsActive() ) {" << std::endl;
1606 source << " " << variableName( itr->name() ) << postfix
1607 << "()->push_back( el." << variableName( itr->name() )
1608 << postfix << "() );" << std::endl;
1609 source << " } else {" << std::endl;
1610
1611 // Extract the type of the variable we're dealing with:
1612 bool ok = true;
1613 const std::string type =
1614 vectorTemplateArgument( itr->type(), ok );
1615 if( ! ok ) {
1616 REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR,
1617 "Version2::writeSource" )
1618 << "Unexpected variable type encountered for "
1619 << "container dumper: " << itr->type();
1620 return StatusCode::FAILURE;
1621 }
1622
1623 // Primitive and complex types have to be treated differently if
1624 // they don't exist in the input:
1625 source << " " << variableName( itr->name() )
1626 << postfix << "()->push_back( ";
1627 if( isPrimitive( type ) ) {
1628 source << "std::numeric_limits< " << type << " >::min()";
1629 } else {
1630 source << type << "()";
1631 }
1632 source << " );" << std::endl;
1633 source << " }" << std::endl;
1634 }
1635 source << " return *this;" << std::endl;
1636 source << " }" << std::endl << std::endl;
1637
1638 //
1639 // Try to find the size variable's name:
1640 //
1641 static const int NSIZEVARS = 2;
1642 static const char* const SIZEVARS[ NSIZEVARS ] = { "n", "N" };
1643 std::string sizeVariable = "";
1645 for( int i = 0; i < NSIZEVARS; ++i ) {
1646 var.setName( SIZEVARS[ i ] );
1647 if( metadata.variables().find( var ) !=
1648 metadata.variables().end() ) {
1649 sizeVariable = var.name() + "()";
1650 break;
1651 }
1652 }
1653
1654 //
1655 // Produce the [] operators:
1656 //
1657 source << " /**" << std::endl;
1658 source << " * This operator can be used to get access to one "
1659 << "element in the" << std::endl;
1660 source << " * collection. This element can then be passed around"
1661 << " between parts" << std::endl;
1662 source << " * of the analysis code easily." << std::endl;
1663 source << " *" << std::endl;
1664 source << " * This version is useful when modifying the variable"
1665 << " contents through" << std::endl;
1666 source << " * the proxy objects." << std::endl;
1667 source << " *" << std::endl;
1668 source << " * @param index Index of the element inside the "
1669 << "collection" << std::endl;
1670 source << " */" << std::endl;
1671 source << " " << classname << "Element& " << classname
1672 << "::operator[]( size_t index ) {" << std::endl
1673 << std::endl;
1674 source << " // Check whether the index makes sense:"
1675 << std::endl;
1676 source << " if( index >= static_cast< size_t >( "
1677 << ( sizeVariable == "" ? "1000000" : sizeVariable )
1678 << " ) ) {" << std::endl;
1679 source << " Fatal( \"operator[]\", \"Proxy with index %i"
1680 << " requested\", static_cast< int >( index ) );"
1681 << std::endl;
1682 source << " // The previous should've stopped the code "
1683 << "already," << std::endl;
1684 source << " // but let's go for sure..." << std::endl;
1685 source << " throw std::runtime_error( \"Too large proxy "
1686 << "index\" );" << std::endl;
1687 source << " }" << std::endl << std::endl;
1688 source << " // Make sure that the proxy exists:" << std::endl;
1689 source << " while( fProxies.size() <= index ) {" << std::endl;
1690 source << " fProxies.push_back( new " << classname
1691 << "Element( fProxies.size(), *this ) );" << std::endl;
1692 source << " }" << std::endl;
1693 source << " return *fProxies[ index ];" << std::endl;
1694 source << " }" << std::endl << std::endl;
1695
1696 source << " /**" << std::endl;
1697 source << " * This operator can be used to get access to one "
1698 << "element in the" << std::endl;
1699 source << " * collection. This element can then be passed around"
1700 << " between parts" << std::endl;
1701 source << " * of the analysis code easily." << std::endl;
1702 source << " *" << std::endl;
1703 source << " * This version is useful when only reading the "
1704 << "variables." << std::endl;
1705 source << " *" << std::endl;
1706 source << " * @param index Index of the element inside the "
1707 << "collection" << std::endl;
1708 source << " */" << std::endl;
1709 source << " const " << classname << "Element& " << classname
1710 << "::operator[]( size_t index ) const {" << std::endl
1711 << std::endl;
1712 source << " // Check whether the index makes sense:"
1713 << std::endl;
1714 source << " if( index >= static_cast< size_t >( "
1715 << ( sizeVariable == "" ? "1000000" : sizeVariable )
1716 << " ) ) {" << std::endl;
1717 source << " Fatal( \"operator[]\", \"Proxy with index %i"
1718 << " requested\", static_cast< int >( index ) );"
1719 << std::endl;
1720 source << " // The previous should've stopped the code "
1721 << "already," << std::endl;
1722 source << " // but let's go for sure..." << std::endl;
1723 source << " throw std::runtime_error( \"Too large proxy "
1724 << "index\" );" << std::endl;
1725 source << " }" << std::endl << std::endl;
1726 source << " // Make sure that the proxy exists:" << std::endl;
1727 source << " while( fProxies.size() <= index ) {" << std::endl;
1728 source << " fProxies.push_back( new " << classname
1729 << "Element( fProxies.size(), *this ) );" << std::endl;
1730 source << " }" << std::endl;
1731 source << " return *fProxies[ index ];" << std::endl;
1732 source << " }" << std::endl << std::endl;
1733
1734 //
1735 // Produce the += operator:
1736 //
1737 source << " /**" << std::endl;
1738 source << " * A convenience operator for adding an 'element' to "
1739 << "this collection." << std::endl;
1740 source << " *" << std::endl;
1741 source << " * @see Add" << std::endl;
1742 source << " * @param el The 'element' that should be added to "
1743 << "the collection" << std::endl;
1744 source << " */" << std::endl;
1745 source << " " << classname << "& " << classname
1746 << "::operator+=( const " << classname << "Element& el ) {"
1747 << std::endl << std::endl;
1748 source << " return this->Add( el );" << std::endl;
1749 source << " }" << std::endl << std::endl;
1750 }
1751
1752 //
1753 // Produce the GetVarHandle(...) function:
1754 //
1755 source << " /**" << std::endl;
1756 source << " * This function is used internally to access VarHandle "
1757 << "members" << std::endl;
1758 source << " * by name. This is necessary to push some setup from "
1759 << "compile time" << std::endl;
1760 source << " * to run time. It may sound weird, but it makes a lot "
1761 << "of sense for large" << std::endl;
1762 source << " * classes." << std::endl;
1763 source << " *" << std::endl;
1764 source << " * @param name The name of the C++ variable (not of the "
1765 << "branch)" << std::endl;
1766 source << " * @returns A pointer to the VarHandle object"
1767 << std::endl;
1768 source << " */" << std::endl;
1769 source << " VarHandleBase* " << classname
1770 << "::GetVarHandle( const char* name ) {" << std::endl
1771 << std::endl;
1772 variableCounter.clear();
1773 itr = metadata.variables().begin();
1774 end = metadata.variables().end();
1775 for( ; itr != end; ++itr ) {
1776 // Construct a possible post-fix for the variable name:
1777 std::string postfix = "";
1778 if( variableCounter.find( itr->name() ) ==
1779 variableCounter.end() ) {
1780 variableCounter[ itr->name() ] = 1;
1781 } else {
1782 postfix =
1783 std::to_string( variableCounter[ itr->name() ] );
1784 variableCounter[ itr->name() ]++;
1785 }
1786 if( itr == metadata.variables().begin() ) {
1787 source << " if( ! ::strcmp( name, \""
1788 << variableName( itr->name() ) << postfix << "\" ) ) {"
1789 << std::endl;
1790 } else {
1791 source << " else if( ! ::strcmp( name, \""
1792 << variableName( itr->name() ) << postfix << "\" ) ) {"
1793 << std::endl;
1794 }
1795 source << " return &" << variableName( itr->name() )
1796 << postfix << ";" << std::endl;
1797 source << " }" << std::endl;
1798 }
1799 source << std::endl << " Error( \"GetVarHandle\", \"Variable \\\"%s"
1800 << "\\\" unknown\", name );" << std::endl;
1801 source << " return 0;" << std::endl;
1802 source << " }" << std::endl << std::endl;
1803
1804 //
1805 // Produce the SetVarHandles(...) function:
1806 //
1807 source << " /**" << std::endl;
1808 source << " * This function is used internally to set up all the "
1809 << "VarHandle members" << std::endl;
1810 source << " * of the class. It speeds up compilation *a lot* to do "
1811 << "this at run-time" << std::endl;
1812 source << " * like this, instead of putting a lot of lines of code "
1813 << "operating on" << std::endl;
1814 source << " * the std::map member." << std::endl;
1815 source << " *" << std::endl;
1816 source << " * @param master Pointer to the master index, or a null "
1817 << "pointer" << std::endl;
1818 source << " */" << std::endl;
1819 source << " void " << classname << "::SetVarHandles( const "
1820 << "::Long64_t* master ) {" << std::endl << std::endl;
1821 source << " // Create a list of variable-branch name pairs:"
1822 << std::endl;
1823 source << " static const Int_t NVARNAMES = "
1824 << metadata.variables().size() << ";" << std::endl;
1825 source << " static const char* VARNAMES[ NVARNAMES ][ 2 ] = {"
1826 << std::endl;
1827 variableCounter.clear();
1828 itr = metadata.variables().begin();
1829 end = metadata.variables().end();
1830 for( ; itr != end; ++itr ) {
1831 // Construct a possible post-fix for the variable name:
1832 std::string postfix = "";
1833 if( variableCounter.find( itr->name() ) ==
1834 variableCounter.end() ) {
1835 variableCounter[ itr->name() ] = 1;
1836 } else {
1837 postfix =
1838 std::to_string( variableCounter[ itr->name() ] );
1839 variableCounter[ itr->name() ]++;
1840 }
1841 // Add the names:
1842 source << " { \"" << variableName( itr->name() ) << postfix
1843 << "\", \"" << variableName( itr->name() ) << "\" }";
1844 if( ++itr != end ) {
1845 source << ",";
1846 }
1847 --itr;
1848 source << std::endl;
1849 }
1850 source << " };" << std::endl << std::endl;
1851 source << " // Set up the fHandles map using this list:"
1852 << std::endl;
1853 source << " for( Int_t i = 0; i < NVARNAMES; ++i ) {"
1854 << std::endl;
1855 source << " VarHandleBase* vh = "
1856 << "GetVarHandle( VARNAMES[ i ][ 0 ] );" << std::endl;
1857 source << " vh->SetName( fPrefix + VARNAMES[ i ][ 1 ] );"
1858 << std::endl;
1859 source << " vh->SetMaster( master );" << std::endl;
1860 source << " fHandles[ VARNAMES[ i ][ 0 ] ] = vh;" << std::endl;
1861 source << " }" << std::endl << std::endl;
1862
1863 /*
1864 source << " // Access the class's dictionary:" << std::endl;
1865 source << " ::TClass* cl = IsA();" << std::endl;
1866 source << " // Get a list of all members:" << std::endl;
1867 source << " ::TList* members = cl->GetListOfDataMembers();"
1868 << std::endl;
1869 source << " // Set up all the VarHandle members:" << std::endl;
1870 source << " for( ::Int_t i = 0; i < members->GetSize(); ++i ) {"
1871 << std::endl;
1872 source << " // Check that it's a VarHandle:" << std::endl;
1873 source << " ::TDataMember* m = dynamic_cast< ::TDataMember* >("
1874 << " members->At( i ) );" << std::endl;
1875 source << " if( ! m ) {" << std::endl;
1876 source << " Fatal( \"SetVarHandles\", \"Found a wrong "
1877 << "data member\" );" << std::endl;
1878 source << " continue;" << std::endl;
1879 source << " }" << std::endl;
1880 source << " const ::TString type = m->GetTypeName();"
1881 << std::endl;
1882 source << " if( ! type.BeginsWith( \"D3PDReader::VarHandle<\" "
1883 << ") ) {" << std::endl;
1884 source << " continue;" << std::endl;
1885 source << " }" << std::endl;
1886 source << " // If it is, let's set it up:" << std::endl;
1887 source << " VarHandleBase* vh = GetVarHandle( m->GetName() );"
1888 << std::endl;
1889 source << " fHandles[ m->GetName() ] = vh;" << std::endl;
1890 source << " }" << std::endl << std::endl;
1891 source << " // Now configure all variables in a second loop:"
1892 << std::endl;
1893 source << " std::map< TString, VarHandleBase* >::const_iterator "
1894 << "itr = fHandles.begin();" << std::endl;
1895 source << " std::map< TString, VarHandleBase* >::const_iterator "
1896 << "end = fHandles.end();" << std::endl;
1897 source << " for( ; itr != end; ++itr ) {" << std::endl;
1898 source << " itr->second->SetName( fPrefix + itr->first );"
1899 << std::endl;
1900 source << " itr->second->SetMaster( master );" << std::endl;
1901 source << " }" << std::endl << std::endl;
1902 */
1903 source << " return;" << std::endl;
1904 source << " }" << std::endl << std::endl;
1905
1906 source << "} // namespace D3PDReader" << std::endl;
1907
1908 source.close();
1909
1910 return StatusCode::SUCCESS;
1911 }
1912
1913 StatusCode writeEventHeader( const std::string& classname, const std::string& dir,
1914 const std::set< ObjectMetadata >& metadata ) {
1915
1916 // Construct the file name:
1917 const std::string fileName = dir + "/" + classname + ".h";
1918
1919 // If the file already exists, let's not overwrite it:
1920 struct stat fileInfo;
1921 if( ! stat( fileName.c_str(), &fileInfo ) ) return StatusCode::SUCCESS;
1922
1923 // Let everyone know what we're doing:
1924 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeEventHeader" )
1925 << "Generating file: " << fileName;
1926
1927 // Open the header file (overwriting a possibly existing file):
1928 std::ofstream header( fileName.c_str() );
1929
1930 // Write a header for the file:
1931 header << CODE_COMMENT << std::endl;
1932 header << "#ifndef D3PDREADER_" << classname << "_H" << std::endl;
1933 header << "#define D3PDREADER_" << classname << "_H" << std::endl << std::endl;
1934
1935 //
1936 // Construct the includes:
1937 //
1938 header << "// Local include(s):" << std::endl;
1939 header << "#include \"D3PDObjectBase.h\"" << std::endl;
1940 std::set< std::string > d3pd_reader_names;
1941 std::set< ObjectMetadata >::const_iterator meta_itr = metadata.begin();
1942 std::set< ObjectMetadata >::const_iterator meta_end = metadata.end();
1943 for( ; meta_itr != meta_end; ++meta_itr ) {
1944 // Check if we already included this class:
1945 std::pair< std::set< std::string >::iterator, bool > ret =
1946 d3pd_reader_names.insert( meta_itr->name() );
1947 if( ! ret.second ) continue;
1948 // If not, then:
1949 header << "#include \"" << meta_itr->name() << ".h\"" << std::endl;
1950 }
1951 header << std::endl;
1952
1953 header << "namespace D3PDReader {" << std::endl << std::endl;
1954
1955 //
1956 // Declare the event class:
1957 //
1958 header << " /**" << std::endl;
1959 header << " * Code generated by CodeGenerator_v2 on:" << std::endl;
1960 header << " * host = " << System::hostName() << std::endl;
1961 header << " * OS = " << System::osName() << " / " << System::osVersion()
1962 << std::endl;
1963 header << " * user = " << System::accountName() << std::endl;
1964 time_t rawtime = time( NULL );
1965 char buf[26];
1966 header << " * time = " << ctime_r( &rawtime, buf );
1967 header << " */" << std::endl;
1968 header << " class " << classname << " : public D3PDObjectBase {" << std::endl
1969 << std::endl;
1970 header << " public:" << std::endl;
1971
1972 //
1973 // Declare the constructors:
1974 //
1975 header << " /// Default constructor, to be used when reading a D3PD" << std::endl;
1976 header << " " << classname << "();" << std::endl;
1977 header << " /// Constructor for only writing data" << std::endl;
1978 header << " " << classname << "( Bool_t onlyForWriting );" << std::endl
1979 << std::endl;
1980
1981 //
1982 // Declare some functions:
1983 //
1984 header << " /// Get the currently configured prefix value" << std::endl;
1985 header << " virtual const char* GetPrefix() const;" << std::endl;
1986 header << " /// Set the prefix for the variables" << std::endl;
1987 header << " virtual void SetPrefix( const char* prefix );" << std::endl
1988 << std::endl;
1989
1990 header << " /// Connect the object to an input TTree" << std::endl;
1991 header << " virtual void ReadFrom( ::TTree* tree );" << std::endl;
1992 header << " /// Connect the object to an output TTree" << std::endl;
1993 header << " virtual void WriteTo( ::TTree* tree );" << std::endl << std::endl;
1994
1995 header << " /// Turn (selected) branches either on or off" << std::endl;
1996 header << " virtual void SetActive( ::Bool_t active = kTRUE," << std::endl;
1997 header << " const ::TString& pattern = \".*\" );"
1998 << std::endl;
1999 header << " /// Read in all the variables that we need to write out as well"
2000 << std::endl;
2001 header << " virtual void ReadAllActive();" << std::endl << std::endl;
2002 header << " /// Get the D3PD reading statistics" << std::endl;
2003 header << " virtual D3PDReadStats GetStatistics() const;" << std::endl
2004 << std::endl;
2005
2006 header << " /// Switch the reader object to a new event" << std::endl;
2007 header << " void GetEntry( ::Long64_t entry );" << std::endl << std::endl;
2008
2009 //
2010 // Declare each object:
2011 //
2012 header << " //" << std::endl;
2013 header << " // All the components of the D3PD:" << std::endl;
2014 header << " //" << std::endl;
2015 FOR_ALL_EVENT_VARIABLES( header << " " << meta_itr->name() << " " << varname
2016 << ";" << std::endl );
2017
2018 // Declare the additional member variable(s):
2019 header << std::endl << " private:" << std::endl;
2020 header << " Long64_t fEntry; ///< Variable storing the current entry number"
2021 << std::endl;
2022 header << " Bool_t fFromInput; "
2023 << "///< Flag specifying if object is used for D3PD reading"
2024 << std::endl << std::endl;
2025
2026 // Close the class definition:
2027 header << " ClassDef( " << classname << ", 0 )" << std::endl << std::endl;
2028 header << " }; // class " << classname << std::endl << std::endl;
2029 header << "} // namespace D3PDReader" << std::endl << std::endl;
2030 header << "#endif // D3PDREADER_" << classname << "_H" << std::endl;
2031
2032 header.close();
2033
2034 return StatusCode::SUCCESS;
2035 }
2036
2037 StatusCode writeEventSource( const std::string& classname, const std::string& dir,
2038 const std::set< ObjectMetadata >& metadata ) {
2039
2040 // Construct the file name:
2041 const std::string fileName = dir + "/" + classname + ".cxx";
2042
2043 // If the file already exists, let's not overwrite it:
2044 struct stat fileInfo;
2045 if( ! stat( fileName.c_str(), &fileInfo ) ) return StatusCode::SUCCESS;
2046
2047 // Let everyone know what we're doing:
2048 REPORT_MESSAGE_WITH_CONTEXT( MSG::INFO, "Version2::writeSource" )
2049 << "Generating file: " << fileName;
2050
2051 // Open the header file (overwriting a possibly existing file):
2052 std::ofstream source( fileName.c_str() );
2053
2054 // Add the common header to the file:
2055 source << CODE_COMMENT << std::endl << std::endl;
2056
2057 // Include the class's header:
2058 source << "#include \"" << classname << ".h\"" << std::endl;
2059 source << "#include \"D3PDPerfStats.h\"" << std::endl << std::endl;
2060
2061 source << "ClassImp( D3PDReader::" << classname << " )" << std::endl << std::endl;
2062
2063 source << "namespace D3PDReader {" << std::endl << std::endl;
2064
2065 //
2066 // Produce the (input) constructor:
2067 //
2068 source << " " << classname << "::" << classname << "()" << std::endl
2069 << " : D3PDObjectBase()," << std::endl;
2070 FOR_ALL_EVENT_VARIABLES( source << " " << varname << "( fEntry, \""
2071 << meta_itr->prefix() << "\" )," << std::endl );
2072 source << " fEntry( 0 )," << std::endl;
2073 source << " fFromInput( kTRUE ) {" << std::endl << std::endl;
2074 source << " }" << std::endl << std::endl;
2075
2076 //
2077 // Produce the (output) constructor:
2078 //
2079 source << " " << classname << "::" << classname << "( Bool_t )" << std::endl
2080 << " : D3PDObjectBase()," << std::endl;
2081 FOR_ALL_EVENT_VARIABLES( source << " " << varname << "( \""
2082 << meta_itr->prefix() << "\" )," << std::endl );
2083 source << " fEntry( 0 )," << std::endl;
2084 source << " fFromInput( kFALSE ) {" << std::endl << std::endl;
2085 source << " }" << std::endl << std::endl;
2086
2087 //
2088 // Produce the prefix handling functions:
2089 //
2090 source << " const char* " << classname << "::GetPrefix() const {" << std::endl
2091 << std::endl;
2092 source << " Warning( \"GetPrefix\", \"A prefix is not defined for this object\" );"
2093 << std::endl;
2094 source << " return \"\";" << std::endl;
2095 source << " }" << std::endl << std::endl;
2096
2097 source << " void " << classname << "::SetPrefix( const char* ) {" << std::endl
2098 << std::endl;
2099 source << " Warning( \"SetPrefix\", \"A prefix is not defined for this object\" );"
2100 << std::endl;
2101 source << " return;" << std::endl;
2102 source << " }" << std::endl << std::endl;
2103
2104 //
2105 // Produce the ReadFrom(...) function:
2106 //
2107 source << " void " << classname << "::ReadFrom( ::TTree* tree ) {" << std::endl
2108 << std::endl;
2109 source << " if( ! fFromInput ) {" << std::endl;
2110 source << " Error( \"ReadFrom\", \"Object can't read a D3PD. Use a different "
2111 << "constructor!\" );" << std::endl;
2112 source << " return;" << std::endl;
2113 source << " }" << std::endl << std::endl;
2114 FOR_ALL_EVENT_VARIABLES( source << " " << varname << ".ReadFrom( tree );"
2115 << std::endl );
2116 source << std::endl << " return;" << std::endl;
2117 source << " }" << std::endl << std::endl;
2118
2119 //
2120 // Produce the WriteTo(...) function:
2121 //
2122 source << " void " << classname << "::WriteTo( ::TTree* tree ) {" << std::endl
2123 << std::endl;
2124 FOR_ALL_EVENT_VARIABLES( source << " " << varname << ".WriteTo( tree );"
2125 << std::endl );
2126 source << std::endl << " return;" << std::endl;
2127 source << " }" << std::endl << std::endl;
2128
2129 //
2130 // Produce the SetActive(...) function:
2131 //
2132 source << " void " << classname << "::SetActive( ::Bool_t active, "
2133 << "const ::TString& pattern ) {" << std::endl << std::endl;
2134 FOR_ALL_EVENT_VARIABLES( source << " " << varname << ".SetActive( "
2135 << "active, pattern );" << std::endl );
2136 source << std::endl << " return;" << std::endl;
2137 source << " }" << std::endl << std::endl;
2138
2139 //
2140 // Produce the ReadAllActive() function:
2141 //
2142 source << " void " << classname << "::ReadAllActive() {" << std::endl
2143 << std::endl;
2144 FOR_ALL_EVENT_VARIABLES( source << " " << varname << ".ReadAllActive();"
2145 << std::endl );
2146 source << std::endl << " return;" << std::endl;
2147 source << " }" << std::endl << std::endl;
2148
2149 //
2150 // Produce the GetStatistics() function:
2151 //
2152 source << " D3PDReadStats " << classname << "::GetStatistics() const {"
2153 << std::endl << std::endl;
2154 source << " // The result object:" << std::endl;
2155 source << " D3PDReadStats result( D3PDPerfStats::Instance()->GetStats() );"
2156 << std::endl << std::endl;
2157 source << " // Collect the statistics from all constituents:" << std::endl;
2158 FOR_ALL_EVENT_VARIABLES( source << " result += " << varname
2159 << ".GetStatistics();" << std::endl );
2160 source << std::endl << " return result;" << std::endl;
2161 source << " }" << std::endl << std::endl;
2162
2163 //
2164 // Produce the GetEntry(...) function:
2165 //
2166 source << " void " << classname << "::GetEntry( ::Long64_t entry ) {" << std::endl
2167 << std::endl;
2168 source << " fEntry = entry;" << std::endl;
2169 source << " return;" << std::endl;
2170 source << " }" << std::endl << std::endl;
2171
2172 source << "} // namespace D3PDReader" << std::endl;
2173 source.close();
2174
2175 return StatusCode::SUCCESS;
2176 }
2177
2178 } // namespace Version2
2179
2180} // namespace D3PD
#define FOR_ALL_EVENT_VARIABLES(EXP)
A convenience macro used in the event class generation.
static const char *const CODE_COMMENT
A little header for all the generated source files.
static const char *const D3PDPERFSTATS_HEADER_NAME
static const char *const USERD3PDOBJECT_CXX_NAME
static const char *const UTILS_HEADER
static const char *const D3PDPERFSTATS_HEADER
static const char *const UTILS_CXX_NAME
static const char *const VARHANDLE_IMPL_NAME
static const char *const D3PDOBJECTBASE_HEADER
static const char *const D3PDREADSTATS_HEADER_NAME
static const char *const D3PDOBJECTBASE_HEADER_NAME
static const char *const VARHANDLE_IMPL
static const char *const VARHANDLE_HEADER
static const char *const D3PDREADSTATS_CXX
static const char *const VARPROXY_IMPL
static const char *const UTILS_HEADER_NAME
static const char *const VARPROXY_IMPL_NAME
static const char *const D3PDPERFSTATS_CXX
static const char *const VARPROXY_HEADER_NAME
static const char *const D3PDREADSTATS_CXX_NAME
static const char *const UTILS_CXX
static const char *const USERD3PDOBJECT_IMPL
static const char *const VARPROXY_HEADER
static const char *const VARHANDLE_CXX
static const char *const USERD3PDOBJECT_HEADER_NAME
static const char *const D3PDPERFSTATS_CXX_NAME
static const char *const USERD3PDOBJECT_IMPL_NAME
static const char *const D3PDREADSTATS_HEADER
static const char *const VARHANDLE_HEADER_NAME
static const char *const USERD3PDOBJECT_HEADER
static const char *const VARHANDLE_CXX_NAME
static const char *const USERD3PDOBJECT_CXX
Helpers for checking error return status codes and reporting errors.
#define REPORT_MESSAGE_WITH_CONTEXT(LVL, CONTEXT_NAME)
Report a message, with an explicitly specified context name.
Internal class keeping track of a single variable.
D3PD variable metadata handling class.
Private namespace for version 2 of the code generator code.
StatusCode writeUtils(const std::string &dir)
This function can be used to create source files containing some utility functions.
StatusCode writeHeader(const std::string &classname, const std::string &dir, const ObjectMetadata &metadata)
This function is used to create the header of the class describing a set of D3PD variables.
StatusCode writeEventSource(const std::string &classname, const std::string &dir, const std::set< ObjectMetadata > &metadata)
Write the source of the main event class describing a D3PD tree.
StatusCode writeD3PDReadStats(const std::string &dir)
This function can be used to create the D3PDReader::D3PDReadStats class's source files.
StatusCode writeSource(const std::string &classname, const std::string &dir, const ObjectMetadata &metadata)
This function is used to generate the source file of a D3PDReader class.
StatusCode writeVarHandle(const std::string &dir)
This function can be used to create the D3PDReader::VarHandle class's source files.
StatusCode writeVarProxy(const std::string &dir)
This function can be used to create the D3PDReader::VarProxy class's source files.
StatusCode writeEventHeader(const std::string &classname, const std::string &dir, const std::set< ObjectMetadata > &metadata)
Write the header of the main event class describing a D3PD tree.
StatusCode writeD3PDObjectBase(const std::string &dir)
This function can be used to create the D3PDReader::D3PDObjectBase class's source files.
StatusCode writeUserD3PDObject(const std::string &dir)
This function can be used to create the D3PDReader::UserD3PDObject class's source files.
StatusCode writeD3PDPerfStats(const std::string &dir)
This function can be used to create the D3PDReader::D3PDPerfStats class's source files.
Block filler tool for noisy FEB information.
bool isPrimitive(const std::string &type)
This function is used in the code generator to determine from a type name if it's a primitive type or...
const std::string spacer
Definition spacer.h:27