Reputation: 49
I am finishing up working on a circular buffer that needs to double it size when it becomes full. However, I am having trouble figuring out how to copy the elements from the old buffer into the new buffer. My code is as follows:
#define startSize 10
#define fiveMin 300
cbuf* cbuf_init(){
cbuf *buffer = malloc(sizeof(cbuf) + 9 * sizeof(quote));
buffer->currSize = 0;
buffer->maxSize = startSize;
//buffer->startAt = 0;
buffer->start = 0;
buffer->end = 0;
buffer->freeSlots = startSize;
//buffer->currIndex = 0;
return buffer;
}
void cbuf_update(cbuf *cb_ptr, unsigned int time, double rate){
if(cb_ptr->freeSlots == 0){
printf("EXPANDING CIRCULAR BUFFER!\n");
cbuf *newBuffer = malloc(sizeof(cbuf) + 19 * sizeof(quote));
newBuffer->maxSize = cb_ptr->maxSize * 2;
newBuffer->start = cb_ptr->start;
newBuffer->end = cb_ptr->end;
newBuffer->freeSlots = newBuffer->maxSize - cb_ptr->maxSize;
int x;
for(x = 0; x < cb_ptr->maxSize; x ++){
printf("Copying from slot %d\n", x);
printf("Currently Copying time: %d\t Rate: %f\n", cb_ptr->quoteBuffer[x].time, cb_ptr->quoteBuffer[x].rate);
newBuffer->quoteBuffer[x].time = cb_ptr->quoteBuffer[x].time;
newBuffer->quoteBuffer[x].rate = cb_ptr->quoteBuffer[x].rate;
}
cb_ptr = newBuffer;
}
//If the start pointer has reached the end of the array and there are still free slots back at the beginning of the array, loop back.
if(cb_ptr->start == cb_ptr->maxSize && cb_ptr->freeSlots > 0){
cb_ptr->start = 0;
};
cb_ptr->quoteBuffer[cb_ptr->start].time = time;
cb_ptr->quoteBuffer[cb_ptr->start].rate = rate;
cb_ptr->start = cb_ptr->start +1;
cb_ptr->freeSlots = cb_ptr->freeSlots -1;
//If any quote in the array is older than 5 minutes when compared to the current quote, flag it as null and move the end pointer up one.
//Also, clear up a freeSlot.
int x;
for(x = cb_ptr->end; x < (cb_ptr->start); x ++){
if((time) - (cb_ptr->quoteBuffer[x].time) >= fiveMin){
cb_ptr->end = cb_ptr->end + 1;
cb_ptr->quoteBuffer[x].time = -1;
cb_ptr->quoteBuffer[x].rate = -1.00;
cb_ptr->freeSlots = cb_ptr->freeSlots +1;
}
}
}
void cbuf_dump(cbuf *cb_ptr){
printf("*****\t DUMPING \t*****\n");
if(cb_ptr->start > cb_ptr->end){
int x;
for(x = cb_ptr->end; x<(cb_ptr->start); x++){
printf("%d.) time = %d, \t rate = %f\n",x,(cb_ptr->quoteBuffer[x].time),(cb_ptr->quoteBuffer[x].rate));
}
}
/*
If the start pointer has been wrapped back around to the beginning of the circular buffer, then the end pointer must be at an index that is greater than the start index. For this, we need to print out the data ranging from the end pointer to the end of the array, and then the data from the start pointer to the end pointer provided the data isn't flagged as null (having -1 for both entries in the quote struct).
*/
if(cb_ptr->end > cb_ptr->start){
int x;
for(x=cb_ptr->end; x < cb_ptr->maxSize; x ++){
printf("%d.) time = %d, \t rate = %f\n",x,(cb_ptr->quoteBuffer[x].time),(cb_ptr->quoteBuffer[x].rate));
}
int y;
for(y = 0; y < cb_ptr->start; y ++){
if(cb_ptr->quoteBuffer[y].time != -1){
printf("%d.) time = %d, \t rate = %f\n",y,(cb_ptr->quoteBuffer[y].time),(cb_ptr->quoteBuffer[y].rate));
}
}
}
printf("freeslots = %d\n", cb_ptr->freeSlots);
}
int main(){
cbuf *cb1 ;
cb1 = cbuf_init() ;
cbuf_update(cb1, 60, 1.291) ;
cbuf_update(cb1, 63, 1.287) ;
cbuf_update(cb1, 63, 1.231) ;
cbuf_update(cb1, 69, 1.229) ;
cbuf_update(cb1, 72, 1.247) ;
//cbuf_dump(cb1);
cbuf_update(cb1,361,1.291);
//cbuf_dump(cb1);
cbuf_update(cb1, 411, 1.291) ;
//cbuf_dump(cb1);
cbuf_update(cb1, 412, 1.281) ;
cbuf_update(cb1, 413, 1.292) ;
cbuf_update(cb1, 414, 1.284) ;
//cbuf_dump(cb1);
cbuf_update(cb1, 414, 1.290) ;
//cbuf_dump(cb1);
//cbuf_update(cb1, 415, 1.290) ;
//cbuf_dump(cb1);
cbuf_update(cb1, 511, 1.241) ;
cbuf_update(cb1, 512, 1.251) ;
cbuf_update(cb1, 513, 1.232) ;
cbuf_update(cb1, 514, 1.202) ;
cbuf_update(cb1, 517, 1.119) ;
cbuf_dump(cb1);
return 0;
}
The issue is in main when it tries to insert the last quote and needs to expand (the last quote being:
cbuf_update(cb1, 517, 1.119)
My confusion is how to assign the newBuffer cbuf struct to the cb_ptr buffer. They are both pointers to cbufs, but how do I assign cb_ptr to the newBuffer?
My output is currently:
EXPANDING CIRCULAR BUFFER!
Copying from slot 0
Currently Copying time: 414 Rate: 1.290000
Copying from slot 1
Currently Copying time: 511 Rate: 1.241000
Copying from slot 2
Currently Copying time: 512 Rate: 1.251000
Copying from slot 3
Currently Copying time: 513 Rate: 1.232000
Copying from slot 4
Currently Copying time: 514 Rate: 1.202000
Copying from slot 5
Currently Copying time: 361 Rate: 1.291000
Copying from slot 6
Currently Copying time: 411 Rate: 1.291000
Copying from slot 7
Currently Copying time: 412 Rate: 1.281000
Copying from slot 8
Currently Copying time: 413 Rate: 1.292000
Copying from slot 9
Currently Copying time: 414 Rate: 1.284000
***** DUMPING *****
freeslots = 0
Upvotes: 1
Views: 291
Reputation: 66194
Save for arrays (which decay to a pointer to their base), everything in C must be passed by address if you want to modify it, including pointers. Like anything else, declare the parameter to be a pointer to the type you want to modify (in this case it will be a pointer to a pointer-to-cbuf), then pass the address of the pointer on the caller side
The most minimal change I can think of for your code would be:
void cbuf_update(cbuf **cb_pptr, unsigned int time, double rate)
{
// extract pointer value stored in in/out parameter
cbuf *cb_ptr = *cb_pptr;
if(cb_ptr->freeSlots == 0)
{
printf("EXPANDING CIRCULAR BUFFER!\n");
cbuf *newBuffer = malloc(sizeof(cbuf) + 19 * sizeof(quote));
newBuffer->maxSize = cb_ptr->maxSize * 2;
newBuffer->start = cb_ptr->start;
newBuffer->end = cb_ptr->end;
newBuffer->freeSlots = newBuffer->maxSize - cb_ptr->maxSize;
int x;
for(x = 0; x < cb_ptr->maxSize; x ++){
printf("Copying from slot %d\n", x);
printf("Currently Copying time: %d\t Rate: %f\n", cb_ptr->quoteBuffer[x].time, cb_ptr->quoteBuffer[x].rate);
newBuffer->quoteBuffer[x].time = cb_ptr->quoteBuffer[x].time;
newBuffer->quoteBuffer[x].rate = cb_ptr->quoteBuffer[x].rate;
}
free(cb_ptr);
*cb_pptr = cb_ptr = newBuffer;
}
//If the start pointer has reached the end of the array and there are still free slots back at the beginning of the array, loop back.
if(cb_ptr->start == cb_ptr->maxSize && cb_ptr->freeSlots > 0){
cb_ptr->start = 0;
};
cb_ptr->quoteBuffer[cb_ptr->start].time = time;
cb_ptr->quoteBuffer[cb_ptr->start].rate = rate;
cb_ptr->start = cb_ptr->start +1;
cb_ptr->freeSlots = cb_ptr->freeSlots -1;
//If any quote in the array is older than 5 minutes when compared to the current quote, flag it as null and move the end pointer up one.
//Also, clear up a freeSlot.
int x;
for(x = cb_ptr->end; x < (cb_ptr->start); x ++){
if((time) - (cb_ptr->quoteBuffer[x].time) >= fiveMin){
cb_ptr->end = cb_ptr->end + 1;
cb_ptr->quoteBuffer[x].time = -1;
cb_ptr->quoteBuffer[x].rate = -1.00;
cb_ptr->freeSlots = cb_ptr->freeSlots +1;
}
}
}
Believe me, it won't get much more minimal-change than that. Unfortunately you will have to change all the update calls. No getting around that. They will take this form:
cbuf_update(&cb1, 60, 1.291);
If you free this thing back on the caller side, free as normal:
free(cb1);
Hope that makes sense. Definitely explore the virtues of memcpy()
for your actual data-copy. It will make it considerably less cluttered.
Upvotes: 2