1 /* Addressable FIFO buffer Copyright (c) 2007 robs@users.sourceforge.net
2 *
3 * This library is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation; either version 2.1 of the License, or (at
6 * your option) any later version.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17
18 #ifndef fifo_included
19 #define fifo_included
20
21 #include <string.h>
22
23 #ifndef FIFO_SIZE_T
24 #define FIFO_SIZE_T size_t
25 #endif
26
27 typedef struct {
28 char * data;
29 size_t allocation; /* Number of bytes allocated for data. */
30 size_t item_size; /* Size of each item in data */
31 size_t begin; /* Offset of the first byte to read. */
32 size_t end; /* 1 + Offset of the last byte byte to read. */
33 } fifo_t;
34
35 #define FIFO_MIN 0x4000
36
fifo_clear(fifo_t * f)37 UNUSED static void fifo_clear(fifo_t * f)
38 {
39 f->end = f->begin = 0;
40 }
41
fifo_reserve(fifo_t * f,FIFO_SIZE_T n)42 UNUSED static void * fifo_reserve(fifo_t * f, FIFO_SIZE_T n)
43 {
44 n *= f->item_size;
45
46 if (f->begin == f->end)
47 fifo_clear(f);
48
49 while (1) {
50 if (f->end + n <= f->allocation) {
51 void *p = f->data + f->end;
52
53 f->end += n;
54 return p;
55 }
56 if (f->begin > FIFO_MIN) {
57 memmove(f->data, f->data + f->begin, f->end - f->begin);
58 f->end -= f->begin;
59 f->begin = 0;
60 continue;
61 }
62 f->allocation += n;
63 f->data = lsx_realloc(f->data, f->allocation);
64 }
65 }
66
fifo_write(fifo_t * f,FIFO_SIZE_T n,void const * data)67 UNUSED static void * fifo_write(fifo_t * f, FIFO_SIZE_T n, void const * data)
68 {
69 void * s = fifo_reserve(f, n);
70 if (data)
71 memcpy(s, data, n * f->item_size);
72 return s;
73 }
74
fifo_trim_to(fifo_t * f,FIFO_SIZE_T n)75 UNUSED static void fifo_trim_to(fifo_t * f, FIFO_SIZE_T n)
76 {
77 n *= f->item_size;
78 f->end = f->begin + n;
79 }
80
fifo_trim_by(fifo_t * f,FIFO_SIZE_T n)81 UNUSED static void fifo_trim_by(fifo_t * f, FIFO_SIZE_T n)
82 {
83 n *= f->item_size;
84 f->end -= n;
85 }
86
fifo_occupancy(fifo_t * f)87 UNUSED static FIFO_SIZE_T fifo_occupancy(fifo_t * f)
88 {
89 return (f->end - f->begin) / f->item_size;
90 }
91
fifo_read(fifo_t * f,FIFO_SIZE_T n,void * data)92 UNUSED static void * fifo_read(fifo_t * f, FIFO_SIZE_T n, void * data)
93 {
94 char * ret = f->data + f->begin;
95 n *= f->item_size;
96 if (n > (FIFO_SIZE_T)(f->end - f->begin))
97 return NULL;
98 if (data)
99 memcpy(data, ret, (size_t)n);
100 f->begin += n;
101 return ret;
102 }
103
104 #define fifo_read_ptr(f) fifo_read(f, (FIFO_SIZE_T)0, NULL)
105
fifo_delete(fifo_t * f)106 UNUSED static void fifo_delete(fifo_t * f)
107 {
108 free(f->data);
109 }
110
fifo_create(fifo_t * f,FIFO_SIZE_T item_size)111 UNUSED static void fifo_create(fifo_t * f, FIFO_SIZE_T item_size)
112 {
113 f->item_size = item_size;
114 f->allocation = FIFO_MIN;
115 f->data = lsx_malloc(f->allocation);
116 fifo_clear(f);
117 }
118
119 #endif
120