Always delete TObjArrays created by TString::Tokenize (Ruben)
[u/mrichter/AliRoot.git] / RAW / AliRawEventHeaderBase.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 // Author: Cvetan Cheshkov  10/10/2005
19
20 //////////////////////////////////////////////////////////////////////////
21 //                                                                      //
22 // AliRawEventHeaderBase                                                //
23 // This a new versioning scheme for raw data root-ification and reading //
24 // For details look at offline weekly meeting 20/10/2005                //
25 //                                                                      //
26 //////////////////////////////////////////////////////////////////////////
27
28 #include <unistd.h>
29
30 #include <Bytes.h>
31 #include <TClass.h>
32 #include <TDataMember.h>
33 #include <TList.h>
34 #include <TMethodCall.h>
35
36 #include "AliLog.h"
37 #include "AliRawEventHeaderBase.h"
38
39 #include <Riostream.h>
40
41 using std::cout;
42 using std::endl;
43 ClassImp(AliRawEventHeaderBase)
44
45 //______________________________________________________________________________
46 AliRawEventHeaderBase::AliRawEventHeaderBase():
47 fSize(0),
48 fMagic(0),
49 fHeadSize(0),
50 fVersion(0),
51 fExtendedDataSize(0),
52 fExtendedAllocSize(0),
53 fExtendedData(NULL),
54 fIsSwapped(kFALSE),
55 fHeaderSize(0),
56 fHeaderBegin(NULL),
57 fFirstEqIndex(-1),
58 fLastEqIndex(-1)
59 {
60   // Default constructor
61 }
62
63 //______________________________________________________________________________
64 void *AliRawEventHeaderBase::HeaderBegin() const
65 {
66   // Returns the pointer to the first data member
67   // beyond the base class data members
68
69   if (fHeaderBegin) return fHeaderBegin;
70
71   TList *datalist = IsA()->GetListOfDataMembers();
72   TIter next(datalist);                           
73   TDataMember *member = (TDataMember *)next();
74
75   if(!strcmp(member->GetTypeName(),"TClass"))
76     member = (TDataMember *)next();
77
78   void *ptr = (void *)((char *)this+member->GetOffset());
79   const_cast<AliRawEventHeaderBase*>(this)->fHeaderBegin = ptr;
80
81   return ptr;
82 }
83
84 //______________________________________________________________________________
85 Int_t AliRawEventHeaderBase::HeaderSize() const
86 {
87   // Returns the size of the data members list
88   // beyond the base class data members
89
90   if (fHeaderSize) return fHeaderSize;
91
92   Int_t size = 0;
93
94   TList *datalist = IsA()->GetListOfDataMembers();
95   TIter next(datalist);                           
96   TDataMember *member;
97   while ((member=(TDataMember *)next()) != 0x0) {
98     if (!strcmp(member->GetTypeName(),"TClass")) continue;
99     UInt_t unitsize = member->GetUnitSize();
100     UInt_t ndim = member->GetArrayDim();
101     if (ndim == 0)
102       size += unitsize;
103     else
104       for(UInt_t i=0;i<ndim;i++) size += member->GetMaxIndex(i)*unitsize;
105   }
106
107   const_cast<AliRawEventHeaderBase*>(this)->fHeaderSize = size;
108
109   return size;
110 }
111
112 //______________________________________________________________________________
113 UInt_t AliRawEventHeaderBase::SwapWord(UInt_t x) const
114 {
115    // Swap the endianess of the integer value 'x'
116
117    return (((x & 0x000000ffU) << 24) | ((x & 0x0000ff00U) <<  8) |
118            ((x & 0x00ff0000U) >>  8) | ((x & 0xff000000U) >> 24));
119 }
120
121 void AliRawEventHeaderBase::Swap()
122 {
123    // Swap base header data.
124    // Update the fIsSwapped flag which
125    // is then use to copy in an appropriate way
126    // the rest of the header data from the raw data stream
127
128    if (IsSwapped()) {
129       fIsSwapped    = kTRUE;
130       fSize         = SwapWord(fSize);
131       fMagic        = SwapWord(fMagic);
132       fHeadSize     = SwapWord(fHeadSize);
133       fVersion      = SwapWord(fVersion);
134    }
135 }
136
137 //______________________________________________________________________________
138 const char *AliRawEventHeaderBase::GetTypeName() const
139 {
140    // Get event type as a string.
141    // Will fail in case data header
142    // does not contain eventType field
143    UInt_t eventType = Get("Type");
144
145    return GetTypeName(eventType);
146 }
147
148 //______________________________________________________________________________
149 const char *AliRawEventHeaderBase::GetTypeName(UInt_t eventType)
150 {
151   // Get event type as a string.
152   // Static method that could be used
153   // from everywhere inside aliroot
154
155    switch (eventType) {
156       case kStartOfRun:
157          return "START_OF_RUN";
158          break;
159       case kEndOfRun:
160          return "END_OF_RUN";
161          break;
162       case kStartOfRunFiles:
163          return "START_OF_RUN_FILES";
164          break;
165       case kEndOfRunFiles:
166          return "END_OF_RUN_FILES";
167          break;
168       case kStartOfBurst:
169          return "START_OF_BURST";
170          break;
171       case kEndOfBurst:
172          return "END_OF_BURST";
173          break;
174       case kPhysicsEvent:
175          return "PHYSICS_EVENT";
176          break;
177       case kCalibrationEvent:
178          return "CALIBRATION_EVENT";
179          break;
180       case kFormatError:
181          return "EVENT_FORMAT_ERROR";
182          break;
183       case kStartOfData:
184          return "START_OF_DATA";
185          break;
186       case kEndOfData:
187          return "END_OF_DATA";
188          break;
189       case kSystemSoftwareTriggerEvent:
190          return "SYSTEM_SOFTWARE_TRIGGER_EVENT";
191          break;
192       case kDetectorSoftwareTriggerEvent:
193          return "DETECTOR_SOFTWARE_TRIGGER_EVENT";
194          break;
195       default:
196          return "UNKNOWN EVENT TYPE NUMBER";
197          break;
198    }
199 }
200
201 //______________________________________________________________________________
202 AliRawEventHeaderBase* AliRawEventHeaderBase::Create(char*& data)
203 {
204   // Static method to create AliRawEventHeaderVX object
205   // The actual header class version is taken from the
206   // raw data
207
208   // First create AlirawEVentHeaderBase class object
209   AliRawEventHeaderBase header;
210
211   // Copy the first common part of the raw data header
212   memcpy(header.HeaderBaseBegin(), data, header.HeaderBaseSize());
213  
214     // Swap header data if needed
215   if (header.IsSwapped())
216     header.Swap();
217
218   // Is header valid...
219   if (!header.IsValid()) {
220     AliFatalClass("Invalid header format!");
221     // try recovery... how?
222     return 0x0;
223   }
224
225   if (header.GetEventSize() < (UInt_t)header.HeaderBaseSize()) {
226     AliFatalClass("Invalid header base size!");
227     // try recovery... how?
228     return 0x0;
229   }
230
231   // Now check the DATE version and create the corresponding header
232   // class object
233   UInt_t version = header.GetVersion();
234   UInt_t majorversion = (version>>16)&0x0000ffff;
235   UInt_t minorversion = version&0x0000ffff;
236   TString classname;
237   classname.Form("AliRawEventHeaderV%d_%d",majorversion,minorversion);
238     
239   TClass *tcl = TClass::GetClass(classname.Data());
240   if (!tcl) {
241     AliFatalClass(Form("Unknown header version (%s)!",classname.Data()));
242     return 0x0;
243   }
244
245   //  header.Dump(); tcl->Dump();
246
247   AliRawEventHeaderBase *hdr = (AliRawEventHeaderBase *)tcl->New();
248   if (!hdr) {
249     AliFatalClass(Form("Can not create object of class %s",classname.Data()));
250     return 0x0;
251   }
252
253   // Copy the base header data members and initialize other data members
254   memcpy(hdr->HeaderBaseBegin(),header.HeaderBaseBegin(), header.HeaderBaseSize());
255   memset(hdr->HeaderBegin(),0, hdr->HeaderSize());
256   hdr->fIsSwapped = header.fIsSwapped;
257
258   // Consistency check
259   if (hdr->GetEventSize() < ((UInt_t)hdr->HeaderBaseSize() + (UInt_t)hdr->HeaderSize())) {
260     AliFatalClass(Form("Invalid header size (%d < %d +%d)!",
261                        hdr->GetEventSize(),hdr->HeaderBaseSize(),hdr->HeaderSize()));
262     // try recovery... how?
263     return 0x0;
264   }
265
266   // Check for the presence of header extension and its size
267   Int_t extsize = (Int_t)hdr->GetHeadSize() - (hdr->HeaderBaseSize() + hdr->HeaderSize());
268   if (extsize < 0) {
269     AliFatalClass(Form("Invalid header size (%d < %d +%d)!",
270                        hdr->GetHeadSize(),hdr->HeaderBaseSize(),hdr->HeaderSize()));
271     // try recovery... how?
272     return 0x0;
273   }
274   else {
275     if (extsize > 0) {
276       hdr->AllocateExtendedData(extsize);
277     }
278   }
279
280   return hdr;
281 }
282
283 void AliRawEventHeaderBase::SwapData(const void* inbuf, const void* outbuf, UInt_t size) {
284   // The method swaps the contents of the
285   // raw-data event header
286   UInt_t  intCount = size/sizeof(UInt_t);
287
288   UInt_t* buf = (UInt_t*) inbuf;    // temporary integers buffer
289   for (UInt_t i=0; i<intCount; i++, buf++) {
290       UInt_t value = SwapWord(*buf);
291       memcpy((UInt_t*)outbuf+i, &value, sizeof(UInt_t)); 
292   }
293 }
294
295 //______________________________________________________________________________
296 Int_t AliRawEventHeaderBase::ReadHeader(char*& data)
297 {
298   // Read header info from DATE data stream.
299   // Returns bytes read
300
301   Long_t start = (Long_t)data;
302   // Swap header data if needed
303   if (DataIsSwapped()) {
304     SwapData(data, HeaderBaseBegin(), HeaderBaseSize());
305     data += HeaderBaseSize();
306     SwapData(data, HeaderBegin(), HeaderSize());
307     data += HeaderSize();
308   }
309   else {
310     memcpy(HeaderBaseBegin(), data, HeaderBaseSize());
311     data += HeaderBaseSize();
312     memcpy(HeaderBegin(), data, HeaderSize());
313     data += HeaderSize();
314   }
315   data += ReadExtendedData(data);
316
317   return (Int_t)((Long_t)data - start);
318 }
319
320 //______________________________________________________________________________
321 void AliRawEventHeaderBase::AllocateExtendedData(Int_t extsize)
322 {
323   // Allocate the space for the header
324   // extended data
325   if (fExtendedData) delete [] fExtendedData;
326   
327   fExtendedDataSize = fExtendedAllocSize = extsize;
328   fExtendedData = new char[fExtendedAllocSize];
329   memset(fExtendedData,0,fExtendedAllocSize);
330 }
331
332 //______________________________________________________________________________
333 Int_t AliRawEventHeaderBase::ReadExtendedData(char*& data)
334 {
335   // Read extended header data
336   // Reallocates memory if the present
337   // buffer is insufficient
338   Int_t extsize = (Int_t)GetHeadSize() - (HeaderBaseSize() + HeaderSize());
339
340   if (extsize == 0) {
341     fExtendedDataSize = 0;
342     return 0;
343   }
344
345   if (extsize < 0) {
346     AliFatal(Form("Invalid header size (%d < %d +%d)!",
347                   GetHeadSize(),HeaderBaseSize(),HeaderSize()));
348     // try recovery... how?
349     return 0;
350   }
351
352   fExtendedDataSize = extsize;
353   if (fExtendedDataSize > fExtendedAllocSize)
354     AllocateExtendedData(fExtendedDataSize);
355
356   if (DataIsSwapped())
357     SwapData(data, fExtendedData, fExtendedDataSize);
358   else
359     memcpy(fExtendedData, data, fExtendedDataSize);
360
361   return fExtendedDataSize;
362 }
363
364 //______________________________________________________________________________
365 UInt_t AliRawEventHeaderBase::Get(const char *datamember) const
366 {
367   // The method to get a data member from the header object
368   // Except for the data members of the base class, all the
369   // other header data should be retrieved ONLY by this method
370   // The name of the data member should be supplied without "f"
371   // in front
372
373   char buf[256] = "f";
374   strncat(buf,datamember,sizeof(buf)-2);
375
376   TDataMember *member = IsA()->GetDataMember(buf);
377   if (!member) {
378     AliFatal(Form("No data member %s is found! Check the raw data version!",buf));
379     return 0;
380   }
381
382   if (member->GetArrayDim() != 0) {
383     AliFatal(Form("Member %s is an array! Use the GetP() method!",buf));
384     return 0;
385   }
386
387   if (strcmp(member->GetTypeName(),"UInt_t") != 0) {
388     AliFatal(Form("Member %s is not of type UInt_t!",buf));
389     return 0;
390   }
391
392   const void *pointer = (char *)this+member->GetOffset();
393
394   return *((UInt_t *)pointer);
395 }
396
397 //______________________________________________________________________________
398 const UInt_t* AliRawEventHeaderBase::GetP(const char *datamember) const
399 {
400   // The method to get a data member from the header object
401   // Except for the data members of the base class, all the
402   // other header data should be retrieved ONLY by this method
403   // The name of the data member should be supplied without "f"
404   // in front
405
406   char buf[256] = "f";
407   strncat(buf,datamember,sizeof(buf)-2);
408
409   TDataMember *member = IsA()->GetDataMember(buf);
410   if (!member) {
411     AliFatal(Form("No data member %s is found! Check the raw data version!",buf));
412     return 0;
413   }
414
415   //  if (member->GetArrayDim() == 0) {
416   //    AliFatal(Form("Member %s is not an array! Use the Get() method!",buf));
417   //    return 0;
418   //  }
419
420   if (strcmp(member->GetTypeName(),"UInt_t") != 0) {
421     AliFatal(Form("Member %s is not of type UInt_t*!",buf));
422     return 0;
423   }
424
425   const void *pointer = (char *)this+member->GetOffset();
426
427   return (const UInt_t*)pointer;
428 }
429
430 //_____________________________________________________________________________
431 void AliRawEventHeaderBase::Print( const Option_t* opt ) const
432 {
433   // Dumps the event or sub-event
434   // header fields
435
436   cout << opt << "  Event size: " << GetEventSize() << endl;
437   cout << opt << "  Event header size: " << GetHeadSize() << endl;
438   cout << opt << "  Event header version: " << GetMajorVersion() << "." << GetMinorVersion() << endl;
439   cout << opt << "  Event type: " << Get("Type") << "( " << GetTypeName() << " )" << endl;
440   cout << opt << "  Run Number: " << Get("RunNb") << endl;
441   const UInt_t *id = GetP("Id");
442   cout << opt << "  Period: " << (((id)[0]>>4)&0x0fffffff) << " Orbit: " << ((((id)[0]<<20)&0xf00000)|(((id)[1]>>12)&0xfffff)) << " Bunch-crossing: " << ((id)[1]&0x00000fff) << endl;
443   cout << opt << "  Trigger pattern: " << GetP("TriggerPattern")[0] << "-" << GetP("TriggerPattern")[1] << endl;
444   cout << opt << "  Detector pattern: " << Get("DetectorPattern") << endl;
445   cout << opt << "  Type attribute: " << GetP("TypeAttribute")[0] << "-" << GetP("TypeAttribute")[1] << "-" << GetP("TypeAttribute")[2] << endl;
446   cout << opt << "  GDC: " << Get("GdcId") << " LDC: " << Get("LdcId") << endl;
447 }
448
449 //_____________________________________________________________________________
450 void AliRawEventHeaderBase::AddEqIndex(Int_t index)
451 {
452   // Adds an equipment by changing properly
453   // the first and last equipment indexes
454   if (fFirstEqIndex < 0) fFirstEqIndex = index; 
455   if (index > fLastEqIndex) fLastEqIndex = index;
456 }
457
458 //_____________________________________________________________________________
459 void AliRawEventHeaderBase::Reset()
460 {
461   fFirstEqIndex = fLastEqIndex = -1;
462 }
463
464 //______________________________________________________________________________
465 void AliRawEventHeaderBase::Streamer(TBuffer &R__b)
466 {
467    // Stream an object of class AliRawEventHeaderBase.
468
469    if (R__b.IsReading()) {
470       UInt_t R__s, R__c;
471       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
472       if (R__v > 3) {
473         R__b.ReadClassBuffer(AliRawEventHeaderBase::Class(),this,R__v,R__s,R__c);
474         return;
475       }
476       TObject::Streamer(R__b);
477       R__b >> fSize;
478       R__b >> fMagic;
479       R__b >> fHeadSize;
480       R__b >> fVersion;
481       R__b >> fExtendedDataSize;
482       delete [] fExtendedData;
483       fExtendedData = new char[fExtendedDataSize];
484       R__b.ReadFastArray(fExtendedData,fExtendedDataSize);
485       R__b >> fIsSwapped;
486       R__b.CheckByteCount(R__s, R__c, AliRawEventHeaderBase::IsA());
487    } else {
488       R__b.WriteClassBuffer(AliRawEventHeaderBase::Class(),this);
489    }
490 }