1  // [License]


2  // The AribaUnderlay Copyright


3  //


4  // Copyright (c) 20082009, Institute of Telematics, UniversitÃ€t Karlsruhe (TH)


5  //


6  // Institute of Telematics


7  // UniversitÃ€t Karlsruhe (TH)


8  // Zirkel 2, 76128 Karlsruhe


9  // Germany


10  //


11  // Redistribution and use in source and binary forms, with or without


12  // modification, are permitted provided that the following conditions are


13  // met:


14  //


15  // 1. Redistributions of source code must retain the above copyright


16  // notice, this list of conditions and the following disclaimer.


17  // 2. Redistributions in binary form must reproduce the above copyright


18  // notice, this list of conditions and the following disclaimer in the


19  // documentation and/or other materials provided with the distribution.


20  //


21  // THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND


22  // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE


23  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR


24  // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR


25  // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,


26  // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,


27  // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR


28  // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF


29  // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING


30  // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS


31  // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


32  //


33  // The views and conclusions contained in the software and documentation


34  // are those of the authors and should not be interpreted as representing


35  // official policies, either expressed or implied, of the Institute of


36  // Telematics.


37  // [License]


38 


39  #ifndef DATA_HPP_


40  #define DATA_HPP_


41 


42  //== library includes ==


43  #include <stdlib.h>


44  #include <iostream>


45  #include <boost/cstdint.hpp>


46  #include <boost/type_traits/make_unsigned.hpp>


47 


48  // forward declaration


49  template<typename T> class DefaultDataModel;


50  template<typename T = uint8_t, typename DataModel = DefaultDataModel<uint8_t> > class DataTpl;


51  typedef DataTpl<> Data;


52  template<typename T, typename DataModel> std::ostream& operator<<(std::ostream& stream, const DataTpl<T, DataModel>& data);


53 


54  //== internal includes ==


55  #include "../internal/Utilities.hpp"


56 


57  //== local includes ==


58  #include "DataUtilities.hpp"


59  #include "Serialization.hpp"


60 


61  /**


62  * This class implements a wrapper for binary data. And this time, when the


63  * word binary is used  it really means binary! Length and manipulation


64  * are specified and operate in bit precision. Most of the operations are


65  * highly effective using inline functions and compiler optimizations.


66  *


67  * Two versions of binaries are supported: static, nonresizeable binaries


68  * and dynamic, resizeable ones. Please note, this class does not manage


69  * memory, reference counting etc. you have to take care about memory


70  * management yourself! However you can use the <code>release()</code>


71  * to delete the underlaying array.


72  *


73  * @author Sebastian Mies


74  */


75  template<typename T, typename DataModel>


