make header_len an integer
[paraslash.git] / ringbuffer.c
1 /*
2 * Copyright (C) 2006 Andre Noll <maan@systemlinux.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
17 */
18
19 /** \file ringbuffer.c simple ringbuffer implementation */
20
21 #include "gcc-compat.h"
22 #include "para.h"
23 #include "ringbuffer.h"
24 #include "string.h"
25
26 /**
27 * holds all information about one ring buffer
28 *
29 * It is intentionally not exported via ringbuffer.h. Think abstract.
30 */
31 struct ringbuffer
32 {
33 /**
34 *
35 *
36 * the size of this ring buffer
37 */
38 unsigned size;
39 /**
40 *
41 *
42 * the actual entries of the ringbuffer
43 */
44 void **entries;
45 /**
46 *
47 *
48 * the next entry will be added at this position
49 */
50 int head;
51 /**
52 *
53 * how many entries the ring buffer contains
54 */
55 unsigned filled;
56 };
57
58 /**
59 * initialize a new ringbuffer
60 *
61 * @param size the number of entries the ringbuffer holds
62 *
63 * This function initializes a circular ring buffer which can hold up to \a
64 * size entries of arbitrary type. If performance is an issue, \a size should
65 * be a power of two to make the underlying modulo operations cheap. Arbitrary
66 * many ringbuffers may be initialized via this function. Each ringbuffer is
67 * identified by a 'cookie'.
68 *
69 * Return value: A 'cookie' which identifies the ringbuffer just created and
70 * which must be passed to ringbuffer_add() and ringbuffer_get().
71 */
72 void *ringbuffer_new(unsigned size)
73 {
74 struct ringbuffer *rb = para_calloc(sizeof(struct ringbuffer));
75 rb->entries = para_calloc(size * sizeof(void *));
76 rb->size = size;
77 return rb;
78 };
79
80 /**
81 * add one entry to a ringbuffer
82 *
83 * @param cookie the ringbuffer identifier
84 * @param data the data to be inserted
85 *
86 * insert \a data into the ringbuffer associated with \a cookie. As soon as
87 * the ringbuffer fills up, its oldest entry is disregarded and replaced by \a
88 * data.
89 *
90 * \return The old \a data pointer which is going to be disregarded, or
91 * NULL if the ringbuffer is not yet full.
92 */
93 void *ringbuffer_add(void *cookie, void *data)
94 {
95 struct ringbuffer *rb = cookie;
96 void *ret = rb->entries[rb->head];
97 rb->entries[rb->head] = data;
98 rb->head = (rb->head + 1) % rb->size;
99 if (rb->filled < rb->size)
100 rb->filled++;
101 return ret;
102 }
103
104 /**
105 * get one entry from a ringbuffer
106 *
107 * @param cookie the ringbuffer identifier
108 * @param num the number of the entry
109 *
110 * \return A pointer to data previously added, or NULL if entry number
111 * \a num is not available. \a num counts backwards from zero, i.e.
112 * ringbuffer_get_entry(0) gets the entry which was added most recently.
113 */
114 void *ringbuffer_get(void *cookie, int num)
115 {
116 struct ringbuffer *rb = cookie;
117 int pos = (rb->head + rb->size - 1 - num) % rb->size;
118 // fprintf(stderr, "pos = %d\n", pos);
119 return rb->entries[pos];
120 }
121
122 /**
123 * get the number of entries in the ring buffer
124 *
125 * @param cookie the ringbuffer identifier
126 *
127 * This function always succeeds and never returns a number greater than the
128 * size of the ring buffer.
129 */
130 unsigned ringbuffer_filled(void *cookie)
131 {
132 struct ringbuffer *rb = cookie;
133 return rb->filled;
134 }