source: roaraudio/libroar/buffer.c @ 5298:a0d70da17a74

Last change on this file since 5298:a0d70da17a74 was 5298:a0d70da17a74, checked in by phi, 12 years ago

converted roar_buffer_next() to a function, added roar_buffer_moveinto() (See: #126)

File size: 19.8 KB
Line 
1//buffer.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
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, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38struct roar_buffer_ring {
39 size_t read_pos;
40 size_t write_pos;
41};
42
43struct roar_buffer {
44 size_t               refc;
45 size_t               len;
46 size_t               user_len;
47 int                  flags;
48 void               * data;
49 void               * user_data;
50 union {
51  void                    * vp;
52  int32_t                   i32;
53  struct roar_buffer_ring   ring;
54 }                    meta;
55 int                  type;
56 struct roar_buffer * next;
57};
58
59#define _ckbuf_free(m)  if ( buf == NULL || (m) ) { roar_err_set(ROAR_ERROR_FAULT); return -1; }
60#define _ckbuf(m)       if ( _ckmem_corruption(buf, (m)) == -1 ) return -1;
61
62// if we use the 'inline' keyword here the program segfaults. why?
63static int _ckmem_corruption(volatile struct roar_buffer * buf, int m) {
64 int flags;
65
66 ROAR_DBG("_ckmem_corruption(buf=%p) = ?", buf);
67
68 // we need to recheck here, why?
69 // gcc changes the order of the above macros. why?
70 // this is a strange world.
71 if ( buf == NULL || m ) {
72  ROAR_DBG("_ckmem_corruption(buf=%p) = -1 // FAULT", buf);
73  roar_err_set(ROAR_ERROR_FAULT);
74  return -1;
75 }
76
77 ROAR_DBG("_ckmem_corruption(buf=%p) = ?", buf);
78
79 flags = buf->flags & (ROAR_BUFFER_FLAG_USEABLE|ROAR_BUFFER_FLAG_FREED);
80
81 ROAR_DBG("_ckmem_corruption(buf=%p{.flags=0x%.4x, ...} = ?", buf, buf->flags);
82
83 if ( flags == ROAR_BUFFER_FLAG_USEABLE ) {
84  // seems ok, continue with next check.
85 } else if ( flags == ROAR_BUFFER_FLAG_FREED ) {
86  roar_panic(ROAR_FATAL_ERROR_MEMORY_USED_AFTER_FREE, NULL);
87  roar_err_set(ROAR_ERROR_FAULT);
88  return -1;
89 } else {
90  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
91  roar_err_set(ROAR_ERROR_BADCKSUM);
92  return -1;
93 }
94
95 if ( buf->refc == 0 ) {
96  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
97 }
98
99 return 0;
100}
101
102int roar_buffer_new_data (struct roar_buffer ** buf, size_t len, void ** data) {
103 void * bufdata;
104 int err;
105
106 if ((bufdata = roar_mm_malloc(len)) == NULL) {
107  return -1;
108 }
109
110 if ( roar_buffer_new_no_ma(buf, len, bufdata) == -1 ) {
111  err = roar_error;
112  roar_mm_free(bufdata);
113  roar_err_set(err);
114  return -1;
115 }
116
117 if ( roar_buffer_set_flag(*buf, ROAR_BUFFER_FLAG_NOFREE, ROAR_BUFFER_RESET) == -1 ) {
118  err = roar_error;
119  roar_buffer_free(*buf);
120  roar_mm_free(bufdata);
121  roar_err_set(err);
122  return -1;
123 }
124
125 if ( data != NULL )
126  *data = bufdata;
127
128 return 0;
129}
130
131int roar_buffer_new_no_ma(struct roar_buffer ** buf, size_t len, void * data) { // no internal malloc
132 struct roar_buffer * new;
133
134 ROAR_DBG("buffer_new(buf=%p, len=%i) = ?", buf, len);
135
136 _ckbuf_free(data == NULL)
137
138 if ((new = roar_mm_malloc(sizeof(struct roar_buffer))) == NULL) {
139  *buf = NULL;
140  return -1;
141 }
142
143 new->refc      =  1;
144
145 new->data      = data;
146
147 new->flags     = ROAR_BUFFER_FLAG_NONE|ROAR_BUFFER_FLAG_NOFREE|ROAR_BUFFER_FLAG_USEABLE;
148 new->type      = -1;
149
150 new->user_data = new->data;
151
152 new->next      = NULL;
153
154 new->len       = len;
155 new->user_len  = len;
156 *buf           = new;
157
158 ROAR_DBG("buffer_new(buf=%p, len=%i): New buffer at %p", buf, len, new);
159
160 return 0;
161}
162
163int roar_buffer_ref      (struct roar_buffer *  buf) {
164 _ckbuf(0)
165
166 buf->refc++;
167
168 return 0;
169}
170
171int roar_buffer_unref     (struct roar_buffer * buf) {
172 struct roar_buffer * next, * cur;
173 int flags;
174
175 ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
176
177 _ckbuf_free(0)
178
179 ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
180
181 flags = buf->flags & (ROAR_BUFFER_FLAG_USEABLE|ROAR_BUFFER_FLAG_FREED);
182 if ( flags == ROAR_BUFFER_FLAG_FREED ) {
183  roar_panic(ROAR_FATAL_ERROR_MEMORY_DOUBLE_FREE, NULL);
184 }
185
186 _ckmem_corruption(buf, 0);
187
188 ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
189
190 if ( buf->refc == 0 ) {
191  ROAR_WARN("roar_buffer_unref(buf=%p): Ref counter is wrong. assuming one.");
192  buf->refc = 1;
193  roar_panic(ROAR_FATAL_ERROR_MEMORY_CORRUPTION, NULL);
194 }
195
196 buf->refc--;
197
198 if ( buf->refc ) {
199  ROAR_DBG("roar_buffer_unref(buf=%p) = 0", buf);
200  return 0;
201 }
202
203 ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
204
205 cur = buf->next;
206 while (cur != NULL) {
207  flags = cur->flags & (ROAR_BUFFER_FLAG_USEABLE|ROAR_BUFFER_FLAG_FREED);
208  if ( flags == ROAR_BUFFER_FLAG_FREED ) {
209   roar_panic(ROAR_FATAL_ERROR_MEMORY_DOUBLE_FREE, NULL);
210  }
211
212  ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
213
214  _ckmem_corruption(cur, 0);
215
216  if ( roar_buffer_get_flag(cur, ROAR_BUFFER_FLAG_NOFREE) != 1 )
217   roar_mm_free(cur->data);
218
219  cur->flags = ROAR_BUFFER_FLAG_FREED;
220  next = cur->next;
221  roar_mm_free(cur);
222  cur = next;
223 }
224
225 ROAR_DBG("roar_buffer_unref(buf=%p) = ?", buf);
226
227 if ( !(buf->flags & ROAR_BUFFER_FLAG_NOFREE) )
228  roar_mm_free(buf->data);
229
230 ROAR_DBG("roar_buffer_unref(buf=%p): setting flags = ROAR_BUFFER_FLAG_FREED", buf);
231 buf->flags = ROAR_BUFFER_FLAG_FREED;
232
233 roar_mm_free(buf);
234
235 ROAR_DBG("roar_buffer_unref(buf=%p) = 0", buf);
236 return 0;
237}
238
239int roar_buffer_delete   (struct roar_buffer * buf, struct roar_buffer ** next) {
240 if ( buf == NULL ) {
241  if ( next != NULL )
242   *next = NULL;
243  roar_err_set(ROAR_ERROR_FAULT);
244  return -1;
245 }
246
247 ROAR_DBG("buffer_delete(buf=%p, next=%p) = ?", buf, next);
248
249 if ( next != NULL )
250  *next = buf->next;
251
252 if ( roar_buffer_get_flag(buf, ROAR_BUFFER_FLAG_NOFREE) != 1 )
253  roar_mm_free(buf->data);
254
255 roar_mm_free(buf);
256
257 ROAR_DBG("buffer_delete(buf=%p, next=%p) = 0", buf, next);
258 return 0;
259}
260
261int roar_buffer_next     (struct roar_buffer ** buf) {
262 return roar_buffer_delete(*buf, buf);
263}
264
265int roar_buffer_add      (struct roar_buffer * buf, struct roar_buffer *  next) {
266 return roar_buffer_moveinto(buf, next);
267}
268
269int roar_buffer_moveinto (struct roar_buffer * buf, struct roar_buffer *  next) {
270 unsigned int deep = 0;
271
272 _ckbuf(0)
273
274 ROAR_DBG("buffer_add(buf=%p, next=%p) = ?", buf, next);
275
276 if ( buf->flags & ROAR_BUFFER_FLAG_RING ) {
277  roar_err_set(ROAR_ERROR_INVAL);
278  return -1;
279 }
280
281 if ( buf == next ) {
282  ROAR_ERR("buffer_add(*): both pointer are of the same destination, This is a error in the application");
283  roar_err_set(ROAR_ERROR_INVAL);
284  return -1;
285 }
286
287 while ( buf->next != NULL ) {
288  ROAR_DBG("buffer_add(*): buf=%p, next=%p (len=%i)", buf, buf->next, buf->user_len);
289//  ROAR_DBG("buffer_add(): buf=%p, buf->next=%p", buf, buf->next);
290  buf = buf->next;
291  deep++;
292
293  if ( buf == next ) {
294   ROAR_ERR("buffer_add(*): Can not add buffer: loop detected at deep %u. This is a error in the application", deep);
295   // why don't we return here?
296  }
297 }
298
299 buf->next = next;
300
301 ROAR_DBG("buffer_add(*): adding buffer at deep %u", deep);
302
303 return 0;
304}
305
306int roar_buffer_get_next (struct roar_buffer *  buf, struct roar_buffer ** next) {
307 _ckbuf(0)
308
309 *next = buf->next;
310
311 return 0;
312}
313
314int roar_buffer_ring_new (struct roar_buffer ** buf, size_t len, int free_running) {
315 struct roar_buffer * n;
316
317 _ckbuf_free(0)
318
319 if ( len == 0 ) {
320  roar_err_set(ROAR_ERROR_RANGE);
321  return -1;
322 }
323
324 // just to be sure:
325 *buf = NULL;
326
327 if ( roar_buffer_new(&n, len) == -1 )
328  return -1;
329
330 n->flags |= ROAR_BUFFER_FLAG_RING;
331
332 if ( free_running )
333  n->flags |= ROAR_BUFFER_FLAG_FREE_RUNNING;
334
335 n->meta.ring.read_pos  = 0;
336 n->meta.ring.write_pos = 0;
337
338 memset(n->data, 0, n->len);
339
340 *buf = n;
341
342 return 0;
343}
344
345int roar_buffer_get_data (struct roar_buffer *  buf, void   ** data) {
346 _ckbuf(0)
347
348 *data = buf->user_data;
349
350 return 0;
351}
352
353int roar_buffer_set_offset (struct roar_buffer *  buf, size_t off) {
354 _ckbuf(0)
355
356 if ( off > buf->user_len ) {
357  roar_err_set(ROAR_ERROR_RANGE);
358  return -1;
359 }
360
361 buf->user_len  -= off;
362 buf->user_data += off;
363
364 return 0;
365}
366
367int roar_buffer_shift_out (struct roar_buffer ** buf, void * data, size_t * len) {
368 size_t todo, cl;
369 struct roar_buffer * cur;
370 void * cd;
371
372 _ckbuf_free(len == NULL || data == NULL);
373
374 if ( *buf == NULL ) {
375  ROAR_DBG("roar_buffer_shift_out(buf=%p, data=%p, len={%lu}) = -1 // Invalid pointer to buffer ring", buf, data, (unsigned long)len);
376  roar_err_set(ROAR_ERROR_FAULT);
377  return -1;
378 }
379
380 todo = *len;
381 cur  = *buf;
382
383 *len = 0;
384
385 while (todo && cur != NULL) {
386  ROAR_DBG("roar_buffer_shift_out(*): todo=%u, cur=%p", (unsigned int) todo, cur);
387
388  _ckmem_corruption(cur, 0);
389
390  if ( roar_buffer_get_len(cur, &cl) == -1 )
391   return -1;
392
393  if ( cl > todo ) {
394   if ( roar_buffer_get_data(cur, &cd) == -1 )
395    return -1;
396
397   cl = todo;
398
399   memcpy(data, cd, cl);
400   todo -= cl;
401   data += cl;
402   *len += cl;
403
404   if ( roar_buffer_set_offset(cur, cl) == -1 )
405    return -1;
406  } else {
407   if ( roar_buffer_get_data(cur, &cd) == -1 )
408    return -1;
409
410   memcpy(data, cd, cl);
411   todo -= cl;
412   data += cl;
413   *len += cl;
414
415   if ( roar_buffer_next(&cur) == -1 )
416    return -1;
417  }
418
419/*
420  if ( cur == NULL )
421   break;
422*/
423 }
424
425 *buf = cur;
426
427 return 0;
428}
429
430int roar_buffer_set_meta (struct roar_buffer * buf, void *  meta) {
431 _ckbuf(0)
432
433 buf->meta.vp = meta;
434
435 return 0;
436}
437
438int roar_buffer_get_meta (struct roar_buffer * buf, void ** meta) {
439 _ckbuf(meta == NULL)
440
441 *meta = buf->meta.vp;
442
443 return 0;
444}
445
446int roar_buffer_set_meta_i32(struct roar_buffer *  buf, int32_t    meta) {
447 _ckbuf(0)
448
449 buf->meta.i32 = meta;
450
451 return 0;
452}
453
454int roar_buffer_get_meta_i32(struct roar_buffer *  buf, int32_t *  meta) {
455 _ckbuf(meta == NULL)
456
457 *meta = buf->meta.i32;
458
459 return 0;
460}
461
462int roar_buffer_set_type    (struct roar_buffer *  buf, int        type) {
463 _ckbuf(0)
464
465 switch (type) {
466  case ROAR_VIO_DFT_RAW:
467  case ROAR_VIO_DFT_PACKET:
468  case ROAR_VIO_DFT_UNFRAMED:
469  case ROAR_VIO_DFT_OGG_PACKET:
470  case ROAR_VIO_DFT_OGG_PAGE:
471   break;
472  default:
473    roar_err_set(ROAR_ERROR_NOTSUP);
474    return -1;
475 }
476
477 buf->type = type;
478
479 return 0;
480}
481
482int roar_buffer_get_type    (struct roar_buffer *  buf, int     *  type) {
483 _ckbuf(type == NULL)
484
485 *type = buf->type;
486
487 return 0;
488}
489
490int roar_buffer_set_len  (struct roar_buffer *  buf, size_t    len) {
491 size_t   totlen;
492 void   * newbuf;
493
494 _ckbuf(0)
495
496 // handle specal case where user length is zero:
497 if ( len && !buf->user_len ) {
498  buf->user_data = buf->data;
499  buf->user_len  = buf->len;
500 }
501
502 if ( len > buf->user_len ) {
503  // we can only enlage a buffer if it's one of our own memory segments
504  if ( buf->flags & ROAR_BUFFER_FLAG_NOFREE )  {
505   roar_err_set(ROAR_ERROR_NOTSUP);
506   return -1;
507  }
508
509  totlen = (buf->len - buf->user_len) + len;
510  newbuf = roar_mm_realloc(buf->data, totlen);
511  if ( newbuf == NULL )
512   return -1;
513
514  buf->user_data = newbuf + (buf->user_data - buf->data);
515  buf->user_len = len;
516  buf->data = newbuf;
517  buf->len  = totlen;
518 } else {
519  buf->user_len = len;
520 }
521
522 return 0;
523}
524
525int roar_buffer_get_len  (struct roar_buffer *  buf, size_t *  len) {
526 _ckbuf(0)
527
528 *len = buf->user_len;
529
530 return 0;
531}
532
533int roar_buffer_set_flag (struct roar_buffer *  buf, int flag, int reset) {
534 _ckbuf(0)
535
536 buf->flags |= flag;
537
538 if ( reset )
539  buf->flags -= flag;
540
541 return 0;
542}
543
544int roar_buffer_get_flag (struct roar_buffer *  buf, int flag) {
545 _ckbuf(0)
546
547 return buf->flags & flag;
548}
549
550int roar_buffer_duplicate (struct roar_buffer *  buf, struct roar_buffer ** copy) {
551 struct roar_buffer *  cur = buf;
552 struct roar_buffer *  new;
553 void * od, * nd;
554 int err;
555
556 _ckbuf(copy == NULL)
557
558 *copy = NULL;
559
560 // TODO:  This function does not handle ring buffers.
561 // FIXME: This function does not error out in case of wrong buffer type in buf.
562 // TODO:  This function does not handle buffer meta data.
563
564 while (cur != NULL) {
565  if ( roar_buffer_new(&new, cur->user_len) == -1 ) {
566   err = roar_error;
567   roar_buffer_free(*copy);
568   roar_err_set(err);
569   return -1;
570  }
571
572  if ( *copy == NULL )
573   *copy = new;
574
575  _LIBROAR_IGNORE_RET(roar_buffer_get_data(cur, &od));
576  _LIBROAR_IGNORE_RET(roar_buffer_get_data(new, &nd));
577  memcpy(nd, od, cur->user_len);
578
579  _LIBROAR_IGNORE_RET(roar_buffer_add(*copy, new));
580
581  cur = cur->next;
582 }
583
584 return 0;
585}
586
587int roar_buffer_ring_stats (struct roar_buffer *  buf, struct roar_buffer_stats * stats) {
588 ROAR_DBG("roar_buffer_ring_stats(buf=%p, stats=%p) = ?", buf, stats);
589
590 _ckbuf(0)
591
592 ROAR_DBG("roar_buffer_ring_stats(buf=%p, stats=%p) = ?", buf, stats);
593
594 stats->parts        = 0;
595 stats->bytes        = 0;
596 stats->memory_usage = 0;
597
598 while (buf != NULL ) {
599  stats->parts++;
600  stats->bytes        += buf->user_len;
601  stats->memory_usage += buf->len + sizeof(struct roar_buffer);
602  buf = buf->next;
603 }
604
605 return 0;
606}
607
608int roar_buffer_ring_read  (struct roar_buffer *  buf, void * data, size_t * len) {
609 struct roar_buffer_ring * ring;
610 size_t havelen;
611 size_t done;
612 size_t tmp;
613
614 _ckbuf(len == NULL)
615
616 if ( buf == NULL || len == NULL )
617  return -1;
618
619 if ( data == NULL && *len != 0 ) {
620  roar_err_set(ROAR_ERROR_FAULT);
621  return -1;
622 }
623
624 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) ) {
625  roar_err_set(ROAR_ERROR_TYPEMM);
626  return -1;
627 }
628
629 if ( *len == 0 )
630  return 0;
631
632 // we may handle this later:
633 if ( *len > buf->user_len ) {
634  roar_err_set(ROAR_ERROR_NOTSUP);
635  return -1;
636 }
637
638 if ( (buf->flags & ROAR_BUFFER_FLAG_FREE_RUNNING) ) {
639  if ( buf->meta.ring.read_pos >= buf->user_len )
640   buf->meta.ring.read_pos -= buf->user_len;
641
642  if ( (*len + buf->meta.ring.read_pos) > buf->user_len ) {
643   // wraped mode:
644   memcpy(data, buf->user_data+buf->meta.ring.read_pos, buf->user_len - buf->meta.ring.read_pos);
645   memcpy(data, buf->user_data, *len + buf->meta.ring.read_pos - buf->user_len);
646 
647   buf->meta.ring.read_pos += *len;
648   buf->meta.ring.read_pos -= buf->user_len;
649   return 0;
650  } else {
651   // unwarped mode:
652   memcpy(data, buf->user_data+buf->meta.ring.read_pos, *len);
653   buf->meta.ring.read_pos += *len;
654   return 0;
655  }
656 } else {
657  ring = &(buf->meta.ring);
658
659  if ( ring->read_pos == ring->write_pos ) {
660   *len = 0;
661   return 0;
662  } else if ( ring->read_pos < ring->write_pos ) {
663   havelen = ring->write_pos - ring->read_pos;
664
665   if ( havelen > *len )
666    havelen = *len;
667
668   memcpy(data, buf->user_data+ring->read_pos, havelen);
669   ring->read_pos += havelen;
670
671   *len = havelen;
672   return 0;
673  } else { // write_pos < read_pos
674   done = 0;
675
676   // first pass: use data up to end of buffer
677
678   havelen = buf->user_len - ring->read_pos;
679
680   if ( havelen > *len )
681    havelen = *len;
682
683   memcpy(data, buf->user_data+ring->read_pos, havelen);
684   ring->read_pos += havelen;
685
686   done += havelen;
687
688   if ( ring->read_pos == buf->user_len ) {
689    ring->read_pos = 0;
690   }
691
692   // second pass: use data from strat of buffer to write pointer
693
694   if ( *len > done ) {
695    tmp = *len - done;
696    if ( roar_buffer_ring_read(buf, data+done, &tmp) == 0 ) {
697     done += tmp;
698    }
699   }
700
701   *len = done;
702   return 0;
703  }
704 }
705
706 roar_err_set(ROAR_ERROR_UNKNOWN);
707 return -1;
708}
709
710int roar_buffer_ring_write (struct roar_buffer *  buf, void * data, size_t * len) {
711 struct roar_buffer_ring * ring;
712 size_t havelen;
713 size_t done;
714 size_t tmp;
715
716 ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = ?", buf, data, len);
717
718 _ckbuf(len == NULL)
719
720 if ( data == NULL && *len != 0 ) {
721  roar_err_set(ROAR_ERROR_FAULT);
722  return -1;
723 }
724
725 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) ) {
726  roar_err_set(ROAR_ERROR_TYPEMM);
727  return -1;
728 }
729
730 if ( *len == 0 )
731  return 0;
732
733 // we may handle this later:
734 if ( *len > buf->user_len ) {
735  roar_err_set(ROAR_ERROR_NOTSUP);
736  return -1;
737 }
738
739 if ( (buf->flags & ROAR_BUFFER_FLAG_FREE_RUNNING) ) {
740  if ( buf->meta.ring.write_pos >= buf->user_len )
741   buf->meta.ring.write_pos -= buf->user_len;
742
743  if ( (*len + buf->meta.ring.write_pos) > buf->user_len ) {
744   // wraped mode:
745   memcpy(buf->user_data+buf->meta.ring.write_pos, data, buf->user_len - buf->meta.ring.write_pos);
746   memcpy(buf->user_data, data, *len + buf->meta.ring.write_pos - buf->user_len);
747
748   buf->meta.ring.write_pos += *len;
749   buf->meta.ring.write_pos -= buf->user_len;
750   return 0;
751  } else {
752   // unwarped mode:
753   memcpy(buf->user_data+buf->meta.ring.write_pos, data, *len);
754   buf->meta.ring.write_pos += *len;
755   return 0;
756  }
757 } else {
758  ring = &(buf->meta.ring);
759  done = 0;
760
761  ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p): write_pos=%u, read_pos=%u, user_len=%u", buf, data, len, (unsigned int)ring->write_pos, (unsigned int)ring->read_pos, (unsigned int)buf->user_len);
762
763  if ( ring->write_pos >= ring->read_pos ) {
764   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = ?", buf, data, len);
765
766   havelen = buf->user_len - ring->write_pos;
767
768   if ( ring->read_pos == 0 )
769    havelen--;
770
771   if ( havelen > *len )
772    havelen = *len;
773
774   memcpy(buf->user_data+ring->write_pos, data, havelen);
775
776   done += havelen;
777   ring->write_pos += havelen;
778
779   if ( ring->write_pos == buf->user_len )
780    ring->write_pos = 0;
781
782   if ( *len > done && ring->read_pos != 0 ) {
783    tmp = *len - done;
784    if ( roar_buffer_ring_write(buf, data+done, &tmp) == 0 ) {
785     done += tmp;
786    }
787   }
788
789   *len = done;
790   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = 0", buf, data, len);
791   return 0;
792  } else {
793   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = ?", buf, data, len);
794
795   // test for buffer-is-full:
796   if ( (ring->write_pos + 1) == ring->read_pos ) {
797    *len = 0;
798    ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = 0", buf, data, len);
799    return 0;
800   }
801
802   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = ?", buf, data, len);
803
804   havelen = ring->read_pos - ring->write_pos - 1;
805
806   if ( havelen > *len )
807    havelen = *len;
808
809   memcpy(buf->user_data+ring->write_pos, data, havelen);
810
811   ring->write_pos += havelen;
812   *len = havelen;
813
814   ROAR_DBG("roar_buffer_ring_write(buf=%p, data=%p, len=%p) = 0", buf, data, len);
815   return 0;
816  }
817 }
818
819 roar_err_set(ROAR_ERROR_UNKNOWN);
820 return -1;
821}
822
823int roar_buffer_ring_avail(struct roar_buffer *  buf, size_t * readlen, size_t * writelen) {
824 struct roar_buffer_ring * ring;
825 size_t have;
826
827 _ckbuf(0)
828
829 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) ) {
830  roar_err_set(ROAR_ERROR_TYPEMM);
831  return -1;
832 }
833
834 ring = &(buf->meta.ring);
835
836 ROAR_DBG("roar_buffer_ring_avail(buf=%p, readlen=%p, writelen=%p) = ?", buf, readlen, writelen);
837
838 if ( readlen != NULL ) {
839  have = 0;
840
841  if ( ring->write_pos >= ring->read_pos ) {
842   have  = ring->write_pos - ring->read_pos;
843  } else {
844   have  = buf->user_len - ring->read_pos;
845   have += ring->write_pos;
846   have -= 1;
847  }
848
849  *readlen = have;
850  ROAR_DBG("roar_buffer_ring_avail(buf=%p, readlen=%p, writelen=%p): readlen=%llu", buf, readlen, writelen, (unsigned long long int)have);
851 }
852
853 if ( writelen != NULL ) {
854  have = 0;
855
856  if ( ring->read_pos > ring->write_pos ) {
857   have  = ring->read_pos - ring->write_pos - 1;
858  } else {
859   have  = buf->user_len - ring->write_pos;
860   have += ring->read_pos;
861   have -= 1;
862  }
863
864  *writelen = have;
865  ROAR_DBG("roar_buffer_ring_avail(buf=%p, readlen=%p, writelen=%p): readlen=%llu", buf, readlen, writelen, (unsigned long long int)have);
866 }
867
868 ROAR_DBG("roar_buffer_ring_avail(buf=%p, readlen=%p, writelen=%p) = 0", buf, readlen, writelen);
869
870 return 0;
871}
872
873int roar_buffer_ring_reset(struct roar_buffer *  buf) {
874 _ckbuf(0)
875
876 if ( !(buf->flags & ROAR_BUFFER_FLAG_RING) ) {
877  roar_err_set(ROAR_ERROR_TYPEMM);
878  return -1;
879 }
880
881 buf->meta.ring.read_pos = buf->meta.ring.write_pos = 0;
882
883 return 0;
884}
885
886//ll
Note: See TracBrowser for help on using the repository browser.