00001
00002
00003 #ifndef _BCP_BUFFER_H
00004 #define _BCP_BUFFER_H
00005
00006 #include <memory>
00007 #include <vector>
00008
00009
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
00042
00043
00044
00045
00046
00047
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);
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 {
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
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
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
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), _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