TMidasEvent.cxx

Go to the documentation of this file.
00001 //
00002 //  TMidasEvent.cxx.
00003 //
00004 //  $Id$
00005 //
00006 
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <time.h>
00010 #include <string.h>
00011 #include <assert.h>
00012 
00013 #include "TMidasEvent.h"
00014 
00015 TMidasEvent::TMidasEvent()
00016 {
00017   fData = NULL;
00018   fAllocatedByUs = false;
00019 
00020   fBanksN = 0;
00021   fBankList = NULL;
00022 
00023   fEventHeader.fEventId      = 0;
00024   fEventHeader.fTriggerMask  = 0;
00025   fEventHeader.fSerialNumber = 0;
00026   fEventHeader.fTimeStamp    = 0;
00027   fEventHeader.fDataSize     = 0;
00028 }
00029 
00030 void TMidasEvent::Copy(const TMidasEvent& rhs)
00031 {
00032   fEventHeader = rhs.fEventHeader;
00033 
00034   fData        = (char*)malloc(fEventHeader.fDataSize);
00035   assert(fData);
00036   memcpy(fData, rhs.fData, fEventHeader.fDataSize);
00037   fAllocatedByUs = true;
00038 
00039   fBanksN      = rhs.fBanksN;
00040   fBankList    = strdup(rhs.fBankList);
00041   assert(fBankList);
00042 }
00043 
00044 TMidasEvent::TMidasEvent(const TMidasEvent &rhs)
00045 {
00046   Copy(rhs);
00047 }
00048 
00049 TMidasEvent::~TMidasEvent()
00050 {
00051   Clear();
00052 }
00053 
00054 TMidasEvent& TMidasEvent::operator=(const TMidasEvent &rhs)
00055 {
00056   if (&rhs != this)
00057     Clear();
00058 
00059   this->Copy(rhs);
00060   return *this;
00061 }
00062 
00063 void TMidasEvent::Clear()
00064 {
00065   if (fBankList)
00066     free(fBankList);
00067   fBankList = NULL;
00068 
00069   if (fData && fAllocatedByUs)
00070     free(fData);
00071   fData = NULL;
00072 
00073   fAllocatedByUs = false;
00074   fBanksN = 0;
00075 
00076   fEventHeader.fEventId      = 0;
00077   fEventHeader.fTriggerMask  = 0;
00078   fEventHeader.fSerialNumber = 0;
00079   fEventHeader.fTimeStamp    = 0;
00080   fEventHeader.fDataSize     = 0;
00081 }
00082 
00083 void TMidasEvent::SetData(uint32_t size, char* data)
00084 {
00085   fEventHeader.fDataSize = size;
00086   assert(!fAllocatedByUs);
00087   assert(IsGoodSize());
00088   fData = data;
00089   fAllocatedByUs = false;
00090   SwapBytes(false);
00091 }
00092 
00093 uint16_t TMidasEvent::GetEventId() const
00094 {
00095   return fEventHeader.fEventId;
00096 }
00097 
00098 uint16_t TMidasEvent::GetTriggerMask() const
00099 {
00100   return fEventHeader.fTriggerMask;
00101 }
00102 
00103 uint32_t TMidasEvent::GetSerialNumber() const
00104 {
00105   return fEventHeader.fSerialNumber;
00106 }
00107 
00108 uint32_t TMidasEvent::GetTimeStamp() const
00109 {
00110   return fEventHeader.fTimeStamp;
00111 }
00112 
00113 uint32_t TMidasEvent::GetDataSize() const
00114 {
00115   return fEventHeader.fDataSize;
00116 }
00117 
00118 char* TMidasEvent::GetData()
00119 {
00120   if (!fData)
00121     AllocateData();
00122   return fData;
00123 }
00124 
00125 TMidas_EVENT_HEADER * TMidasEvent::GetEventHeader()
00126 {
00127   return &fEventHeader;
00128 }
00129 
00130 bool TMidasEvent::IsGoodSize() const
00131 {
00132   return fEventHeader.fDataSize > 0 && fEventHeader.fDataSize <= 500 * 1024 * 1024;
00133 }
00134 
00135 bool TMidasEvent::IsBank32() const
00136 {
00137   return ((TMidas_BANK_HEADER *)fData)->fFlags & (1<<4);
00138 }
00139 
00140 int TMidasEvent::LocateBank(const void *unused, const char *name, void **pdata) const
00141 {
00142   /// See FindBank()
00143 
00144   int bktype, bklen;
00145 
00146   int status = FindBank(name, &bklen, &bktype, pdata);
00147   
00148   if (!status)
00149     {
00150       *pdata = NULL;
00151       return 0;
00152     }
00153 
00154   return bklen;
00155 }
00156 
00157 static const unsigned TID_SIZE[] = {0, 1, 1, 1, 2, 2, 4, 4, 4, 4, 8, 1, 0, 0, 0, 0, 0};
00158 static const unsigned TID_MAX = (sizeof(TID_SIZE)/sizeof(TID_SIZE[0]));
00159 
00160 int TMidasEvent::FindBank(const char* name, int *bklen, int *bktype, void **pdata) const
00161 {
00162   /// Find a data bank.
00163   /// \param [in] name Name of the data bank to look for.
00164   /// \param [out] bklen Number of array elements in this bank.
00165   /// \param [out] bktype Bank data type (MIDAS TID_xxx).
00166   /// \param [out] pdata Pointer to bank data, Returns NULL if bank not found.
00167   /// \returns 1 if bank found, 0 otherwise.
00168   ///
00169 
00170   const TMidas_BANK_HEADER *pbkh = (const TMidas_BANK_HEADER*)fData; 
00171   TMidas_BANK *pbk;
00172   //uint32_t dname;
00173 
00174   if (((pbkh->fFlags & (1<<4)) > 0)) {
00175 #if 0
00176     TMidas_BANK32 *pbk32;
00177     pbk32 = (TMidas_BANK32 *) (pbkh + 1);
00178     memcpy(&dname, name, 4);
00179     do {
00180       if (*((uint32_t *) pbk32->fName) == dname) {
00181         *pdata = pbk32 + 1;
00182         if (TID_SIZE[pbk32->fType & 0xFF] == 0)
00183           *bklen = pbk32->fDataSize;
00184         else
00185           *bklen = pbk32->fDataSize / TID_SIZE[pbk32->fType & 0xFF];
00186 
00187         *bktype = pbk32->fType;
00188         return 1;
00189       }
00190       pbk32 = (TMidas_BANK32 *) ((char*) (pbk32 + 1) +
00191                           (((pbk32->fDataSize)+7) & ~7));
00192     } while ((char*) pbk32 < (char*) pbkh + pbkh->fDataSize + sizeof(TMidas_BANK_HEADER));
00193 #endif
00194 
00195     TMidas_BANK32 *pbk32 = NULL;
00196 
00197     while (1) {
00198       IterateBank32(&pbk32, (char**)pdata);
00199       //printf("looking for [%s] got [%s]\n", name, pbk32->fName);
00200       if (pbk32 == NULL)
00201         break;
00202 
00203       if (name[0]==pbk32->fName[0] &&
00204           name[1]==pbk32->fName[1] &&
00205           name[2]==pbk32->fName[2] &&
00206           name[3]==pbk32->fName[3]) {
00207         
00208         if (TID_SIZE[pbk32->fType & 0xFF] == 0)
00209           *bklen = pbk32->fDataSize;
00210         else
00211           *bklen = pbk32->fDataSize / TID_SIZE[pbk32->fType & 0xFF];
00212         
00213         *bktype = pbk32->fType;
00214         return 1;
00215       }
00216     }
00217   } else {
00218     pbk = (TMidas_BANK *) (pbkh + 1);
00219     do {
00220       if (name[0]==pbk->fName[0] &&
00221           name[1]==pbk->fName[1] &&
00222           name[2]==pbk->fName[2] &&
00223           name[3]==pbk->fName[3]) {
00224         *pdata = pbk + 1;
00225         if (TID_SIZE[pbk->fType & 0xFF] == 0)
00226           *bklen = pbk->fDataSize;
00227         else
00228           *bklen = pbk->fDataSize / TID_SIZE[pbk->fType & 0xFF];
00229 
00230         *bktype = pbk->fType;
00231         return 1;
00232       }
00233       pbk = (TMidas_BANK *) ((char*) (pbk + 1) + (((pbk->fDataSize)+7) & ~7));
00234     } while ((char*) pbk < (char*) pbkh + pbkh->fDataSize + sizeof(TMidas_BANK_HEADER));
00235   }
00236   //
00237   // bank not found
00238   //
00239   *pdata = NULL;
00240   return 0;
00241 }
00242 
00243 void TMidasEvent::Print(const char *option) const
00244 {
00245   /// Print data held in this class.
00246   /// \param [in] option If 'a' (for "all") then the raw data will be
00247   /// printed out too.
00248   ///
00249   
00250   time_t t = (time_t)fEventHeader.fTimeStamp;
00251 
00252   printf("Event start:\n");
00253   printf("  event id:       0x%04x\n", fEventHeader.fEventId);
00254   printf("  trigger mask:   0x%04x\n", fEventHeader.fTriggerMask);
00255   printf("  serial number:%8d\n", fEventHeader.fSerialNumber);
00256   printf("  time stamp:     %d, %s", fEventHeader.fTimeStamp, ctime(&t));
00257   printf("  data size:    %8d\n", fEventHeader.fDataSize);
00258   if ((fEventHeader.fEventId & 0xffff) == 0x8000)
00259     {
00260       printf("Begin of run %d\n", fEventHeader.fSerialNumber);
00261     }
00262   else if ((fEventHeader.fEventId & 0xffff) == 0x8001)
00263     {
00264       printf("End of run %d\n", fEventHeader.fSerialNumber);
00265     }
00266   else if (fBanksN <= 0)
00267     {
00268       printf("TMidasEvent::Print: Use SetBankList() before Print() to print bank data\n");
00269     }
00270   else
00271     {
00272       printf("Banks: %s\n", fBankList);
00273 
00274       for (int i = 0; i < fBanksN * 4; i += 4)
00275         {
00276           int bankLength = 0;
00277           int bankType = 0;
00278           void *pdata = 0;
00279           int found = FindBank(&fBankList[i], &bankLength, &bankType, &pdata);
00280           
00281           printf("Bank %c%c%c%c, length %6d, type %2d\n",
00282                  fBankList[i], fBankList[i+1], fBankList[i+2], fBankList[i+3],
00283                  bankLength, bankType);
00284 
00285           if (option[0] == 'a' && found)
00286             switch (bankType)
00287               {
00288               case 4: // TID_WORD
00289                 for (int j = 0; j < bankLength; j++)
00290                   printf("0x%04x%c", ((uint16_t*)pdata)[j], (j%10==9)?'\n':' ');
00291                 printf("\n");
00292                 break;
00293               case 6: // TID_DWORD
00294                 for (int j = 0; j < bankLength; j++)
00295                   printf("0x%08x%c", ((uint32_t*)pdata)[j], (j%10==9)?'\n':' ');
00296                 printf("\n");
00297                 break;
00298               case 7: // TID_nd280 (like a DWORD?)
00299                 for (int j = 0; j < bankLength; j++)
00300                   printf("0x%08x%c", ((uint32_t*)pdata)[j], (j%10==9)?'\n':' ');
00301                 printf("\n");
00302                 break;
00303               case 9: // TID_FLOAT
00304                 for (int j = 0; j < bankLength; j++)
00305                   printf("%.8g%c", ((float*)pdata)[j], (j%10==9)?'\n':' ');
00306                 printf("\n");
00307                 break;
00308               case 10: // TID_DOUBLE
00309                 for (int j = 0; j < bankLength; j++)
00310                   printf("%.16g%c", ((double*)pdata)[j], (j%10==9)?'\n':' ');
00311                 printf("\n");
00312                 break;
00313               default:
00314                 printf("TMidasEvent::Print: Do not know how to print bank of type %d\n", bankType);
00315                 break;
00316               }
00317         }
00318     }
00319 }
00320 
00321 void TMidasEvent::AllocateData()
00322 {
00323   assert(!fAllocatedByUs);
00324   assert(IsGoodSize());
00325   fData = (char*)malloc(fEventHeader.fDataSize);
00326   assert(fData);
00327   fAllocatedByUs = true;
00328 }
00329 
00330 const char* TMidasEvent::GetBankList() const
00331 {
00332   return fBankList;
00333 }
00334 
00335 int TMidasEvent::SetBankList()
00336 {
00337   if (fEventHeader.fEventId <= 0)
00338     return 0;
00339 
00340   if (fBankList)
00341     return fBanksN;
00342 
00343   int listSize = 0;
00344 
00345   fBanksN = 0;
00346 
00347   TMidas_BANK32 *pmbk32 = NULL;
00348   TMidas_BANK *pmbk = NULL;
00349   char *pdata = NULL;
00350 
00351   while (1)
00352     {
00353       if (fBanksN*4 >= listSize)
00354         {
00355           listSize += 400;
00356           fBankList = (char*)realloc(fBankList, listSize);
00357         }
00358 
00359       if (IsBank32())
00360         {
00361           IterateBank32(&pmbk32, &pdata);
00362           if (pmbk32 == NULL)
00363             break;
00364           memcpy(fBankList+fBanksN*4, pmbk32->fName, 4);
00365           fBanksN++;
00366         }
00367       else
00368         {
00369           IterateBank(&pmbk, &pdata);
00370           if (pmbk == NULL)
00371             break;
00372           memcpy(fBankList+fBanksN*4, pmbk->fName, 4);
00373           fBanksN++;
00374         }
00375     }
00376 
00377   fBankList[fBanksN*4] = 0;
00378 
00379   return fBanksN;
00380 }
00381 
00382 int TMidasEvent::IterateBank(TMidas_BANK **pbk, char **pdata) const
00383 {
00384   /// Iterates through banks inside an event. The function can be used
00385   /// to enumerate all banks of an event.
00386   /// \param [in] pbk Pointer to the bank header, must be NULL for the
00387   /// first call to this function. Returns NULL if no more banks
00388   /// \param [in] pdata Pointer to data area of bank. Returns NULL if no more banks
00389   /// \returns Size of bank in bytes or 0 if no more banks.
00390   ///
00391   const TMidas_BANK_HEADER* event = (const TMidas_BANK_HEADER*)fData;
00392 
00393   if (*pbk == NULL)
00394     *pbk = (TMidas_BANK *) (event + 1);
00395   else
00396     *pbk = (TMidas_BANK *) ((char*) (*pbk + 1) + ((((*pbk)->fDataSize)+7) & ~7));
00397 
00398   *pdata = (char*)((*pbk) + 1);
00399 
00400   if ((char*) *pbk >=  (char*) event + event->fDataSize + sizeof(TMidas_BANK_HEADER))
00401     {
00402       *pbk = NULL;
00403       *pdata = NULL;
00404       return 0;
00405     }
00406 
00407   return (*pbk)->fDataSize;
00408 }
00409 
00410 int TMidasEvent::IterateBank32(TMidas_BANK32 **pbk, char **pdata) const
00411 {
00412   /// See IterateBank()
00413 
00414   const TMidas_BANK_HEADER* event = (const TMidas_BANK_HEADER*)fData;
00415   if (*pbk == NULL)
00416     *pbk = (TMidas_BANK32 *) (event + 1);
00417   else {
00418     uint32_t length = (*pbk)->fDataSize;
00419     uint32_t length_adjusted = (length+7) & ~7;
00420     //printf("length %6d 0x%08x, 0x%08x\n", length, length, length_adjusted);
00421     *pbk = (TMidas_BANK32 *) ((char*) (*pbk + 1) + length_adjusted);
00422   }
00423 
00424   TMidas_BANK32 *bk4 = (TMidas_BANK32*)(((char*) *pbk) + 4);
00425 
00426   //printf("iterate bank32: pbk 0x%p, align %d, type %d %d, name [%s], next [%s], TID_MAX %d\n", *pbk, (int)( ((uint64_t)(*pbk))&7), (*pbk)->fType, bk4->fType, (*pbk)->fName, bk4->fName, TID_MAX);
00427 
00428   if ((*pbk)->fType > TID_MAX) // bad - unknown bank type - it's invalid MIDAS file?
00429     {
00430       if (bk4->fType <= TID_MAX) // okey, this is a malformed T2K/ND280 data file
00431         {
00432           *pbk = bk4;
00433 
00434           //printf("iterate bank32: pbk 0x%p, align %d, type %d, name [%s]\n", *pbk, (int)(((uint64_t)(*pbk))&7), (*pbk)->fType, (*pbk)->fName);
00435         }
00436       else
00437         {
00438           // truncate invalid data
00439           *pbk = NULL;
00440           *pdata = NULL;
00441           return 0;
00442         }
00443     }
00444 
00445   *pdata = (char*)((*pbk) + 1);
00446 
00447   if ((char*) *pbk >= (char*)event  + event->fDataSize + sizeof(TMidas_BANK_HEADER))
00448     {
00449       *pbk = NULL;
00450       *pdata = NULL;
00451       return 0;
00452     }
00453 
00454   return (*pbk)->fDataSize;
00455 }
00456 
00457 typedef uint8_t BYTE;
00458 
00459 /// Byte swapping routine.
00460 ///
00461 #define QWORD_SWAP(x) { BYTE _tmp;       \
00462 _tmp= *((BYTE *)(x));                    \
00463 *((BYTE *)(x)) = *(((BYTE *)(x))+7);     \
00464 *(((BYTE *)(x))+7) = _tmp;               \
00465 _tmp= *(((BYTE *)(x))+1);                \
00466 *(((BYTE *)(x))+1) = *(((BYTE *)(x))+6); \
00467 *(((BYTE *)(x))+6) = _tmp;               \
00468 _tmp= *(((BYTE *)(x))+2);                \
00469 *(((BYTE *)(x))+2) = *(((BYTE *)(x))+5); \
00470 *(((BYTE *)(x))+5) = _tmp;               \
00471 _tmp= *(((BYTE *)(x))+3);                \
00472 *(((BYTE *)(x))+3) = *(((BYTE *)(x))+4); \
00473 *(((BYTE *)(x))+4) = _tmp; }
00474 
00475 /// Byte swapping routine.
00476 ///
00477 #define DWORD_SWAP(x) { BYTE _tmp;       \
00478 _tmp= *((BYTE *)(x));                    \
00479 *((BYTE *)(x)) = *(((BYTE *)(x))+3);     \
00480 *(((BYTE *)(x))+3) = _tmp;               \
00481 _tmp= *(((BYTE *)(x))+1);                \
00482 *(((BYTE *)(x))+1) = *(((BYTE *)(x))+2); \
00483 *(((BYTE *)(x))+2) = _tmp; }
00484 
00485 /// Byte swapping routine.
00486 ///
00487 #define WORD_SWAP(x) { BYTE _tmp;        \
00488 _tmp= *((BYTE *)(x));                    \
00489 *((BYTE *)(x)) = *(((BYTE *)(x))+1);     \
00490 *(((BYTE *)(x))+1) = _tmp; }
00491 
00492 void TMidasEvent::SwapBytesEventHeader()
00493 {
00494   WORD_SWAP(&fEventHeader.fEventId);
00495   WORD_SWAP(&fEventHeader.fTriggerMask);
00496   DWORD_SWAP(&fEventHeader.fSerialNumber);
00497   DWORD_SWAP(&fEventHeader.fTimeStamp);
00498   DWORD_SWAP(&fEventHeader.fDataSize);
00499 }
00500 
00501 int TMidasEvent::SwapBytes(bool force)
00502 {
00503   TMidas_BANK_HEADER *pbh;
00504   TMidas_BANK *pbk;
00505   TMidas_BANK32 *pbk32;
00506   void *pdata;
00507   uint16_t type;
00508 
00509   pbh = (TMidas_BANK_HEADER *) fData;
00510 
00511   uint32_t dssw = pbh->fDataSize;
00512 
00513   DWORD_SWAP(&dssw);
00514 
00515   //printf("SwapBytes %d, flags 0x%x 0x%x\n", force, pbh->fFlags, pbh->fDataSize);
00516   //printf("evh.datasize: 0x%08x, SwapBytes: %d, pbh.flags: 0x%08x, pbh.datasize: 0x%08x swapped 0x%08x\n", fEventHeader.fDataSize, force, pbh->fFlags, pbh->fDataSize, dssw);
00517 
00518   //
00519   // only swap if flags in high 16-bit
00520   //
00521   if (pbh->fFlags < 0x10000 && ! force)
00522     return 0;
00523 
00524   if (pbh->fDataSize == 0x6d783f3c) // string "<xml..." in wrong-endian format
00525     return 1;
00526 
00527   if (pbh->fDataSize == 0x3c3f786d) // string "<xml..."
00528     return 1;
00529 
00530   if (dssw > fEventHeader.fDataSize + 100) // swapped data size looks wrong. do not swap.
00531     return 1;
00532 
00533   //
00534   // swap bank header
00535   //
00536   DWORD_SWAP(&pbh->fDataSize);
00537   DWORD_SWAP(&pbh->fFlags);
00538   //
00539   // check for 32-bit banks
00540   //
00541   bool b32 = IsBank32();
00542 
00543   pbk = (TMidas_BANK *) (pbh + 1);
00544   pbk32 = (TMidas_BANK32 *) pbk;
00545   //
00546   // scan event
00547   //
00548   while ((char*) pbk < (char*) pbh + pbh->fDataSize + sizeof(TMidas_BANK_HEADER)) {
00549     //
00550     // swap bank header
00551     //
00552     if (b32) {
00553       DWORD_SWAP(&pbk32->fType);
00554       DWORD_SWAP(&pbk32->fDataSize);
00555       pdata = pbk32 + 1;
00556       type = (uint16_t) pbk32->fType;
00557     } else {
00558       WORD_SWAP(&pbk->fType);
00559       WORD_SWAP(&pbk->fDataSize);
00560       pdata = pbk + 1;
00561       type = pbk->fType;
00562     }
00563     //
00564     // pbk points to next bank
00565     //
00566     if (b32) {
00567       assert(pbk32->fDataSize < fEventHeader.fDataSize + 100);
00568       pbk32 = (TMidas_BANK32 *) ((char*) (pbk32 + 1) +
00569                           (((pbk32->fDataSize)+7) & ~7));
00570       pbk = (TMidas_BANK *) pbk32;
00571     } else {
00572       assert(pbk->fDataSize < fEventHeader.fDataSize + 100);
00573       pbk = (TMidas_BANK *) ((char*) (pbk + 1) +  (((pbk->fDataSize)+7) & ~7));
00574       pbk32 = (TMidas_BANK32 *) pbk;
00575     }
00576 
00577     switch (type) {
00578     case 4:
00579     case 5:
00580       while (pdata < pbk) {
00581         WORD_SWAP(pdata);
00582         pdata = ((char*)pdata) + 2;
00583       }
00584       break;
00585     case 6:
00586     case 7:
00587     case 8:
00588     case 9:
00589       while (pdata < pbk) {
00590         DWORD_SWAP(pdata);
00591         pdata = ((char*)pdata) + 4;
00592       }
00593       break;
00594     case 10:
00595       while (pdata < pbk) {
00596         QWORD_SWAP(pdata);
00597         pdata = ((char*)pdata) + 8;
00598       }
00599       break;
00600     }
00601   }
00602   return 1;
00603 }
00604 
00605 // end

Generated on 12 Feb 2016 for ROOT Analyzer by  doxygen 1.6.1