1 /*
2 * Copyright (c) 2002-2014 Balabit
3 * Copyright (c) 2014 Laszlo Budai
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 * As an additional exemption you are allowed to compile & link against the
20 * OpenSSL libraries as published by the OpenSSL project. See the file
21 * COPYING for details.
22 *
23 */
24
25 #include "ringbuffer.h"
26
27 void
ring_buffer_init(RingBuffer * self)28 ring_buffer_init(RingBuffer *self)
29 {
30 self->head = 0;
31 self->tail = 0;
32 self->count = 0;
33 self->capacity = 0;
34 self->element_size = 0;
35 self->buffer = NULL;
36 }
37
38 void
ring_buffer_alloc(RingBuffer * self,guint32 element_size,guint32 capacity)39 ring_buffer_alloc(RingBuffer *self, guint32 element_size, guint32 capacity)
40 {
41 g_assert(capacity > 0);
42 self->head = 0;
43 self->tail = 0;
44 self->count = 0;
45 self->capacity = capacity;
46 self->element_size = element_size;
47 self->buffer = g_malloc0(element_size * self->capacity);
48 }
49
50 gboolean
ring_buffer_is_allocated(RingBuffer * self)51 ring_buffer_is_allocated(RingBuffer *self)
52 {
53 return (self->buffer != NULL);
54 }
55
56 void
ring_buffer_free(RingBuffer * self)57 ring_buffer_free(RingBuffer *self)
58 {
59 g_free(self->buffer);
60 self->head = 0;
61 self->tail = 0;
62 self->count = 0;
63 self->capacity = 0;
64 self->element_size = 0;
65 self->buffer = NULL;
66 }
67
68 gboolean
ring_buffer_is_full(RingBuffer * self)69 ring_buffer_is_full(RingBuffer *self)
70 {
71 return self->capacity == self->count ? TRUE : FALSE;
72 }
73
74 gboolean
ring_buffer_is_empty(RingBuffer * self)75 ring_buffer_is_empty(RingBuffer *self)
76 {
77 return (self->count == 0) ? TRUE : FALSE;
78 }
79
80 gpointer
ring_buffer_push(RingBuffer * self)81 ring_buffer_push(RingBuffer *self)
82 {
83 gpointer r = ring_buffer_tail(self);
84
85 if (!r)
86 return NULL;
87
88 ++self->count;
89 self->tail = (self->tail + 1) % self->capacity;
90
91 return r;
92 }
93
94 gpointer
ring_buffer_tail(RingBuffer * self)95 ring_buffer_tail (RingBuffer *self)
96 {
97 g_assert(self->buffer != NULL);
98
99 if (ring_buffer_is_full(self))
100 return NULL;
101
102 gpointer r = (guint8 *) (self->buffer) + self->tail * self->element_size;
103
104 return r;
105 }
106
107 gpointer
ring_buffer_pop(RingBuffer * self)108 ring_buffer_pop(RingBuffer *self)
109 {
110 g_assert(self->buffer != NULL);
111
112 if (ring_buffer_is_empty(self))
113 return NULL;
114
115 gpointer r = (guint8 *) (self->buffer) + self->head * self->element_size;
116
117 --self->count;
118 self->head = (self->head + 1) % self->capacity;
119
120 return r;
121 }
122
123 gboolean
ring_buffer_drop(RingBuffer * self,guint32 n)124 ring_buffer_drop(RingBuffer *self, guint32 n)
125 {
126 g_assert(self->buffer != NULL);
127
128 if (ring_buffer_count(self) < n)
129 return FALSE;
130
131 self->count -= n;
132 self->head = (self->head + n) % self->capacity;
133
134 return TRUE;
135 }
136
137 guint32
ring_buffer_capacity(RingBuffer * self)138 ring_buffer_capacity(RingBuffer *self)
139 {
140 return self->buffer ? self->capacity : 0;
141 }
142
143 guint32
ring_buffer_count(RingBuffer * self)144 ring_buffer_count(RingBuffer *self)
145 {
146 return self->count;
147 }
148
149 gpointer
ring_buffer_element_at(RingBuffer * self,guint32 idx)150 ring_buffer_element_at(RingBuffer *self, guint32 idx)
151 {
152 g_assert(self->buffer != NULL);
153
154 if (idx >= self->count)
155 return NULL;
156
157 return (guint8 *) (self->buffer) + ((self->head + idx) % self->capacity) * self->element_size;
158 }
159
160 guint32
ring_buffer_get_continual_range_length(RingBuffer * self,RingBufferIsContinuousPredicate pred)161 ring_buffer_get_continual_range_length(RingBuffer *self, RingBufferIsContinuousPredicate pred)
162 {
163 guint32 r = 0, i;
164
165 g_assert(self->buffer != NULL);
166
167 for (i = 0; i < ring_buffer_count(self); i++)
168 {
169 if (!pred(ring_buffer_element_at(self, i)))
170 {
171 break;
172 }
173 ++r;
174 }
175
176 return r;
177 }
178