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