]> git.rkrishnan.org Git - dttsp.git/blob - jDttSP/ringb.c
8a1cfaf6752720cd7e5063141d89770e3c67f1ac
[dttsp.git] / jDttSP / ringb.c
1 /*
2   Memory-mapped ringbuffer
3   Derived from jack/ringbuffer.h
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU Lesser General Public License as published by
7     the Free Software Foundation; either version 2.1 of the License, or
8     (at your option) any later version.
9     
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU Lesser General Public License for more details.
14     
15     You should have received a copy of the GNU Lesser General Public License
16     along with this program; if not, write to the Free Software 
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19     Original
20     Copyright (C) 2000 Paul Davis
21     Copyright (C) 2003 Rohan Drape
22
23     Derived
24     Copyright (C) 2004 by Frank Brickle, AB2KT and Bob McGwier, N4HY
25 */
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <ringb.h>
30
31 ringb_t *
32 ringb_create(char *usemem, size_t sz2) {
33   ringb_t *rb = (ringb_t *) usemem;
34   rb->buf = usemem + sizeof(ringb_t);
35   rb->size = sz2;       // power-of-2-sized
36   rb->mask = rb->size - 1;
37   rb->wptr = rb->rptr = 0;
38   return rb;
39 }
40
41 void
42 ringb_reset(ringb_t *rb) {
43   // NB not thread-safe
44   rb->rptr = 0;
45   rb->wptr = 0;
46 }
47
48 void
49 ringb_clear(ringb_t *rb, size_t nbytes) {
50   size_t i;
51   char zero = 0;
52   for (i = 0; i < nbytes; i++)
53     ringb_write(rb, &zero, 1);
54 }
55
56 void
57 ringb_restart(ringb_t *rb, size_t nbytes) {
58   ringb_reset(rb);
59   ringb_clear(rb, nbytes);
60 }
61
62 size_t
63 ringb_read_space(const ringb_t *rb) {
64   size_t w = rb->wptr, r = rb->rptr;
65   if (w > r) return w - r;
66   else return (w - r + rb->size) & rb->mask;
67 }
68
69 size_t
70 ringb_write_space(const ringb_t *rb) {
71   size_t w = rb->wptr, r = rb->rptr;
72   if (w > r) return ((r - w + rb->size) & rb->mask) - 1;
73   else if (w < r) return r - w - 1;
74   else return rb->size - 1;
75 }
76
77 size_t
78 ringb_read(ringb_t *rb, char *dest, size_t cnt) {
79   size_t free_cnt, cnt2, to_read, n1, n2;
80   if ((free_cnt = ringb_read_space(rb)) == 0) return 0;
81   to_read = cnt > free_cnt ? free_cnt : cnt;
82   if ((cnt2 = rb->rptr + to_read) > rb->size)
83     n1 = rb->size - rb->rptr, n2 = cnt2 & rb->mask;
84   else
85     n1 = to_read, n2 = 0;
86   memcpy(dest, &(rb->buf[rb->rptr]), n1);
87   rb->rptr = (rb->rptr + n1) & rb->mask;
88   if (n2) {
89     memcpy(dest + n1, &(rb->buf[rb->rptr]), n2);
90     rb->rptr = (rb->rptr + n2) & rb->mask;
91   }
92   return to_read;
93 }
94
95 size_t
96 ringb_peek(ringb_t *rb, char *dest, size_t cnt) {
97   size_t free_cnt, cnt2, to_read, n1, n2, tmp_rptr;
98   tmp_rptr = rb->rptr;
99   if ((free_cnt = ringb_read_space(rb)) == 0) return 0;
100   to_read = cnt > free_cnt ? free_cnt : cnt;
101   if ((cnt2 = tmp_rptr + to_read) > rb->size)
102     n1 = rb->size - tmp_rptr, n2 = cnt2 & rb->mask;
103   else
104     n1 = to_read, n2 = 0;
105   memcpy(dest, &(rb->buf[tmp_rptr]), n1);
106   tmp_rptr = (tmp_rptr + n1) & rb->mask;
107   if (n2)
108     memcpy(dest + n1, &(rb->buf[tmp_rptr]), n2);
109   return to_read;
110 }
111
112 size_t
113 ringb_write(ringb_t *rb, const char *src, size_t cnt) {
114   size_t free_cnt, cnt2, to_write, n1, n2;
115   if ((free_cnt = ringb_write_space(rb)) == 0) return 0;
116   to_write = cnt > free_cnt ? free_cnt : cnt;
117   if ((cnt2 = rb->wptr + to_write) > rb->size)
118     n1 = rb->size - rb->wptr, n2 = cnt2 & rb->mask;
119   else
120     n1 = to_write, n2 = 0;
121   memcpy(&(rb->buf[rb->wptr]), src, n1);
122   rb->wptr = (rb->wptr + n1) & rb->mask;
123   if (n2) {
124     memcpy(&(rb->buf[rb->wptr]), src + n1, n2);
125     rb->wptr = (rb->wptr + n2) & rb->mask;
126   }
127   return to_write;
128 }
129
130 void
131 ringb_read_advance(ringb_t *rb, size_t cnt) {
132   rb->rptr = (rb->rptr + cnt) & rb->mask;
133 }
134
135 void
136 ringb_write_advance(ringb_t *rb, size_t cnt) {
137   rb->wptr = (rb->wptr + cnt) & rb->mask;
138 }
139
140 void
141 ringb_get_read_vector(const ringb_t *rb, ringb_data_t *vec) {
142   size_t free_cnt, cnt2,
143          w = rb->wptr, r = rb->rptr;
144   if (w > r) free_cnt = w - r;
145   else free_cnt = (w - r + rb->size) & rb->mask;
146   if ((cnt2 = r + free_cnt) > rb->size) {
147     vec[0].buf = &(rb->buf[r]), vec[0].len = rb->size - r;
148     vec[1].buf = rb->buf, vec[1].len = cnt2 & rb->mask;
149   } else {
150     vec[0].buf = &(rb->buf[r]), vec[0].len = free_cnt;
151     vec[1].len = 0;
152   }
153 }
154
155 void
156 ringb_get_write_vector(const ringb_t *rb, ringb_data_t *vec) {
157   size_t free_cnt, cnt2,
158          w = rb->wptr, r = rb->rptr;
159   if (w > r) free_cnt = ((r - w + rb->size) & rb->mask) - 1;
160   else if (w < r) free_cnt = r - w - 1;
161   else free_cnt = rb->size - 1;
162   if ((cnt2 = w + free_cnt) > rb->size) {
163     vec[0].buf = &(rb->buf[w]), vec[0].len = rb->size - w;
164     vec[1].buf = rb->buf, vec[1].len = cnt2 & rb->mask;
165   } else {
166     vec[0].buf = &(rb->buf[w]), vec[0].len = free_cnt;
167     vec[1].len = 0;
168   }
169 }