Bcp 1.4.4
Loading...
Searching...
No Matches
BCP_buffer.hpp
Go to the documentation of this file.
1// Copyright (C) 2000, International Business Machines
2// Corporation and others. All Rights Reserved.
3#ifndef _BCP_BUFFER_H
4#define _BCP_BUFFER_H
5
6#include <memory>
7#include <vector>
8
9// This file is fully docified.
10
11#include "BCP_error.hpp"
12#include "BCP_string.hpp"
13#include "BCP_message_tag.hpp"
14#include "BCP_message.hpp"
15#include "BCP_vector.hpp"
16
40public:
41 /* The data members are public for efficiency reasons. The message
42 environment's receiving function should be able to directly manipulate
43 these fields. However, making the virtual base class of all message
44 passing environment to be a friend doesn't help... Anyway, access these
45 fields sparingly.<br>
46 THINK: maybe it's not that inefficient to access the fields thru
47 functions... */
75 size_t _pos;
77 size_t _max_size;
80 size_t _size;
82 char* _data;
85public:
86 //=========================================================================
90 inline BCP_message_tag msgtag() const { return _msgtag; }
93 inline int sender() const { return _sender; }
95 inline int size() const { return _size; }
97 inline const char* data() const { return _data; }
99 //=========================================================================
100
104 inline void set_position(const int pos) throw(BCP_fatal_error) {
105 if (pos < 0 || pos > size())
106 throw BCP_fatal_error("Incorrest buffer position setting.\n");
107 _pos = pos;
108 }
110 inline void set_size(const int s) throw(BCP_fatal_error) {
111 if (s < 0 || s > size())
112 throw BCP_fatal_error("Incorrest buffer position setting.\n");
113 _size = s;
114 }
116 inline void set_msgtag(const BCP_message_tag tag) { _msgtag = tag; }
117
119 void set_content(const char* data, const size_t size,
121 _sender = sender;
122 _msgtag = msgtag;
123 if (_max_size < size) {
124 delete[] _data;
125 _data = new char[size];
126 _max_size = size;
127 }
128 _pos = 0;
129 _size = size;
130 if (_size)
131 memcpy(_data, data, size * sizeof(char));
132 }
133
134
137 _msgtag = buf._msgtag;
138 _sender = buf._sender;
139 _pos = buf._pos;
140 if (_max_size < buf._max_size) {
141 delete[] _data;
142 _data = new char[buf._max_size];
143 _max_size = buf._max_size;
144 }
145 _size = buf._size;
146 if (_size)
147 memcpy(_data, buf._data, _size * sizeof(char));
148 return *this;
149 }
153 inline void make_fit(const int add_size){
154 if (_max_size < _size + add_size) {
155 _max_size = _size + add_size;
156 /* If > 1M then have spare space of 1/16th (~6%) of used space,
157 if <= 1M then have 64K spare space */
158 _max_size += (_max_size > 1<<20) ? (_max_size >> 4) : (1 << 16) ;
159 char *new_data = new char[_max_size];
160 if (_size)
161 memcpy(new_data, _data, _size);
162 delete[] _data;
163 _data = new_data;
164 }
165 }
168 inline void clear(){
170 _size = 0;
171 _pos = 0;
172 _sender = -1;
173 }
174
177 template <class T> BCP_buffer& pack(const T& value) {
178 make_fit( sizeof(T) );
179 memcpy(_data + _size, &value, sizeof(T));
180 _size += sizeof(T);
181 return *this;
182 }
183
186 template <class T> BCP_buffer& unpack(T& value){
187#ifdef PARANOID
188 if (_pos + sizeof(T) > _size)
189 throw BCP_fatal_error("Reading over the end of buffer.\n");
190#endif
191 memcpy(&value, _data + _pos, sizeof(T));
192 _pos += sizeof(T);
193 return *this;
194 }
195
197 template <class T> BCP_buffer& pack(const T* const values,
198 const int length){
199 make_fit( sizeof(int) + sizeof(T) * length );
200 memcpy(_data + _size, &length, sizeof(int));
201 _size += sizeof(int);
202 if (length > 0){
203 memcpy(_data + _size, values, sizeof(T) * length);
204 _size += sizeof(T) * length;
205 }
206 return *this;
207 }
208
222 template <class T> BCP_buffer& unpack(T*& values, int& length,
223 bool allocate = true)
224 throw(BCP_fatal_error) {
225 if (allocate) {
226#ifdef PARANOID
227 if (_pos + sizeof(int) > _size)
228 throw BCP_fatal_error("Reading over the end of buffer.\n");
229#endif
230 memcpy(&length, _data + _pos, sizeof(int));
231 _pos += sizeof(int);
232 if (length > 0){
233#ifdef PARANOID
234 if (_pos + sizeof(T)*length > _size)
235 throw BCP_fatal_error("Reading over the end of buffer.\n");
236#endif
237 values = new T[length];
238 memcpy(values, _data + _pos, sizeof(T)*length);
239 _pos += sizeof(T) * length;
240 }
241
242 } else { /* ! allocate */
243
244 int l;
245#ifdef PARANOID
246 if (_pos + sizeof(int) > _size)
247 throw BCP_fatal_error("Reading over the end of buffer.\n");
248#endif
249 memcpy(&l, _data + _pos, sizeof(int));
250 _pos += sizeof(int);
251 if (l != length)
252 throw BCP_fatal_error("BCP_buffer::unpack() : bad array lentgh.\n");
253 if (length > 0){
254#ifdef PARANOID
255 if (_pos + sizeof(T)*length > _size)
256 throw BCP_fatal_error("Reading over the end of buffer.\n");
257#endif
258 memcpy(values, _data + _pos, sizeof(T)*length);
259 _pos += sizeof(T) * length;
260 }
261
262 }
263
264 return *this;
265 }
266
268 BCP_buffer& pack(const BCP_string& value){
269 // must define here, 'cos in BCP_message.C we have only templated members
270 int len = value.length();
271 make_fit( sizeof(int) + len );
272 memcpy(_data + _size, &len, sizeof(int));
273 _size += sizeof(int);
274 if (len > 0){
275 memcpy(_data + _size, value.c_str(), len);
276 _size += len;
277 }
278 return *this;
279 }
282 // must define here, 'cos in BCP_message.C we have only templated members
283 int len = value.length();
284 make_fit( sizeof(int) + len );
285 memcpy(_data + _size, &len, sizeof(int));
286 _size += sizeof(int);
287 if (len > 0){
288 memcpy(_data + _size, value.c_str(), len);
289 _size += len;
290 }
291 return *this;
292 }
295 int len;
296 unpack(len);
297 value.assign(_data + _pos, len);
298 _pos += len;
299 return *this;
300 }
301
302 // packing/unpacking for BCP_vec
304 template <class T> BCP_buffer& pack(const BCP_vec<T>& vec) {
305 int objnum = vec.size();
306 int new_bytes = objnum * sizeof(T);
307 make_fit( sizeof(int) + new_bytes );
308 memcpy(_data + _size, &objnum, sizeof(int));
309 _size += sizeof(int);
310 if (objnum > 0){
311 memcpy(_data + _size, vec.begin(), new_bytes);
312 _size += new_bytes;
313 }
314 return *this;
315 }
316
318 template <class T> BCP_buffer& pack(const std::vector<T>& vec) {
319 int objnum = vec.size();
320 int new_bytes = objnum * sizeof(T);
321 make_fit( sizeof(int) + new_bytes );
322 memcpy(_data + _size, &objnum, sizeof(int));
323 _size += sizeof(int);
324 if (objnum > 0){
325 memcpy(_data + _size, &vec[0], new_bytes);
326 _size += new_bytes;
327 }
328 return *this;
329 }
330
332 template <class T> BCP_buffer& unpack(BCP_vec<T>& vec) {
333 int objnum;
334#ifdef PARANOID
335 if (_pos + sizeof(int) > _size)
336 throw BCP_fatal_error("Reading over the end of buffer.\n");
337#endif
338 memcpy(&objnum, _data + _pos, sizeof(int));
339 _pos += sizeof(int);
340 vec.clear();
341 if (objnum > 0){
342#ifdef PARANOID
343 if (_pos + sizeof(T)*objnum > _size)
344 throw BCP_fatal_error("Reading over the end of buffer.\n");
345#endif
346 vec.reserve(objnum);
347 vec.insert(vec.end(), _data + _pos, objnum);
348 _pos += objnum * sizeof(T);
349 }
350 return *this;
351 }
352
354 template <class T> BCP_buffer& unpack(std::vector<T>& vec) {
355 int objnum;
356#ifdef PARANOID
357 if (_pos + sizeof(int) > _size)
358 throw BCP_fatal_error("Reading over the end of buffer.\n");
359#endif
360 memcpy(&objnum, _data + _pos, sizeof(int));
361 _pos += sizeof(int);
362 vec.clear();
363 if (objnum > 0){
364#ifdef PARANOID
365 if (_pos + sizeof(T)*objnum > _size)
366 throw BCP_fatal_error("Reading over the end of buffer.\n");
367#endif
368 vec.insert(vec.end(), objnum, T());
369 memcpy(&vec[0], _data + _pos, objnum * sizeof(T));
370 _pos += objnum * sizeof(T);
371 }
372 return *this;
373 }
374
382 _max_size(1<<16/*64K*/), _size(0),
383 _data(new char[_max_size]) {}
385 BCP_buffer(const BCP_buffer& buf) :
387 _max_size(0), _size(0), _data(0){
388 operator=(buf);
389 }
393 delete[] _data;
394 }
396};
397
398#endif
BCP_message_tag
This enumerative constant describes the message tags different processes of BCP understand.
@ BCP_Msg_NoMessage
Used to indicate that there is no message in the buffer of a process.
This class describes the message buffer used for all processes of BCP.
BCP_buffer & operator=(const BCP_buffer &buf)
Make an exact replica of the other buffer.
void clear()
Completely clear the buffer.
BCP_buffer(const BCP_buffer &buf)
The copy constructor makes an exact replica of the other buffer.
BCP_buffer & pack(const BCP_vec< T > &vec)
Pack a BCP_vec into the buffer.
int size() const
Return the size of the current message in the buffer.
BCP_buffer & unpack(BCP_vec< T > &vec)
Unpack a BCP_vec from the buffer.
void make_fit(const int add_size)
Reallocate the buffer if necessary so that at least add_size number of additional bytes will fit into...
const char * data() const
Return a const pointer to the data stored in the buffer.
size_t _pos
The next read position in the buffer.
void set_content(const char *data, const size_t size, int sender, BCP_message_tag msgtag)
Set the buffer to be a copy of the given data.
void set_size(const int s)
Cut off the end of the buffer.
int sender() const
Return a const pointer to the process id of the sender of the message in the buffer.
BCP_buffer & unpack(T *&values, int &length, bool allocate=true)
Unpack an array of objects of type T, where T must be a built-in type (ar at least something that can...
int _sender
The process id of the sender of the last received message.
BCP_buffer()
The default constructor creates a buffer of size 16 Kbytes with no message in it.
BCP_buffer & pack(const BCP_string &value)
Pack a BCP_string into the buffer.
BCP_buffer & pack(const T *const values, const int length)
Pack a C style array of objects of type T.
void set_position(const int pos)
Position the read head in the buffer.
void set_msgtag(const BCP_message_tag tag)
Set the message tag on the buffer.
BCP_buffer & unpack(BCP_string &value)
Unpack a BCP_string from the buffer.
size_t _size
The current size of the message (the first _size bytes of the buffer).
BCP_buffer & pack(const std::vector< T > &vec)
Pack a std::vector into the buffer.
BCP_buffer & pack(const T &value)
Pack a single object of type T.
BCP_message_tag msgtag() const
Return the message tag of the message in the buffer.
char * _data
Pointer to the buffer itself.
BCP_buffer & unpack(T &value)
Unpack a single object of type T.
BCP_message_tag _msgtag
The message tag of the last received message.
size_t _max_size
The amount of memory allocated for the buffer.
BCP_buffer & unpack(std::vector< T > &vec)
Unpack a std::vector from the buffer.
BCP_buffer & pack(BCP_string &value)
Pack a BCP_string into the buffer.
~BCP_buffer()
The desctructor deletes all data members (including freeing the buffer).
Currently there isn't any error handling in BCP.
Definition BCP_error.hpp:20
This class is a very simple impelementation of a constant length string.
int length() const
const char * c_str() const
BCP_string & assign(const char *source, const int len)
The class BCP_vec serves the same purpose as the vector class in the standard template library.
void clear()
Delete every entry.
iterator end()
Return an iterator to the end of the object.
size_t size() const
Return the current number of entries.
iterator begin()
Return an iterator to the beginning of the object.
void reserve(const size_t n)
Reallocate the object to make space for n entries.
void insert(iterator position, const void *first, const size_t num)
Insert num entries starting from memory location first into the vector from position pos.