//---------------------------------------------------------------------------// #ifndef IMCRAW #define IMCRAW #include // #include #include "hexshow.hpp" #include "imc_key.hpp" #include "imc_block.hpp" #include "imc_datatype.hpp" #include "imc_object.hpp" #include "imc_result.hpp" #include "imc_channel.hpp" //---------------------------------------------------------------------------// namespace imc { class raw { // (path of) raw-file and its basename std::string raw_file_, file_name_; // buffer of raw-file std::vector buffer_; // list and map of imc-blocks std::vector rawblocks_; std::map mapblocks_; // check computational complexity for parsing blocks unsigned long int cplxcnt_; // list groups and channels with their affiliate blocks std::map channel_envs_; public: // constructor raw() {}; raw(std::string raw_file): raw_file_(raw_file) { set_file(raw_file); }; // provide new raw-file void set_file(std::string raw_file) { raw_file_ = raw_file; this->fill_buffer(); this->parse_blocks(); this->generate_block_map(); this->generate_channel_env(); } private: // open file and stream data into buffer void fill_buffer() { // 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 buffer((std::istreambuf_iterator(fin)), (std::istreambuf_iterator())); 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() ); } } // parse all raw blocks in buffer void parse_blocks() { // reset counter to identify computational complexity cplxcnt_ = 0; // start parsing raw-blocks in buffer for ( std::vector::iterator it=buffer_.begin(); it!=buffer_.end(); ++it ) { cplxcnt_++; // check for "magic byte" if ( *it == ch_bgn_ ) { // check for (non)critical key if ( *(it+1) == imc::key_crit_ || *(it+1) == imc::key_non_crit_ ) { // compose (entire) key std::string newkey = { (char)*(it+1), (char)*(it+2) }; imc::key itkey(*(it+1) == imc::key_crit_,newkey); // 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); // try to retrieve full key itkey.version_ = version; itkey = imc::get_key(itkey.critical_,itkey.name_,itkey.version_); // check for known keys (including version) if ( imc::check_key(itkey) ) { // 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 and initialize corresponding key and block // imc::key bkey( *(it+1)==imc::key_crit_ , newkey, // imc::keys.at(newkey).description_, version ); imc::block blk(itkey,it-buffer_.begin(), it-buffer_.begin()+pos+1+length, raw_file_, &buffer_); // add block to list rawblocks_.push_back(blk); // skip the remaining block according to its length if ( it-buffer_.begin()+length < buffer_.size() ) { std::advance(it,length); } } else { // all critical must be known !! while a noncritical may be ignored if ( *(it+1) == imc::key_crit_ ) { throw std::runtime_error( std::string("unknown critical key: ") + newkey + std::to_string(version) ); } else { std::cout<<"WARNING: unknown noncritical key '" <check_consistency(); } // check consistency of blocks void check_consistency() { for ( unsigned long int b = 0; b < this->rawblocks_.size()-1; b++ ) { if ( this->rawblocks_[b].get_end() >= this->rawblocks_[b+1].get_begin() ) { throw std::runtime_error( std::string("inconsistent subsequent blocks:\n") + std::to_string(b) + std::string("-th block:\n") + this->rawblocks_[b].get_info() + std::string("\n") + std::to_string(b+1) + std::string("-th block:\n") + this->rawblocks_[b+1].get_info() ); } } } // generate map of blocks using their uuid void generate_block_map() { for ( imc::block blk: rawblocks_ ) { mapblocks_.insert( std::pair(blk.get_uuid(),blk) ); } } // generate channel "environments" void generate_channel_env() { // collect affiliate blocks for every channel WITH CHANNEL and AFFILIATE // BLOCK CORRESPONDENCE GOVERNED BY BLOCK ORDER IN BUFFER!! for ( imc::block blk: rawblocks_ ) { // declare first channel environment imc::channel_env chnenv; // if ( blk.get_key() == imc::keys.at("CB") ) chnenv.CBuuid_ = blk.get_uuid(); // if ( blk.get_key() == imc::keys.at("CG") ) chnenv.CGuuid_ = blk.get_uuid(); // if ( blk.get_key() == imc::keys.at("CC") ) chnenv.CCuuid_ = blk.get_uuid(); // if ( blk.get_key() == imc::keys.at("CN") ) chnenv.CNuuid_ = blk.get_uuid(); // // // if ( blk.get_key() == imc::keys.at("CD") ) chnenv.CDuuid_ = blk.get_uuid(); // if ( blk.get_key() == imc::keys.at("CT") ) chnenv.CTuuid_ = blk.get_uuid(); // if ( blk.get_key() == imc::keys.at("Cb") ) chnenv.Cbuuid_ = blk.get_uuid(); // if ( blk.get_key() == imc::keys.at("CP") ) chnenv.CPuuid_ = blk.get_uuid(); // if ( blk.get_key() == imc::keys.at("CR") ) chnenv.CRuuid_ = blk.get_uuid(); // if ( blk.get_key() == imc::keys.at("CS") ) chnenv.CSuuid_ = blk.get_uuid(); // // // if ( blk.get_key() == imc::keys.at("NT") ) chnenv.NTuuid_ = blk.get_uuid(); // if ( blk.get_key() == imc::keys.at("NO") ) chnenv.NOuuid_ = blk.get_uuid(); // // // a component is closed by any of {CS, CC, CG, CB} // if ( blk.get_key() == imc::keys.at("CS") || blk.get_key() == imc::keys.at("CC") // || blk.get_key() == imc::keys.at("CG") || blk.get_key() == imc::keys.at("CB") ) // { // chnenv.uuid_ = chnenv.CNuuid_; // channel_envs_.insert( // std::pair(chnenv.CNuuid_,chnenv) // ); // } } } // parse channel's raw data template void convert_data_to_type(std::vector& subbuffer, std::vector& channel) { // check number of elements of type "datatype" in buffer if ( subbuffer.size() != channel.size()*sizeof(datatype) ) { throw std::runtime_error("size mismatch between subbuffer and datatype"); } // extract every single number of type "datatype" from buffer for ( unsigned long int i = 0; i < channel.size(); i++ ) { // declare number of required type and point it to first byte in buffer // representing the number datatype df; uint8_t* dfcast = reinterpret_cast(&df); for ( unsigned long int j = 0; j < sizeof(datatype); j++ ) { dfcast[j] = (int)subbuffer[i*sizeof(datatype)+j]; } // save number in channel channel[i] = df; } } public: // provide buffer size unsigned long int buffer_size() { return buffer_.size(); } // get blocks std::vector& blocks() { return rawblocks_; } // get computational complexity unsigned long int& computational_complexity() { return cplxcnt_; } // list a particular type of block std::vector list_blocks(imc::key mykey) { std::vector myblocks; for ( imc::block blk: this->rawblocks_ ) { if ( blk.get_key() == mykey ) myblocks.push_back(blk); } return myblocks; } // list all groups (associated to blocks "CB") std::vector list_groups() { return this->list_blocks(imc::get_key(true,"CB")); } // list all channels std::vector list_channels() { std::vector channels; for ( imc::block blk: this->rawblocks_ ) { if ( blk.get_key() == imc::get_key(true,"CN") ) { imc::parameter prm = blk.get_parameters()[6]; channels.push_back(blk.get_parameter(prm)); } } return channels; } // get specific channel data // TODO generalize and simplify channel extraction!! // imc::channel_tab get_channel(std::string channel) // { // // declare single channel table // imc::channel_tab chtab; // // // ordinate parameters // std::string yunit = std::string(""); // unsigned long int num_samples = -1; // // imc::datatype dtype; // int numbits = -1; // double yoffset = -1.0, yfactor = -1.0; // // // abscissa parameters // double dx = -1.0; // double xoffset = -1.0; // std::string xunit = std::string(""); // // // search block for required parameters // for ( imc::block blk: this->rawblocks_ ) // { // if ( blk.get_key() == imc::keys.at("CR") ) // { // yunit = blk.get_parameter(blk.get_parameters()[7]); // } // // if ( blk.get_key() == imc::keys.at("Cb") ) // { // num_samples = std::stoul(blk.get_parameter(blk.get_parameters()[7])); // xoffset = std::stod(blk.get_parameter(blk.get_parameters()[11])); // } // // if ( blk.get_key() == imc::keys.at("CP") ) // { // numbits = std::stoi(blk.get_parameter(blk.get_parameters()[5])); // } // // if ( blk.get_key() == imc::keys.at("CR") ) // { // yfactor = std::stod(blk.get_parameter(blk.get_parameters()[3])); // yoffset = std::stod(blk.get_parameter(blk.get_parameters()[4])); // yunit = blk.get_parameter(blk.get_parameters()[7]); // } // // if ( blk.get_key() == imc::keys.at("CD") ) // { // std::cout<<"got CD\n"; // dx = std::stod(blk.get_parameter(blk.get_parameters()[2])); // xunit = blk.get_parameter(blk.get_parameters()[7]); // } // } // // std::cout<<"yunit:"<