/home/coin/SVN-release/Bcp-1.2.1/Bcp/src/include/BCP_buffer.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2000, International Business Machines
00002 // Corporation and others.  All Rights Reserved.
00003 #ifndef _BCP_BUFFER_H
00004 #define _BCP_BUFFER_H
00005 
00006 #include <memory>
00007 #include <vector>
00008 
00009 // This file is fully docified.
00010 
00011 #include "BCP_error.hpp"
00012 #include "BCP_string.hpp"
00013 #include "BCP_message_tag.hpp"
00014 #include "BCP_message.hpp"
00015 #include "BCP_vector.hpp"
00016 
00039 class BCP_buffer{
00040 public:
00041    /* The data members are public for efficiency reasons. The message
00042        environment's receiving function should be able to directly manipulate
00043        these fields. However, making the virtual base class of all message
00044        passing environment to be a friend doesn't help... Anyway, access these
00045        fields sparingly.<br>
00046        THINK: maybe it's not that inefficient to access the fields thru
00047        functions... */
00070    BCP_message_tag _msgtag;
00073    int    _sender;
00075    size_t _pos;
00077    size_t _max_size;
00080    size_t _size;
00082    char*  _data;
00085 public:
00086    //=========================================================================
00090    inline BCP_message_tag msgtag() const { return _msgtag; }
00093    inline int         sender() const { return _sender; }
00095    inline int         size() const { return _size; }
00097    inline const char* data() const { return _data; }
00099    //=========================================================================
00100 
00104    inline void set_position(const int pos) throw(BCP_fatal_error) {
00105      if (pos < 0 || pos > size())
00106        throw BCP_fatal_error("Incorrest buffer position setting.\n");
00107      _pos = pos;
00108    }
00110    inline void set_size(const int s) throw(BCP_fatal_error) {
00111      if (s < 0 || s > size())
00112        throw BCP_fatal_error("Incorrest buffer position setting.\n");
00113      _size = s;
00114    }
00116    inline void set_msgtag(const BCP_message_tag tag) { _msgtag = tag; }
00117 
00119   void set_content(const char* data, const size_t size,
00120                    int sender, BCP_message_tag msgtag) {
00121     _sender = sender;
00122     _msgtag = msgtag;
00123     if (_max_size < size) {
00124       delete[] _data;
00125       _data = new char[size];
00126       _max_size = size;
00127     }
00128     _pos = 0;
00129     _size = size;
00130     if (_size)
00131       memcpy(_data, data, size * sizeof(char));
00132    }
00133      
00134     
00136    BCP_buffer& operator=(const BCP_buffer& buf) {
00137       _msgtag = buf._msgtag;
00138       _sender = buf._sender;
00139       _pos = buf._pos;
00140       if (_max_size < buf._max_size) {
00141          delete[] _data;
00142          _data = new char[buf._max_size];
00143          _max_size = buf._max_size;
00144       }
00145       _size = buf._size;
00146       if (_size)
00147          memcpy(_data, buf._data, _size * sizeof(char));
00148       return *this;
00149    }
00153    inline void make_fit(const int add_size){
00154       if (_max_size < _size + add_size) {
00155          _max_size = _size + add_size;
00156          /* If > 1M then have spare space of 1/16th (~6%) of used space,
00157             if <= 1M then have 64K spare space */
00158          _max_size += (_max_size > 1<<20) ? (_max_size >> 4) : (1 << 16) ;
00159          char *new_data = new char[_max_size];
00160          if (_size)
00161             memcpy(new_data, _data, _size);
00162          delete[] _data;
00163          _data = new_data;
00164       }
00165    }
00168    inline void clear(){
00169       _msgtag = BCP_Msg_NoMessage;
00170       _size = 0;
00171       _pos = 0;
00172       _sender = -1;
00173    }
00174 
00177    template <class T> BCP_buffer& pack(const T& value) {
00178      make_fit( sizeof(T) );
00179      memcpy(_data + _size, &value, sizeof(T));
00180      _size += sizeof(T);
00181      return *this;
00182    }
00183 
00186    template <class T> BCP_buffer& unpack(T& value){
00187 #ifdef PARANOID
00188      if (_pos + sizeof(T) > _size)
00189        throw BCP_fatal_error("Reading over the end of buffer.\n");
00190 #endif
00191      memcpy(&value, _data + _pos, sizeof(T));
00192      _pos += sizeof(T);
00193      return *this;
00194    }
00195 
00197    template <class T> BCP_buffer& pack(const T* const values,
00198                                        const int length){
00199      make_fit( sizeof(int) + sizeof(T) * length );
00200      memcpy(_data + _size, &length, sizeof(int));
00201      _size += sizeof(int);
00202      if (length > 0){
00203        memcpy(_data + _size, values, sizeof(T) * length);
00204        _size += sizeof(T) * length;
00205      }
00206      return *this;
00207    }
00208 
00222    template <class T> BCP_buffer& unpack(T*& values, int& length,
00223                                          bool allocate = true)
00224      throw(BCP_fatal_error) {
00225      if (allocate) {
00226 #ifdef PARANOID
00227        if (_pos + sizeof(int) > _size)
00228          throw BCP_fatal_error("Reading over the end of buffer.\n");
00229 #endif
00230        memcpy(&length, _data + _pos, sizeof(int));
00231        _pos += sizeof(int);
00232        if (length > 0){
00233 #ifdef PARANOID
00234          if (_pos + sizeof(T)*length > _size)
00235            throw BCP_fatal_error("Reading over the end of buffer.\n");
00236 #endif
00237          values = new T[length];
00238          memcpy(values, _data + _pos, sizeof(T)*length);
00239          _pos += sizeof(T) * length;
00240        }
00241        
00242      } else { /* ! allocate */
00243 
00244        int l;
00245 #ifdef PARANOID
00246        if (_pos + sizeof(int) > _size)
00247          throw BCP_fatal_error("Reading over the end of buffer.\n");
00248 #endif
00249        memcpy(&l, _data + _pos, sizeof(int));
00250        _pos += sizeof(int);
00251        if (l != length)
00252          throw BCP_fatal_error("BCP_buffer::unpack() : bad array lentgh.\n");
00253        if (length > 0){
00254 #ifdef PARANOID
00255          if (_pos + sizeof(T)*length > _size)
00256            throw BCP_fatal_error("Reading over the end of buffer.\n");
00257 #endif
00258          memcpy(values, _data + _pos, sizeof(T)*length);
00259          _pos += sizeof(T) * length;
00260        }
00261        
00262      }
00263      
00264      return *this;
00265    }
00266 
00268    BCP_buffer& pack(const BCP_string& value){
00269       // must define here, 'cos in BCP_message.C we have only templated members
00270       int len = value.length();
00271       make_fit( sizeof(int) + len );
00272       memcpy(_data + _size, &len, sizeof(int));
00273       _size += sizeof(int);
00274       if (len > 0){
00275          memcpy(_data + _size, value.c_str(), len);
00276          _size += len;
00277       }
00278       return *this;
00279    }
00281    BCP_buffer& pack(BCP_string& value){
00282       // must define here, 'cos in BCP_message.C we have only templated members
00283       int len = value.length();
00284       make_fit( sizeof(int) + len );
00285       memcpy(_data + _size, &len, sizeof(int));
00286       _size += sizeof(int);
00287       if (len > 0){
00288          memcpy(_data + _size, value.c_str(), len);
00289          _size += len;
00290       }
00291       return *this;
00292    }
00294    BCP_buffer& unpack(BCP_string& value){
00295       int len;
00296       unpack(len);
00297       value.assign(_data + _pos, len);
00298       _pos += len;
00299       return *this;
00300    }
00301 
00302    // packing/unpacking for BCP_vec
00304    template <class T> BCP_buffer& pack(const BCP_vec<T>& vec) {
00305      int objnum = vec.size();
00306      int new_bytes = objnum * sizeof(T);
00307      make_fit( sizeof(int) + new_bytes );
00308      memcpy(_data + _size, &objnum, sizeof(int));
00309      _size += sizeof(int);
00310      if (objnum > 0){
00311        memcpy(_data + _size, vec.begin(), new_bytes);
00312        _size += new_bytes;
00313      }
00314      return *this;
00315    }
00316 
00318    template <class T> BCP_buffer& pack(const std::vector<T>& vec) {
00319      int objnum = vec.size();
00320      int new_bytes = objnum * sizeof(T);
00321      make_fit( sizeof(int) + new_bytes );
00322      memcpy(_data + _size, &objnum, sizeof(int));
00323      _size += sizeof(int);
00324      if (objnum > 0){
00325        memcpy(_data + _size, &vec[0], new_bytes);
00326        _size += new_bytes;
00327      }
00328      return *this;
00329    }
00330 
00332    template <class T> BCP_buffer& unpack(BCP_vec<T>& vec) {
00333      int objnum;
00334 #ifdef PARANOID
00335      if (_pos + sizeof(int) > _size)
00336        throw BCP_fatal_error("Reading over the end of buffer.\n");
00337 #endif
00338      memcpy(&objnum, _data + _pos, sizeof(int));
00339      _pos += sizeof(int);
00340      vec.clear();
00341      if (objnum > 0){
00342 #ifdef PARANOID
00343        if (_pos + sizeof(T)*objnum > _size)
00344          throw BCP_fatal_error("Reading over the end of buffer.\n");
00345 #endif
00346        vec.reserve(objnum);
00347        vec.insert(vec.end(), _data + _pos, objnum);
00348        _pos += objnum * sizeof(T);
00349      }
00350      return *this;
00351    }
00352 
00354    template <class T> BCP_buffer& unpack(std::vector<T>& vec) {
00355      int objnum;
00356 #ifdef PARANOID
00357      if (_pos + sizeof(int) > _size)
00358        throw BCP_fatal_error("Reading over the end of buffer.\n");
00359 #endif
00360      memcpy(&objnum, _data + _pos, sizeof(int));
00361      _pos += sizeof(int);
00362      vec.clear();
00363      if (objnum > 0){
00364 #ifdef PARANOID
00365        if (_pos + sizeof(T)*objnum > _size)
00366          throw BCP_fatal_error("Reading over the end of buffer.\n");
00367 #endif
00368        vec.insert(vec.end(), objnum, T());
00369        memcpy(&vec[0], _data + _pos, objnum * sizeof(T));
00370        _pos += objnum * sizeof(T);
00371      }
00372      return *this;
00373    }
00374 
00381    BCP_buffer() : _msgtag(BCP_Msg_NoMessage), _sender(-1), _pos(0),
00382                   _max_size(1<<16/*64K*/), _size(0),
00383                   _data(new char[_max_size]) {}
00385    BCP_buffer(const BCP_buffer& buf) :
00386       _msgtag(BCP_Msg_NoMessage), _sender(-1), _pos(0),
00387       _max_size(0), _size(0), _data(0){
00388          operator=(buf);
00389    }
00392    ~BCP_buffer() {
00393       delete[] _data;
00394    }
00396 };
00397 
00398 #endif

Generated on Thu Jan 15 03:00:58 2009 for coin-Bcp by  doxygen 1.4.7