1 /*
2 * Copyright (c) 2004-2006 Maxim Sobolev <sobomax@FreeBSD.org>
3 * Copyright (c) 2006-2015 Sippy Software, Inc., http://www.sippysoft.com
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29 #include <stdlib.h>
30 #include <stddef.h>
31 #include <string.h>
32
33 #include "rtpp_types.h"
34 #include "rtpp_refcnt.h"
35 #include "rtpp_ringbuf.h"
36 #include "rtpp_ringbuf_fin.h"
37 #include "rtpp_mallocs.h"
38
39 struct rtpp_ringbuf_priv
40 {
41 struct rtpp_ringbuf pub;
42 void *elements;
43 int nelements;
44 size_t el_size;
45 int c_elem;
46 int b_full;
47 };
48
49 static void rtpp_ringbuf_dtor(struct rtpp_ringbuf_priv *);
50 static void rtpp_ringbuf_push(struct rtpp_ringbuf *, void *);
51 static void rtpp_ringbuf_flush(struct rtpp_ringbuf *);
52 static int rtpp_ringbuf_locate(struct rtpp_ringbuf *, void *);
53
54 #define PUB2PVT(pubp) ((struct rtpp_ringbuf_priv *)((char *)(pubp) - \
55 offsetof(struct rtpp_ringbuf_priv, pub)))
56
57 struct rtpp_ringbuf *
rtpp_ringbuf_ctor(size_t el_size,int nelements)58 rtpp_ringbuf_ctor(size_t el_size, int nelements)
59 {
60 struct rtpp_ringbuf_priv *pvt;
61 struct rtpp_refcnt *rcnt;
62
63 pvt = rtpp_rzmalloc(sizeof(struct rtpp_ringbuf_priv), &rcnt);
64 if (pvt == NULL) {
65 goto e0;
66 }
67 pvt->pub.rcnt = rcnt;
68 pvt->elements = rtpp_zmalloc(el_size * nelements);
69 if (pvt->elements == NULL) {
70 goto e1;
71 }
72 pvt->el_size = el_size;
73 pvt->nelements = nelements;
74 pvt->pub.push = rtpp_ringbuf_push;
75 pvt->pub.flush = rtpp_ringbuf_flush;
76 pvt->pub.locate = rtpp_ringbuf_locate;
77 CALL_SMETHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_ringbuf_dtor,
78 pvt);
79 return (&pvt->pub);
80 e1:
81 CALL_SMETHOD(pvt->pub.rcnt, decref);
82 free(pvt);
83 e0:
84 return (NULL);
85 }
86
87 static void
rtpp_ringbuf_dtor(struct rtpp_ringbuf_priv * pvt)88 rtpp_ringbuf_dtor(struct rtpp_ringbuf_priv *pvt)
89 {
90
91 rtpp_ringbuf_fin(&(pvt->pub));
92 free(pvt->elements);
93 free(pvt);
94 }
95
96 static void
rtpp_ringbuf_push(struct rtpp_ringbuf * self,void * data)97 rtpp_ringbuf_push(struct rtpp_ringbuf *self, void *data)
98 {
99 struct rtpp_ringbuf_priv *pvt;
100 void *dp;
101
102 pvt = PUB2PVT(self);
103 dp = (char *)pvt->elements + (pvt->el_size * pvt->c_elem);
104 memcpy(dp, data, pvt->el_size);
105 pvt->c_elem++;
106 if (pvt->c_elem == pvt->nelements) {
107 if (pvt->b_full == 0) {
108 pvt->b_full = 1;
109 }
110 pvt->c_elem = 0;
111 }
112 }
113
114 static void
rtpp_ringbuf_flush(struct rtpp_ringbuf * self)115 rtpp_ringbuf_flush(struct rtpp_ringbuf *self)
116 {
117 struct rtpp_ringbuf_priv *pvt;
118
119 pvt = PUB2PVT(self);
120 pvt->b_full = 0;
121 pvt->c_elem = 0;
122 }
123
124 static int
rtpp_ringbuf_locate(struct rtpp_ringbuf * self,void * data)125 rtpp_ringbuf_locate(struct rtpp_ringbuf *self, void *data)
126 {
127 struct rtpp_ringbuf_priv *pvt;
128 int i, last_el;
129 void *dp;
130
131 pvt = PUB2PVT(self);
132 last_el = (pvt->b_full != 0) ? pvt->nelements : pvt->c_elem;
133 for (i = 0; i < last_el; i++) {
134 dp = (char *)pvt->elements + (pvt->el_size * i);
135 if (memcmp(dp, data, pvt->el_size) == 0) {
136 return (i);
137 }
138 }
139 return (-1);
140 }
141