mirror of
https://github.com/sesps/EventBuilder_Skeleton.git
synced 2025-04-22 07:08:50 -04:00
203 lines
5.2 KiB
C++
203 lines
5.2 KiB
C++
/*
|
|
CompassFile.cpp
|
|
Wrapper class around a shared pointer to an ifstream. Here the shared pointer is used
|
|
to overcome limitations of the ifstream class, namely that it is written such that ifstream
|
|
cannot be modified by move semantics. Contains all information needed to parse a single binary
|
|
CompassFile. Currently has a class wide defined buffer size; may want to make this user input
|
|
in the future.
|
|
|
|
Written by G.W. McCann Oct. 2020
|
|
*/
|
|
#include "CompassFile.h"
|
|
|
|
namespace EventBuilder {
|
|
|
|
CompassFile::CompassFile() :
|
|
m_filename(""), m_bufferIter(nullptr), m_bufferEnd(nullptr), m_smap(nullptr), m_hitUsedFlag(true), m_hitsize(0), m_buffersize(0),
|
|
m_file(std::make_shared<std::ifstream>()), m_eofFlag(false)
|
|
{
|
|
}
|
|
|
|
CompassFile::CompassFile(const std::string& filename) :
|
|
m_filename(""), m_bufferIter(nullptr), m_bufferEnd(nullptr), m_smap(nullptr), m_hitUsedFlag(true), m_hitsize(0), m_buffersize(0),
|
|
m_file(std::make_shared<std::ifstream>()), m_eofFlag(false)
|
|
{
|
|
Open(filename);
|
|
}
|
|
|
|
CompassFile::CompassFile(const std::string& filename, int bsize) :
|
|
m_filename(""), m_bufferIter(nullptr), m_bufferEnd(nullptr), m_smap(nullptr), m_hitUsedFlag(true), m_bufsize(bsize), m_hitsize(0),
|
|
m_buffersize(0), m_file(std::make_shared<std::ifstream>()), m_eofFlag(false)
|
|
{
|
|
Open(filename);
|
|
}
|
|
|
|
CompassFile::~CompassFile()
|
|
{
|
|
Close();
|
|
}
|
|
|
|
void CompassFile::Open(const std::string& filename)
|
|
{
|
|
m_eofFlag = false;
|
|
m_hitUsedFlag = true;
|
|
m_filename = filename;
|
|
m_file->open(m_filename, std::ios::binary | std::ios::in);
|
|
|
|
m_file->seekg(0, std::ios_base::end);
|
|
m_size = m_file->tellg();
|
|
if(m_size == 2)
|
|
{
|
|
m_eofFlag = true;
|
|
}
|
|
else
|
|
{
|
|
m_file->seekg(0, std::ios_base::beg);
|
|
ReadHeader();
|
|
m_nHits = m_size/m_hitsize;
|
|
m_buffersize = m_hitsize*m_bufsize;
|
|
m_hitBuffer.resize(m_buffersize);
|
|
}
|
|
}
|
|
|
|
void CompassFile::Close()
|
|
{
|
|
if(IsOpen())
|
|
{
|
|
m_file->close();
|
|
}
|
|
}
|
|
|
|
void CompassFile::ReadHeader()
|
|
{
|
|
if(!IsOpen())
|
|
{
|
|
EVB_WARN("Unable to read header from file. State not validated", m_filename);
|
|
return;
|
|
}
|
|
|
|
char* header = new char[2];
|
|
m_file->read(header, 2);
|
|
m_header = *((uint16_t*)header);
|
|
m_hitsize = 16; //default hitsize of 16 bytes
|
|
if(IsEnergy())
|
|
m_hitsize += 2;
|
|
if(IsEnergyCalibrated())
|
|
m_hitsize += 8;
|
|
if(IsEnergyShort())
|
|
m_hitsize += 2;
|
|
if(IsWaves())
|
|
{
|
|
m_hitsize += 5;
|
|
char* firstHit = new char[m_hitsize]; //A compass hit by default has 24 bytes (at least in our setup)
|
|
m_file->read(firstHit, m_hitsize);
|
|
firstHit += m_hitsize - 4;
|
|
uint32_t nsamples = *((uint32_t*) firstHit);
|
|
m_hitsize += nsamples * 2; //Each sample is a 2 byte data value
|
|
m_file->seekg(0, std::ios_base::beg);
|
|
m_file->read(header, 2);
|
|
delete[] firstHit;
|
|
}
|
|
|
|
delete[] header;
|
|
}
|
|
|
|
/*
|
|
GetNextHit() is the function which... gets the next hit
|
|
Has to check if the buffer needs refilled/filled for the first time
|
|
Upon pulling a hit, sets the UsedFlag to false, letting the next level know
|
|
that the hit should be free game.
|
|
|
|
If the file cannot be opened, signals as though file is EOF
|
|
*/
|
|
bool CompassFile::GetNextHit()
|
|
{
|
|
if(!IsOpen()) return true;
|
|
|
|
if((m_bufferIter == nullptr || m_bufferIter == m_bufferEnd) && !IsEOF())
|
|
{
|
|
GetNextBuffer();
|
|
}
|
|
|
|
if(!IsEOF())
|
|
{
|
|
ParseNextHit();
|
|
m_hitUsedFlag = false;
|
|
}
|
|
|
|
return m_eofFlag;
|
|
}
|
|
|
|
/*
|
|
GetNextBuffer() ... self-explanatory name
|
|
Note tht this is where the EOF flag is set. The EOF is only singaled
|
|
after the LAST buffer is completely read (i.e literally no more data). ifstream sets its eof
|
|
bit upon pulling the last buffer, but this class waits until that entire
|
|
last buffer is read to singal EOF (the true end of file).
|
|
*/
|
|
void CompassFile::GetNextBuffer()
|
|
{
|
|
|
|
if(m_file->eof())
|
|
{
|
|
m_eofFlag = true;
|
|
return;
|
|
}
|
|
|
|
m_file->read(m_hitBuffer.data(), m_hitBuffer.size());
|
|
|
|
m_bufferIter = m_hitBuffer.data();
|
|
m_bufferEnd = m_bufferIter + m_file->gcount(); //one past the last datum
|
|
|
|
}
|
|
|
|
void CompassFile::ParseNextHit()
|
|
{
|
|
|
|
m_currentHit.board = *((uint16_t*)m_bufferIter);
|
|
m_bufferIter += 2;
|
|
m_currentHit.channel = *((uint16_t*)m_bufferIter);
|
|
m_bufferIter += 2;
|
|
m_currentHit.timestamp = *((uint64_t*)m_bufferIter);
|
|
m_bufferIter += 8;
|
|
if(IsEnergy())
|
|
{
|
|
m_currentHit.energy = *((uint16_t*)m_bufferIter);
|
|
m_bufferIter += 2;
|
|
}
|
|
if(IsEnergyCalibrated())
|
|
{
|
|
m_currentHit.energyCalibrated = *((uint64_t*)m_bufferIter);
|
|
m_bufferIter += 8;
|
|
}
|
|
if(IsEnergyShort())
|
|
{
|
|
m_currentHit.energyShort = *((uint16_t*)m_bufferIter);
|
|
m_bufferIter += 2;
|
|
}
|
|
m_currentHit.flags = *((uint32_t*)m_bufferIter);
|
|
m_bufferIter += 4;
|
|
if(IsWaves())
|
|
{
|
|
m_currentHit.waveCode = *((uint8_t*)m_bufferIter);
|
|
m_bufferIter += 1;
|
|
m_currentHit.Ns = *((uint32_t*)m_bufferIter);
|
|
m_bufferIter += 4;
|
|
if(m_currentHit.samples.size() != m_currentHit.Ns)
|
|
m_currentHit.samples.resize(m_currentHit.Ns);
|
|
for(size_t i=0; i<m_currentHit.samples.size(); i++)
|
|
{
|
|
m_currentHit.samples[i] = *((uint16_t*)m_bufferIter);
|
|
m_bufferIter += 2;
|
|
}
|
|
}
|
|
|
|
if(m_smap != nullptr)
|
|
{ //memory safety
|
|
int gchan = m_currentHit.channel + m_currentHit.board*m_channels_per_board;
|
|
m_currentHit.timestamp += m_smap->GetShift(gchan);
|
|
}
|
|
|
|
}
|
|
|
|
} |