Last active
June 1, 2016 20:31
-
-
Save saolsen/ebb01ee64d37d29086c66f7e28c88bea to your computer and use it in GitHub Desktop.
circular chat buffer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if 0 | |
echo Compiling... | |
cc -Wall -g -std=c99 $0 -o 2016-04-13 && ./2016-04-13 | |
exit | |
#endif | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <assert.h> | |
#include <string.h> | |
typedef struct { | |
int msg_index; | |
int length; | |
} ChatMsg; | |
typedef struct { | |
ChatMsg* items; | |
int capacity; | |
int next_message; // 0 | |
int oldest_message; // 0 equal means empty | |
char* txt_buf; | |
int txt_buf_capacity; | |
int next_char; | |
int oldest_char; | |
} RingBuffer; | |
void ringBufferAllocate(RingBuffer *ring_buffer) | |
{ | |
ring_buffer->items = malloc(sizeof(ChatMsg)*5); | |
ring_buffer->capacity = 5; | |
ring_buffer->next_message = 0; | |
ring_buffer->oldest_message = 0; | |
ring_buffer->txt_buf = malloc(sizeof(char)*256); | |
ring_buffer->txt_buf_capacity = 256; | |
ring_buffer->next_char = 0; | |
ring_buffer->oldest_char = 0; | |
} | |
void | |
ringBufferDropOldestMsg(RingBuffer *ring_buffer) | |
{ | |
ChatMsg *oldest = ring_buffer->items + ring_buffer->oldest_message++; | |
ring_buffer->oldest_message %= ring_buffer->capacity; | |
ring_buffer->oldest_char += oldest->length; | |
ring_buffer->oldest_char %= ring_buffer->txt_buf_capacity; | |
} | |
int | |
ringBufferIsFull(RingBuffer *ring_buffer) | |
{ | |
return ((ring_buffer->next_message + 1) % ring_buffer->capacity) == | |
ring_buffer->oldest_message; | |
} | |
int | |
ringBufferFreeSpace(RingBuffer *ring_buffer) | |
{ | |
int freespace; | |
if (ring_buffer->next_char >= ring_buffer->oldest_char) { | |
freespace = ring_buffer->next_char + ring_buffer->txt_buf_capacity; | |
freespace += ring_buffer->oldest_char; | |
} else { | |
freespace = ring_buffer->oldest_char - ring_buffer->next_char; | |
} | |
return freespace; | |
} | |
void | |
ringBufferPushMsg(RingBuffer *ring_buffer, char* msg, int length) | |
{ | |
if (length > ring_buffer->txt_buf_capacity) { | |
// string is bigger than our buffer, so nah. | |
return; | |
} | |
if (ringBufferIsFull(ring_buffer)) { | |
ringBufferDropOldestMsg(ring_buffer); | |
} | |
ChatMsg *item = ring_buffer->items + ring_buffer->next_message++; | |
ring_buffer->next_message %= ring_buffer->capacity; | |
while(ringBufferFreeSpace(ring_buffer) < length) { | |
ringBufferDropOldestMsg(ring_buffer); | |
} | |
item->length = length; | |
item->msg_index = ring_buffer->next_char; | |
// write message | |
for (int i=0; i<length; i++) { | |
int buf_index = (ring_buffer->next_char + i) % | |
ring_buffer->txt_buf_capacity; | |
ring_buffer->txt_buf[buf_index] = msg[i]; | |
} | |
ring_buffer->next_char += length; | |
} | |
void ringBufferEnumerateItems(RingBuffer *ring_buffer) | |
{ | |
printf("Buffer Items: "); | |
for(int message_index = ring_buffer->oldest_message; | |
message_index != ring_buffer->next_message; | |
message_index = (message_index + 1) % ring_buffer->capacity) { | |
ChatMsg *msg = ring_buffer->items + message_index; | |
for (int i=0; i<msg->length; i++) { | |
int c = (msg->msg_index + i) % ring_buffer->txt_buf_capacity; | |
printf("%c", ring_buffer->txt_buf[c]); | |
} | |
printf(", "); | |
} | |
printf("\n"); | |
} | |
char* messages[] = { | |
"Message one", | |
"Message two", | |
"A really long message for three like so long it's just gonna trash everyting else", | |
}; | |
int main() | |
{ | |
RingBuffer ring_buffer; | |
ringBufferAllocate(&ring_buffer); | |
for (int next_int = 0; next_int < 16; next_int++) { | |
char* m = messages[next_int % 3]; | |
int l = strlen(m); | |
ringBufferPushMsg(&ring_buffer, m, l); | |
ringBufferEnumerateItems(&ring_buffer); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment