CMS 3D CMS Logo

Public Member Functions | Private Member Functions | Private Attributes

DaqData< Format > Class Template Reference

#include <DaqData.h>

List of all members.

Public Member Functions

char * Buffer () const
 DaqData (std::vector< unsigned int > &v)
 DaqData (const unsigned char *ptr, int sizeinbytes)
 DaqData (const DaqData &a)
unsigned int getValue (int indfield, int indobj=0) const
int Nobjects () const
int Size () const
 ~DaqData ()

Private Member Functions

void compressObject (const unsigned char *ptr, std::vector< unsigned int >::iterator &vit, int &bitsalreadyfilled)
void uncompressObject (const unsigned char *ptr, std::vector< unsigned int > &objdata, int &bitsalreadyfilled)

Private Attributes

unsigned char * buffer_
std::map< int, std::vector
< unsigned int > > 
data_
int nobjects_
int size_

Detailed Description

template<class Format>
class DaqData< Format >

This is the basic class accomplishing raw data formatting/unformatting.

1) Creation of a buffer of bytes representing the raw data

the user must create a DaqData object providing as input the data in the form of a vector of unsigned integers. The input data are all the values necessary to specify one (or more) object of the given format, which is the templated type. In case more than one object of the same given format should be put in the buffer, then the values of the second object must follow in the vector those of the first object and so on. DaqData will then compress these values in a bitstream according to the desired format. The bitstream is always aligned to the byte. The user, after successful compression, can request the pointer to the beginning of the buffer of bytes that represent the raw data (method Buffer() ) and the length of this buffer (method Size() ).

2) Interpretation of a buffer of bytes representing the raw data

the user must create a DaqData object providing as input a pointer to a buffer of bytes and the length in bytes of this buffer. DaqData will then extract the values (unsigned integers) present in the buffer according to a proper format, which is again the templated type. After successful uncompression of the buffer, the user can request the number of objects of the given format that were present in the buffer ( method Nobjects() ) and retrieve the individual values characterizing these objects ( method getValue() ).

WARNING: at the moment the interpretation of a buffer of bytes proceeds through the constructor of DaqData. This operation implies more than one copy of the data, which is not the most efficient way of accomplishing the task. In a future version of DaqData, more efficient methods will be made available.

Date:
2005/10/06 18:25:22
Revision:
1.2
Author:
G. Bruno - CERN, EP Division

Definition at line 56 of file DaqData.h.


Constructor & Destructor Documentation

template<class Format >
DaqData< Format >::DaqData ( std::vector< unsigned int > &  v) [inline]

Definition at line 60 of file DaqData.h.

References DaqData< Format >::buffer_, DaqData< Format >::compressObject(), gather_cfg::cout, DaqData< Format >::data_, i, AlCaRecoCosmics_cfg::name, DaqData< Format >::nobjects_, L1TEmulatorMonitor_cff::p, asciidump::s, and DaqData< Format >::size_.

                                       : size_(0), buffer_(0), nobjects_(0) {

    try {

      if (v.size() == 0)  throw string("DaqData: empty input data vector provided: ");     

      int Nfields = Format::getNumberOfFields();
      if (v.size()%Nfields != 0)  throw string("DaqData: ERROR. You must provide a number of input values compatibles with the requested format: ");


      int ObjSize = Format::getFieldLastBit(Nfields-1)+1;
      nobjects_ = v.size()/Nfields;
      //      cout<<"Going to create "<<nobjects_<< " objects of type "<<typeid(Format).name()<<endl;

      
      size_ = (int) ceil(((double)(ObjSize*nobjects_))/8);
      buffer_= new  char[size_];      
      //   cout<<"The buffer will be "<<size_ <<" bytes long"<<endl; 

      std::vector<unsigned int>::iterator vit = v.begin();
      char * p = buffer_;
      int bitsalreadyfilled = 0;

      int Totbytes=1;

      for(int i=0; i<nobjects_; i++) {

        //additional bytes necessary to accomodate the current object
        int Nbytes = (int) ceil((double)(Format::getFieldLastBit(Nfields-1)+1-8+bitsalreadyfilled)/8); 

        if ((Totbytes+=Nbytes)  > size_) throw string("Exceeded allocated buffer size");
        
        compressObject(p, vit, bitsalreadyfilled);

        // cout<<"Successfully compressed object "<< i <<endl; 
          
        data_.insert(std::pair< int, std::vector<unsigned int> >(i,std::vector<unsigned int>(vit-Nfields,vit) ));

        //the second term is necessary in the case the last byte has been fully used 
        p+=(Nbytes+(8-bitsalreadyfilled)/8) ;
        Totbytes+=(8-bitsalreadyfilled)/8 ;
      }
      if(bitsalreadyfilled==0) Totbytes--;

      /*
       cout << "Compression successful. "<< Totbytes<<" bytes compressed in total"<< endl;
       cout<< "Buffer pointer: "<<hex<< buffer_<< dec << "Size of buffer= "<< size_<<endl;
      for(int i=0; i<nobjects_; i++) {
        cout << "Object # "<< i << " fields: " <<endl;
        for(int j=0; j<Format::getNumberOfFields(); j++) cout << getValue(j,i) <<endl;
      }
      */

    }

    catch (std::string s){

      cout<<"DaqData - Exception caught: " << s <<endl;
      cout<<"Object compression failed! No data has been constructed for format: "<< string(typeid(Format).name())<<endl; 
      
    }

  }