76  class DataTpl: public Serializeable { SERIALIZEABLE


77  protected:


78  typedef DataTpl<T,DataModel> _Data;


79  DataModel model;


80 


81  public:


82  static const size_t word_width = sizeof(T) * 8;


83 


84  class DataManipulator {


85  private:


86  DataModel bits;


87  size_t index;


88 


89  public:


90  finline DataManipulator( DataModel& _bits, size_t _index) :


91  bits(_bits), index(_index) {


92  }


93 


94  template<typename X>


95  finline operator X() const {


96  return bitget<X>(bits.buffer(), index);


97  }


98 


99  template<typename X>


100  finline DataManipulator& operator=(X value) {


101  bitset(value, bits.buffer(), index );


102  return *this;


103  }


104 


105  template<typename X>


106  finline void set(X value, size_t length = sizeof(X) * 8, if_uint(X)) {


107  bitcpy(value, 0, bits.buffer(), index, length);


108  }


109 


110  template<typename X>


111  finline void set(X value, size_t length = sizeof(X) * 8, if_int(X)) {


112  set(_unsigned(value),length);


113  }


114 


115  template<typename X>


116  finline void get(X& value, size_t length = sizeof(X) * 8, if_uint(X)) const {


117  value = bitget<X> (bits.buffer(), index, length);


118  }


119 


120  template<typename X>


121  finline void get(X& value, size_t length = sizeof(X) * 8, if_int(X)) const {


122  typedef typename boost::make_unsigned<X>::type unsigned_type;


123  _unsigned(value) = bitget<unsigned_type> (bits.buffer(), index, length);


124  }


125 


126  finline void get(bool& value) const {


127  value = bitget( bits.buffer(), index );


128  }


129  };


130 


131  public:


132  static const Data UNSPECIFIED;


133 


134  /**


135  * Constructs a dynamic bitdata object of variable size.


136  */


137  finline DataTpl() : model() {


138  }


139 


140  /**


141  * Contructs a copy of an existing data buffer


142  */


143  finline DataTpl(const DataTpl<T, DataModel>& copy) {


144  this>model = copy.model;


145  }


146 


147  finline DataTpl( const DataModel& _model ) : model( _model ) {


148  }


149 


150  /**


151  * Constructs a static bitdata object with the given buffer.


152  */


153  finline DataTpl(const T* buffer, size_t length) {


154  model.buffer() = buffer;


155  model.length() = length;


156  }


157 


158  /**


159  * Constructs a dynamic bitdata object with the given buffer.


160  */


161  finline DataTpl( T* buffer, size_t length ) {


162  model.buffer() = buffer;


163  model.length() = length;


164  }


165 


166  /**


167  * Constructs a dynamic bitdata object of variable size with the given


168  * initial size.


169  */


170  finline DataTpl(size_t length) : model() {


171  model.resize(length);


172  }


173 


174 


175  /**


176  * Returns the internal buffer of the data.


177  */


178  finline T* getBuffer() const {


179  return model.buffer();


180  }


181 


182  /**


183  * Returns the length of the data in bits


184  */


185  finline size_t getLength() const {


186  return model.length();


187  }


188  /**


189  * Sets the length of the data in bits


190  */


191  void setLength(size_t new_length) {


192  model.resize(new_length);


193  }


194 


195  /**


196  * Ensures that the buffer pointer has the given


197  * number of bits of memory reserved.


198  *


199  * @param neededLength The minimum data length required.


200  */


201  finline void ensureLength( size_t neededLength ) {


202  if ((int) neededLength > model.length() ) model.resize(neededLength);


203  }


204 


205  /**


206  * Returns a manipulator object for a certain bit position.


207  *


208  * @param index The index in bits quantitites.


209  * @return A data manipulation object


210  */


211  finline DataManipulator operator[](size_t index) {


212  return DataManipulator(model, index);


213  }


214 


215  /**


216  * Returns a constant manipulator object for a certain bit position.


217  *


218  * @param index The index in bits quantitites.


219  * @return A constant data manipulation object


220  */


221  finline const DataManipulator operator[](size_t index) const {


222  return DataManipulator(model, index);


223  }


224 


225  _Data sub( size_t index, size_t length = ~0 ) {


226  if (length == ~0) length = model.length()index;


227  return _Data(model.sub(index,length));


228  }


229 


230  /**


231  * Returns a copy of the specified bit range.


232  *


233  * @param index The first bit to copy


234  * @param length The length of the bit range


235  * @return The cloned data object


236  */


237  _Data clone( size_t index, size_t length ) const {


238  DataModel new_model = model.clone(index,length);


239  return _Data(new_model);


240  }


241 


242  /**


243  * Returns a copy of the data.


244  *


245  * @return A cloned data object


246  */


247  _Data clone() const {


248  DataModel new_model = model.clone( 0, model.length() );


249  return _Data(new_model);


250  }


251 


252  /**


253  * Returns true, if the data is empty (zero length)


254  *


255  * @return True, if the data is empty (zero length)


256  */


257  finline bool isEmpty() const {


258  return (model.length() == 0);


259  }


260 


261  /**


262  * Returns true, if the data buffer is unspecified.


263  * In this case no memory is associated with this data object.


264  *


265  * @return True, if the data buffer is unspecified.


266  */


267  finline bool isUnspecified() const {


268  return model.isUnspecified();


269  }


270 


271  /**


272  * This method frees the memory associated with


273  * this data object and sets this object into an unspecified


274  * state.


275  */


276  finline void release() {


277  model.release();


278  }


279 


280  // operators


281 


282  /**


283  * Assigns another buffer


284  */


285  template<typename X>


286  _Data& operator= (const DataTpl<X>& source) {


287  this>model = source.model;


288  return *this;


289  }


290 


291  /**


292  * Returns true, if the datas buffer's pointer and length


293  * are the same.


294  */


295  template<typename X>


296  finline bool operator==( DataTpl<X>& data) {


297  return (data.model.buffer() == model.buffer() &&


298  data.model.length() == model.length() );


299  }


300 


301  finline _Data& operator&=(_Data& data) {


302  return *this;


303  }


304 


305  finline _Data& operator=(_Data& data) {


306  return *this;


307  }


308 


309  finline _Data& operator^=(_Data& data) {


310  return *this;


311  }


312 


313  /* implied operators */


314 


315  finline _Data operator&(_Data& data) {


316  return (this>clone() &= data);


317  }


318 


319  finline _Data operator(_Data& data) {


320  return (this>clone() = data);


321  }


322 


323  finline _Data operator^(_Data& data) {


324  return (this>clone() ^= data);


325  }


326  };


