source: roaraudio/libroar/buffer.c @ 5348:83fcc9598253

Last change on this file since 5348:83fcc9598253 was 5348:83fcc9598253, checked in by phi, 12 years ago

Converted roar_buffer API to fully use refcounter (Closes: #126)

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