1 /**************************************************************************************\
2 * *
3 * The Lisa Emulator Project V1.2.6 DEV 2007.12.04 *
4 * http://lisaem.sunder.net *
5 * *
6 * Copyright (C) 1998, 2007 Ray A. Arachelian *
7 * All Rights Reserved *
8 * *
9 * This program is free software; you can redistribute it and/or *
10 * modify it under the terms of the GNU General Public License *
11 * as published by the Free Software Foundation; either version 2 *
12 * of the License, or (at your option) any later version. *
13 * *
14 * This program is distributed in the hope that it will be useful, *
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17 * GNU General Public License for more details. *
18 * *
19 * You should have received a copy of the GNU General Public License *
20 * along with this program; if not, write to the Free Software *
21 * Foundation, Inc., 59 Temple Place #330, Boston, MA 02111-1307, USA. *
22 * *
23 * or visit: http://www.gnu.org/licenses/gpl.html *
24 * *
25 * *
26 * FLIFLO Queue Structures for various *
27 * Lisa emulator usage *
28 \**************************************************************************************/
29
30
31 // This sure would work better as a C++ class. :) But we're not writing in C++, so there.
32 // thththththpt!
33 //
34 // FIFO's are FIRST IN FIRST OUT i.e. circular buffers
35 // LIFO's are LAST IN, FIRST OUT queues, i.e. stacks
36 //
37 // FLIFLO's are both. You can add data at the end of the queue,
38 // you can pop data off the end like a stack, or get it from the begining,
39 // like a fifo.
40
41 #define IN_FLIFLO_QUEUE_C
42 #include "vars.h"
43
44 //typedef struct
45 //{
46 // uint32 size;
47 // uint8 *buffer;
48 // uint32 start;
49 // uint32 end;
50 //} FLIFLO_QUEUE_t;
51
52
53
54 //int fliflo_buff_is_full(FLIFLO_QUEUE_t *b);
55 //int fliflo_buff_has_data(FLIFLO_QUEUE_t *b);
56 //int fliflo_buff_is_empty(FLIFLO_QUEUE_t *b);
57 //uint32 fliflo_buff_size(FLIFLO_QUEUE_t *b);
58 //uint32 fliflo_buff_percent_full(FLIFLO_QUEUE_t *b);
59 //int fliflo_buff_add(FLIFLO_QUEUE_t *b,uint8 data);
60 //uint8 fliflo_buff_pop(FLIFLO_QUEUE_t *b);
61 //uint8 fliflo_buff_get(FLIFLO_QUEUE_t *b);
62 //uint8 fliflo_buff_peek(FLIFLO_QUEUE_t *b);
63 //uint8 fliflo_buff_peek_end(FLIFLO_QUEUE_t *b);
64 //int fliflo_buff_create(FLIFLO_QUEUE_t *b, uint32 size);
65 //void fliflo_buff_destroy(FLIFLO_QUEUE_t *b);
66
67
next_idx(FLIFLO_QUEUE_t * b,int index)68 static inline int next_idx(FLIFLO_QUEUE_t *b, int index)
69 {
70 if ( !b) return 0;
71 if ( !b->size) return 0;
72 return (index+1) % b->size;
73 }
74
previous_idx(FLIFLO_QUEUE_t * b,int index)75 static inline int previous_idx(FLIFLO_QUEUE_t *b, int index)
76 {
77 if ( !b) return 0;
78 if ( !b->size) return 0;
79
80 if (!index) return b->size-1;
81
82 return (index-1) % b->size;
83 }
84
85
86
fliflo_buff_is_full(FLIFLO_QUEUE_t * b)87 int fliflo_buff_is_full(FLIFLO_QUEUE_t *b) {if (!b) return -1; return b->size ? ( ( (b->end+1) % b->size)==b->start ):0;}
88
fliflo_buff_has_data(FLIFLO_QUEUE_t * b)89 int fliflo_buff_has_data(FLIFLO_QUEUE_t *b) {if (!b) return 0; \
90 if (!b->buffer) return 0; \
91 if (!b->size) return 0; \
92 return( b->start!=b->end);}
93
94
fliflo_buff_is_empty(FLIFLO_QUEUE_t * b)95 int fliflo_buff_is_empty(FLIFLO_QUEUE_t *b) {if (!b) return -1; \
96 if (!b->buffer) return -2; \
97 if (!b->size) return -3; \
98 return( b->start==b->end);}
99
fliflo_buff_size(FLIFLO_QUEUE_t * b)100 uint32 fliflo_buff_size(FLIFLO_QUEUE_t *b)
101 {
102 if (!b) return -1;
103 if (!b->size) return -1;
104
105 if ( b->end == b->start) return 0;
106
107 if ( b->end > b->start) return (b->end) - (b->start);
108 else return (b->end+b->size) - (b->start);
109 }
110
fliflo_buff_percent_full(FLIFLO_QUEUE_t * b)111 uint32 fliflo_buff_percent_full(FLIFLO_QUEUE_t *b)
112 {
113 int t=fliflo_buff_size(b);
114 if (t<0) return 0;
115 return 100*(b->size-t);
116 }
117
118
119
fliflo_buff_add(FLIFLO_QUEUE_t * b,uint8 data)120 int fliflo_buff_add(FLIFLO_QUEUE_t *b,uint8 data) // checked
121 {
122 if (!b->size) return -4;
123
124 if ( !b) {DEBUG_LOG(0,"null queue!"); return -2;}
125 if (!b->buffer) {DEBUG_LOG(0,"buffer is missing!"); return -3;}
126 if ( fliflo_buff_is_full(b)) {DEBUG_LOG(0,"buffer is full"); return -1;}
127
128 #ifdef DEBUG
129 if ((b->end) > (b->size)) {EXITR(178,0,"ERROR! end:%d pointer>size! %d",b->end,b->size);}
130 if ((b->start)> (b->size)) {EXITR(179,0,"ERROR! start:%d pointer>size! %d",b->start,b->size);}
131 #endif
132
133 DEBUG_LOG(0,"adding %d to buffer at index:%d",data,b->end);
134 b->buffer[b->start]=data;
135 b->end=next_idx(b,b->end);
136 return 0;
137 }
138
fliflo_dump(FLIFLO_QUEUE_t * b,char * s)139 void fliflo_dump(FLIFLO_QUEUE_t *b,char *s)
140 {
141 uint32 i;
142 fprintf(buglog,"FLIFLO QUEUE DUMP OF %s start,end,size:%d,%d,%d::",s,b->start,b->end,b->size);
143 for (i=0; i<b->size; i++) fprintf(buglog,"%02x ",b->buffer[i]);
144 fprintf(buglog,"\n\n");
145 }
146
147
148
fliflo_buff_pop(FLIFLO_QUEUE_t * b)149 uint8 fliflo_buff_pop(FLIFLO_QUEUE_t *b) // checked
150 {
151 uint8 data;
152 if ( !b) return 0;
153 if ( fliflo_buff_is_empty(b)) return 0;
154 if (!b->buffer) return 0;
155 b->end=previous_idx(b,b->end);
156 data=b->buffer[b->end];
157 b->buffer[b->end]=0;
158 return data;
159 }
160
fliflo_buff_get(FLIFLO_QUEUE_t * b)161 uint8 fliflo_buff_get(FLIFLO_QUEUE_t *b) // checked.
162 {
163 uint8 data;
164 if ( !b) return 0;
165 if ( fliflo_buff_is_empty(b)) return 0;
166 if (!b->buffer) return 0;
167 data=b->buffer[b->start];
168 b->buffer[b->start]=0; // clobber it to make sure
169 b->start=next_idx(b,b->start);
170
171 return data;
172 }
173
174
fliflo_buff_peek(FLIFLO_QUEUE_t * b)175 uint8 fliflo_buff_peek(FLIFLO_QUEUE_t *b)
176 {
177 uint8 data;
178 if ( !b) return 0;
179 if ( fliflo_buff_is_empty(b)) return 0;
180 if (!b->buffer) return 0;
181 data=b->buffer[b->start];
182 return data;
183 }
184
fliflo_buff_peek_end(FLIFLO_QUEUE_t * b)185 uint8 fliflo_buff_peek_end(FLIFLO_QUEUE_t *b)
186 {
187 uint8 data;
188 if ( !b) return 0;
189 if ( fliflo_buff_is_empty(b)) return 0;
190 if (!b->buffer) return 0;
191 data=b->buffer[previous_idx(b,b->end)];
192 return data;
193 }
194
195
196
fliflo_buff_create(FLIFLO_QUEUE_t * b,uint32 size)197 int fliflo_buff_create(FLIFLO_QUEUE_t *b, uint32 size)
198 {
199 if ( !b) return -2;
200 if ( size<2 ) return -3;
201 size++;
202 b->buffer=malloc(size);
203 if ( !b->buffer) return -1;
204 //memset(b->buffer,0,size-1);
205 b->start=0;
206 b->end=0;
207 b->size=size;
208 return 0;
209 }
210
fliflo_buff_destroy(FLIFLO_QUEUE_t * b)211 void fliflo_buff_destroy(FLIFLO_QUEUE_t *b)
212 {
213
214 if ( !b) return;
215 b->size=0;
216 b->start=0;
217 b->end=0;
218 if (b->buffer) free(b->buffer);
219 b->buffer=NULL;
220 }
221
222 #ifdef NEWCODE
223
224
225 /* give a size value, find the next bitmask that contains this size.
226 I.e give it 2 returns 3, give it 4,5,6 reurns 7, etc. So can use val &
227 mask instead of modulo division.) */
228
findfittingbitmask(uint32 size)229 uint32 findfittingbitmask(uint32 size)
230 {uint32 count=0;
231 while(size>>=1) count++;
232 return (1<<(count+1))-1;
233 // check the need for +1 above
234 }
235
236 //S=start pointer. E=end pointer.
237
238 #define s (RB->start)
239 #define e (RB->end)
240 #define size (RB->rbsize)
241 #define data (RB->data)
242 #define CHKRB {if (!RB) return -2;}
243
rb_is_empty(RB)244 inline static int rb_is_empty(RB) {CHKRB; return(s==e);}
rb_is_full(RB)245 inline static int rb_is_full(RB) {CHKRB; return(next(e)==s);}
rb_has_data(RB)246 inline static int rb_has_data(RB) {CHKRB; return(s!=e);}
rb_size(RB)247 inline static int rb_size(RB)
248 { CHKRB;
249 if (e>=s) return e-s;
250 return (RB->buffersize-(s-e));
251 }
252
rb_remaining_space(RB)253 inline static rb_remaining_space(RB)
254 { return RB->buffersize-rb_size(RB); }
255
rb_percent_full(RB)256 inline static int rb_percent_full(RB)
257 { if (!RB) return 100;
258 return rb_size(RB)*100/RB->buffersize;
259 }
260
next(RB,int i)261 inline static int next(RB, int i)
262 { CHKRB; i++; if (i>=RB->buffersize) return 0;
263 return i; }
264
next(RB,int i)265 inline static prev next(RB, int i)
266 { CHKRB; i--; if (i<0) return RB->buffersize-1;
267 return i; }
268
add(RB,void * x)269 int add(RB,void *x)
270 {CHKRB; if (is_full(RB)) return -1;
271 data[prev(RB,e)]=x; e=next(RB,e);
272 size++;
273 return 0;
274 }
275
get(RB)276 void *get(RB)
277 {
278 int sold;
279 CHKRB; if (is_empty(RB)) return NULL;
280 sold=s; s=next(RB,s);
281 return data[sold];
282 }
283
peek(RB)284 void *peek(RB)
285 {CHKRB; if (is_empty(RB)) return NULL;
286 return data[s];
287 }
288
peek_end(RB)289 void *peek_end(RB)
290 {if (!RB || is_empty(RB)) return NULL;
291 return data[prev(RB,e)];
292 }
293
get_end(RB)294 void *get_end(RB)
295 { CHKRB; if (is_empty(RB)) return -1;
296 e=prev(RB,e);
297 return data[e];
298 }
299
add_start(RB,void * x)300 int add_start(RB, void *x)
301 {
302 int ps=prev(RB,s);
303 CHKRB; if (is_full(RB) || ps==e) return -1;
304 s=ps;
305 data[ps]=x;
306 return 0;
307 }
308
309 #endif
310