template<class Format >
DaqData< Format >::DaqData ( const unsigned char *  ptr,
int  sizeinbytes 
) [inline]

Definition at line 125 of file DaqData.h.

References gather_cfg::cout, DaqData< Format >::data_, i, AlCaRecoCosmics_cfg::name, DaqData< Format >::nobjects_, L1TEmulatorMonitor_cff::p, asciidump::s, and DaqData< Format >::uncompressObject().

                           : size_(0), buffer_(0), nobjects_(0) {


    try {

      if (sizeinbytes==0) throw std::string("Buffer size is zero");

      int Nfields = Format::getNumberOfFields();
      int ObjSize = Format::getFieldLastBit(Nfields-1)+1;
      nobjects_ = (sizeinbytes*8)/ObjSize;

      // cout<<"Going to create "<<nobjects_<< " objects of type "<<typeid(Format).name()<<endl;
      // cout<<"The buffer will be "<<size_ <<" bytes long"<<endl;      

      if ((sizeinbytes*8)%ObjSize != 0) {
        cout<<"DaqData: there will be  " << (sizeinbytes*8)%ObjSize <<" meaningless bits at the end of the buffer"<<endl;
      }

      //     buffer_ = new char[sizeinbytes];
      //     memmove(buffer_,ptr,sizeinbytes);

      //      char * p = buffer_;

      const unsigned char * p = ptr;
      int bitsalreadyfilled = 0;
      
      int Totbytes=1;

      for(int i=0; i<nobjects_; i++) {

        std::vector<unsigned int> objdata;
        objdata.reserve(Nfields);

        //additional bytes necessary to accomodate the current object
        int Nbytes = (int) ceil((double)(Format::getFieldLastBit(Nfields-1)+1-8+bitsalreadyfilled)/8); 


        if ((Totbytes+=Nbytes) > sizeinbytes) throw std::string("Exceeded allocated buffer size");

        
        uncompressObject(p, objdata, bitsalreadyfilled);
     
        //      cout<<"Successfully uncompressed object "<< i <<endl; 
        data_.insert(std::pair< int, std::vector<unsigned int> >(i,objdata) );

        //the second term is necessary in the case the last byte has been fully used 
        p+= (Nbytes + (8-bitsalreadyfilled)/8);
        Totbytes+= (8-bitsalreadyfilled)/8;

      }

      if(bitsalreadyfilled==0) Totbytes--;

      /*
      cout << "Uncompression succeeded. "<< Totbytes<<" bytes uncompressed in total"<< endl;
      cout<< "Buffer pointer: "<<hex<< buffer_<< dec<< "Size of buffer= "<< size_<<endl;

      for(int i=0; i<nobjects_; i++) {
        cout << "Object # "<< i << " fields: " <<endl;
        for(int j=0; j<Format::getNumberOfFields(); j++) cout << getValue(j,i) <<endl;
      }
      */

    }
    catch (std::string s){

      std::cout<<"DaqData - Exception caught: " << s <<std::endl;
      std::cout<<"Object uncompression failed! No data has been constructed for format: "<<std::string(typeid(Format).name())<<endl; 
      
    }

  }
