source: roaraudio/libroar/buffer.c @ 5393:f50243718494

Last change on this file since 5393:f50243718494 was 5381:430b1d26e12d, checked in by phi, 12 years ago

updated copyright years

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