Bug Summary

File:/home/sdobbs/work/clang/halld_recon/src/libraries/DAQ/Df250EmulatorAlgorithm_v3.cc
Warning:line 336, column 10
Division by zero

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -main-file-name Df250EmulatorAlgorithm_v3.cc -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0 -D HAVE_EVIO -D HAVE_TMVA=1 -I .Linux_CentOS7.7-x86_64-gcc4.8.5/libraries/DAQ -I libraries/DAQ -I . -I libraries -I libraries/include -I /w/halld-scifs17exp/home/sdobbs/clang/halld_recon/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I libraries -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/evio/evio-4.4.6/Linux-x86_64/include -I /w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include -I /group/halld/Software/builds/Linux_CentOS7.7-x86_64-gcc4.8.5/root/root-6.08.06/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../include/c++/4.8.5/backward -internal-isystem /usr/local/include -internal-isystem /w/halld-scifs17exp/home/sdobbs/clang/llvm-project/install/lib/clang/12.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /home/sdobbs/work/clang/halld_recon/src -ferror-limit 19 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /tmp/scan-build-2021-01-21-110224-160369-1 -x c++ libraries/DAQ/Df250EmulatorAlgorithm_v3.cc

libraries/DAQ/Df250EmulatorAlgorithm_v3.cc