template<class Format >
DaqData< Format >::DaqData ( const DaqData< Format > &  a) [inline]

Definition at line 200 of file DaqData.h.

References DaqData< Format >::Buffer(), DaqData< Format >::buffer_, DaqData< Format >::data_, DaqData< Format >::getValue(), i, j, DaqData< Format >::Nobjects(), DaqData< Format >::nobjects_, DaqData< Format >::Size(), and DaqData< Format >::size_.

                             {

    size_ = a.Size();
    buffer_ = new char[size_];
    memmove(buffer_,a.Buffer(),size_);    
    nobjects_ = a.Nobjects();

    for(int i=0; i<nobjects_; i++) {
      std::vector<unsigned int> vec;
      for(int j=0; j<Format::getNumberOfFields(); j++) vec.push_back(a.getValue(j,i)); 
      data_.insert(std::pair< int, std::vector<unsigned int> >(i, vec));
    }

  }
template<class Format >
DaqData< Format >::~DaqData ( ) [inline]

Definition at line 216 of file DaqData.h.

References DaqData< Format >::buffer_.

            {

    // cout<<"Deleting DaqData of type "<<typeid(Format).name()<<endl;
    if (buffer_!=0) delete [] buffer_;

  };

Member Function Documentation

template<class Format >
char* DaqData< Format >::Buffer ( ) const [inline]

Definition at line 224 of file DaqData.h.

References DaqData< Format >::buffer_.

Referenced by DaqData< Format >::DaqData().

{return buffer_;}
template<class Format >
void DaqData< Format >::compressObject ( const unsigned char *  ptr,
std::vector< unsigned int >::iterator &  vit,
int &  bitsalreadyfilled 
) [inline, private]

Definition at line 375 of file DaqData.h.

References funct::pow().

Referenced by DaqData< Format >::DaqData().

                                                                                                                 {

    int Nfields = Format::getNumberOfFields();

    int bitstoaccomodate=Format::getFieldLastBit(0)+1; // of current field
    
    if (*vit > pow(2.,bitstoaccomodate)-1) throw string("The value is too large to fit in the field ");
 
    int ifield = 0;

    //Lower all bits but those already filled
    *ptr &= 0xff + 1 - (unsigned int)pow(2.,8-bitsalreadyfilled);

    while (ifield < Nfields) {


      if(bitstoaccomodate > 8 - bitsalreadyfilled ) {

        // cout<<"Field cannot be compressed from what left in current byte"<<endl;
        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;

        *ptr += (((*vit) >> (bitstoaccomodate - (8 - bitsalreadyfilled))) & 0xff);
        // cout<< "value: "<< hex << *vit <<" - " << dec <<  *vit<< endl;
        // cout<< "byte: "<< hex << (unsigned int)(*ptr) <<" - "<< dec << (unsigned int)(*ptr) << endl;


        bitstoaccomodate -= (8-bitsalreadyfilled);
        bitsalreadyfilled = 0;
        ptr++;
        *ptr &= 0xff + 1 - (unsigned int)pow(2.,8-bitsalreadyfilled);

        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;

      } 

      else if(bitstoaccomodate < (8 - bitsalreadyfilled) && bitstoaccomodate >0){

        // cout<<"Field can be compressed in the current byte, which will not be completely filled"<<endl;

        *ptr += ( (((*vit) << 8-bitstoaccomodate) & 0xff) >> (bitsalreadyfilled) );

        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;
        // cout<< "value: "<< hex << *vit <<" - " << dec <<  *vit<< endl;
        // cout<< "byte: "<< hex << (unsigned int)(*ptr) <<" - "<< dec << (unsigned int)(*ptr) << endl;

        vit++;
        bitsalreadyfilled+=bitstoaccomodate;

        // cout<<"Field completed"<<endl;

        if(ifield==Nfields-1) return;

        // cout<<"Compressing new Field"<<endl;
       
        ifield++;
        bitstoaccomodate=Format::getFieldLastBit(ifield)-Format::getFieldLastBit(ifield-1); 
        if (*vit > pow(2.,bitstoaccomodate)-1) throw string("The value is too large to fit in the field ");

        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;

      }

      else if(bitstoaccomodate == (8 - bitsalreadyfilled) && bitstoaccomodate >0){

        // cout<<"Field can be compressed in the current byte, which will be completely filled"<<endl;


        *ptr += ( (((*vit) << 8-bitstoaccomodate) & 0xff) >> (bitsalreadyfilled) );

        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;
        // cout<< "value: "<< hex << *vit <<" - " << dec <<  *vit<< endl;
        // cout<< "byte: "<< hex << (unsigned int)(*ptr) <<" - "<< dec << (unsigned int)(*ptr) << endl;

        vit++;
        bitsalreadyfilled=0;

        // cout<<"Field completed"<<endl;

        if(ifield==Nfields-1) return;

        // cout<<"Compressing new Field"<<endl;

        ptr++;
        *ptr &= 0xff + 1 - (unsigned int)pow(2.,8-bitsalreadyfilled);

        ifield++;
        bitstoaccomodate=Format::getFieldLastBit(ifield)-Format::getFieldLastBit(ifield-1);     

        if (*vit > pow(2.,bitstoaccomodate)-1) throw string("The value is too large to fit in the field ");

        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;

      }
      else throw string(" unexpected situation during compression");

    } //end of cycle over fields
    
  }
