|
Boost : |
From: Paul Vanlint (paul_at_[hidden])
Date: 2003-06-20 10:11:15
So there seems to be some interest at least from a couple of people.
To further clarify what I have, here is a piece of code using my msg buffer
class to do a few different things and also, a snippet of the public part of
my class definition.
At one point there were functions which allowed data to be directly read
from and written to a TCP socket, however that relied on another custom
class which I did not write, so I have removed it.
It also uses a custom logging mechanism which I did write, but it is
probably best if I remove that and simply write the error messages to cerr
#include <iostream>
#include "msg_buffer.h"
using namespace std;
int
main()
{
Msg_buffer tmp;
char* sample_str1 = "01234567890123456789012345678901234567890123456789";
char* sample_str2 = "Test1";
char* sample_str3 = "Test2";
char* sample_str4 = "Test3";
int sample_int1 = 257;
char sample_char1 = '!';
// Writing data directly into the buffer structure,
// e.g. how it may be done from a socket
// In this case, we are simulating an incoming
// stream giving 1 byte at a time
size_t total_len = strlen(sample_str1)+1;
char* str_ptr = sample_str1;
size_t chunk_size = 1;
char* buff_ptr;
do
{
size_t len = tmp.get_write_chunk(&buff_ptr, chunk_size);
memcpy(buff_ptr, str_ptr, len);
total_len -= len;
str_ptr += len;
} while (total_len > 0);
// Add data into buffer using structured data functions
tmp.put_msg_params("s", sample_str1);
unsigned int reserved_id = tmp.reserve_space(sizeof(unsigned int));
size_t written = tmp.put_msg_params("sdcss", sample_str2,
sample_int1, sample_char1,
sample_str3, sample_str4);
// Back fill the reserved space
tmp.fill_reserved(reserved_id, "u", written);
// At this point, data buffer should have folloiwng data in order:
char* str1;
char* str1b;
unsigned int uint1;
char* str2;
int int1;
char char1;
char* str3;
char* str4;
// Read data from buffer.
// Note that for strings, we are simply getting a pointer to the
// Buffer instead of copying out for performance reasons
if (false == tmp.get_msg_params("ssusdcss", &str1, &str1b, &uint1,
&str2, &int1, &char1, &str3, &str4))
{ cout << "Error in get_msg_params()\n"; }
else
{
cout << "Retrieved:"
<< "\n str1 = \"" << str1
<< "\"\n str1b = \"" << str1b
<< "\n uint1 = " << uint1
<< "\"\n str2 = \"" << str2
<< "\"\n int1 = " << int1
<< "\n char1 = '" << char1
<< "'\n str3 = \"" << str3
<< "\"\n str4 = \"" << str4 << "\"\n";
}
}
Will display:
Retrieved:
str1 = "01234567890123456789012345678901234567890123456789"
str1b = "01234567890123456789012345678901234567890123456789
uint1 = 23"
str2 = "Test1"
int1 = 257
char1 = '!'
str3 = "Test2"
str4 = "Test3"
class Msg_buffer
{
public:
Msg_buffer();
~Msg_buffer();
bool has_data();
size_t get_total_data_len();
size_t get_chunk_count();
// This function resets pointers back to the beginning of the buffers
// and does any housekeeping that is required.
// After running reset_buffer(), the object may be treated as brand new.
// It is suggested that the same buffer be reused to reduce overhead of
// memory allocation.
// Any previously allocated memory will be assumed to be freed at this
// point even though we may actually keep it allocated for efficiency.
bool reset_buffer();
// Read functions
// Gets next char in buffer without incrementing read ptr
bool peek(char& ch);
// Read a formatted parameter list from the message buffer
bool get_msg_params(char const* fmt, ...);
// Read raw data from message buffer into buff_ptr
bool get(unsigned int len, char const** buff_ptr);
// Write functions
// This is used if we need to mark a point in the message that will be
// filled in later, such as length fields which go at the front.
// It returns a handle to the reserved space, not a pointer
// A return handle of 0 means error
unsigned int reserve_space(size_t len);
// This allows us to fill a previously reserved space.
// The reserved_id is the handle returned by reserve_space
bool fill_reserved(unsigned int reserved_id, char const* fmt, ...);
// This allows us to write a formatted parameter list into the message
// buffer
// Returns the number of bytes written, -1 means error
ssize_t put_msg_params(char const* fmt, ...);
ssize_t put(char ch);
ssize_t put(char const* str_ptr);
ssize_t put(ssize_t len, char const* data_ptr);
ssize_t put(int value);
ssize_t put(unsigned int value);
ssize_t put(unsigned long value);
// These would be used by TCP functions to access buffer chunks
// directly. Note that successive calls to this function will return
// successive chunks in the chain.
// If request_len is zero, then it returns the rest of the buffer
// For get_read_chunk, it only returns chunks and chunk pieces up to
// the current write position
// For get_write_chunk, if not enough buffer space is available,
// then what is available is returned. If no space is available in an
// existing chunk then a new chunk is allocated.
// Returns the actual length of the buffer returned, 0 means error
size_t get_read_chunk(char** buff_ptr, size_t request_len);
size_t get_write_chunk(char** buff_ptr, size_t request_len);
// This will write all data out to a file, including length, and
// appending a CRC
ssize_t file_write(int file_id);
ssize_t file_write(int file_id, size_t max_len);
// Read data in from a file
bool file_read(int file_id, bool& done, int& msglen);
// Jump around the buffer using bookmarks
unsigned int get_read_bookmark();
bool set_read_bookmark(unsigned int bookmark,
unsigned int incremental_offset = 0);
};
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk