complex struct

L

Larry

Hi,

I have those structs:

const int numbuff = 3;

struct buffer
{
unsigned char data[1024];
int bytesRecorded;
int user;
buffer(const unsigned char * data_, const int bytesRecorded_, const int
user_) :
bytesRecorded(bytesRecorded_), user(user_)
{
copy(data_, data_ + bytesRecorded_, data);
}
};

struct circular
{
circular_buffer<buffer> cb[numbuff];
};

// circular is an array of numbiff buffer(s).


Now, I can't seem to access buffer's fields by circular anymore! All I can
access is buffer constructor:

circular c;

c.cb->push_back(buffer(NULL, 0, 0)); // write or overwrite buffer

If I were to read the last element from buffer how could I go about it?

thanks
 
J

John H.

struct buffer
{
 unsigned char data[1024];
 int bytesRecorded;
 buffer(const unsigned char * data_, const int bytesRecorded_, const int
user_);
};

struct circular
{
 circular_buffer<buffer> cb[numbuff];

};

// circular is an array of numbiff buffer(s).

More accurately, circular HAS an array. That array contains numbuff
circular_buffers. Those circular_buffers are themselves containers
that can contain buffers.
circular c;

Now, I can't seem to access buffer's fields by circular anymore! All I can
access is buffer constructor:

c; // gives you the circular object
c.cb; // gives you the array of circular_buffers in c
c.cb[0]; // gives you the first of the circular_buffers in the array
in c
c.cb[0][0]; // gives you the first of the buffers inside the first
circular_buffer in the array in c
c.cb[0][0].data // gives you the data of the first of the buffers
inside the first circular_buffer in the array in c
If I were to read the last element from buffer how could I go about it?

If you really ment "last element from buffer", perhaps you want to
access the last byte in a buffer object's data member. If this is the
case then:
buffer buff(...);
buff.data[1023];
Perhaps you ment the last byte recorded to the buffer, then something
like:
buff.data[buffer.bytesRecorded-1];
c.cb->push_back(buffer(NULL, 0, 0));

What you are doing here is taking your circular object named c,
getting the array of circular_buffers named cb, then taking the first
of those circular_buffers, and pushing back a buffer into it. This
might be written more clearly as:
c.cb[0].push_back(buffer(NULL, 0, 0));
Neither of these statement will do anything because all of our
circular_buffers in the array in c are of size 0.

Since you didn't talk much about what you are trying to do, I can only
speculate, but I am guessing that your design here is not doing what
you want it to.
 
L

Larry

Since you didn't talk much about what you are trying to do, I can only
speculate, but I am guessing that your design here is not doing what
you want it to.

This is what I am tring to do: a tiny streaming server to stream to at least
a couple of clients at the same time. (capturing from a given wave in
device, mp3 encoding and streaming) for the moment I am coding the server
part:

#include <iostream>
#include <string>
#include <map>
#include <algorithm>
#include <process.h>
#include <cstdlib>
#include <ctime>
#include "socket.h"
#include <boost/circular_buffer.hpp>
using namespace std;
using namespace boost;

const string CRLF = "\r\n";
const int numbuff = 3;
const int buflen = 30;

unsigned int __stdcall Consumer(void* sock);
unsigned int __stdcall Producer(void*);

void getDateTime(char * szTime);

struct buffer
{
unsigned char data[1024];
int bytesRecorded;
int user;
buffer(const unsigned char * data_, const int bytesRecorded_, const int
user_) :
bytesRecorded(bytesRecorded_), user(user_)
{
copy(data_, data_ + bytesRecorded_, data);
}
};

struct circular
{
circular_buffer<buffer> cb[numbuff];
circular_buffer<buffer>::const_iterator it;
};

map<int, circular> users;
map<int, circular>::iterator uit;

int main()
{
// Launch Producer
unsigned int prodRet;
_beginthreadex(0,0,Producer,NULL,0,&prodRet);
if(prodRet)
cout << "Launched Producer Thread!" << endl;

// Set up server (port: 8000, maxconn: 10)
SocketServer sockIn(8000, 10);

while(1)
{
// ...wait for incoming connections...
Socket* s = sockIn.Accept();
unsigned int sockRet;
_beginthreadex(0,0,Consumer,s,0,&sockRet);
if(sockRet)
cout << "Spawned a new thread!" << endl;
else
cout << "Thread error!" << endl;
}

sockIn.Close();

system("pause");
return EXIT_SUCCESS;
}

