From 44ab3645e8e85b3848fe9496b96f42633f658859 Mon Sep 17 00:00:00 2001 From: Mario Fink Date: Fri, 22 Jan 2021 16:28:36 +0100 Subject: [PATCH] * update tdm_datatype * tdm_reaper.cpp: introduce datatype checks, add datatype maps, finish get_channel --- lib/tdm_datatype.hpp | 6 +- lib/tdm_reaper.cpp | 181 +++++++++++++++++++++++++------------------ lib/tdm_reaper.hpp | 6 +- src/main.cpp | 2 +- 4 files changed, 114 insertions(+), 81 deletions(-) diff --git a/lib/tdm_datatype.hpp b/lib/tdm_datatype.hpp index 01135ad..5baccf8 100644 --- a/lib/tdm_datatype.hpp +++ b/lib/tdm_datatype.hpp @@ -30,8 +30,8 @@ public: tdmdatatype(): sint16_(0), sint32_(0), uint8_(0), uint16_(0), uint32_(0), float32_(0.0), float64_(0.0), - dtidx_(0) { std::cout<<"tdmdatatype constructor\n"; }; - // every supported datatype get its own constructor + dtidx_(0) { }; + // every supported datatype gets its own constructor tdmdatatype(eInt16Usi num): sint16_(num), dtidx_(0) {}; tdmdatatype(eInt32Usi num): sint32_(num), dtidx_(1) {}; tdmdatatype(eUInt8Usi num): uint8_(num), dtidx_(2) {}; @@ -273,7 +273,7 @@ struct tdm_datatype { std::string channel_datatype_; int numeric_; std::string value_sequence_; - int size_; + unsigned int size_; std::string description_; const std::string get_info() { return get_info(defformat); } diff --git a/lib/tdm_reaper.cpp b/lib/tdm_reaper.cpp index c35aa95..40764e1 100644 --- a/lib/tdm_reaper.cpp +++ b/lib/tdm_reaper.cpp @@ -66,6 +66,47 @@ void tdm_reaper::process_tdm(bool showlog) throw std::runtime_error(std::string("failed to load tdm file: ") + e.what()); } + // check datatype consistency, i.e. "local" representation of datatypes + // and build map(s) for "tdm_datatypes" + for ( tdm_datatype el: tdm_datatypes ) + { + if ( el.name_ == "eInt16Usi" ) + { + if ( el.size_ != sizeof(eInt16Usi) ) throw std::logic_error("invalid representation of eInt16Usi"); + } + else if ( el.name_ == "eInt32Usi" ) + { + if ( el.size_ != sizeof(eInt32Usi) ) throw std::logic_error("invalid representation of eInt32Usi"); + } + else if ( el.name_ == "eUInt8Usi" ) + { + if ( el.size_ != sizeof(eUInt8Usi) ) throw std::logic_error("invalid representation of eUInt8Usi"); + } + else if ( el.name_ == "eUInt16Usi" ) + { + if ( el.size_ != sizeof(eUInt16Usi) ) throw std::logic_error("invalid representation of eUInt16Usi"); + } + else if ( el.name_ == "eUInt32Usi" ) + { + if ( el.size_ != sizeof(eUInt32Usi) ) throw std::logic_error("invalid representation of eUInt32Usi"); + } + else if ( el.name_ == "eFloat32Usi" ) + { + if ( el.size_ != sizeof(eFloat32Usi) ) throw std::logic_error("invalid representation of eFloat32Usi"); + } + else if ( el.name_ == "eFloat64Usi" ) + { + if ( el.size_ != sizeof(eFloat64Usi) ) throw std::logic_error("invalid representation of eFloat64Usi"); + } + else + { + throw std::logic_error("missing datatype validation"); + } + + tdmdt_name_.insert(std::pair(el.name_,el)); + tdmdt_chan_.insert(std::pair(el.channel_datatype_,el)); + } + // process elements of XML this->process_include(showlog); this->process_root(showlog); @@ -359,12 +400,24 @@ void tdm_reaper::process_localcolumns(bool showlog) if ( tdmchannels_.size() == 0 ) throw std::logic_error("tdmchannels_ not initialized"); // determine "channel_datatype_" and map it to its sequence type + if ( tdmchannels_.count(locc.measurement_quantity_) != 1 ) + { + throw std::runtime_error(std::string("measurement_quantity: ") + + locc.measurement_quantity_ + + std::string(" is ambiguous") ); + } std::string dt = tdmchannels_.at(locc.measurement_quantity_).datatype_; std::string sequence_type; - for( auto itd = std::begin(tdm_datatypes); itd != std::end(tdm_datatypes); ++itd) + // for( auto itd = std::begin(tdm_datatypes); itd != std::end(tdm_datatypes); ++itd) + // { + // if ( dt == itd->channel_datatype_ ) sequence_type = itd->value_sequence_; + // } + if ( tdmdt_chan_.count(dt) != 1 ) { - if ( dt == itd->channel_datatype_ ) sequence_type = itd->value_sequence_; + throw std::runtime_error(std::string("datatype: ") + dt + + std::string(" is unknown/invalid") ); } + sequence_type = tdmdt_chan_.at(dt).value_sequence_; for ( pugi::xml_node seq = tdmdata.child(sequence_type.c_str()); seq; seq = seq.next_sibling(sequence_type.c_str()) ) @@ -593,86 +646,62 @@ std::vector tdm_reaper::get_channel(std::string& id) // use "values" id to map to external block block blk = tdx_blocks_.at(loccol.external_id_); - // // distinguish numeric datatypes - // switch ( blk.value_type_ ) - // { - // case "eInt16Usi" : - // break; - // case "eInt32Usi" : - // break; - // case "eUInt8Usi" : - // break; - // case "eUInt16Usi" : - // break; - // case "eUInt32Usi" : - // break; - // case "eFloat32Usi" : - // // declare buffer covering the required range of "tdxbuffer_" - // std::vector blkF32( tdxbuffer_.begin()+blk.byte_offset_, - // tdxbuffer_.begin()+blk.byte_offset_ - // + blk.length_*sizeof(eFloat32Usi) ); - // std::vector datvecF32(blk.length_); - // this->convert_data_to_type(blkF32,datvecF32); - // return datvecF32; - // break; - // case "eFloat64Usi" : - // // declare buffer covering the required range of "tdxbuffer_" - // std::vector blkF64( tdxbuffer_.begin()+blk.byte_offset_, - // tdxbuffer_.begin()+blk.byte_offset_ - // + blk.length_*sizeof(eFloat64Usi) ); - // std::vector datvecF64(blk.length_); - // this->convert_data_to_type(blkF64,datvecF64); - // return datvecF64; - // break; - // case "eStringUsi" : - // throw std::runtime_error("datatype 'eStringUsi' is not supported"); - // break; - // } + // declare vector of appropriate length + std::vector datavec(blk.length_); + + // retrieve corresponding TDM datatype + tdm_datatype dtyp = this->tdmdt_name_.at(blk.value_type_); + + // declare buffer covering the required range of "tdxbuffer_" + // (consider both channel-wise and block-wise ordering) + unsigned long int strtidx = blk.block_offset_*blk.block_size_ + + blk.byte_offset_, + fnshidx = strtidx + blk.length_*dtyp.size_; + std::vector tdxblk( tdxbuffer_.begin()+strtidx, + tdxbuffer_.begin()+fnshidx ); + + // distinguish numeric datatypes included in "tdmdatatype" + if ( blk.value_type_ == std::string("eInt16Usi") ) + { + this->convert_data_to_type(tdxblk,datavec); + } + else if ( blk.value_type_ == std::string("eInt32Usi") ) + { + this->convert_data_to_type(tdxblk,datavec); + } + else if ( blk.value_type_ == std::string("eUInt8Usi") ) + { + this->convert_data_to_type(tdxblk,datavec); + } + else if ( blk.value_type_ == std::string("eUInt16Usi") ) + { + this->convert_data_to_type(tdxblk,datavec); + } + else if ( blk.value_type_ == std::string("eUInt32Usi") ) + { + this->convert_data_to_type(tdxblk,datavec); + } + else if ( blk.value_type_ == std::string("eFloat32Usi") ) + { + this->convert_data_to_type(tdxblk,datavec); + } + else if ( blk.value_type_ == std::string("eFloat64Usi") ) + { + this->convert_data_to_type(tdxblk,datavec); + } + else + { + throw std::runtime_error(std::string("unsupported/unknown datatype") + blk.value_type_); + } + + return datavec; } else { throw std::invalid_argument(std::string("channel id does not exist: ") + id); } - - std::vector data; - eFloat32Usi m(4); - data.push_back(m); - // std::vector(); - return data; } -// template std::vector tdm_reaper::get_channel(std::string& id); - -// std::vector tdm_reaper::get_channel(std::string &id) -// { -// // check for existence of required channel id (=key) -// if ( tdmchannels_.count(id) == 1 ) -// { -// // retrieve full channel info -// tdm_channel chn = tdmchannels_.at(id); -// -// // extract (first) "localcolumn" for channel -// localcolumn loccol = localcolumns_.at(chn.local_columns_[0]); -// -// // use "values" id to map to external block -// block blk = tdx_blocks_.at(loccol.external_id_); -// -// // declare buffer covering the required range of "tdxbuffer_" -// std::vector blkbuff( tdxbuffer_.begin()+blk.byte_offset_, -// tdxbuffer_.begin()+blk.byte_offset_ -// + blk.length_*sizeof(double) ); -// -// std::vector datvec(blk.length_); -// this->convert_data_to_type(blkbuff,datvec); -// -// return datvec; -// } -// else -// { -// throw std::invalid_argument(std::string("channel id does not exist: ") + id); -// } -// } - void tdm_reaper::print_channel(std::string &id, const char* filename) { std::ofstream fou(filename); @@ -688,7 +717,7 @@ void tdm_reaper::print_channel(std::string &id, const char* filename) template void tdm_reaper::convert_data_to_type(std::vector &buffer, - std::vector &channel) + std::vector &channel) { // check number of elements of type "datatype" in buffer if ( buffer.size() != channel.size()*sizeof(datatype) ) diff --git a/lib/tdm_reaper.hpp b/lib/tdm_reaper.hpp index 0614774..3fbe7f5 100644 --- a/lib/tdm_reaper.hpp +++ b/lib/tdm_reaper.hpp @@ -43,6 +43,10 @@ class tdm_reaper // blocks of data in .tdx file std::map tdx_blocks_; + // resconstruct "tdm_datatype.hpp: tdm_datatypes" as map to quickly map + // "valueType"/"channel_datatype" to full datatype + std::map tdmdt_name_, tdmdt_chan_; + // tdm root tdm_root tdmroot_; @@ -192,7 +196,7 @@ private: template void convert_data_to_type(std::vector &buffer, - std::vector &channel); + std::vector &channel); }; diff --git a/src/main.cpp b/src/main.cpp index 626e6e2..ea6cf09 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,7 @@ const std::string githash("HASHSTRING"); void show_usage() { std::cout<<"\n" - <<"tdmreaper ["<