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
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
00157
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 {
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
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
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
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), _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