source: roaraudio/libroar/buffer.c @ 1953:50f564826d28

Last change on this file since 1953:50f564826d28 was 1953:50f564826d28, checked in by phi, 15 years ago

addding some additional checks

File size: 7.2 KB
Line 
1//buffer.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 *  NOTE for everyone want's to change something and send patches:
24 *  read README and HACKING! There a addition information on
25 *  the license of this document you need to read before you send
26 *  any patches.
27 *
28 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
29 *  or libpulse*:
30 *  The libs libroaresd, libroararts and libroarpulse link this lib
31 *  and are therefore GPL. Because of this it may be illigal to use
32 *  them with any software that uses libesd, libartsc or libpulse*.
33 */
34
35#include "libroar.h"
36
37int roar_buffer_new      (struct roar_buffer ** buf, size_t len) {
38 void * data;
39
40 if ((data = malloc(len)) == NULL) {
41  return -1;
42 }
43
44 if ( roar_buffer_new_no_ma(buf, len, data) == -1 ) {
45  free(data);
46  return -1;
47 }
48
49 if ( roar_buffer_set_flag(*buf, ROAR_BUFFER_FLAG_NOFREE, ROAR_BUFFER_RESET) == -1 ) {
50  roar_buffer_free(*buf);
51  free(data);
52  return -1;
53 }
54
55 return 0;
56}
57
58int roar_buffer_new_no_ma(struct roar_buffer ** buf, size_t len, void * data) { // no internal malloc
59 struct roar_buffer * new;
60
61 ROAR_DBG("buffer_new(buf=%p, len=%i) = ?", buf, len);
62
63 if ( buf == NULL || data == NULL )
64  return -1;
65
66 if ((new = malloc(sizeof(struct roar_buffer))) == NULL) {
67  *buf = NULL;
68  return -1;
69 }
70
71 new->data      = data;
72
73 new->flags     = ROAR_BUFFER_FLAG_NONE|ROAR_BUFFER_FLAG_NOFREE;
74
75 new->user_data = new->data;
76
77 new->next      = NULL;
78
79 new->len       = len;
80 new->user_len  = len;
81 *buf           = new;
82
83 ROAR_DBG("buffer_new(buf=%p, len=%i): New buffer at %p", buf, len, new);
84
85 return 0;
86}
87
88int roar_buffer_free     (struct roar_buffer * buf) {
89 struct roar_buffer * next;
90
91 if ( buf == NULL )
92  return -1;
93
94 while ((next = buf->next)) {
95  free(buf->data);
96  free(buf);
97  buf = next;
98 }
99
100 if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
101  free(buf->data);
102
103 free(buf);
104
105 return 0;
106}
107
108int roar_buffer_delete   (struct roar_buffer * buf, struct roar_buffer ** next) {
109 if ( buf == NULL ) {
110  if ( next != NULL )
111   *next = NULL;
112  return -1;
113 }
114
115 ROAR_DBG("buffer_delete(buf=%p, next=%p) = ?", buf, next);
116
117 if ( next != NULL )
118  *next = buf->next;
119
120 free(buf->data);
121 free(buf);
122
123 ROAR_DBG("buffer_delete(buf=%p, next=%p) = 0", buf, next);
124 return 0;
125}
126
127int roar_buffer_add      (struct roar_buffer * buf, struct roar_buffer *  next) {
128 unsigned int deep = 0;
129
130 if ( buf == NULL )
131  return -1;
132
133 ROAR_DBG("buffer_add(buf=%p, next=%p) = ?", buf, next);
134
135 if ( buf == next ) {
136  ROAR_ERR("buffer_add(*): both pointer are of the same destination, This is a error in the application");
137  return -1;
138 }
139
140 while ( buf->next != NULL ) {
141  ROAR_DBG("buffer_add(*): buf=%p, next=%p (len=%i)", buf, buf->next, buf->user_len);
142//  ROAR_DBG("buffer_add(): buf=%p, buf->next=%p", buf, buf->next);
143  buf = buf->next;
144  deep++;
145
146  if ( buf == next ) {
147   ROAR_ERR("buffer_add(*): Can not add buffer: loop detected at deep %u. This is a error in the application", deep);
148  }
149 }
150
151 buf->next = next;
152
153 ROAR_DBG("buffer_add(*): adding buffer at deep %u", deep);
154
155 return 0;
156}
157
158int roar_buffer_get_next (struct roar_buffer *  buf, struct roar_buffer ** next) {
159 if ( buf == NULL )
160  return -1;
161
162 *next = buf->next;
163
164 return 0;
165}
166
167int roar_buffer_get_data (struct roar_buffer *  buf, void   ** data) {
168 if ( buf == NULL )
169  return -1;
170
171 *data = buf->user_data;
172
173 return 0;
174}
175
176int roar_buffer_set_offset (struct roar_buffer *  buf, size_t off) {
177 if ( buf == NULL )
178  return -1;
179
180 buf->user_len  -= off;
181 buf->user_data += off;
182
183 return 0;
184}
185
186int roar_buffer_shift_out (struct roar_buffer ** buf, void * data, size_t * len) {
187 size_t todo, cl;
188 struct roar_buffer * cur;
189 void * cd;
190
191 if ( len == NULL || buf == NULL || data == NULL ) {
192  ROAR_DBG("roar_buffer_shift_out(buf=%p, data=%p, len={%lu}) = -1 // Invalid input", buf, data, (unsigned long)len);
193  return -1;
194 }
195
196 if ( *buf == NULL ) {
197  ROAR_DBG("roar_buffer_shift_out(buf=%p, data=%p, len={%lu}) = -1 // Invalid pointer to buffer ring", buf, data, (unsigned long)len);
198  return -1;
199 }
200
201 todo = *len;
202 cur  = *buf;
203
204 *len = 0;
205
206 while (todo) {
207  ROAR_DBG("roar_buffer_shift_out(*): todo=%u, cur=%p", (unsigned int) todo, cur);
208
209  if ( roar_buffer_get_len(cur, &cl) == -1 )
210   return -1;
211
212  if ( cl > todo ) {
213   if ( roar_buffer_get_data(cur, &cd) == -1 )
214    return -1;
215
216   cl = todo;
217
218   memcpy(data, cd, cl);
219   todo -= cl;
220   data += cl;
221   *len += cl;
222
223   if ( roar_buffer_set_offset(cur, cl) == -1 )
224    return -1;
225  } else {
226   if ( roar_buffer_get_data(cur, &cd) == -1 )
227    return -1;
228
229   memcpy(data, cd, cl);
230   todo -= cl;
231   data += cl;
232   *len += cl;
233
234   if ( roar_buffer_next(&cur) == -1 )
235    return -1;
236  }
237
238/*
239  if ( cur == NULL )
240   break;
241*/
242 }
243
244 *buf = cur;
245
246 return 0;
247}
248
249int roar_buffer_set_meta (struct roar_buffer * buf, void *  meta) {
250 if ( buf == NULL )
251  return -1;
252
253 buf->meta = meta;
254
255 return 0;
256}
257
258int roar_buffer_get_meta (struct roar_buffer * buf, void ** meta) {
259 if ( buf == NULL )
260  return -1;
261
262 *meta = buf->meta;
263
264 return 0;
265}
266
267int roar_buffer_set_len  (struct roar_buffer *  buf, size_t    len) {
268 if ( buf == NULL )
269  return -1;
270
271 buf->user_len = len;
272
273 return 0;
274}
275
276int roar_buffer_get_len  (struct roar_buffer *  buf, size_t *  len) {
277 if ( buf == NULL )
278  return -1;
279
280 *len = buf->user_len;
281
282 return 0;
283}
284
285int roar_buffer_set_flag (struct roar_buffer *  buf, int flag, int reset) {
286 if ( buf == NULL )
287  return -1;
288
289 buf->flags |= flag;
290
291 if ( reset )
292  buf->flags -= flag;
293
294 return 0;
295}
296
297int roar_buffer_get_flag (struct roar_buffer *  buf, int flag) {
298 if ( buf == NULL )
299  return -1;
300
301 return buf->flags & flag;
302}
303
304int roar_buffer_duplicate (struct roar_buffer *  buf, struct roar_buffer ** copy) {
305 struct roar_buffer *  cur = buf;
306 struct roar_buffer *  new;
307 void * od, * nd;
308
309 *copy = NULL;
310
311 while (cur) {
312  if ( roar_buffer_new(&new, cur->user_len) == -1 ) {
313   roar_buffer_free(*copy);
314   return -1;
315  }
316
317  if ( *copy == NULL )
318   *copy = new;
319
320  roar_buffer_get_data(cur, &od);
321  roar_buffer_get_data(new, &nd);
322  memcpy(nd, od, cur->user_len);
323
324  roar_buffer_add(*copy, new);
325
326  cur = cur->next;
327 }
328 return 0;
329}
330
331int roar_buffer_ring_stats (struct roar_buffer *  buf, struct roar_buffer_stats * stats) {
332 if ( buf == NULL )
333  return -1;
334
335 stats->parts        = 0;
336 stats->bytes        = 0;
337 stats->memory_usage = 0;
338
339 while (buf) {
340  stats->parts++;
341  stats->bytes        += buf->user_len;
342  stats->memory_usage += buf->len + sizeof(struct roar_buffer);
343  buf = buf->next;
344 }
345
346 return 0;
347}
348
349//ll
Note: See TracBrowser for help on using the repository browser.