327 


328  /* unspecified type */


329  template<typename T, typename DataModel>


330  const Data DataTpl<T, DataModel>::UNSPECIFIED;


331 


332  /**


333  * This class implements the default data model


334  *


335  * @author Sebastian Mies


336  */


337  template<typename _T>


338  class DefaultDataModel {


339  public:


340  typedef _T T;


341  typedef DefaultDataModel<T> _Model;


342 


343  private:


344 


345  int32_t bufferLen;


346  T* bufferPtr;


347 


348  static finline int calcLength(int length) {


349  if (length<0) return 0;


350  return ((length/8)/sizeof(T)+1);


351  }


352  public:


353  finline DefaultDataModel() {


354  bufferPtr = NULL;


355  bufferLen = 1;


356  }


357 


358  finline DefaultDataModel( void* buffer, size_t length ) {


359  bufferPtr = (T*)buffer;


360  bufferLen = length;


361  }


362 


363  finline DefaultDataModel( const _Model& source ) {


364  this>bufferPtr = source.bufferPtr;


365  this>bufferLen = source.bufferLen;


366  }


367 


368  finline _Model& operator=( const _Model& source ) {


369  this>bufferPtr = source.bufferPtr;


370  this>bufferLen = source.bufferLen;


371  return *this;


372  }


373 


374  finline T*& buffer() {


375  return bufferPtr;


376  }


377 


378  finline T* buffer() const {


379  return bufferPtr;


380  }


381 


382  finline int32_t& length() {


383  return bufferLen;


384  }


385 


386  finline int32_t length() const {


387  return (bufferLen == 1) ? 0 : bufferLen;


388  }


389 


390  finline bool isUnspecified() const {


391  return bufferLen < 0;


392  }


393 


394  finline void resize( size_t new_length ) {


395  size_t old_length = calcLength(bufferLen);


396  size_t res_length = calcLength(new_length);


397  if (old_length != res_length) {


398  T* new_buffer = new T[res_length];


399  if (bufferPtr != NULL) {


400  size_t clength = res_length < old_length ? res_length : old_length;


401  memcpy( new_buffer, bufferPtr, clength*sizeof(T) );


402  delete [] bufferPtr;


403  }


404  bufferPtr = new_buffer;


405  bufferLen = new_length;


406  }


407  }


408 


409  finline void release() {


410  if (bufferPtr!=NULL && bufferLen>=0) delete [] bufferPtr;


411  bufferPtr = NULL;


412  bufferLen = 1;


413  }


414 


415  finline _Model sub( size_t index, size_t length ) {


416  return _Model( bufferPtr + index/sizeof(T), length );


417  }


418 


419  finline _Model clone( size_t index, size_t length ) const {


420  _Model new_model;


421  new_model.resize( length );


422  bitcpy( this>buffer(), index, new_model.buffer(), 0, length );


423  return new_model;


424  }


425  };


426 


427  /* serialization */


428  sznBeginDefault( Data, X ){


429  for (size_t i = 0; i< getLength() / word_width; i++) X && getBuffer()[i];


430  }sznEnd();


431 


432  /* default human readable text output */


433  template<typename T, typename DataModel>


434  std::ostream& operator<<(std::ostream& stream, const DataTpl<T, DataModel>& data) {


435  stream << "[" << bitstr(data.getBuffer(), data.getLength(), 4)


436  << "'";


437  const char* buffer = (const char*) data.getBuffer();


438  for (size_t i = 0; i < data.getLength() / 8; i++) {


439  char c = buffer[i] < 32 ? '.' : buffer[i];


440  stream << c;


441  }


442  stream << "']";


443  return stream;


444  }


445  #endif /* DATA_HPP_ */

