1 /*
2 * Copyright (C) 2002 2003 2005, Magnus Hjorth
3 *
4 * This file is part of mhWaveEdit.
5 *
6 * mhWaveEdit is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * mhWaveEdit is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with mhWaveEdit; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21
22 #include <config.h>
23 #include "ringbuf.h"
24 #include <string.h>
25
ringbuf_new(guint32 size)26 Ringbuf *ringbuf_new(guint32 size)
27 {
28 Ringbuf *r;
29
30 r = g_malloc(sizeof(Ringbuf)+size);
31
32 r->size = size;
33 r->start = r->end = 0;
34
35 return r;
36 }
37
ringbuf_free(Ringbuf * bufptr)38 void ringbuf_free(Ringbuf *bufptr)
39 {
40 g_free(bufptr);
41 }
42
ringbuf_available(Ringbuf * buf)43 guint32 ringbuf_available(Ringbuf *buf)
44 {
45 guint32 start,end;
46
47 start = buf->start;
48 end = buf->end;
49
50 if (end >= start)
51 return end-start;
52 else
53 return buf->size+1 + end - start;
54 }
55
ringbuf_freespace(Ringbuf * buf)56 guint32 ringbuf_freespace(Ringbuf *buf)
57 {
58 guint32 start,end;
59
60 start = buf->start;
61 end = buf->end;
62
63 if (start > end)
64 return start - end - 1;
65 else
66 return buf->size + start - end;
67 }
68
ringbuf_drain(Ringbuf * buf)69 void ringbuf_drain(Ringbuf *buf)
70 {
71 buf->end = buf->start;
72 }
73
ringbuf_isempty(Ringbuf * buf)74 gboolean ringbuf_isempty(Ringbuf *buf)
75 {
76 return (buf->end == buf->start);
77 }
78
ringbuf_isfull(Ringbuf * buf)79 gboolean ringbuf_isfull(Ringbuf *buf)
80 {
81 guint32 start,end;
82
83 start = buf->start;
84 end = buf->end;
85
86 if (start == 0)
87 return (end == buf->size);
88 else
89 return (end == start-1);
90 }
91
ringbuf_enqueue(Ringbuf * buf,gpointer data,guint32 datasize)92 guint32 ringbuf_enqueue(Ringbuf *buf, gpointer data, guint32 datasize)
93 {
94 guint32 blksize;
95 guint32 start,end;
96 guint32 bytes_done = 0;
97
98 start = buf->start;
99 end = buf->end;
100
101 if (end >= start) {
102
103 if (start == 0)
104 blksize = MIN(datasize, buf->size - end);
105 else
106 blksize = MIN(datasize, 1+buf->size - end);
107
108 if (blksize == 0) return 0;
109 memcpy( buf->data + end, data, blksize );
110 end += blksize;
111 if (end == 1+buf->size) {
112 end = 0;
113 bytes_done = blksize;
114 /* Fall through */
115 } else {
116 buf->end = end;
117 return blksize;
118 }
119 }
120
121 blksize = MIN ( datasize-bytes_done, start - end - 1);
122
123 if (blksize == 0) { buf->end = end; return bytes_done; }
124
125 memcpy( buf->data + end,
126 G_STRUCT_MEMBER_P( data, bytes_done ), blksize);
127
128 end += blksize;
129 bytes_done += blksize;
130
131 buf->end = end;
132
133 return bytes_done;
134 }
135
ringbuf_enqueue_zeroes(Ringbuf * buf,guint32 count)136 guint32 ringbuf_enqueue_zeroes(Ringbuf *buf, guint32 count)
137 {
138 guint32 blksize;
139 guint32 start,end;
140 guint32 bytes_done = 0;
141
142 start = buf->start;
143 end = buf->end;
144
145 if (end >= start) {
146
147 if (start == 0)
148 blksize = MIN(count, buf->size - end);
149 else
150 blksize = MIN(count, 1+buf->size - end);
151
152 if (blksize == 0) return 0;
153 memset( buf->data + end, 0, blksize );
154 end += blksize;
155 if (end == 1+buf->size) {
156 end = 0;
157 bytes_done = blksize;
158 /* Fall through */
159 } else {
160 buf->end = end;
161 return blksize;
162 }
163 }
164
165 blksize = MIN ( count-bytes_done, start - end - 1);
166
167 if (blksize == 0) { buf->end = end; return bytes_done; }
168
169 memset( buf->data + end, 0, blksize);
170
171 end += blksize;
172 bytes_done += blksize;
173
174 buf->end = end;
175
176 return bytes_done;
177 }
178
ringbuf_dequeue(Ringbuf * buf,gpointer data,guint32 datasize)179 guint32 ringbuf_dequeue(Ringbuf *buf, gpointer data, guint32 datasize)
180 {
181 guint32 blksize,start,end;
182 guint32 bytes_done = 0;
183
184 start = buf->start;
185 end = buf->end;
186
187 if (start > end) {
188 blksize = MIN ( datasize, buf->size+1 - start );
189 memcpy(data, buf->data+start, blksize);
190 start += blksize;
191 if (start == buf->size+1) {
192 start = 0;
193 bytes_done = blksize;
194 /* Fall through */
195 } else {
196 buf->start = start;
197 return blksize;
198 }
199 }
200
201 blksize = MIN ( datasize - bytes_done, end - start );
202 if (blksize == 0) { buf->start=start; return bytes_done; }
203
204 memcpy ( G_STRUCT_MEMBER_P(data,bytes_done), buf->data + start, blksize );
205
206 start += blksize;
207 bytes_done += blksize;
208
209 buf->start = start;
210
211 return bytes_done;
212 }
213
ringbuf_transfer(Ringbuf * source,Ringbuf * dest)214 guint32 ringbuf_transfer ( Ringbuf *source, Ringbuf *dest )
215 {
216 guint32 blksize;
217 guint32 dest_start,dest_end;
218 guint32 bytes_done = 0;
219
220 dest_start = dest->start;
221 dest_end = dest->end;
222
223 if (dest_end >= dest_start) {
224
225 if (dest_start == 0)
226 blksize = dest->size - dest_end;
227 else
228 blksize = 1+dest->size - dest_end;
229
230 if (blksize == 0) return 0;
231 blksize = ringbuf_dequeue(source, dest->data + dest_end, blksize);
232 dest_end += blksize;
233 if (dest_end == 1+dest->size) {
234 dest_end = 0;
235 bytes_done = blksize;
236 /* Fall through */
237 } else {
238 dest->end = dest_end;
239 return blksize;
240 }
241 }
242
243 blksize = dest_start - dest_end - 1;
244
245 if (blksize == 0) { dest->end = dest_end; return bytes_done; }
246
247 blksize = ringbuf_dequeue(source, dest->data + dest_end, blksize);
248
249 dest_end += blksize;
250 bytes_done += blksize;
251
252 dest->end = dest_end;
253
254 return bytes_done;
255 }
256
257