1#include <DAQ/Df250EmulatorAlgorithm_v3.h>
2
3// corresponds to version 0x0C12 of the fADC250 firmware
4
5Df250EmulatorAlgorithm_v3::Df250EmulatorAlgorithm_v3(JEventLoop *loop){
6 // Enables forced use of default values
7 FORCE_DEFAULT = 0;
8
9 USE_CRATE_DEFAULTS = 1;
10
11 // Default values for the essential parameters
12 NSA_DEF = 20;
13 NSB_DEF = 5;
14 THR_DEF = 120;
15 NPED_DEF = 4;
16 MAXPED_DEF = 512;
17 NSAT_DEF = 2;
18
19 // DEBUG
20 NSA_DEF = 15;
21 NSB_DEF = 1;
22 THR_DEF = 108;
23 NPED_DEF = 4;
24 MAXPED_DEF = 512;
25 NSAT_DEF = 2;
26
27
28 // Set verbosity
29 VERBOSE = 0;
30
31 if(gPARMS){
32 gPARMS->SetDefaultParameter("EMULATION250:USE_CRATE_DEFAULTS", USE_CRATE_DEFAULTS,"Set to >0 to force use of crate-dependent default values");
33 gPARMS->SetDefaultParameter("EMULATION250:FORCE_DEFAULT", FORCE_DEFAULT,"Set to >0 to force use of default values");
34 gPARMS->SetDefaultParameter("EMULATION250:NSA", NSA_DEF,"Set NSA for firmware emulation, will be overwritten by BORConfig if present");
35 gPARMS->SetDefaultParameter("EMULATION250:NSB", NSB_DEF,"Set NSB for firmware emulation, will be overwritten by BORConfig if present");
36 gPARMS->SetDefaultParameter("EMULATION250:THR", THR_DEF,"Set threshold for firmware emulation, will be overwritten by BORConfig if present");
37 gPARMS->SetDefaultParameter("EMULATION250:NPED", NPED_DEF,"Set NPED for firmware emulation, will be overwritten by BORConfig if present");
38 gPARMS->SetDefaultParameter("EMULATION250:MAXPED", MAXPED_DEF,"Set MAXPED for firmware emulation, will be overwritten by BORConfig if present");
39 gPARMS->SetDefaultParameter("EMULATION250:NSAT", NSAT_DEF,"Set NSAT for firmware emulation, will be overwritten by BORConfig if present");
40 gPARMS->SetDefaultParameter("EMULATION250:VERBOSE", VERBOSE,"Set verbosity for f250 emulation");
41 }
42}
43
44void Df250EmulatorAlgorithm_v3::EmulateFirmware(const Df250WindowRawData* rawData,
45 std::vector<Df250PulseData*> &pdat_objs)
46{
47 // This is the main routine called by JEventSource_EVIO::GetObjects() and serves as the entry point for the code.
48 if (VERBOSE > 0) {
1
Assuming field 'VERBOSE' is <= 0
2
Taking false branch
49 jout << " Df250EmulatorAlgorithm_v3::EmulateFirmware ==> Starting emulation <==" << endl;
50 jout << "rocid : " << rawData->rocid << " slot: " << rawData->slot << " channel: " << rawData->channel << endl;
51 }
52
53 // First check that we have window raw data available
54 if (rawData == NULL__null) {
3
Assuming 'rawData' is not equal to NULL
4
Taking false branch
55 jerr << " ERROR: Df250EmulatorAlgorithm_v3::EmulateFirmware - raw sample data is missing" << endl;
56 jerr << " Contact mstaib@jlab.org" << endl;
57 return;
58 }
59 if (rawData->samples.size() == 0) {
5
Assuming the condition is false
6
Taking false branch
60 jerr << " ERROR: Df250EmulatorAlgorithm_v3::EmulateFirmware - raw sample data has zero size" << endl;
61 jerr << "rocid : " << rawData->rocid << " slot: " << rawData->slot << " channel: " << rawData->channel << endl;
62 //jerr << " Contact mstaib@jlab.org" << endl;
63 return;
64 }
65
66 // We need the channel number to get the threshold
67 uint32_t channel = rawData->channel;
68
69 // First grab the config objects from the raw data and get the quantities we need from them
70 // The only things we need for this version of the f250 firmware are NSB, NSA, and the threshold.
71 // These are all stored in the BOR config. We can grab this from the raw data since that was already associated in JEventSource_EVIO::GetObjects.
72 const Df250BORConfig *f250BORConfig = NULL__null;
73 rawData->GetSingle(f250BORConfig);
7
Calling 'JObject::GetSingle'
12
Returning from 'JObject::GetSingle'
74
75 uint32_t NSA;
76 int32_t NSB;
77 uint32_t NPED, MAXPED;
78 uint16_t THR;
79 uint16_t NSAT;
80 //If this does not exist, or we force it, use the default values
81 if (f250BORConfig
12.1
'f250BORConfig' is not equal to NULL
12.1
'f250BORConfig' is not equal to NULL
== NULL__null || FORCE_DEFAULT){
13
Assuming field 'FORCE_DEFAULT' is 0
14
Taking false branch
82 static int counter = 0;
83 NSA = NSA_DEF;
84 NSB = NSB_DEF;
85 THR = THR_DEF;
86 NPED = NPED_DEF;
87 MAXPED = MAXPED_DEF;
88 NSAT = NSAT_DEF;
89 if (counter < 10){
90 counter++;
91 if (counter == 10) jout << " WARNING Df250EmulatorAlgorithm_v3::EmulateFirmware No Df250BORConfig == Using default values == LAST WARNING" << endl;
92 else jout << " WARNING Df250EmulatorAlgorithm_v3::EmulateFirmware No Df250BORConfig == Using default values " << endl;
93 //<< rawData->rocid << "/" << rawData->slot << "/" << rawData->channel << endl;
94 }
95
96
97 if(USE_CRATE_DEFAULTS) {
98 // BASED on run 71137
99 // FCAL, crates = 11-22
100 if( (rawData->rocid >= 11) && (rawData->rocid <= 22) ) {
101 NSA = 15;
102 NSB = 1;
103 THR = 108;
104 //NPED = NPED_DEF;
105 //MAXPED = MAXPED_DEF;
106 NSAT = 2;
107 }
108 // BCAL, crates = 31-46
109 else if( (rawData->rocid >= 31) && (rawData->rocid <= 46) ) {
110 NSA = 26;
111 NSB = 1;
112 THR = 105;
113 //NPED = NPED_DEF;
114 //MAXPED = MAXPED_DEF;
115 NSAT = 2;
116 }
117 // TAGH, crates 73-74, 75[slot 7-16]
118 else if( (rawData->rocid == 73) || (rawData->rocid == 74) || ( (rawData->rocid == 75) && (rawData->slot >= 7) && (rawData->slot <= 16)) ) {
119 NSA = 6;
120 NSB = 3;
121 THR = 300;
122 //NPED = NPED_DEF;
123 //MAXPED = MAXPED_DEF;
124 NSAT = 2;
125 }
126 // TAGM, crates 71-72, 75[slot 3-6]
127 else if( (rawData->rocid == 71) || (rawData->rocid == 72) || ( (rawData->rocid == 75) && (rawData->slot >= 3) && (rawData->slot <= 6)) ) {
128 NSA = 6;
129 NSB = 3;
130 THR = 150;
131 //NPED = NPED_DEF;
132 //MAXPED = MAXPED_DEF;
133 NSAT = 2;
134 }
135 // TOF, crates = 77
136 else if( rawData->rocid == 77 ) {
137 NSA = 10;
138 NSB = 1;
139 THR = 160;
140 //NPED = NPED_DEF;
141 //MAXPED = MAXPED_DEF;
142 NSAT = 2;
143 }
144 // PS, crates = 83-84
145 else if( (rawData->rocid >= 83) && (rawData->rocid <= 84) ) {
146 NSA = 10;
147 NSB = 3;
148 THR = 130;
149 //NPED = NPED_DEF;
150 //MAXPED = MAXPED_DEF;
151 NSAT = 2;
152 }
153 // ST, crates = 94
154 else if( rawData->rocid == 94 ) {
155 NSA = 20;
156 NSB = 5;
157 THR = 120;
158 //NPED = NPED_DEF;
159 //MAXPED = MAXPED_DEF;
160 NSAT = 2;
161 }
162 }
163 }
164 else{
165 NSA = f250BORConfig->NSA;
166 NSB = f250BORConfig->NSB;
167 THR = f250BORConfig->adc_thres[channel];
168 NPED = f250BORConfig->NPED;
15
Value assigned to 'NPED'
169 MAXPED = f250BORConfig->MaxPed;
170 NSAT = f250BORConfig->NSAT;
171 //if (VERBOSE > 0) jout << "Df250EmulatorAlgorithm_v3::EmulateFirmware NSA: " << NSA << " NSB: " << NSB << " THR: " << THR << endl;
172 }
173
174 if (VERBOSE
15.1
Field 'VERBOSE' is <= 0
15.1
Field 'VERBOSE' is <= 0
> 0) jout << "Df250EmulatorAlgorithm_v3::EmulateFirmware NSA: " << NSA << " NSB: " << NSB << " THR: " << THR << endl;
16
Taking false branch
175
176 // Note that in principle we could get this information from the Df250Config objects as well, but generally only NPED and the value of NSA+NSB are saved
177 // not the individual NSA and NSB values
178
179 /*
180 // TEST
181 if( (rawData->rocid >= 31) || (rawData->rocid <= 46) ) {
182 NSA = NSA_DEF;
183 NSB = NSB_DEF;
184 }
185 */
186
187 // quality bits
188 bool bad_pedestal = false;
189 bool bad_timing_pedestal = false;
190 bool no_timing_calculation = false;
191
192 // Now we can start to loop over the raw data
193 // This requires a few passes due to some features in the way the quantities are calculated...
194 // The first step is to scan the samples for TC (threshold crossing sample) and compute the
195 // integrals of all pulses found.
196
197 vector<uint16_t> samples = rawData->samples;
198 uint16_t NW = samples.size();
199 uint32_t npulses = 0;
200 const int max_pulses = 3;
201 uint32_t TC[max_pulses] = {};
202 uint32_t TMIN[max_pulses] = {3};
203 //uint32_t TNSAT[max_pulses] = {};
204 uint32_t pulse_integral[max_pulses] = {};
205 bool has_overflow_samples[max_pulses] = {false};
206 bool has_underflow_samples[max_pulses] = {false};
207 uint32_t number_samples_above_threshold[max_pulses] = {0};
208 bool NSA_beyond_PTW[max_pulses] = {false};
209 bool vpeak_beyond_NSA[max_pulses] = {false};
210 bool vpeak_not_found[max_pulses] = {false};
211
212 // some verbose debugging output
213 if(VERBOSE
16.1
Field 'VERBOSE' is <= 0
16.1
Field 'VERBOSE' is <= 0
> 0) {
17
Taking false branch
214 for (unsigned int i=0; i < NW; i++) {
215 if(VERBOSE > 2) {
216 if(samples[i] == 0x1fff)
217 jout << "Overflow at sample " << i << endl;
218 if(samples[i] == 0x1000)
219 jout << "Underflow at sample " << i << endl;
220 }
221 if (VERBOSE > 5) jout << "Df250EmulatorAlgorithm_v3::EmulateFirmware samples[" << i << "]: " << samples[i] << endl;
222 }
223 }
224
225
226 // look for the threhold crossings and compute the integrals
227 //unsigned int MAX_SAMPLE = (NSB>0) ? (NW-NSAT) : (NW-NSAT+NSB-1)); // check this
228 unsigned int MAX_SAMPLE = NW-NSAT;
229 //cerr << " MAX_SAMPLE = " << MAX_SAMPLE << " NW = " << NW << " NSAT = " << NSAT << endl;
230 //for (unsigned int i=0; i < MAX_SAMPLE; i++) {
231 for (unsigned int i=0; i < MAX_SAMPLE; i++) {
18
Assuming 'i' is >= 'MAX_SAMPLE'
19
Loop condition is false. Execution continues on line 312
232 if ((samples[i] & 0xfff) > THR) {
233 if (VERBOSE > 1) {
234 jout << "threshold crossing at " << i << endl;
235 }
236
237 // save threshold crossing - could be overwritten
238 TC[npulses] = i+1;
239
240 // check that we have more than NSAT samples over threshold
241 if( NSAT>1 ){
242 int samples_over_threshold = 1;
243
244 if(i==0) {
245 // the algorithm only terminates if we dip below threshold...
246 //for(unsigned int j=i+1; ((samples[j]&0xfff)>=THR) && (j<MAX_SAMPLE+1); j++) {
247 for(unsigned int j=i+1; ((samples[j]&0xfff)>THR) && (j<MAX_SAMPLE+1); j++) {
248 // only count samples actually above threshold
249 if ((samples[j] & 0xfff) > THR)
250 samples_over_threshold++;
251
252 if( samples_over_threshold == NSAT ) {
253 //TC[npulses] = j+1;
254 //i=j;
255 break;
256 }
257
258 }
259 } else {
260 for(unsigned int j=i+1; ((samples[j]&0xfff)>THR) && (j<MAX_SAMPLE+1); j++) {
261 samples_over_threshold++;
262
263 if( samples_over_threshold == NSAT )
264 break;
265 }
266 }
267
268 // if we couldn't find NSAT samples above threshold, move on...
269 if( samples_over_threshold != NSAT )
270 continue;
271 }
272 //else {
273 //TNSAT[npulses] = TC[npulses];
274 //}
275
276
277 // calculate integral
278 unsigned int ibegin;
279 if(NSB > 0)
280 ibegin = i > uint32_t(NSB) ? (i - NSB) : 0; // Set to beginning of window if too early
281 else {
282 ibegin = i - NSB;
283 if(ibegin > uint32_t(NW)) // make sure we don't start looking outside the window
284 break;
285 }
286 unsigned int iend = (i + NSA) < uint32_t(NW) ? (i + NSA) : NW; // Set to last sample if too late
287 // check to see if NSA extends beyond the end of the window
288 NSA_beyond_PTW[npulses] = (i + NSA - 1) >= uint32_t(NW);
289 for (i = ibegin; i < iend; ++i) {
290 pulse_integral[npulses] += (samples[i] & 0xfff);
291 // quality monitoring
292 if(samples[i] == 0x1fff) {
293 has_overflow_samples[npulses] = true;
294 }
295 if(samples[i] == 0x1000) {
296 has_underflow_samples[npulses] = true;
297 }
298 // count number of samples within NSA that are above thresholds
299 if( (i+1>=TC[npulses]) && ((samples[i] & 0xfff) > THR) )
300 number_samples_above_threshold[npulses]++;
301 }
302 for (; i < NW && (samples[i] & 0xfff) >= THR; ++i) {}
303 if (++npulses == max_pulses)
304 break;
305 TMIN[npulses] = i;
306 }
307 }
308
309 // That concludes the first pass over the data.
310 // Now we can head into the fine timing pass over the data.
311
312 uint32_t VPEAK[max_pulses] = {};
313 uint32_t TPEAK[max_pulses] = {};
314 uint16_t TMID[max_pulses] = {};
315 uint16_t VMID[max_pulses] = {};
316 uint16_t TFINE[max_pulses] = {};
317 uint32_t pulse_time[max_pulses] = {};
318
319 // The pulse pedestal is the sum of NPED (4-15) samples at the beginning of the window
320 uint32_t pedestal = 0;
321 uint32_t VMIN = 0; // VMIN is just the average of the first 4 samples, needed for timing algorithm
322 for (unsigned int i=0; i < NPED; i++) {
20
Assuming 'i' is >= 'NPED'
21
Loop condition is false. Execution continues on line 336
323 pedestal += (samples[i] & 0xfff);
324 if(i<4)
325 VMIN += (samples[i] & 0xfff);
326 // error conditions
327 // sample larger than MaxPed
328 if ((samples[i] & 0xfff) > MAXPED) {
329 bad_pedestal = true;
330 }
331 // samples with underflow/overflow
332 if( (samples[i] == 0x1fff) || (samples[i] == 0x1000) ) {
333 bad_pedestal = true;
334 }
335 }
336 VMIN /= NPED; // compute average
22
Division by zero
337
338 // error conditions for timing algorithm
339 //bool pedestal_underflow = false;
340 for (unsigned int i=0; i < 4; i++) {
341 // We set the "Time Quality bit 0" to 1 if any of the first 4 samples is greated than MaxPed or TET...
342 if ( ((samples[i] & 0xfff) > MAXPED) || ((samples[i] & 0xfff) > THR) ) {
343 bad_timing_pedestal = true;
344 }
345 // ... or is overflow or underflow
346 if ( (samples[i] == 0x1000) || (samples[i] == 0x1fff) ) {
347 bad_timing_pedestal = true;
348 }
349 //}
350
351 // "If any of the first 4 samples is greater than TET the TDC will NOT proceed..."
352 // Waiit for iiit...
353 if( (samples[i] & 0xfff) > THR ) {
354 no_timing_calculation = true;
355 }
356 }
357
358
359 for (unsigned int p=0; p < npulses; ++p) {
360
361 // "If any of the first 4 samples is greater than TET or underflow the TDC will NOT proceed
362 // 1. pulse time is set to TC
363 // 2. pulse peak is set to zero - not anymore!
364 // 3. Time quality bits 0 and 1 are set to 1"
365 if(no_timing_calculation) {
366 TMID[p] = TC[p];
367 TFINE[p] = 0;
368 VPEAK[p] = 0;
369 //vpeak_not_found[p] = true; // this is "time quality bit 1"
370 // "Time Quality bit 0" should already be set
371 } // should just put an else here...
372
373 // we set up a loop so that we can break out of it at appropriate times...
374 // note that currently the timing algorithm is run when the pedestal has underflow samples,
375 // but according to the documentation, it shouldn't...
376 // NOTE that we should always run the calculation since we always need to search for the
377 // peak position, just in some edge cases we don't need to run the timing algorithm
378
379 //while ( (!no_timing_calculation || pedestal_underflow) && true) {
380 while (true) {
381 //if (VMIN == 99999) {
382 // VPEAK[p] = 0;
383 // reportTC[p] = true;
384 // pulse_time[p] = (TC[p] << 6);
385 // break;
386 // }
387
388 // search for the peak of the pulse
389 // has to be after the threshold crossing (NO?)
390 // has to be before the last sample
391 unsigned int ipeak;
392 for (ipeak = TC[p]; (int)ipeak < NW-1; ++ipeak) {
393 //for (ipeak = TC[p]+1; ipeak < NW-1; ++ipeak) {
394 if ((samples[ipeak] & 0xfff) < (samples[ipeak-1] & 0xfff)) {
395 VPEAK[p] = (samples[ipeak-1] & 0xfff);
396 TPEAK[p] = ipeak-1;
397 break;
398 }
399 }
400
401 // check to see if the peak is beyond the NSA
402 if(ipeak > TC[p]+NSA)
403 vpeak_beyond_NSA[p] = true;
404
405 if (VERBOSE > 1) {
406 jout << " pulse " << p << ": VMIN: " << VMIN
407 << " TC: " << TC[p] << " VPEAK: " << VPEAK[p] << endl;
408 }
409
410 // set error conditions in case we didn't find the peak
411 if (VPEAK[p] == 0) {
412 TMID[p] = TC[p];
413 TFINE[p] = 0;
414 VPEAK[p] = 0;
415 vpeak_beyond_NSA[p] = true;
416 vpeak_not_found[p] = true;
417 break;
418 }
419
420 // we have found the peak position, now ignore the timing calculation if need be...
421 if(no_timing_calculation)
422 break;
423
424 // VMID is the half amplitude
425 VMID[p] = (VMIN + VPEAK[p]) >> 1;
426
427
428 // look down the leading edge for the sample that satisfies V(N1) <= VMID < V(N+1)
429 // N1 is then the coarse time
430 // note that when analyzing pulses after the first, we could end up with a time for the
431 // second pulse that is before the first one! this is a little crazy, but is how
432 // the algorithm is currently implemented
433 for (unsigned int i = TPEAK[p]; i >= 1; --i) {
434 if ( ((samples[i-1] & 0xfff) <= VMID[p]) && ((samples[i] & 0xfff) > VMID[p]) ) { // V(N1) <= VMID < V(N+1)
435 // if ( ((samples[i-1] & 0xfff) <= VMID[p]) // V(N1) <= VMID < V(N+1)
436 // || ( (samples[i-1] & 0xfff) > (samples[i] & 0xfff) ) ) { // we aren't on the leading edge anymore
437 TMID[p] = i;
438 break;
439 }
440 }
441
442 if (TMID[p] == 0) { // handle the case where we couldn't find a coarse time - redundant?
443 TFINE[p] = 0;
444 }
445 else {
446 // fine timing algorithm (see documentation)
447 int Vnext = (samples[TMID[p]] & 0xfff);
448 int Vlast = (samples[TMID[p]-1] & 0xfff);
449 if (VERBOSE > 2) {
450 jout << " TMIN = " << TMIN[p] << " TMID = " << TMID[p] << " TPEAK = " << TPEAK[p] << endl
451 << " VMID = " << VMID[p] << " Vnext = " << Vnext << " Vlast = " << Vlast << endl;
452 }
453 if (Vnext > Vlast && VMID[p] >= Vlast)
454 TFINE[p] = 64 * (VMID[p] - Vlast) / (Vnext - Vlast);
455 else
456 TFINE[p] = 62;
457 if(TFINE[p] == 64)
458 TFINE[p] = 0;
459 }
460 pulse_time[p] = ((TMID[p]-1) << 6) + TFINE[p];
461 break;
462 }
463 VMIN = (VMIN < 99999)? VMIN : 0; // deprecated?
464
465 if (VERBOSE > 1) {
466 jout << " pulse " << p << ": VMID: " << VMID[p] << " TMID: " << TMID[p]
467 << " TFINE: " << TFINE[p] << " time: " << pulse_time[p]
468 << " integral: " << pulse_integral[p] << endl;
469 if (VERBOSE > 2) {
470 jout << " TMIN = " << TMIN[p] << " TMID = " << TMID[p] << " TPEAK = " << TPEAK[p] << endl;
471 //<< " VMID = " << VMID[p] << " Vnext = " << Vnext << " Vlast = " << Vlast << endl;
472 }
473 }
474
475 // algorithm is finished, fill the information
476 Df250PulseData* f250PulseData;
477 if( p < pdat_objs.size() ) {
478 f250PulseData = pdat_objs[p];
479
480 if(f250PulseData == NULL__null) {
481 jerr << " NULL f250PulseData object!" << endl;
482 continue;
483 }
484 } else {
485 // make a fresh object if one does not exist
486 f250PulseData = new Df250PulseData;
487
488 f250PulseData->rocid = rawData->rocid;
489 f250PulseData->slot = rawData->slot;
490 f250PulseData->channel = rawData->channel;
491 f250PulseData->itrigger = rawData->itrigger;
492 // word 1
493 f250PulseData->event_within_block = 1;
494 f250PulseData->QF_pedestal = bad_pedestal;
495 f250PulseData->pedestal = pedestal;
496 // word 2
497 f250PulseData->integral = pulse_integral[p];
498 f250PulseData->QF_NSA_beyond_PTW = NSA_beyond_PTW[p];
499 f250PulseData->QF_overflow = has_overflow_samples[p];
500 f250PulseData->QF_underflow = has_underflow_samples[p];
501 f250PulseData->nsamples_over_threshold = number_samples_above_threshold[p];
502 // word 3
503 f250PulseData->course_time = TMID[p];
504 f250PulseData->fine_time = TFINE[p];
505 f250PulseData->QF_vpeak_beyond_NSA = vpeak_beyond_NSA[p];
506 f250PulseData->QF_vpeak_not_found = vpeak_not_found[p];
507 f250PulseData->QF_bad_pedestal = bad_timing_pedestal;
508 // other information
509 f250PulseData->pulse_number = p;
510 f250PulseData->nsamples_integral = NSA + NSB;
511 f250PulseData->nsamples_pedestal = NPED;
512 f250PulseData->emulated = true;
513
514 f250PulseData->AddAssociatedObject(rawData);
515 const_cast<Df250WindowRawData*>(rawData)->AddAssociatedObject(f250PulseData);
516 pdat_objs.push_back(f250PulseData);
517 }
518
519 // copy over emulated values
520 f250PulseData->integral_emulated = pulse_integral[p];
521 f250PulseData->pedestal_emulated = pedestal;
522 f250PulseData->pulse_peak_emulated = VPEAK[p];
523 f250PulseData->course_time_emulated = TMID[p];
524 f250PulseData->fine_time_emulated = TFINE[p];
525
526 // check the emulated quality factors as well
527 uint32_t QF = 0; // make single quality factor number for compactness
528 if( bad_pedestal ) QF |= (1<<0);
529 if( NSA_beyond_PTW[p] ) QF |= (1<<1);
530 if( has_overflow_samples[p] ) QF |= (1<<2);
531 if( has_underflow_samples[p] ) QF |= (1<<3);
532 if( vpeak_beyond_NSA[p] ) QF |= (1<<4);
533 if( vpeak_not_found[p] ) QF |= (1<<5);
534 if( bad_timing_pedestal ) QF |= (1<<6);
535 f250PulseData->QF_emulated = QF;
536
537 if(VERBOSE > 3) {
538 cout << boolalpha;
539 cout << "bad_pedestal = " << bad_pedestal << endl;
540 cout << "NSA_beyond_PTW = " << NSA_beyond_PTW[p] << endl;
541 cout << "has_overflow_samples = " << has_overflow_samples[p] << endl;
542 cout << "has_underflow_samples = " << has_underflow_samples[p] << endl;
543 cout << "vpeak_beyond_NSA = " << vpeak_beyond_NSA[p] << endl;
544 cout << "vpeak_not_found = " << vpeak_not_found[p] << endl;
545 cout << "bad_timing_pedestal = " << bad_timing_pedestal << endl;
546 cout << "total QF = " << QF << endl;
547 }
548
549 // if we are using the emulated values, copy them
550 if( f250PulseData->emulated ) {
551 f250PulseData->integral = f250PulseData->integral_emulated;
552 f250PulseData->pedestal = f250PulseData->pedestal_emulated;
553 f250PulseData->pulse_peak = f250PulseData->pulse_peak_emulated;
554 f250PulseData->course_time = f250PulseData->course_time_emulated;
555 f250PulseData->fine_time = f250PulseData->fine_time_emulated;
556
557 /*
558 if( (rawData->rocid >= 31) || (rawData->rocid <= 46) ) {
559 f250PulseData->nsamples_integral = NSA + NSB;
560 }
561 */
562
563 }
564
565 }
566
567 if (VERBOSE > 0) jout << " Df250EmulatorAlgorithm_v3::EmulateFirmware ==> Emulation complete <==" << endl;
568 return;
569}

