source: roaraudio/libroar/buffer.c @ 5119:66203ccc8f12

Last change on this file since 5119:66203ccc8f12 was 5111:090c5c2831a7, checked in by phi, 13 years ago

fixed some compiler warnings

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