source: roaraudio/libroar/buffer.c @ 5823:f9f70dbaa376

Last change on this file since 5823:f9f70dbaa376 was 5823:f9f70dbaa376, checked in by phi, 11 years ago

updated copyright

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