/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JObject.h

1// $Id: JObject.h 1709 2006-04-26 20:34:03Z davidl $
2//
3// File: JObject.h
4// Created: Wed Aug 17 10:57:09 EDT 2005
5// Creator: davidl (on Darwin wire129.jlab.org 7.8.0 powerpc)
6//
7
8#ifndef _JObject_
9#define _JObject_
10
11#include <cstdio>
12#include <sstream>
13#include <cassert>
14#include <map>
15#include <vector>
16#include <set>
17#include <string>
18#include <cstdint>
19#include <type_traits>
20#include <typeinfo>
21#include <stdint.h>
22using std::pair;
23using std::map;
24using std::set;
25using std::vector;
26using std::string;
27using std::stringstream;
28
29// The following is here just so we can use ROOT's THtml class to generate documentation.
30#include "cint.h"
31
32
33/// The JObject class is a base class for all data classes.
34/// (See JFactory and JFactory_base for algorithm classes.)
35///
36///
37/// The following line should be included in the public definition of all
38/// classes which inherit from JObject with the argument being the name of the
39/// class without any quotes.
40/// e.g. for a class named "MyClass" :
41///
42/// public:
43/// JOBJECT_PUBLIC(MyClass);
44///
45/// This will define a virtual method <i>className()</i> and a static
46/// method <i>static_className()</i> that are used by JANA to identify
47/// the object's last generation in the inheritance chain by name. This
48/// also allows for possible upgrades to JANA in the future without
49/// requiring classes that inherit from JObject to be redefined explicity.
50#define JOBJECT_PUBLIC(T)virtual const char* className(void) const {return static_className
();} static const char* static_className(void) {return "T";} virtual
JObject* Clone() const {return CloneObject<T>( *this )
;}
\
51 virtual const char* className(void) const {return static_className();} \
52 static const char* static_className(void) {return #T;} \
53 virtual JObject* Clone() const {return CloneObject<T>( *this );}
54
55
56
57// Place everything in JANA namespace
58namespace jana{
59
60class JFactory_base;
61class JEventLoop;
62
63class JObject{
64
65 public:
66 JOBJECT_PUBLIC(JObject)virtual const char* className(void) const {return static_className
();} static const char* static_className(void) {return "JObject"
;} virtual JObject* Clone() const {return CloneObject<JObject
>( *this );}
;
67
68 typedef unsigned long long oid_t;
69
70 JObject() : id((oid_t)this),append_types(false),factory(NULL__null) {}
71 JObject( oid_t aId ) : id( aId ),append_types(false),factory(NULL__null) {}
72
73 virtual ~JObject(){
74 for(unsigned int i=0; i<auto_delete.size(); i++)delete auto_delete[i];
75 }
76
77 // Copy constructor
78 JObject(const JObject& o) :
79 id( (oid_t)this ), append_types(o.append_types), associated(
80 o.associated), auto_delete(), messagelog(
81 o.messagelog), factory(o.factory) {
82 // Deep copy the objects in auto_delete vector
83 for( auto obj : o.auto_delete ) {
84 auto_delete.push_back( obj->Clone() );
85 }
86 }
87
88 // Move constructor
89 JObject( const JObject&& o ) : id( (oid_t)this ), append_types(o.append_types), associated(
90 std::move(o.associated)), auto_delete(std::move(o.auto_delete)), messagelog( std::move(
91 o.messagelog)), factory(o.factory) {
92 factory = nullptr;
93 }
94
95 // Assignment operator
96 JObject& operator=( const JObject& o) {
97 if( this == &o ) return *this;
98 append_types = o.append_types;
99 associated = o.associated;
100 messagelog = o.messagelog;
101 factory = o.factory;
102 auto_delete.clear();
103 for( auto obj : o.auto_delete ) {
104 auto_delete.push_back( obj->Clone() );
105 }
106 return *this;
107 }
108
109 // Define template static method for cloning the object of this type. This would get called from a
110 // virtual method define for each subclass to polymorphically clone the objects.
111 template<typename TYPE>
112 static typename std::enable_if<
113 (std::is_abstract <TYPE>::value || !std::is_copy_constructible<TYPE>::value), JObject*>::type CloneObject(
114 const TYPE& obj) {
115 // For abstract method it will return null pointer, and probably will cause problems. But
116 // there sohuld not be any object of abstract class to start with.
117 return nullptr;
118 }
119 template<typename TYPE>
120 static typename std::enable_if<
121 (!std::is_abstract <TYPE>::value
122 && std::is_copy_constructible <TYPE>::value ), JObject*>::type CloneObject(
123 const TYPE& obj) {
124 // For non-abstract class create a new object using the copy constructor of the class
125 // given in the template argument.
126 return new TYPE(obj);
127 }
128
129 /// Test if this object is of type T by checking its className() against T::static_className()
130 template<typename T> bool IsA(const T *t) const {return dynamic_cast<const T*>(this)!=0L;}
131
132 /// Test if this object is of type T (or a descendant) by attempting a dynamic cast
133 template<typename T> bool IsAT(const T *t) const {return dynamic_cast<const T*>(this)!=0L;}
134
135 // Methods for handling associated objects
136 inline void AddAssociatedObject(const JObject *obj);
137 inline void AddAssociatedObjectAutoDelete(JObject *obj, bool auto_delete=true);
138 inline void RemoveAssociatedObject(const JObject *obj);
139 inline void ClearAssociatedObjects(void);
140 inline bool IsAssociated(const JObject* locObject) const {return (associated.find(locObject) != associated.end());}
141 template<typename T> void Get(vector<const T*> &ptrs, string classname="", int max_depth=1000000) const ;
142 template<typename T> void GetT(vector<const T*> &ptrs) const ;
143 template<typename T> void GetSingle(const T* &ptrs, string classname="") const ;
144 template<typename T> void GetSingleT(const T* &ptrs) const ;
145 template<typename T> void GetAssociatedAncestors(set<const JObject*> &already_checked, int &max_depth, set<const T*> &objs_found, string classname="") const;
146 template<typename T> void GetAssociatedDescendants(JEventLoop *loop, vector<const T*> &associatedTo, int max_depth=1000000);
147 void GetAssociatedDescendants(JEventLoop *loop, vector<const JObject*> &associatedTo, int max_depth=1000000);
148
149 template<typename T,typename S> void CopyToVector(T itbegin, T itend, vector<const S*> &v) const;
150
151 // Methods for handling pretty formatting for dumping to the screen or file
152 virtual void toStrings(vector<pair<string,string> > &items)const;
153 template<typename T> void AddString(vector<pair<string,string> > &items, const char *name, const char *format, const T &val) const;
154
155 // Methods for attaching and retrieving log messages to/from object
156 void AddLog(string &message) const {messagelog.push_back(message);}
157 void AddLog(vector<string> &messages) const {messagelog.insert(messagelog.end(), messages.begin(), messages.end());}
158 void GetLog(vector<string> &messagelog) const {messagelog = this->messagelog;}
159
160 // Misc methods
161 bool GetAppendTypes(void) const {return append_types;} ///< Get state of append_types flag (for AddString)
162 void SetAppendTypes(bool append_types){this->append_types=append_types;} ///< Set state of append_types flag (for AddString)
163 void SetFactoryPointer(JFactory_base *factory){this->factory=factory;}
164 JFactory_base * GetFactoryPointer(void) const {return factory;}
165 string GetName(void) const {return string(className());}
166 string GetTag(void) const ;
167 string GetNameTag(void) const {return GetName() + (GetTag()=="" ? "":":") + GetTag();}
168
169 oid_t id;
170
171 private:
172
173 bool append_types;
174 set<const JObject*> associated;
175 // map<const JObject*, string> associated; replaced with set in jana 0.7.7
176 vector<JObject*> auto_delete;
177 mutable vector<string> messagelog;
178 JFactory_base *factory;
179
180};
181
182#if !defined(__CINT__) && !defined(__CLING__)
183
184
185//--------------------------
186// AddAssociatedObject
187//--------------------------
188void JObject::AddAssociatedObject(const JObject *obj)
189{
190 /// Add a JObject to the list of associated objects
191
192 assert(obj!=NULL)((obj!=__null) ? static_cast<void> (0) : __assert_fail (
"obj!=__null", "/w/halld-scifs17exp/halld2/home/sdobbs/Software/jana/jana_0.8.2/Linux_CentOS7.7-x86_64-gcc4.8.5/include/JANA/JObject.h"
, 192, __PRETTY_FUNCTION__))
;
193
194 associated.insert(obj);
195 //associated[obj] = obj->className();
196}
197
198//--------------------------
199// AddAssociatedObjectAutoDelete
200//--------------------------
201void JObject::AddAssociatedObjectAutoDelete(JObject *obj, bool auto_delete)
202{
203 /// Add a JObject to the list of associated objects. If the auto_delete
204 /// flag is true, then automatically delete it when this object is
205 /// deleted. Otherwise, this behaves identically to the AddAssociatedObject
206 /// method.
207 ///
208 /// Note that if the object is removed via RemoveAssociatedObject(...)
209 /// then the object is NOT deleted. BUT, if the entire list of associated
210 /// objects is cleared via ClearAssociatedObjects, then the object will
211 /// be deleted.
212
213 AddAssociatedObject(obj);
214
215 if(auto_delete)this->auto_delete.push_back(obj);
216}
217
218//--------------------------
219// RemoveAssociatedObject
220//--------------------------
221void JObject::RemoveAssociatedObject(const JObject *obj)
222{
223 /// Remove the specified JObject from the list of associated
224 /// objects. This will NOT delete the object even if the
225 /// object was added with the AddAssociatedObjectAutoDelete(...)
226 /// method with the auto_delete flag set.
227
228 // map<const JObject*, string>::iterator iter = associated.find(obj);
229 auto iter = associated.find(obj);
230
231 if(iter!=associated.end()){
232 associated.erase(iter);
233 }
234}
235
236//--------------------------
237// ClearAssociatedObjects
238//--------------------------
239void JObject::ClearAssociatedObjects(void)
240{
241 /// Remove all associated objects from the associated objects list.
242 /// This will also delete any objects that were added via the
243 /// AddAssociatedObjectAutoDelete(...) method with the auto_delete
244 /// flag set.
245
246 // Clear pointers to associated objects
247 associated.clear();
248
249 // Delete objects in the auto_delete list
250 for(unsigned int i=0; i<auto_delete.size(); i++)delete auto_delete[i];
251 auto_delete.clear();
252}
253
254//--------------------------
255// CopyToVector
256//
257// This litte utility method is here because the g++ 4.4.7
258// compiler was complaining about the declaration of
259// set<const T*>::iterator it; in the Get method. Very strange
260// but this at least avoids ever having to declare the variable.
261//--------------------------
262template<typename T,typename S>
263void JObject::CopyToVector(T itbegin, T itend, vector<const S*> &v) const
264{
265 for(T it=itbegin; it!=itend; it++) v.push_back(*it);
266}
267
268//--------------------------
269// Get
270//--------------------------
271template<typename T>
272void JObject::Get(vector<const T*> &ptrs, string classname, int max_depth) const
273{
274 /// Fill the given vector with pointers to the associated objects of the
275 /// type on which the vector is based. The objects are chosen by matching
276 /// their class names (obtained via JObject::className()) either to the
277 /// one provided in classname or to T::static_className() if classname is
278 /// an empty string. Associations will be searched to a level of max_depth
279 /// to find all objects of the requested type. By default, max_depth is
280 /// set to a very large number so that all associations are found. To
281 /// limit the search to only objects directly associated with this one,
282 /// set max_depth to either "0" or "1".
283 ///
284 /// The contents of ptrs are cleared upon entry.
285
286 if(classname=="")classname=T::static_className();
287
288 // Use the GetAssociatedAncestors method which may call itself
289 // recursively to search all levels of association (at or
290 // below this object. Objects for which this is an associated
291 // object are not checked for).
292 set<const JObject*> already_checked;
293 set<const T*> objs_found;
294 int my_max_depth = max_depth;
295 GetAssociatedAncestors(already_checked, my_max_depth, objs_found, classname);
296
297 // Copy results into caller's container
298 ptrs.clear();
299 CopyToVector(objs_found.begin(), objs_found.end(), ptrs);
300// set<const T*>::iterator it;
301// for(it=objs_found.begin(); it!=objs_found.end(); it++){
302// ptrs.push_back(*it);
303// }
304}
305
306//--------------------------
307// GetAssociatedAncestors
308//--------------------------
309template<typename T>
310void JObject::GetAssociatedAncestors(set<const JObject*> &already_checked, int &max_depth, set<const T*> &objs_found, string classname) const
311{
312 /// Get associated objects of the specified type (either "T" or classname).
313 /// Check also for associated objects of any associated objects
314 /// to a level of max_depth associations. This method calls itself
315 /// recursively so care is taken to only check the associated objects
316 /// of each object encountered only once.
317 ///
318 /// The "already_checked" parameter should be passed in as an empty container
319 /// that is used to keep track of which objects had their direct associations
320 /// checked. "max_depth" indicates the maximum level of associations to check
321 /// (n.b. both "0" and "1" means only check direct associations.) This must
322 /// be passed as a reference to an existing int since it is modified in order
323 /// to keep track of the current depth in the recursive calls. Set max_depth
324 /// to a very high number (like 1000000) to check all associations. The
325 /// "objs_found" container will contain the actual associated objects found.
326 /// The objects are chosen by matching their class names (obtained via
327 /// JObject::className()) either to the one provided in "classname" or to
328 /// T::static_className() if classname is an empty string.
329
330 if(already_checked.find(this) == already_checked.end()) already_checked.insert(this);
331
332 if(classname=="")classname=T::static_className();
333 max_depth--;
334
335 //map<const JObject*, string>::const_iterator iter = associated.begin();
336 for( auto obj : associated ){
337
338 // Add to list if appropriate
339 if( classname == obj->className() ){
340 objs_found.insert( dynamic_cast<const T*>(obj) );
341 }
342
343 // Check this object's associated objects if appropriate
344 if(max_depth<=0) continue;
345 if(already_checked.find(obj) != already_checked.end()) continue;
346 already_checked.insert(obj);
347 obj->GetAssociatedAncestors(already_checked, max_depth, objs_found, classname);
348 }
349
350 max_depth++;
351}
352
353//--------------------------
354// GetAssociatedDescendants
355//--------------------------
356template<typename T>
357void GetAssociatedDescendants(JEventLoop *loop, vector<const T*> &associatedTo, int max_depth=1000000)
358{
359 /// Find objects of type "T" for which this object appears in its
360 /// associated ancestors list. (This is kind of the opposite of
361 /// the "Get()" method.)
362 ///
363 /// WARNING: this must build and search the ancestor list of EVERY
364 /// object produced by EVERY factory. It is an expensive method
365 /// to call. Use it with great caution!
366 ///
367 /// WARNING: this only searches objects that have already been
368 /// created. It will not activate factories they may eventually
369 /// claim this as an associated object so the list returned may
370 /// be incomplete.
371 ///
372 /// WARNING: this templated method works by first calling the
373 /// JObject form and then dynamically casting each of those to see
374 /// if they of type "T". This makes this an even more expensive
375 /// call. Again, use with great caution!!
376
377 vector<const JObject*> ajobjs;
378 GetAssociatedDescendants(loop, ajobjs, max_depth);
379 for(uint32_t i=0; i<ajobjs.size(); i++){
380 const T *ptr = dynamic_cast<const T*>(ajobjs[i]);
381 if(ptr != NULL__null) associatedTo.push_back(ptr);
382 }
383}
384
385//--------------------------
386// GetT
387//--------------------------
388template<typename T>
389void JObject::GetT(vector<const T*> &ptrs) const
390{
391 /// Fill the given vector with pointers to the associated
392 /// JObjects of the type on which the vector is based. This is
393 /// similar to the Get() method except objects are selected
394 /// by attempting a dynamic_cast to type const T*. This allows
395 /// one to select a list of all objects who have a type T
396 /// somewhere in their inheritance chain.
397 ///
398 /// A potential issue with this method is that the dynamic_cast
399 /// does not always work correctly for objects created via a
400 /// plugin when the cast occurs outside of the plugin or
401 /// vice versa.
402 ///
403 /// The contents of ptrs are cleared upon entry.
404
405 ptrs.clear();
406
407 //map<const JObject*, string>::const_iterator iter = associated.begin();
408 //for(; iter!=associated.end(); iter++){
409 for( auto obj : associated ){
410 const T *ptr = dynamic_cast<const T*>(obj);
411 if(ptr != NULL__null)ptrs.push_back(ptr);
412 }
413}
414
415//-------------
416// GetSingle
417//-------------
418template<class T>
419void JObject::GetSingle(const T* &t, string classname) const
420{
421 /// This is a convenience method that can be used to get a pointer to the single
422 /// associate object of type T.
423 ///
424 /// The objects are chosen by matching their class names
425 /// (obtained via JObject::className()) either
426 /// to the one provided in classname or to T::static_className()
427 /// if classname is an empty string.
428 ///
429 /// If no object of the specified type is found, a NULL pointer is
430 /// returned.
431
432 t = NULL__null;
433
434 if(classname=="")classname=T::static_className();
8
Taking false branch
435
436 //map<const JObject*, string>::const_iterator iter = associated.begin();
437 //for(; iter!=associated.end(); iter++){
438 for( auto obj : associated ){
439 if( classname == obj->className() ){
9
Value assigned to field 'NPED'
10
Taking true branch
440 t = dynamic_cast<const T*>(obj);
441 if(t
10.1
't' is not equal to NULL
10.1
't' is not equal to NULL
!=NULL__null)return;
11
Taking true branch
442 }
443 }
444}
445
446//-------------
447// GetSingleT
448//-------------
449template<class T>
450void JObject::GetSingleT(const T* &t) const
451{
452 /// This is a convenience method that can be used to get a pointer to the single
453 /// associate object of type T.
454 ///
455 /// This is similar to the GetSingle() method except objects are selected
456 /// by attempting a dynamic_cast to type const T*. This allows
457 /// one to select a list of all objects who have a type T
458 /// somewhere in their inheritance chain.
459 /// The objects are chosen by matching their class names
460 /// (obtained via JObject::className()) either
461 /// to the one provided in classname or to T::static_className()
462 /// if classname is an empty string.
463 ///
464 /// If no object of the specified type is found, a NULL pointer is
465 /// returned.
466
467 t = NULL__null;
468
469 //map<const JObject*, string>::const_iterator iter = associated.begin();
470 //for(; iter!=associated.end(); iter++){
471 for( auto obj : associated ){
472 t = dynamic_cast<const T*>(obj);
473 if(t!=NULL__null)return;
474 }
475}
476
477//--------------------------
478// toStrings
479//--------------------------
480inline void JObject::toStrings(vector<pair<string,string> > &items) const
481{
482 /// Fill the given "items" vector with items representing the (important)
483 /// data members of this object. The structure of "items" is a vector
484 /// of pairs. The "first" element of the pair is the name of the item
485 /// as it should be displayed when dumping the item to the screen. For
486 /// example, one may wish to include units using a string like "r (cm)".
487 /// The "second" element of the pair is a formatted string containing the
488 /// value as it should be displayed.
489 ///
490 /// To facilitate this, the AddString() method exists which allows
491 /// items to be added with the desired formatting using a single line.
492 ///
493 /// This is a virtual method that is expected (but not required)
494 /// to be implemented by all classes that inherit from JObject.
495
496 AddString(items, "JObject", "0x%08x", (unsigned long)this);
497}
498
499//--------------------------
500// AddString
501//--------------------------
502template<typename T>
503void JObject::AddString(vector<pair<string,string> > &items, const char *name, const char *format, const T &val) const
504{
505 /// Write the given value (val) to a string using the sprintf style formatting
506 /// string (format) and add it to the given vector (items) with the column
507 /// name "name". This is intended for use in the toStrings() method of
508 /// classes that inherit from JObject.
509 ///
510 /// The append_type flag provides a facility for recording the data type
511 /// and value with default formatting into items. This can be used
512 /// by a generic convertor (not part of JANA) to auto-generate a
513 /// representation of this object for use in some other persistence
514 /// package (e.g. ROOT files).
515 ///
516 /// If the append_types flag is set then the data type of "val" is
517 /// automatically appended with a colon (:) separator to the
518 /// name (first) part of the pair. In addition, "val" is converted
519 /// using stringstream and appended as well, also with a colon (:)
520 /// separator. For example, if the value of name passed in is "px"
521 /// and T is of type double, then the first member of the pair
522 /// appended to items will be something like "px:double:1.23784"
523 /// which can be decifered later to get the name, type, and value
524 /// of the data member.
525 ///
526 /// By default, the append_types flag is not set and the name part
527 /// of the pair is a straight copy of the name argument that is
528 /// passed in.
529
530 char str[256];
531 sprintf(str, format, val);
532
533 stringstream ss;
534 ss<<name;
535 if(append_types){
536 if(typeid(T)==typeid(int)){
537 ss<<":int:"<<val;
538 }else if(typeid(T)==typeid(int32_t)){
539 ss<<":int:"<<val;
540 }else if(typeid(T)==typeid(unsigned int)){
541 ss<<":uint:"<<val;
542 }else if(typeid(T)==typeid(uint32_t)){
543 ss<<":uint:"<<val;
544 }else if(typeid(T)==typeid(long)){
545 ss<<":long:"<<val;
546 }else if(typeid(T)==typeid(int64_t)){
547 ss<<":long:"<<val;
548 }else if(typeid(T)==typeid(unsigned long)){
549 ss<<":ulong:"<<val;
550 }else if(typeid(T)==typeid(uint64_t)){
551 ss<<":ulong:"<<val;
552 }else if(typeid(T)==typeid(short)){
553 ss<<":short:"<<val;
554 }else if(typeid(T)==typeid(int16_t)){
555 ss<<":short:"<<val;
556 }else if(typeid(T)==typeid(unsigned short)){
557 ss<<":ushort:"<<val;
558 }else if(typeid(T)==typeid(uint16_t)){
559 ss<<":ushort:"<<val;
560 }else if(typeid(T)==typeid(float)){
561 ss<<":float:"<<val;
562 }else if(typeid(T)==typeid(double)){
563 ss<<":double:"<<val;
564 }else if(typeid(T)==typeid(string)){
565 ss<<":string:"<<val;
566 }else if(typeid(T)==typeid(const char*)){
567 ss<<":string:"<<val;
568 }else if(typeid(T)==typeid(char*)){
569 ss<<":string:"<<val;
570 }else{
571 ss<<":unknown:"<<str;
572 }
573 }
574
575 pair<string, string> item;
576 item.first = ss.str();
577 item.second = string(str);
578 items.push_back(item);
579}
580
581#endif // __CINT__ __CLING__
582
583
584} // Close JANA namespace
585
586#endif // _JObject_
587