source: roaraudio/libroar/buffer.c @ 5297:9dc3f254b670

Last change on this file since 5297:9dc3f254b670 was 5297:9dc3f254b670, checked in by phi, 12 years ago

removed roar_buffer_clear_next() (See: #130)

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