// Consumer
unsigned int __stdcall Consumer(void* sock)
{
Socket* s = (Socket*) sock;

s->SendBytes("Hello World!" + CRLF);

int threadid = (int)GetCurrentThreadId();

// Prepare & add circular buffer to the map
circular c;
c.cb->push_back(buffer(NULL,0,0));
c.cb->push_back(buffer(NULL,0,0));
c.cb->push_back(buffer(NULL,0,0));

users.insert(make_pair(threadid, c));

// TODO:
// Read data from the buffer
// and send it to the client
Sleep(10000);

// Remove buffer from the map
users.erase(threadid);

// Say bye to the client
s->SendBytes("Bye bye!" + CRLF);

// Disconnect client
cout << "Closing thread..." << endl;
s->Close();
delete s;
return 0;
}

// Producer
unsigned int __stdcall Producer(void*)
{
while(1)
{
Sleep(1000);
char szTime[30]; getDateTime(szTime);
for(uit=users.begin(); uit!=users.end(); ++uit)
{
users[uit->first].cb->push_back(buffer((unsigned char*)szTime, 30, 1));
cout << "Producer is writing to: " << uit->first << endl;
}
}
return 0;
}

void getDateTime(char * szTime)
{
time_t rawtime = time(NULL);
struct tm timeinfo;
gmtime_s(&timeinfo, &rawtime);
strftime(szTime, 30, "%a, %d %b %Y %X GMT", &timeinfo);
}

thanks
 
L

Larry

Since you didn't talk much about what you are trying to do, I can only
speculate, but I am guessing that your design here is not doing what
you want it to.

anyway,before I was doing:

struct buffer
{
char data[1024];
int bytesRecorded;
buffer(const char * data_, const int bytesRecorded_) :
bytesRecorded(bytesRecorded_)
{
copy(data_, data_ + (bytesRecorded_ * sizeof(char)), data);
}
};

int main()
{
circular_buffer<buffer> cb(numbuff);

// Insert elements
cout << "Push elements:" << endl;
for(int i = 0; i < 10; i++)
{
char szTime[30]; getDateTime(szTime);

cb.push_back( buffer(szTime, 30) );

cout << szTime << endl;

Sleep(1000);
}

// Show elements:
cout << "Show elements:" << endl;
for(int i = 0; i<(int)cb.size(); i++)
{
cout << &cb.data[0] << endl;
}

system("pause");
return EXIT_SUCCESS;
}

that worked great! But now I needed to to something like:

std::map<int, circular_buffer<buffer> cb(numbuff)> users

which is impossible, that's why I thought I'd wrap up into another struct:

struct circular
{
circular_buffer<buffer> cb[numbuff];
};

so that I should do:

std::map<int, circular> users

but that led me to some problems...
 
L

Larry

What you give is an object, not a type. only circular_buffer<buffer>
Again, you *must* use a pointer(i.e, circular_buffer<buffer>*), or your
application will not work!

I read up a little better on boost::circular_buffer so I can now do like
this:

const int numbuff = 3;

struct buffer
{
unsigned char data[1024];
int bytesRecorded;
int user;
buffer(const unsigned char * data_, const int bytesRecorded_, const int
user_) :
bytesRecorded(bytesRecorded_), user(user_)
{
copy(data_, data_ + bytesRecorded_, data);
}
};

struct circular
{
circular_buffer<buffer> cb;
};

int main()
{
map<int, circular> users;

int regkey = 1000;

circular k;
k.cb.set_capacity(numbuff); // Finally!

// Prepare buffer
for(int i = 0; i<numbuff; i++)
{
k.cb.push_back(buffer(NULL,0,0));
}

// Add buffer
k.cb.push_back(buffer((unsigned char*)"hellow world!", 15,1));
k.cb.push_back(buffer((unsigned char*)"hellow world!", 15,2));
k.cb.push_back(buffer((unsigned char*)"hellow world!", 15,3));

// Push in the map
users.insert(make_pair(regkey, k));

// Show map: element regkey

// First element
cout << users[regkey].cb.at(0).user << endl; // 1

// Last element
cout << users[regkey].cb.at(numbuff-1).user << endl; // 3

// Remove from map
users.erase(regkey);
}

I cannot use std::string since I need to deal with binary data
 
L

Larry

std::basic_string<unsigned char>
std::vector<unsigned char>

std::basic_string<char>
std::vector<char>

or typedef a "byte" type the way you prefer.


There is nothing in std::basic_string<> nor in std::string (which is
just std::basic_string<char>) that makes it unable to hold binary
data.

Several people have been trying to recommend you to give up on writing
code that is so prone to buffer overflow and memory violations. C++
offers you tool to make life for yourself much easier.

I am going to deal with chars form 0x00 to 0xFF mostly.I don't think the
lastest code I have written (and posted above) is so prone to buffer
overflow as well as memory violations.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,054
Latest member
LucyCarper

Latest Threads

Top