template<class Format >
unsigned int DaqData< Format >::getValue ( int  indfield,
int  indobj = 0 
) const [inline]

Definition at line 236 of file DaqData.h.

References gather_cfg::cout, DaqData< Format >::data_, and DaqData< Format >::nobjects_.

Referenced by DaqData< Format >::DaqData().

                                                          {
    
    if (indobj<nobjects_ && indfield < Format::getNumberOfFields()) {
      std::map < int, std::vector<unsigned int> >::const_iterator it = data_.find(indobj);
      if (it != data_.end()) return ((*it).second)[indfield];
      else {
        cout<<"DaqData - Strange: object should exist but was not found "<<endl;
        return 0;
      }
    }
    else  cout<<"DaqData - Non existent field or object"<<endl;
    return 0;

  }
template<class Format >
int DaqData< Format >::Nobjects ( ) const [inline]

Definition at line 228 of file DaqData.h.

References DaqData< Format >::nobjects_.

Referenced by DaqData< Format >::DaqData().

                       {
    return nobjects_;
    /*    cout<<"Nobjects()"<<endl;
    int Nfields = Format::getNumberOfFields();
    return size_/(Format::getFieldLastBit(Nfields-1)+1);
    */
  }
template<class Format >
int DaqData< Format >::Size ( ) const [inline]

Definition at line 226 of file DaqData.h.

References DaqData< Format >::size_.

Referenced by DaqData< Format >::DaqData().

{return size_;}
template<class Format >
void DaqData< Format >::uncompressObject ( const unsigned char *  ptr,
std::vector< unsigned int > &  objdata,
int &  bitsalreadyfilled 
) [inline, private]

Definition at line 253 of file DaqData.h.

References relativeConstraints::value.

