blob: 2902363a6ccc92590344a4800d59bc1027ab45f7 [file] [log] [blame]
Benny Prijonoe7224612005-11-13 19:40:44 +00001/* $Id$
2 */
3/*
4 * PJLIB - PJ Foundation Library
5 * (C)2003-2005 Benny Prijono <bennylp@bulukucing.org>
6 *
7 * Author:
8 * Benny Prijono <bennylp@bulukucing.org>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24#include <pj/fifobuf.h>
25#include <pj/log.h>
26#include <pj/assert.h>
27#include <pj/os.h>
28
29#define THIS_FILE "fifobuf"
30
31#define SZ sizeof(unsigned)
32
33PJ_DEF(void)
34pj_fifobuf_init (pj_fifobuf_t *fifobuf, void *buffer, unsigned size)
35{
36 PJ_CHECK_STACK();
37
38 PJ_LOG(6, (THIS_FILE,
39 "fifobuf_init fifobuf=%p buffer=%p, size=%d",
40 fifobuf, buffer, size));
41
42 fifobuf->first = buffer;
43 fifobuf->last = fifobuf->first + size;
44 fifobuf->ubegin = fifobuf->uend = fifobuf->first;
45 fifobuf->full = 0;
46}
47
48PJ_DEF(unsigned)
49pj_fifobuf_max_size (pj_fifobuf_t *fifobuf)
50{
51 unsigned s1, s2;
52
53 PJ_CHECK_STACK();
54
55 if (fifobuf->uend >= fifobuf->ubegin) {
56 s1 = fifobuf->last - fifobuf->uend;
57 s2 = fifobuf->ubegin - fifobuf->first;
58 } else {
59 s1 = s2 = fifobuf->ubegin - fifobuf->uend;
60 }
61
62 return s1<s2 ? s2 : s1;
63}
64
65PJ_DEF(void*)
66pj_fifobuf_alloc (pj_fifobuf_t *fifobuf, unsigned size)
67{
68 unsigned available;
69 char *start;
70
71 PJ_CHECK_STACK();
72
73 if (fifobuf->full) {
74 PJ_LOG(6, (THIS_FILE,
75 "fifobuf_alloc fifobuf=%p, size=%d: full!",
76 fifobuf, size));
77 return NULL;
78 }
79
80 /* try to allocate from the end part of the fifo */
81 if (fifobuf->uend >= fifobuf->ubegin) {
82 available = fifobuf->last - fifobuf->uend;
83 if (available >= size+SZ) {
84 char *ptr = fifobuf->uend;
85 fifobuf->uend += (size+SZ);
86 if (fifobuf->uend == fifobuf->last)
87 fifobuf->uend = fifobuf->first;
88 if (fifobuf->uend == fifobuf->ubegin)
89 fifobuf->full = 1;
90 *(unsigned*)ptr = size+SZ;
91 ptr += SZ;
92
93 PJ_LOG(6, (THIS_FILE,
94 "fifobuf_alloc fifobuf=%p, size=%d: returning %p, p1=%p, p2=%p",
95 fifobuf, size, ptr, fifobuf->ubegin, fifobuf->uend));
96 return ptr;
97 }
98 }
99
100 /* try to allocate from the start part of the fifo */
101 start = (fifobuf->uend <= fifobuf->ubegin) ? fifobuf->uend : fifobuf->first;
102 available = fifobuf->ubegin - start;
103 if (available >= size+SZ) {
104 char *ptr = start;
105 fifobuf->uend = start + size + SZ;
106 if (fifobuf->uend == fifobuf->ubegin)
107 fifobuf->full = 1;
108 *(unsigned*)ptr = size+SZ;
109 ptr += SZ;
110
111 PJ_LOG(6, (THIS_FILE,
112 "fifobuf_alloc fifobuf=%p, size=%d: returning %p, p1=%p, p2=%p",
113 fifobuf, size, ptr, fifobuf->ubegin, fifobuf->uend));
114 return ptr;
115 }
116
117 PJ_LOG(6, (THIS_FILE,
118 "fifobuf_alloc fifobuf=%p, size=%d: no space left! p1=%p, p2=%p",
119 fifobuf, size, fifobuf->ubegin, fifobuf->uend));
120 return NULL;
121}
122
123PJ_DEF(pj_status_t)
124pj_fifobuf_unalloc (pj_fifobuf_t *fifobuf, void *buf)
125{
126 char *ptr = buf;
127 char *endptr;
128 unsigned sz;
129
130 PJ_CHECK_STACK();
131
132 ptr -= SZ;
133 sz = *(unsigned*)ptr;
134
135 endptr = fifobuf->uend;
136 if (endptr == fifobuf->first)
137 endptr = fifobuf->last;
138
139 if (ptr+sz != endptr) {
140 pj_assert(!"Invalid pointer to undo alloc");
141 return -1;
142 }
143
144 fifobuf->uend = ptr;
145 fifobuf->full = 0;
146
147 PJ_LOG(6, (THIS_FILE,
148 "fifobuf_unalloc fifobuf=%p, ptr=%p, size=%d, p1=%p, p2=%p",
149 fifobuf, buf, sz, fifobuf->ubegin, fifobuf->uend));
150
151 return 0;
152}
153
154PJ_DEF(pj_status_t)
155pj_fifobuf_free (pj_fifobuf_t *fifobuf, void *buf)
156{
157 char *ptr = buf;
158 char *end;
159 unsigned sz;
160
161 PJ_CHECK_STACK();
162
163 ptr -= SZ;
164 if (ptr < fifobuf->first || ptr >= fifobuf->last) {
165 pj_assert(!"Invalid pointer to free");
166 return -1;
167 }
168
169 if (ptr != fifobuf->ubegin && ptr != fifobuf->first) {
170 pj_assert(!"Invalid free() sequence!");
171 return -1;
172 }
173
174 end = (fifobuf->uend > fifobuf->ubegin) ? fifobuf->uend : fifobuf->last;
175 sz = *(unsigned*)ptr;
176 if (ptr+sz > end) {
177 pj_assert(!"Invalid size!");
178 return -1;
179 }
180
181 fifobuf->ubegin = ptr + sz;
182
183 /* Rollover */
184 if (fifobuf->ubegin == fifobuf->last)
185 fifobuf->ubegin = fifobuf->first;
186
187 /* Reset if fifobuf is empty */
188 if (fifobuf->ubegin == fifobuf->uend)
189 fifobuf->ubegin = fifobuf->uend = fifobuf->first;
190
191 fifobuf->full = 0;
192
193 PJ_LOG(6, (THIS_FILE,
194 "fifobuf_free fifobuf=%p, ptr=%p, size=%d, p1=%p, p2=%p",
195 fifobuf, buf, sz, fifobuf->ubegin, fifobuf->uend));
196
197 return 0;
198}