Skip to content

Instantly share code, notes, and snippets.

@saolsen
Last active June 1, 2016 20:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save saolsen/ebb01ee64d37d29086c66f7e28c88bea to your computer and use it in GitHub Desktop.
Save saolsen/ebb01ee64d37d29086c66f7e28c88bea to your computer and use it in GitHub Desktop.
circular chat buffer
#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