Referenced by DaqData< Format >::DaqData().

                                                 {

    int Nfields = Format::getNumberOfFields();

    int bitstoaccomodate=Format::getFieldLastBit(0)+1; // of current field

    int ifield = 0;
    unsigned int value = 0; 

    while (ifield < Nfields) {

      if(bitstoaccomodate > 8 - bitsalreadyfilled ) {

        // cout<<"can't complete value from current byte"<<endl;
        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;

        //1)The syntax below could be faster. 
        //  To be checked as soon as time available(check started with prog test4.C) .
        //2)check if all cast to unsigned int are really necessary(done, they are not).
        //3)Instead of using pow(2,1;2;3;4;5..), a faster enum could be used
        //Lower all bits but those not yet read
        //value += ( (*ptr & ((unsigned int)pow(2.,8-bitsalreadyfilled)-1)) << bitstoaccomodate + bitsalreadyfilled - 8 ) ;
        //              if(bitstoaccomodate > 8) value += ( ((((unsigned int)(*ptr)) << bitsalreadyfilled) & 0xff) << (bitstoaccomodate - 8) );
        //      else value += ( ((((unsigned int)(*ptr)) << bitsalreadyfilled) & 0xff) >> (8 - bitstoaccomodate) );


        if(bitstoaccomodate > 8) value += ( ( (*ptr << bitsalreadyfilled) & 0xff ) << (bitstoaccomodate - 8) );
        else value += ( ( (*ptr << bitsalreadyfilled) & 0xff) >> (8 - bitstoaccomodate) );
        

        // cout<< "value: "<< hex << value << " - " << dec <<  value<< endl;
        // cout<< "byte: "<< hex << (unsigned int)(*ptr) << " - " << dec << (unsigned int)(*ptr) << endl;


        ptr++;
        bitstoaccomodate -= (8-bitsalreadyfilled);
        bitsalreadyfilled = 0;

        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;
        
      } 

      else if(bitstoaccomodate < (8 - bitsalreadyfilled) && bitstoaccomodate >0){
        // cout<<"value can be completed from current byte, which still contain info"<<endl;

        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;

        //1)The syntax below could be faster. 
        //  To be checked as soon as time available.
        //2)check if all cast to unsigned int are really necessary.
        //3)Instead of using pow(2,1;2;3;4;5..), a faster enum could be used
        //Lower all bits but those not yet read
        //value += (*ptr & ((unsigned int)pow(2.,8-bitsalreadyfilled)-1)) >> (8 - bitstoaccomodate - bitsalreadyfilled);

        value += ( ( (*ptr << bitsalreadyfilled) & 0xff ) >> (8 - bitstoaccomodate) ) ;

        // cout<< "value: "<< hex << value << " - " << dec <<  value<< endl;
        // cout<< "byte: "<< hex << (unsigned int)(*ptr) << " - " << dec << (unsigned int)(*ptr) << endl;


        objdata.push_back(value);
        value = 0;
        bitsalreadyfilled+=bitstoaccomodate;

        // cout<<"Field completed"<<endl;

        if(ifield==Nfields-1) return;
       
        // cout<<"Uncompressing new Field"<<endl;

        ifield++;
        bitstoaccomodate=Format::getFieldLastBit(ifield)-Format::getFieldLastBit(ifield-1); 
        
        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;

      }

      else if(bitstoaccomodate == (8 - bitsalreadyfilled) && bitstoaccomodate >0){
        // cout<<"value can be completed from what left in current byte"<<endl; 
        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;

        //1)The syntax below could be faster. 
        //  To be checked as soon as time available.
        //2)check if all cast to unsigned int are really necessary.
        //3)Instead of using pow(2,1;2;3;4;5..), a faster enum could be used
        //Lower all bits but those not yet read
        //      value += *ptr & ((unsigned int)pow(2.,8-bitsalreadyfilled)-1);

        value += ( ( (*ptr << bitsalreadyfilled) & 0xff ) >> (8 - bitstoaccomodate) ) ;

        // cout<< "value: "<< hex << value << " - " << dec <<  value<< endl;
        // cout<< "byte: "<< hex << (unsigned int)(*ptr) << " - " << dec << (unsigned int)(*ptr) << endl;


        objdata.push_back(value);
        value = 0;
        bitsalreadyfilled=0;

        // cout<<"Field completed"<<endl;

        if(ifield==Nfields-1) return;

        // cout<<"Uncompressing new Field"<<endl;

        ptr++;
        ifield++;
        bitstoaccomodate=Format::getFieldLastBit(ifield)-Format::getFieldLastBit(ifield-1);     

        // cout <<"bitstoaccomodate= "<<bitstoaccomodate<<" bitsalreadyfilled= "<<bitsalreadyfilled<<" ifield="<< ifield<<" Nfields="<<Nfields<<endl;

      }
      else throw std::string(" unexpected situation during uncompression");

    } //end of cycle over fields
    
  }

Member Data Documentation

template<class Format >
unsigned char* DaqData< Format >::buffer_ [private]
template<class Format >
std::map< int, std::vector<unsigned int> > DaqData< Format >::data_ [private]

Definition at line 477 of file DaqData.h.

Referenced by DaqData< Format >::DaqData(), and DaqData< Format >::getValue().

template<class Format >
int DaqData< Format >::nobjects_ [private]
template<class Format >
int DaqData< Format >::size_ [private]

Definition at line 479 of file DaqData.h.

Referenced by DaqData< Format >::DaqData(), and DaqData< Format >::Size().