source: roaraudio/libroar/buffer.c

tip
Last change on this file was 6052:d48765b2475e, checked in by phi, 9 years ago

updated copyright headers

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