]> git.rkrishnan.org Git - dttsp.git/blob - jDttSP/ringb.c
1e6c31ed5dcf939925126cd630c39b211cbce099
[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 size_t
49 ringb_read_space(const ringb_t *rb) {
50   size_t w = rb->wptr, r = rb->rptr;
51   if (w > r) return w - r;
52   else return (w - r + rb->size) & rb->mask;
53 }
54
55 size_t
56 ringb_write_space(const ringb_t *rb) {
57   size_t w = rb->wptr, r = rb->rptr;
58   if (w > r) return ((r - w + rb->size) & rb->mask) - 1;
59   else if (w < r) return r - w - 1;
60   else return rb->size - 1;
61 }
62
63 size_t
64 ringb_read(ringb_t *rb, char *dest, size_t cnt) {
65   size_t free_cnt, cnt2, to_read, n1, n2;
66   if ((free_cnt = ringb_read_space(rb)) == 0) return 0;
67   to_read = cnt > free_cnt ? free_cnt : cnt;
68   if ((cnt2 = rb->rptr + to_read) > rb->size)
69     n1 = rb->size - rb->rptr, n2 = cnt2 & rb->mask;
70   else
71     n1 = to_read, n2 = 0;
72   memcpy(dest, &(rb->buf[rb->rptr]), n1);
73   rb->rptr = (rb->rptr + n1) & rb->mask;
74   if (n2) {
75     memcpy(dest + n1, &(rb->buf[rb->rptr]), n2);
76     rb->rptr = (rb->rptr + n2) & rb->mask;
77   }
78   return to_read;
79 }
80
81 size_t
82 ringb_peek(ringb_t *rb, char *dest, size_t cnt) {
83   size_t free_cnt, cnt2, to_read, n1, n2, tmp_rptr;
84   tmp_rptr = rb->rptr;
85   if ((free_cnt = ringb_read_space(rb)) == 0) return 0;
86   to_read = cnt > free_cnt ? free_cnt : cnt;
87   if ((cnt2 = tmp_rptr + to_read) > rb->size)
88     n1 = rb->size - tmp_rptr, n2 = cnt2 & rb->mask;
89   else
90     n1 = to_read, n2 = 0;
91   memcpy(dest, &(rb->buf[tmp_rptr]), n1);
92   tmp_rptr = (tmp_rptr + n1) & rb->mask;
93   if (n2)
94     memcpy(dest + n1, &(rb->buf[tmp_rptr]), n2);
95   return to_read;
96 }
97
98 size_t
99 ringb_write(ringb_t *rb, const char *src, size_t cnt) {
100   size_t free_cnt, cnt2, to_write, n1, n2;
101   if ((free_cnt = ringb_write_space(rb)) == 0) return 0;
102   to_write = cnt > free_cnt ? free_cnt : cnt;
103   if ((cnt2 = rb->wptr + to_write) > rb->size)
104     n1 = rb->size - rb->wptr, n2 = cnt2 & rb->mask;
105   else
106     n1 = to_write, n2 = 0;
107   memcpy(&(rb->buf[rb->wptr]), src, n1);
108   rb->wptr = (rb->wptr + n1) & rb->mask;
109   if (n2) {
110     memcpy(&(rb->buf[rb->wptr]), src + n1, n2);
111     rb->wptr = (rb->wptr + n2) & rb->mask;
112   }
113   return to_write;
114 }
115
116 void
117 ringb_read_advance(ringb_t *rb, size_t cnt) {
118   rb->rptr = (rb->rptr + cnt) & rb->mask;
119 }
120
121 void
122 ringb_write_advance(ringb_t *rb, size_t cnt) {
123   rb->wptr = (rb->wptr + cnt) & rb->mask;
124 }
125
126 void
127 ringb_get_read_vector(const ringb_t *rb, ringb_data_t *vec) {
128   size_t free_cnt, cnt2,
129          w = rb->wptr, r = rb->rptr;
130   if (w > r) free_cnt = w - r;
131   else free_cnt = (w - r + rb->size) & rb->mask;
132   if ((cnt2 = r + free_cnt) > rb->size) {
133     vec[0].buf = &(rb->buf[r]), vec[0].len = rb->size - r;
134     vec[1].buf = rb->buf, vec[1].len = cnt2 & rb->mask;
135   } else {
136     vec[0].buf = &(rb->buf[r]), vec[0].len = free_cnt;
137     vec[1].len = 0;
138   }
139 }
140
141 void
142 ringb_get_write_vector(const ringb_t *rb, ringb_data_t *vec) {
143   size_t free_cnt, cnt2,
144          w = rb->wptr, r = rb->rptr;
145   if (w > r) free_cnt = ((r - w + rb->size) & rb->mask) - 1;
146   else if (w < r) free_cnt = r - w - 1;
147   else free_cnt = rb->size - 1;
148   if ((cnt2 = w + free_cnt) > rb->size) {
149     vec[0].buf = &(rb->buf[w]), vec[0].len = rb->size - w;
150     vec[1].buf = rb->buf, vec[1].len = cnt2 & rb->mask;
151   } else {
152     vec[0].buf = &(rb->buf[w]), vec[0].len = free_cnt;
153     vec[1].len = 0;
154   }
155 }