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