memzap

replay memory writes
git clone git://git.2f30.org/memzap
Log | Files | Refs | README | LICENSE

ringbuffer.c (2672B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 /* for ptrdiff_t */
      5 #include <stddef.h>
      6 
      7 #include <string.h>
      8 
      9 #include "ringbuffer.h"
     10 
     11 int init_ringbuffer(struct ringbuffer *r, size_t size)
     12 {
     13 	r->buf = (char*)malloc(size);
     14 	if (!r->buf)
     15 		return ERINGBUFFER_ALLOC_FAIL;
     16 	r->size = size;
     17 	clear_ringbuffer(r);
     18 
     19 	return 0;
     20 }
     21 
     22 void free_ringbuffer(struct ringbuffer *r)
     23 {
     24 	free(r->buf);
     25 }
     26 
     27 void clear_ringbuffer(struct ringbuffer *r)
     28 {
     29 	r->begin = 0;
     30 	r->end = 0;
     31 }
     32 
     33 size_t ringbuffer_free_space(struct ringbuffer *r)
     34 {
     35 	if (r->begin == 0 && r->end == 0)
     36 		return r->size;
     37 
     38 	if (r->begin < r->end)
     39 		return r->size - (r->end - r->begin) - 1;
     40 	else
     41 		return r->begin - r->end - 1;
     42 }
     43 
     44 size_t ringbuffer_data_size(struct ringbuffer *r)
     45 {
     46 	if (r->begin == 0 && r->end == 0)
     47 		return 0;
     48 
     49 	if (r->begin <= r->end)
     50 		return r->end - r->begin + 1;
     51 	else
     52 		return r->size - (r->begin - r->end) + 1;
     53 }
     54 
     55 
     56 void ringbuffer_push(struct ringbuffer *r, const void *data, size_t size)
     57 {
     58 	if (ringbuffer_free_space(r) < size)
     59 		return;
     60 
     61 	if (r->begin == 0 && r->end == 0) {
     62 		memcpy(r->buf, data, size);
     63 		r->begin = r->buf;
     64 		r->end = r->buf + size - 1;
     65 		return;
     66 	}
     67 
     68 	r->end++;
     69 	if (r->begin < r->end) {
     70 		if ((size_t)(r->buf + (ptrdiff_t)r->size - r->begin) >= size) {
     71 			/* we can fit without cut */
     72 			memcpy(r->end, data, size);
     73 			r->end += size - 1;
     74 		} else {
     75 			/* make a cut */
     76 			size_t s = r->buf + r->size - r->end;
     77 			memcpy(r->end, data, s);
     78 			size -= s;
     79 			memcpy(r->buf, (char*)data+s, size);
     80 			r->end = r->buf + size - 1;
     81 		}
     82 	} else {
     83 		memcpy(r->end, data, size);
     84 		r->end += size - 1;
     85 	}
     86 }
     87 
     88 void ringbuffer_pop(struct ringbuffer *r, void *data, size_t size)
     89 {
     90 	if (ringbuffer_data_size(r) < size)
     91 		return;
     92 
     93 	int need_clear = 0;
     94 	if (ringbuffer_data_size(r) == size)
     95 		need_clear = 1;
     96 
     97 	if (r->begin < r->end) {
     98 		if (data) memcpy(data, r->begin, size);
     99 		r->begin += size;
    100 	} else {
    101 		if ((size_t)(r->buf + (ptrdiff_t)r->size - r->begin) >= size) {
    102 			if (data) memcpy(data, r->begin, size);
    103 			r->begin += size;
    104 		} else {
    105 			size_t s = r->buf + r->size - r->begin;
    106 			if (data) memcpy(data, r->begin, s);
    107 			size -= s;
    108 			if (data) memcpy((char*)data+s, r->buf, size);
    109 			r->begin = r->buf + size;
    110 		}
    111 	}
    112 
    113 	if (need_clear)
    114 		clear_ringbuffer(r);
    115 }
    116 
    117 void ringbuffer_read(struct ringbuffer *r, void *data, size_t size)
    118 {
    119 	if (ringbuffer_data_size(r) < size)
    120 		return;
    121 
    122 	if (r->begin < r->end)
    123 		memcpy(data, r->begin, size);
    124 	else {
    125 		if ((size_t)(r->buf + (ptrdiff_t)r->size - r->begin) >= size)
    126 			memcpy(data, r->begin, size);
    127 		else {
    128 			size_t s = r->buf + r->size - r->begin;
    129 			memcpy(data, r->begin, s);
    130 			size -= s;
    131 			memcpy((char*)data+s, r->buf, size);
    132 		}
    133 	}
    134 }
    135