HIPO  4.3.0
High Performance Output data format for experimental physics
reader.cpp
Go to the documentation of this file.
1 //******************************************************************************
2 //* ██╗ ██╗██╗██████╗ ██████╗ ██╗ ██╗ ██████╗ *
3 //* ██║ ██║██║██╔══██╗██╔═══██╗ ██║ ██║ ██╔═████╗ *
4 //* ███████║██║██████╔╝██║ ██║ ███████║ ██║██╔██║ *
5 //* ██╔══██║██║██╔═══╝ ██║ ██║ ╚════██║ ████╔╝██║ *
6 //* ██║ ██║██║██║ ╚██████╔╝ ██║██╗╚██████╔╝ *
7 //* ╚═╝ ╚═╝╚═╝╚═╝ ╚═════╝ ╚═╝╚═╝ ╚═════╝ *
8 //************************ Jefferson National Lab (2017) ***********************
9 /*
10  * Copyright (c) 2017. Jefferson Lab (JLab). All rights reserved. Permission
11  * to use, copy, modify, and distribute this software and its documentation
12  * for educational, research, and not-for-profit purposes, without fee and
13  * without a signed licensing agreement.
14  *
15  * IN NO EVENT SHALL JLAB BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL
16  * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
17  * OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JLAB HAS
18  * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19  *
20  * JLAB SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE. THE HIPO DATA FORMAT SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF
23  * ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". JLAB HAS NO OBLIGATION TO
24  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
25  *
26  * This software was developed under the United States Government license.
27  * For more information contact author at gavalian@jlab.org
28  * Department of Experimental Nuclear Physics, Jefferson Lab.
29  */
30  /*
31  * File: reader.cpp
32  * Author: gavalian
33  *
34  * Additions by: dglazier
35  * Created on April 11, 2017, 2:07 PM
36  */
37 
42 #include "reader.h"
43 #include "constants.h"
44 #include "hipoexceptions.h"
45 #include "record.h"
46 
47 #include <cstdlib>
52 namespace hipo {
59  printWarning();
60  //hipoutils.printLogo();
61  }
62 
67  if(inputStream.is_open()==true){
68  inputStream.close();
69  }
70  }
71 
72  void reader::about(){
73  hipoutils.printLogo();
74  }
75  /*
76  * Open file, if file stream is open, it is closed first.
77  * At open time verification of file structure is performed.
78  * If the signature does not match EVIO/HIPO template, the
79  * file will be closed and warning message is printed.
80  */
81  void reader::open(const char *filename){
82 
83  if(inputStream.is_open()==true){
84  inputStream.close();
85 
86  }
87 
88  inputStream.open(filename, std::ios::binary);
89  inputStream.seekg(0,std::ios_base::end);
90  inputStreamSize = inputStream.tellg();
91  inputStream.seekg(0,std::ios_base::beg);
92  if(inputStream.is_open()==false){
93  printf("[ERROR] something went wrong with openning file : %s\n",
94  filename);
95  return;
96  }
97  readHeader();
98  readIndex();
99 }
100 
105  void reader::readHeader(){
106 
107  std::vector<char> headerBuffer;
108  headerBuffer.resize(80);
109  inputStream.read(&headerBuffer[0],80);
110 
111  header.uniqueid = *(reinterpret_cast<int *>(&headerBuffer[FH_UNIQUE_WORD_OFFSET]));
112  header.filenumber = *(reinterpret_cast<int *>(&headerBuffer[FH_FILE_NUMBER_OFFSET]));
113  header.headerLength = *(reinterpret_cast<int *>(&headerBuffer[FH_HEADER_LENGTH_OFFSET]));
114  header.recordCount = *(reinterpret_cast<int *>(&headerBuffer[FH_RECORD_COUNT_OFFSET]));
115 
116  header.indexArrayLength = *(reinterpret_cast<int *>(&headerBuffer[FH_INDEX_ARRAY_LEN_OFFSET]));
117  int word_8 = *(reinterpret_cast<int *>(&headerBuffer[FH_BIT_INFO_OFFSET]));
118 
119  header.userHeaderLength = *(reinterpret_cast<int *>(&headerBuffer[FH_USER_HEADER_LEN_OFFSET]));
120  header.magicNumber = *(reinterpret_cast<int *>(&headerBuffer[FH_MAGIC_NUMBER_OFFSET]));
121  header.userRegister = *(reinterpret_cast<long *>(&headerBuffer[FH_USER_REGISTER_OFFSET]));
122  header.trailerPosition = *(reinterpret_cast<long *>(&headerBuffer[FH_TRAILER_POS_OFFSET]));
123  // If magic word is reversed, then the file was written in BIG_ENDIAN
124  // format, the bytes have to be swapped
125  if(header.magicNumber==HEADER_MAGIC_BE){
126  printf(" THIS FILE IS BIG ENDIAN: SWAPPING BYTES\n");
127  header.uniqueid = __builtin_bswap32(header.uniqueid);
128  header.filenumber = __builtin_bswap32(header.filenumber);
129  header.headerLength = __builtin_bswap32(header.headerLength);
130  header.recordCount = __builtin_bswap32(header.recordCount);
131  header.userHeaderLength = __builtin_bswap32(header.userHeaderLength);
132  header.indexArrayLength = __builtin_bswap32(header.indexArrayLength);
133  word_8 = __builtin_bswap32(word_8);
134  header.userRegister = __builtin_bswap64(header.userRegister);
135  header.trailerPosition = __builtin_bswap64(header.trailerPosition);
136  }
137 
138  header.version = word_8&BITINFO_VERSION_MASK;
139  header.bitInfo = (word_8>>BITINFO_VERSION_BITS)&STRUCT_SIZE_MASK;
140  header.firstRecordPosition = 4*header.headerLength + header.userHeaderLength;
141  if(_verbose){
142  printf("----------------------------------------\n");
143  printf("**** reader:: header version : %d \n",header.version);
144  printf("**** reader:: header length : %d \n",header.headerLength*4);
145  printf("**** reader:: first record pos : %lu\n",header.firstRecordPosition);
146  printf("**** reader:: trailer position : %lu\n",header.trailerPosition);
147  printf("**** reader:: file size : %lu\n",inputStreamSize);
148  printf("----------------------------------------\n");
149  }
150  //int *signature = reinterpret_cast<int *>(&headerBuffer[0]);
151  //printf("signature = %X\n",(unsigned int) *signature);
152  //std::cout << "signature = " << std::ios::hex << (*signature) << '\n';
153 }
154 
162 void reader::readIndex(){
163 
164  inputRecord.readRecord(inputStream,header.trailerPosition,0);
165  if(_verbose)printf("*** reader:: trailer record event count : %d\n",inputRecord.getEventCount());
166 
167  //a catch for broken files
168  //can use hiporeader.getNRecords() to see if succesfull (=-1 if not)
169  if(inputRecord.getEventCount()==0) return;//dglazier
170 
171  hipo::event event;
172  inputRecord.readHipoEvent(event,0);
173  if(_verbose)event.show();
174  hipo::structure base;
175  event.getStructure(base,FILE_INDEX_GROUP,FILE_INDEX_ITEM);
176  if(_verbose)base.show();
177  readerEventIndex.clear();
178  int rows = base.getSize()/32;
179 
180  //printf(" number of rows = %d\n",rows);
181  for(int i = 0; i < rows; i++){
182  long position = base.getLongAt( i*8);
183  int entries = base.getIntAt ( rows*12 + i*4);
184  long uid1 = base.getLongAt( rows*16 + i*8);
185  if(tagsToRead.size()==0){
186  readerEventIndex.addSize(entries);
187  readerEventIndex.addPosition(position);
188  } else {
189  bool accept = false;
190  for(long jr : tagsToRead){
191  if(jr==uid1) accept = true;
192  }
193  if(accept==true){
194  readerEventIndex.addSize(entries);
195  readerEventIndex.addPosition(position);
196  }
197  }
198  }
199  readerEventIndex.rewind();
200  //printf("**** reader:: header version : %d \n",readerEventIndex.getMaxEvents());
201  if(_verbose)printf("**** reader:: # of events : %d \n",readerEventIndex.getMaxEvents());
202 }
207 bool reader::hasNext(){ return readerEventIndex.canAdvance();}
208 
209 /*
210  * Reads next event from the file, the event pointer is automatically
211  * advanced to the next event.
212  */
213 bool reader::next(hipo::event &dataevent){
214  if(readerEventIndex.canAdvance()==false) return false;
215  int recordNumber = readerEventIndex.getRecordNumber();
216  readerEventIndex.advance();
217  int recordToBeRead = readerEventIndex.getRecordNumber();
218  if(recordToBeRead!=recordNumber){
219  long position = readerEventIndex.getPosition(recordToBeRead);
220  inputRecord.readRecord(inputStream,position,0);
221  /*printf(" record changed from %d to %d at event %d total event # %d\n",
222  recordNumber, recordToBeRead,readerEventIndex.getEventNumber(),
223  readerEventIndex.getMaxEvents());*/
224  }
225  int eventNumberInRecord = readerEventIndex.getRecordEventNumber();
226  inputRecord.readHipoEvent(dataevent,eventNumberInRecord);
227  return true;
228 }
229 /*
230  * Reads current event from the record without advancing the current event
231  * position. Multiple reads can be performed on the same event.
232  */
233 void reader::read(hipo::event &dataevent){
234  int eventNumberInRecord = readerEventIndex.getRecordEventNumber();
235  inputRecord.readHipoEvent(dataevent,eventNumberInRecord);
236 }
237 /*
238  * Reads the structure from the current event without copying the event
239  * buffer.
240  */
241 void reader::getStructure(hipo::structure &structure,int group, int item){
243  int eventNumberInRecord = readerEventIndex.getRecordEventNumber();
244  inputRecord.getData(data,eventNumberInRecord);
246 }
247 /*
248  * Reads the structure from the current event without copying the event
249  * buffer and without copying the structure buffer. This should be used
250  * very carefully, since it sets the pointer of the structure directly
251  * to the buffer owned by the record. If new record is loaded this
252  * structure will be pointing to the wrong part of the buffer.
253  */
256  int eventNumberInRecord = readerEventIndex.getRecordEventNumber();
257  inputRecord.getData(data,eventNumberInRecord);
259 }
260 
261 bool reader::next(std::vector<hipo::bank> &list){
262  bool status = next();
263  if(status==false) return false;
264  read(event);
265  //printf("---------- reader::next() event with next()\n");
266  //event.show();
267  for(size_t k = 0; k < list.size(); k++){
268  event.read(list[k]);
269  }
270  return true;
271 }
272 
273 std::vector<hipo::bank> reader::getBanks(std::vector<std::string> names){
274  std::vector<hipo::bank> list;
275  readDictionary(factory);
276  for(size_t k = 0; k < names.size(); k++){
277  hipo::bank b(factory.getSchema(names[k].c_str()),48);
278  list.push_back(b);
279  }
280  return list;
281 }
282 
283  void reader::readUserConfig(std::map<std::string,std::string> &mapConfig){
284 
285  if(inputStream.is_open()==false){
286  throw hipo::file_error("hipo::reader::readUserConfig: file is not open");
287  }
288  long position = header.headerLength*4;
289  hipo::record dictRecord;
290  dictRecord.readRecord(inputStream,position,0);
291  int nevents = dictRecord.getEventCount();
292  hipo::structure sKey;
293  hipo::structure sConfig;
295  for(int i = 0; i < nevents; i++){
296  dictRecord.readHipoEvent(event,i);
297  event.getStructure(sKey,CONFIG_GROUP,CONFIG_KEY_ITEM);
298  event.getStructure(sConfig,CONFIG_GROUP,CONFIG_STRING_ITEM);
299  if(sKey.getSize()>0){
300  mapConfig[std::string(sKey.getStringAt(0).c_str())] = std::string(sConfig.getStringAt(0).c_str());
301  }
302  //printf("schema : %s\n",schemaStructure.getStringAt(0).c_str());
303  //dict.parse(schemaStructure.getStringAt(0).c_str());
304  }
305 }
306 
307 /*
308  * Reads the dictionary for the file. C++ API is reading packed dictionary
309  * format from node (120,2), parses each schema and creates schema dictionary.
310  */
312  if(inputStream.is_open()==false){
313  throw hipo::file_error("hipo::reader::readDictionary: file is not open");
314  }
315  long position = header.headerLength*4;
316  hipo::record dictRecord;
317  dictRecord.readRecord(inputStream,position,0);
318  int nevents = dictRecord.getEventCount();
319  hipo::structure schemaStructure;
321  for(int i = 0; i < nevents; i++){
322  dictRecord.readHipoEvent(event,i);
323  event.getStructure(schemaStructure,DICT_GROUP,DICT_ITEM);
324  //printf("schema : %s\n",schemaStructure.getStringAt(0).c_str());
325  dict.parse(schemaStructure.getStringAt(0).c_str());
326  }
327 }
335  if(readerEventIndex.canAdvance()==false) return false;
336  int recordNumber = readerEventIndex.getRecordNumber();
337  readerEventIndex.advance();
338  int recordToBeRead = readerEventIndex.getRecordNumber();
339  if(recordToBeRead!=recordNumber){
340  long position = readerEventIndex.getPosition(recordToBeRead);
341  inputRecord.readRecord(inputStream,position,0);
342  /*printf(" record changed from %d to %d at event %d total event # %d\n",
343  recordNumber, recordToBeRead,readerEventIndex.getEventNumber(),
344  readerEventIndex.getMaxEvents());*/
345  }
346  return true;
347 }
348 /*
349  * Moves the pointer of the event to the event number provided. If the event
350  * number is within the same record no reading is done, otherwise the appropriate
351  * record is loaded and event indicies are updated.
352  */
353 bool reader::gotoEvent(int eventNumber){
354  int recordNumber = readerEventIndex.getRecordNumber();
355 
356  //goto event in index if exists, if not return
357  if(readerEventIndex.gotoEvent(eventNumber)==false){
358  printf("[WARNING] hipo::reader::gotoEvent event %d greater than max events = %d, will stay at current event\n",
359  eventNumber, readerEventIndex.getMaxEvents());
360  return false;
361  }
362 
363  int recordToBeRead = readerEventIndex.getRecordNumber();
364 
365  if(recordToBeRead!=recordNumber){
366  //readerEventIndex.show(); - commented out by gg, this was for debugging
367  long position = readerEventIndex.getPosition(recordToBeRead);
368  inputRecord.readRecord(inputStream,position,0);
369  /*printf(" record changed from %d to %d at event %d total event # %d\n",
370  recordNumber, recordToBeRead,readerEventIndex.getEventNumber(),
371  readerEventIndex.getMaxEvents());*/
372  }
373  return true;
374 }
375 /*
376  * Moves the current event pointer to the new record # irec. The readerIndex
377  * is updated so current event is the first event in loaded record.
378  */
379 bool reader::gotoRecord(int irec){
380  bool status = readerEventIndex.gotoRecord(irec);
381  if(status==false) return false;
382  long position = readerEventIndex.getPosition(irec);
383  inputRecord.readRecord(inputStream,position,0);
384  return true;
385 }
386 
387 //dglazier
388 // Added by Derek - for some reason
389 // Use gotoRecord instead, since it checks first if record exists.
390 bool reader::loadRecord(int irec){
391  long position = readerEventIndex.getPosition(irec);
392  inputRecord.readRecord(inputStream,position,0);
393  return readerEventIndex.loadRecord(irec);
394 }
395 
397  long position = readerEventIndex.getPosition(irec);
398  record.readRecord(inputStream,position,0);
399  return true;
400 }
401 
402 std::vector<int> reader::getInt( const char *bank, const char *column, int max ){
403  std::vector<int> rowvec;
404  std::vector<hipo::bank> b = getBanks({bank});
405  int item = b[0].getSchema().getEntryOrder(column);
406  int counter = 0;
407  while(next(b)==true){
408  for(int row = 0 ; row < b[0].getRows();row++){
409  rowvec.push_back(b[0].getInt(item,row));
410  counter++;
411  }
412  if(max>0&&counter>max) break;
413  }
414  return rowvec;
415 }
416 
417 std::vector<float> reader::getFloat(const char *bank, const char *column, int max ){
418  std::vector<float> rowvec;
419  std::vector<hipo::bank> b = getBanks({bank});
420  int item = b[0].getSchema().getEntryOrder(column);
421  int counter = 0;
422  while(next(b)==true){
423  for(int row = 0 ; row < b[0].getRows();row++){
424  rowvec.push_back(b[0].getFloat(item,row));
425  counter++;
426  }
427  if(max>0&&counter>max) break;
428  }
429  return rowvec;
430 }
431 
432 //dglazier
434  if(readerEventIndex.canAdvanceInRecord()==false) return false;
435  readerEventIndex.advance();
436  return true;
437 }
443  #ifndef __LZ4__
444  std::cout << "******************************************************" << std::endl;
445  std::cout << "* WARNING: *" << std::endl;
446  std::cout << "* This library war compiled without LZ4 support. *" << std::endl;
447  std::cout << "* Reading and writing compressed buffers will not *" << std::endl;
448  std::cout << "* work. However un-compressed file I/O will work. *" << std::endl;
449  std::cout << "******************************************************" << std::endl;
450  #endif
451  }
452 }
453 
454 //*****************************************************************************
455 //* Implementation of reader index class to keep track of events and records
456 //*****************************************************************************
457 //--
458 namespace hipo {
462 void readerIndex::addSize(int size){
463  if(recordEvents.size()==0){
464  recordEvents.push_back(0);
465  recordEvents.push_back(size);
466  } else {
467  int cz = recordEvents[recordEvents.size()-1] + size;
468  recordEvents.push_back(cz);
469  }
470 }
476  return (currentEvent<getMaxEvents()-1);
477 }
485  if(recordEvents.size()==0) return false;
486  if(currentEvent+1<recordEvents[currentRecord+1]){
487  currentEvent++;
488  currentRecordEvent++;
489  return true;
490  }
491  if(recordEvents.size() < currentRecord + 2 + 1){
492  printf("advance(): Warning, reached the limit of events.\n");
493  return false;
494  }
495  currentEvent++;
496  currentRecord++;
497  currentRecordEvent = 0;
498  return true;
499 }
500 /*
501  * Moves the event pointer to give event number. The record number and
502  * relative event number in the record are recalculated.
503  */
504 bool readerIndex::gotoEvent(int eventNumber){
505  //check if event exists
506  if(eventNumber>=getMaxEvents()) return false;
507  // The proper record number is found by binary search through records array
508  //------
509  // G.Gavalian (July 25/2022)
510  // Changed the eventNumber -> eventNumber+1 in binary search. Now it changes the
511  // record number properly and starts with record event number from 0
512  // I think this was a bug.
513 
514  std::vector<int>::iterator l_bound =
515  std::lower_bound(recordEvents.begin(), recordEvents.end(), eventNumber+1);
516 
517 
518  long position = (l_bound - recordEvents.begin()) - 1;
519  //printf("event # %d , lbound = %ld\n",eventNumber,position);
520  currentRecord = position;
521  currentRecordEvent = eventNumber - recordEvents[currentRecord];
522  currentEvent = eventNumber;
523  return true;
524 }
525 
526 
528  for(size_t i = 0; i < recordEvents.size(); i++){
529  printf("record = %8zu, %8d\n",i,recordEvents[i]);
530  }
531  }
537  if(recordEvents.size()==0) return 0;
538  return recordEvents[recordEvents.size()-1];
539 }
540 /*
541  * Sets the event pointer to the first event of provided record.
542  * Originally implemented by Derek as loadRecord(), renamed for
543  * consistency but left the old one not to break clas12root code.
544  */
545 bool readerIndex::gotoRecord(int irec){
546  if(irec==0){
547  currentEvent=-1; currentRecord=0; currentRecordEvent = -1;
548  return true;
549  }
550  if(irec+1>(int)recordEvents.size())
551  return false;
552  currentEvent = recordEvents[irec]-1; currentRecord=irec;
553  currentRecordEvent = -1;
554  return true;
555 }
556 //dglazier
560 bool readerIndex::loadRecord(int irec){
561  if(irec==0){
562  currentEvent=-1;
563  currentRecord=0;
564  currentRecordEvent = -1;
565  return true;
566  }
567  if(irec+1>(int)recordEvents.size())
568  return false;
569 
570  currentEvent = recordEvents[irec]-1;
571  currentRecord=irec;
572  currentRecordEvent = -1;
573  return true;
574 }
575 //dglazier
582  return (currentEvent<recordEvents[currentRecord+1]-1);
583 }
584 
585 }
Represents a HIPO bank, a tabular data structure with rows and typed columns.
Definition: bank.h:352
Lightweight wrapper for a raw data pointer with type, size, and offset metadata.
Definition: record.h:91
const char * getDataPtr()
Return the raw data pointer.
Definition: record.h:120
Collection of schema definitions, typically read from a HIPO file header.
Definition: dictionary.h:248
bool parse(const char *schemaString)
Parse a full schema string and add it to the dictionary.
Definition: dictionary.cpp:130
schema & getSchema(const char *name)
Retrieve a schema by name.
Definition: dictionary.h:271
Represents a HIPO event, a container for multiple structures/banks.
Definition: event.h:77
static void getStructureNoCopy(const char *buffer, hipo::structure &str, int group, int item)
Extract a structure from a raw buffer without copying the data.
Definition: event.cpp:97
void getStructure(hipo::structure &str, int group, int item)
Extract a structure from the event by group and item identifiers.
Definition: event.cpp:72
Exception thrown for HIPO file I/O errors (e.g., file not found, read failure).
int getMaxEvents()
Definition: reader.cpp:536
void addPosition(long position)
Register a record position.
Definition: reader.h:209
bool gotoRecord(int irec)
Jump to a specific record.
Definition: reader.cpp:545
bool loadRecord(int irec)
Load a specific record by index.
Definition: reader.cpp:560
void clear()
Remove all record entries from the index.
Definition: reader.h:222
void show()
Print index information to stdout.
Definition: reader.cpp:527
bool canAdvanceInRecord()
Check if more events remain in the current record.
Definition: reader.cpp:581
void rewind()
Reset the index to the beginning (before the first event).
Definition: reader.h:218
int getRecordEventNumber()
Definition: reader.h:201
bool canAdvance()
Check if there are more events to read.
Definition: reader.cpp:475
bool advance()
Advance to the next event, loading new records as needed.
Definition: reader.cpp:484
void addSize(int size)
Register a record with the given number of events.
Definition: reader.cpp:462
int getRecordNumber()
Definition: reader.h:199
bool gotoEvent(int eventNumber)
Jump to a specific event number.
Definition: reader.cpp:504
long getPosition(int index)
Definition: reader.h:211
void read(hipo::event &dataevent)
Read the current event into the given event object.
Definition: reader.cpp:233
std::vector< hipo::bank > getBanks(std::vector< std::string > names)
Create bank objects for the given bank names.
Definition: reader.cpp:273
void readDictionary(hipo::dictionary &dict)
Read the schema dictionary from the file header.
Definition: reader.cpp:311
void getStructureNoCopy(hipo::structure &structure, int group, int item)
Extract a structure without copying (zero-copy).
Definition: reader.cpp:254
bool nextInRecord()
Advance to the next event within the current record.
Definition: reader.cpp:433
void printWarning()
Print a warning message (e.g., end of file).
Definition: reader.cpp:442
reader()
Default constructor.
Definition: reader.cpp:58
bool loadRecord(int irec)
Load a specific record by index into the internal buffer.
Definition: reader.cpp:390
void getStructure(hipo::structure &structure, int group, int item)
Extract a structure from the current event by group and item.
Definition: reader.cpp:241
bool next()
Advance to the next event.
Definition: reader.cpp:334
std::vector< int > getInt(const char *bank, const char *column, int max=-1)
Read all integer values from a bank column across events.
Definition: reader.cpp:402
void open(const char *filename)
Open a HIPO file for reading.
Definition: reader.cpp:81
bool hasNext()
Check if more events are available without advancing.
Definition: reader.cpp:207
void about()
Print file information to stdout.
Definition: reader.cpp:72
bool gotoRecord(int irec)
Jump to a specific record.
Definition: reader.cpp:379
bool gotoEvent(int eventNumber)
Jump to a specific event number.
Definition: reader.cpp:353
std::vector< float > getFloat(const char *bank, const char *column, int max=-1)
Read all float values from a bank column across events.
Definition: reader.cpp:417
void readUserConfig(std::map< std::string, std::string > &mapConfig)
Read user configuration key-value pairs from the file header.
Definition: reader.cpp:283
Represents a single HIPO record containing multiple events.
Definition: record.h:196
int getEventCount()
Return the number of events stored in this record.
Definition: record.cpp:393
void readRecord(std::ifstream &stream, long position, int dataOffset)
Read a record from a file stream at the specified position.
Definition: record.cpp:61
void readHipoEvent(hipo::event &event, int index)
Read an event and populate a hipo::event object.
Definition: record.cpp:485
void getData(hipo::data &data, int index)
Get a lightweight data handle for a specific event.
Definition: record.cpp:411
Low-level data structure representing a HIPO structure.
Definition: bank.h:64
int getSize() const noexcept
Definition: bank.h:106
virtual void show() const
Display the structure contents to standard output.
Definition: bank.cpp:122
long getLongAt(int index) const noexcept
Definition: bank.h:180
int getIntAt(int index) const noexcept
Definition: bank.h:154
std::string getStringAt(int index)
Definition: bank.cpp:127
static void printLogo()
Prints the HIPO library logo to standard output.
Definition: utils.cpp:85
Exception classes for HIPO library error handling.
Definition: bank.cpp:47
constexpr uint32_t HEADER_MAGIC_BE
Definition: constants.h:9
constexpr int FILE_INDEX_ITEM
Definition: constants.h:61
constexpr int FH_USER_HEADER_LEN_OFFSET
Definition: constants.h:26
constexpr int FH_INDEX_ARRAY_LEN_OFFSET
Definition: constants.h:24
constexpr int DICT_GROUP
Definition: constants.h:54
constexpr int CONFIG_GROUP
Definition: constants.h:57
constexpr int CONFIG_KEY_ITEM
Definition: constants.h:58
constexpr int FH_RECORD_COUNT_OFFSET
Definition: constants.h:23
constexpr int FH_FILE_NUMBER_OFFSET
Definition: constants.h:21
constexpr int FILE_INDEX_GROUP
Definition: constants.h:60
constexpr int FH_UNIQUE_WORD_OFFSET
Definition: constants.h:20
constexpr uint32_t BITINFO_VERSION_MASK
Definition: constants.h:104
constexpr int FH_BIT_INFO_OFFSET
Definition: constants.h:25
constexpr int FH_HEADER_LENGTH_OFFSET
Definition: constants.h:22
constexpr int BITINFO_VERSION_BITS
Definition: constants.h:105
constexpr int FH_USER_REGISTER_OFFSET
Definition: constants.h:28
constexpr int FH_MAGIC_NUMBER_OFFSET
Definition: constants.h:27
constexpr int FH_TRAILER_POS_OFFSET
Definition: constants.h:29
constexpr int DICT_ITEM
Definition: constants.h:55
constexpr uint32_t STRUCT_SIZE_MASK
Definition: constants.h:126
constexpr int CONFIG_STRING_ITEM
Definition: constants.h:59
Sequential and random-access reader for HIPO files with event filtering and dictionary support.
HIPO record reading and event extraction.
int userHeaderLength
User header length in bytes.
Definition: reader.h:135
long userRegister
User-defined 64-bit register.
Definition: reader.h:137
int filenumber
Split file number.
Definition: reader.h:129
int recordCount
Number of records in the file.
Definition: reader.h:131
int magicNumber
Magic number for endianness detection (0xc0da0100)
Definition: reader.h:136
int bitInfo
Bit-packed info (version, flags, padding)
Definition: reader.h:133
int indexArrayLength
Length of the index array in bytes.
Definition: reader.h:132
int uniqueid
File format identifier (HIPO: 0x43455248)
Definition: reader.h:128
long firstRecordPosition
File offset to the first record.
Definition: reader.h:139
long trailerPosition
File offset to trailer header (0 = none)
Definition: reader.h:138
int headerLength
Header length in 32-bit words (usually 14)
Definition: reader.h:130
int version
File format version.
Definition: reader.h:134