00001
00002
00003
00004
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
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
00163
00164
00165
00166
00167
00168
00169
00170 const TMidas_BANK_HEADER *pbkh = (const TMidas_BANK_HEADER*)fData;
00171 TMidas_BANK *pbk;
00172
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
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
00238
00239 *pdata = NULL;
00240 return 0;
00241 }
00242
00243 void TMidasEvent::Print(const char *option) const
00244 {
00245
00246
00247
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:
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:
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:
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:
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:
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
00385
00386
00387
00388
00389
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
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
00421 *pbk = (TMidas_BANK32 *) ((char*) (*pbk + 1) + length_adjusted);
00422 }
00423
00424 TMidas_BANK32 *bk4 = (TMidas_BANK32*)(((char*) *pbk) + 4);
00425
00426
00427
00428 if ((*pbk)->fType > TID_MAX)
00429 {
00430 if (bk4->fType <= TID_MAX)
00431 {
00432 *pbk = bk4;
00433
00434
00435 }
00436 else
00437 {
00438
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
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
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
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
00516
00517
00518
00519
00520
00521 if (pbh->fFlags < 0x10000 && ! force)
00522 return 0;
00523
00524 if (pbh->fDataSize == 0x6d783f3c)
00525 return 1;
00526
00527 if (pbh->fDataSize == 0x3c3f786d)
00528 return 1;
00529
00530 if (dssw > fEventHeader.fDataSize + 100)
00531 return 1;
00532
00533
00534
00535
00536 DWORD_SWAP(&pbh->fDataSize);
00537 DWORD_SWAP(&pbh->fFlags);
00538
00539
00540
00541 bool b32 = IsBank32();
00542
00543 pbk = (TMidas_BANK *) (pbh + 1);
00544 pbk32 = (TMidas_BANK32 *) pbk;
00545
00546
00547
00548 while ((char*) pbk < (char*) pbh + pbh->fDataSize + sizeof(TMidas_BANK_HEADER)) {
00549
00550
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
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