full imc raw format revision
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
#define HEXSHOW
|
||||
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
|
113
lib/imc_block.hpp
Normal file
113
lib/imc_block.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef IMCBLOCK
|
||||
#define IMCBLOCK
|
||||
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
namespace imc
|
||||
{
|
||||
// define "magic bytes" announcing start/end of blocks and separation within
|
||||
const unsigned char ch_bgn_ = 0x7c, ch_end_ = 0x3b, ch_sep_ = 0x2c;
|
||||
|
||||
// single parameter (in a block) is determined by offset of its first/last byte
|
||||
class parameter
|
||||
{
|
||||
// offset of first/last byte of parameter
|
||||
unsigned long int begin_, end_;
|
||||
|
||||
public:
|
||||
|
||||
parameter(unsigned long int begin, unsigned long int end):
|
||||
begin_(begin), end_(end)
|
||||
{
|
||||
if ( end_ <= begin_ )
|
||||
{
|
||||
throw std::logic_error("parameter: offset of first byte larger than last byte's offset");
|
||||
}
|
||||
}
|
||||
|
||||
// access members
|
||||
unsigned long int& begin() { return begin_; }
|
||||
unsigned long int& end() { return end_; }
|
||||
};
|
||||
|
||||
// define properties of a raw file block
|
||||
class block
|
||||
{
|
||||
// associated key
|
||||
key thekey_;
|
||||
|
||||
// offset (in byte) of first (=ch_bgn_) and last byte (=ch_end_) of block
|
||||
// w.r.t. to entire raw file
|
||||
unsigned long int begin_, end_;
|
||||
|
||||
// name and buffer of associated raw file
|
||||
std::string raw_file_;
|
||||
const std::vector<unsigned char>* buffer_;
|
||||
|
||||
// offset of first/last byte of parameters in block (separated by ch_sep_)
|
||||
// w.r.t. to first byte of block (=0)
|
||||
std::vector<parameter> parameters_;
|
||||
|
||||
public:
|
||||
|
||||
// constructor
|
||||
block(key thekey, unsigned long int begin, unsigned long int end,
|
||||
std::string raw_file, std::vector<unsigned char>* buffer):
|
||||
thekey_(thekey)
|
||||
{
|
||||
if ( keys.count(thekey.name_) != 1 ) throw std::logic_error("unknown key");
|
||||
begin_ = begin;
|
||||
end_ = end;
|
||||
if ( end_ <= begin_ )
|
||||
{
|
||||
throw std::logic_error("block: offset of first byte larger than last byte's offset");
|
||||
}
|
||||
raw_file_ = raw_file;
|
||||
buffer_ = buffer;
|
||||
}
|
||||
|
||||
// access members
|
||||
imc::key& get_key() { return thekey_; }
|
||||
unsigned long int& get_begin() { return begin_; }
|
||||
unsigned long int& get_end() { return end_; }
|
||||
|
||||
// get parameter
|
||||
std::vector<unsigned char> extract_parameter(parameter& param)
|
||||
{
|
||||
// check parameter w.r.t. to block
|
||||
if ( param.begin() < begin_ || param.end() > end_ )
|
||||
{
|
||||
throw std::logic_error("inconsistent parameter offsets");
|
||||
}
|
||||
std::vector<unsigned char> parambuff(buffer_->begin()+begin_+param.begin(),
|
||||
buffer_->begin()+begin_+param.end());
|
||||
return parambuff;
|
||||
}
|
||||
|
||||
// get info string
|
||||
std::string get_info(int width = 20)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<std::setw(width)<<std::left<<"block-key:"<<thekey_.name_<<"\n"
|
||||
<<std::setw(width)<<std::left<<"begin:"<<begin_<<"\n"
|
||||
<<std::setw(width)<<std::left<<"end:"<<end_<<"\n"
|
||||
<<std::setw(width)<<std::left<<"rawfile:"<<raw_file_<<"\n"
|
||||
<<std::setw(width)<<std::left<<"buffersize:"<<buffer_->size()<<"\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------//
|
89
lib/imc_key.hpp
Normal file
89
lib/imc_key.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef IMCKEY
|
||||
#define IMCKEY
|
||||
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
namespace imc
|
||||
{
|
||||
|
||||
// define properties of marker/key
|
||||
struct key
|
||||
{
|
||||
// (non)critical key
|
||||
bool critical_;
|
||||
// name of key (two uppercase letters)
|
||||
std::string name_;
|
||||
// short description
|
||||
std::string description_;
|
||||
// version of marker
|
||||
int version_;
|
||||
|
||||
// constructor
|
||||
key(bool critical, std::string name,
|
||||
std::string description = std::string(""), int version = 1)
|
||||
{
|
||||
critical_ = critical;
|
||||
if ( name.size() != 2 ) throw std::logic_error("invalid key name");
|
||||
name_ = name;
|
||||
description_ = description;
|
||||
version_ = version;
|
||||
}
|
||||
|
||||
// get info string
|
||||
std::string get_info(int width = 20)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<std::setw(width)<<std::left<<"critical:"<<(critical_?"yes":"no")<<"\n"
|
||||
<<std::setw(width)<<std::left<<"name:"<<name_<<"\n"
|
||||
<<std::setw(width)<<std::left<<"decription:"<<description_<<"\n"
|
||||
<<std::setw(width)<<std::left<<"version:"<<version_<<"\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// define (non)critial markers/keys
|
||||
std::map<std::string,key> keys = {
|
||||
|
||||
// critical keys
|
||||
{"CF", key(true,"CF","format version and processor",1)},
|
||||
{"CK", key(true,"CK","start of group of keys",1)},
|
||||
{"CB", key(true,"CB","group of channels",1)},
|
||||
{"CT", key(true,"CT","text definition",1)},
|
||||
{"CG", key(true,"CG","group of components",1)},
|
||||
{"CD", key(true,"CD","abscissa description",1)},
|
||||
{"CD", key(true,"CD","abscissa description",2)},
|
||||
{"CZ", key(true,"CZ","scaling of z-axis",1)},
|
||||
{"CC", key(true,"CC","start of component",1)},
|
||||
{"CP", key(true,"CP","buffer, datatype and samples of component ",1)},
|
||||
{"Cb", key(true,"Cb","buffer description",1)},
|
||||
{"CR", key(true,"CR","permissible range of values in component",1)},
|
||||
{"CN", key(true,"CN","name and comment of channel",1)},
|
||||
{"CS", key(true,"CS","raw binary data",1)},
|
||||
{"CI", key(true,"CI","single numerical value",1)},
|
||||
{"Ca", key(true,"Ca","add reference key",1)},
|
||||
|
||||
// noncritical keys
|
||||
{"NO", key(false,"NO","origin of data",1)},
|
||||
{"NT", key(false,"NT","timestamp of trigger",1)},
|
||||
{"ND", key(false,"ND","(color) display properties",1)},
|
||||
{"NU", key(false,"NU","user defined key",1)},
|
||||
{"Np", key(false,"Np","property of channel",1)},
|
||||
{"NE", key(false,"NE","extraction rule for BUS channels",1)}
|
||||
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------//
|
135
lib/imc_raw.hpp
Normal file
135
lib/imc_raw.hpp
Normal file
@@ -0,0 +1,135 @@
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#ifndef IMCRAW
|
||||
#define IMCRAW
|
||||
|
||||
#include <fstream>
|
||||
// #include <filesystem>
|
||||
|
||||
#include "hexshow.hpp"
|
||||
#include "imc_key.hpp"
|
||||
#include "imc_block.hpp"
|
||||
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
namespace imc
|
||||
{
|
||||
class raw
|
||||
{
|
||||
// (path of) raw-file and its basename
|
||||
std::string raw_file_, file_name_;
|
||||
|
||||
// buffer of raw-file
|
||||
std::vector<unsigned char> buffer_;
|
||||
|
||||
// list of imc-blocks
|
||||
std::vector<block> rawblocks_;
|
||||
|
||||
public:
|
||||
|
||||
// constructor
|
||||
raw() {};
|
||||
raw(std::string raw_file): raw_file_(raw_file) { this->parse(); };
|
||||
|
||||
// provide new raw-file
|
||||
void set_file(std::string raw_file)
|
||||
{
|
||||
raw_file_ = raw_file;
|
||||
this->parse();
|
||||
}
|
||||
|
||||
// list all blocks in buffer
|
||||
void parse()
|
||||
{
|
||||
// open file and put data in buffer
|
||||
try {
|
||||
std::ifstream fin(raw_file_.c_str(),std::ifstream::binary);
|
||||
if ( !fin.good() ) throw std::runtime_error("failed to open file");
|
||||
std::vector<unsigned char> buffer((std::istreambuf_iterator<char>(fin)),
|
||||
(std::istreambuf_iterator<char>()));
|
||||
buffer_ = buffer;
|
||||
fin.close();
|
||||
} catch ( const std::exception& e ) {
|
||||
throw std::runtime_error(
|
||||
std::string("failed to open raw-file and stream data in buffer: ") + e.what()
|
||||
);
|
||||
}
|
||||
|
||||
// start parsing raw-blocks in buffer
|
||||
for ( std::vector<unsigned char>::iterator it=buffer_.begin();
|
||||
it!=buffer_.end(); ++it )
|
||||
{
|
||||
// check for "magic byte"
|
||||
if ( *it == ch_bgn_ )
|
||||
{
|
||||
// check for (non)critical key
|
||||
if ( *(it+1) == 0x43 || *(it+1) == 0x4e )
|
||||
{
|
||||
// compose entire key
|
||||
std::string newkey = { (char)*(it+1), (char)*(it+2) };
|
||||
|
||||
// check for known keys
|
||||
if ( keys.count(newkey) == 1 )
|
||||
{
|
||||
// expecting ch_sep_ after key
|
||||
if ( *(it+3) == ch_sep_ )
|
||||
{
|
||||
// extract key version
|
||||
std::string vers("");
|
||||
unsigned long int pos = 4;
|
||||
while ( *(it+pos) != ch_sep_ )
|
||||
{
|
||||
vers.push_back((char)*(it+pos));
|
||||
pos++;
|
||||
}
|
||||
int version = std::stoi(vers);
|
||||
|
||||
// get block length
|
||||
std::string leng("");
|
||||
pos++;
|
||||
while ( *(it+pos) != ch_sep_ )
|
||||
{
|
||||
leng.push_back((char)*(it+pos));
|
||||
pos++;
|
||||
}
|
||||
unsigned long length = std::stoul(leng);
|
||||
|
||||
// declare corresponding key and block
|
||||
imc::key bkey( (*(it+1)-0x43)==0, newkey,
|
||||
imc::keys.at(newkey).description_, version );
|
||||
imc::block blk(bkey,it-buffer_.begin(),
|
||||
it-buffer_.begin()+8+length,
|
||||
raw_file_, &buffer_);
|
||||
|
||||
// add block to list
|
||||
rawblocks_.push_back(blk);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error( std::string("invalid block or corrupt buffer at byte: ")
|
||||
+ std::to_string(it-buffer_.begin()) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(std::string("unknown IMC key: ") + newkey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// get blocks
|
||||
std::vector<imc::block>& blocks()
|
||||
{
|
||||
return rawblocks_;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------//
|
Reference in New Issue
Block a user