/home/coin/SVN-release/CoinAll-1.1.0/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... */
00069    BCP_message_tag _msgtag;
00072    BCP_proc_id*    _sender;
00074    size_t _pos;
00076    size_t _max_size;
00079    size_t _size;
00081    char*  _data;
00084 public:
00085    //=========================================================================
00089    inline BCP_message_tag msgtag() const { return _msgtag; }
00092    inline const BCP_proc_id* sender() const { return _sender; }
00094    inline int                size() const { return _size; }
00096    inline const char*        data() const { return _data; }
00098    //=========================================================================
00099 
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_msgtag(const BCP_message_tag tag) { _msgtag = tag; }
00111 
00113   void set_content(const char* data, const size_t size,
00114                    BCP_proc_id* sender, BCP_message_tag msgtag) {
00115     _sender = sender;
00116     _msgtag = msgtag;
00117     if (_max_size < size) {
00118       delete[] _data;
00119       _data = new char[size];
00120       _max_size = size;
00121     }
00122     _pos = 0;
00123     _size = size;
00124     if (_size)
00125       memcpy(_data, data, size * sizeof(char));
00126    }
00127      
00128     
00130    BCP_buffer& operator=(const BCP_buffer& buf) {
00131       _msgtag = buf._msgtag;
00132       _sender = buf._sender ? buf._sender->clone() : 0;
00133       _pos = buf._pos;
00134       if (_max_size < buf._max_size) {
00135          delete[] _data;
00136          _data = new char[buf._max_size];
00137          _max_size = buf._max_size;
00138       }
00139       _size = buf._size;
00140       if (_size)
00141          memcpy(_data, buf._data, _size * sizeof(char));
00142       return *this;
00143    }
00147    inline void make_fit(const int add_size){
00148       if (_max_size < _size + add_size){
00149          _max_size = 2 * (_size + add_size + 0x1000/*4K*/);
00150          char *new_data = new char[_max_size];
00151          if (_size)
00152             memcpy(new_data, _data, _size);
00153          delete[] _data;
00154          _data = new_data;
00155       }
00156    }
00159    inline void clear(){
00160       _msgtag = BCP_Msg_NoMessage;
00161       _size = 0;
00162       _pos = 0;
00163       delete _sender; _sender = 0;
00164    }
00165 
00168    template <class T> BCP_buffer& pack(const T& value) {
00169      make_fit( sizeof(T) );
00170      memcpy(_data + _size, &value, sizeof(T));
00171      _size += sizeof(T);
00172      return *this;
00173    }
00174 
00177    template <class T> BCP_buffer& unpack(T& value){
00178 #ifdef PARANOID
00179      if (_pos + sizeof(T) > _size)
00180        throw BCP_fatal_error("Reading over the end of buffer.\n");
00181 #endif
00182      memcpy(&value, _data + _pos, sizeof(T));
00183      _pos += sizeof(T);
00184      return *this;
00185    }
00186 
00188    template <class T> BCP_buffer& pack(const T* const values,
00189                                        const int length){
00190      make_fit( sizeof(int) + sizeof(T) * length );
00191      memcpy(_data + _size, &length, sizeof(int));
00192      _size += sizeof(int);
00193      if (length > 0){
00194        memcpy(_data + _size, values, sizeof(T) * length);
00195        _size += sizeof(T) * length;
00196      }
00197      return *this;
00198    }
00199 
00213    template <class T> BCP_buffer& unpack(T*& values, int& length,
00214                                          bool allocate = true)
00215      throw(BCP_fatal_error) {
00216      if (allocate) {
00217 #ifdef PARANOID
00218        if (_pos + sizeof(int) > _size)
00219          throw BCP_fatal_error("Reading over the end of buffer.\n");
00220 #endif
00221        memcpy(&length, _data + _pos, sizeof(int));
00222        _pos += sizeof(int);
00223        if (length > 0){
00224 #ifdef PARANOID
00225          if (_pos + sizeof(T)*length > _size)
00226            throw BCP_fatal_error("Reading over the end of buffer.\n");
00227 #endif
00228          values = new T[length];
00229          memcpy(values, _data + _pos, sizeof(T)*length);
00230          _pos += sizeof(T) * length;
00231        }
00232        
00233      } else { /* ! allocate */
00234 
00235        int l;
00236 #ifdef PARANOID
00237        if (_pos + sizeof(int) > _size)
00238          throw BCP_fatal_error("Reading over the end of buffer.\n");
00239 #endif
00240        memcpy(&l, _data + _pos, sizeof(int));
00241        _pos += sizeof(int);
00242        if (l != length)
00243          throw BCP_fatal_error("BCP_buffer::unpack() : bad array lentgh.\n");
00244        if (length > 0){
00245 #ifdef PARANOID
00246          if (_pos + sizeof(T)*length > _size)
00247            throw BCP_fatal_error("Reading over the end of buffer.\n");
00248 #endif
00249          memcpy(values, _data + _pos, sizeof(T)*length);
00250          _pos += sizeof(T) * length;
00251        }
00252        
00253      }
00254      
00255      return *this;
00256    }
00257 
00259    BCP_buffer& pack(const BCP_string& value){
00260       // must define here, 'cos in BCP_message.C we have only templated members
00261       int len = value.length();
00262       make_fit( sizeof(int) + len );
00263       memcpy(_data + _size, &len, sizeof(int));
00264       _size += sizeof(int);
00265       if (len > 0){
00266          memcpy(_data + _size, value.c_str(), len);
00267          _size += len;
00268       }
00269       return *this;
00270    }
00272    BCP_buffer& pack(BCP_string& value){
00273       // must define here, 'cos in BCP_message.C we have only templated members
00274       int len = value.length();
00275       make_fit( sizeof(int) + len );
00276       memcpy(_data + _size, &len, sizeof(int));
00277       _size += sizeof(int);
00278       if (len > 0){
00279          memcpy(_data + _size, value.c_str(), len);
00280          _size += len;
00281       }
00282       return *this;
00283    }
00285    BCP_buffer& unpack(BCP_string& value){
00286       int len;
00287       unpack(len);
00288       value.assign(_data + _pos, len);
00289       _pos += len;
00290       return *this;
00291    }
00292 
00293    // packing/unpacking for BCP_vec
00295    template <class T> BCP_buffer& pack(const BCP_vec<T>& vec) {
00296      int objnum = vec.size();
00297      int new_bytes = objnum * sizeof(T);
00298      make_fit( sizeof(int) + new_bytes );
00299      memcpy(_data + _size, &objnum, sizeof(int));
00300      _size += sizeof(int);
00301      if (objnum > 0){
00302        memcpy(_data + _size, vec.begin(), new_bytes);
00303        _size += new_bytes;
00304      }
00305      return *this;
00306    }
00307 
00309    template <class T> BCP_buffer& pack(const std::vector<T>& vec) {
00310      int objnum = vec.size();
00311      int new_bytes = objnum * sizeof(T);
00312      make_fit( sizeof(int) + new_bytes );
00313      memcpy(_data + _size, &objnum, sizeof(int));
00314      _size += sizeof(int);
00315      if (objnum > 0){
00316        memcpy(_data + _size, &vec[0], new_bytes);
00317        _size += new_bytes;
00318      }
00319      return *this;
00320    }
00321 
00323    template <class T> BCP_buffer& unpack(BCP_vec<T>& vec) {
00324      int objnum;
00325 #ifdef PARANOID
00326      if (_pos + sizeof(int) > _size)
00327        throw BCP_fatal_error("Reading over the end of buffer.\n");
00328 #endif
00329      memcpy(&objnum, _data + _pos, sizeof(int));
00330      _pos += sizeof(int);
00331      vec.clear();
00332      if (objnum > 0){
00333 #ifdef PARANOID
00334        if (_pos + sizeof(T)*objnum > _size)
00335          throw BCP_fatal_error("Reading over the end of buffer.\n");
00336 #endif
00337        vec.reserve(objnum);
00338        vec.insert(vec.end(), _data + _pos, objnum);
00339        _pos += objnum * sizeof(T);
00340      }
00341      return *this;
00342    }
00343 
00345    template <class T> BCP_buffer& unpack(std::vector<T>& vec) {
00346      int objnum;
00347 #ifdef PARANOID
00348      if (_pos + sizeof(int) > _size)
00349        throw BCP_fatal_error("Reading over the end of buffer.\n");
00350 #endif
00351      memcpy(&objnum, _data + _pos, sizeof(int));
00352      _pos += sizeof(int);
00353      vec.clear();
00354      if (objnum > 0){
00355 #ifdef PARANOID
00356        if (_pos + sizeof(T)*objnum > _size)
00357          throw BCP_fatal_error("Reading over the end of buffer.\n");
00358 #endif
00359        vec.insert(vec.end(), objnum, T());
00360        memcpy(&vec[0], _data + _pos, objnum * sizeof(T));
00361        _pos += objnum * sizeof(T);
00362      }
00363      return *this;
00364    }
00365 
00372    BCP_buffer() : _msgtag(BCP_Msg_NoMessage), _sender(0), _pos(0),
00373       _max_size(0x4000/*16K*/), _size(0), _data(new char[_max_size]) {}
00375    BCP_buffer(const BCP_buffer& buf) :
00376       _msgtag(BCP_Msg_NoMessage), _sender(0), _pos(0),
00377       _max_size(0), _size(0), _data(0){
00378          operator=(buf);
00379    }
00382    ~BCP_buffer() {
00383       delete _sender;   _sender = 0;
00384       delete[] _data;
00385    }
00387 };
00388 
00389 #endif

Generated on Sun Nov 14 14:06:29 2010 for Coin-All by  doxygen 1.4.7