1
/******************************************************
3
* zexy - implementation file
5
* copyleft (c) IOhannes m zm�lnig
7
* 1999:forum::f�r::uml�ute:2004
9
* institute of electronic music and acoustics (iem)
11
******************************************************
13
* license: GNU General Public License v.2
15
******************************************************/
17
/* 2305:forum::f�r::uml�ute:2001 */
23
/* ------------------------- lifop ------------------------------- */
26
* a LIFO (last-in first-out) with priorities
28
* an incoming list is added to a lifo (based on its priority)
29
* "bang" outputs the last element of the non-empty lifo with the highest priority
31
* high priority means low numeric value
34
static t_class *lifop_class;
36
typedef struct _lifop_list {
39
struct _lifop_list *next;
42
typedef struct _lifop_prioritylist {
44
t_lifop_list *lifo_start;
45
struct _lifop_prioritylist *next;
46
} t_lifop_prioritylist;
50
t_lifop_prioritylist *lifo_list;
51
unsigned long counter;
52
t_float priority; /* current priority */
53
t_outlet *x_out, *x_infout;
56
static t_lifop_prioritylist*lifop_genprioritylist(t_lifop*x, t_float priority)
58
t_lifop_prioritylist*result=0, *dummy=0;
63
* do we already have this priority ?
64
* if so, just return a pointer to that lifo
65
* else set the dummy-pointer to the lifo BEFORE the new one
69
t_float prio=dummy->priority;
70
if(prio==priority)return dummy;
71
if(prio>priority)break;
77
/* create a new priority list */
78
result = (t_lifop_prioritylist*)getbytes(sizeof( t_lifop_prioritylist));
79
result->priority=priority;
82
/* insert it into the list of priority lists */
84
/* insert at the beginning */
85
result->next=x->lifo_list;
88
/* post insert into the list of LIFOs */
89
result->next=dummy->next;
93
/* return the result */
97
static int add2lifo(t_lifop_prioritylist*lifoprio, int argc, t_atom *argv)
102
error("plifo: no lifos available");
106
/* create an entry for the lifo */
107
if(!(entry = (t_lifop_list*)getbytes(sizeof(t_lifop_list))))
109
error("plifo: couldn't add entry to end of lifo");
112
if(!(entry->argv=(t_atom*)getbytes(argc*sizeof(t_atom)))){
113
error("plifo: couldn't add list to lifo!");
116
memcpy(entry->argv, argv, argc*sizeof(t_atom));
120
entry->next=lifoprio->lifo_start;
121
lifoprio->lifo_start=entry;
125
static t_lifop_prioritylist*getLifo(t_lifop_prioritylist*plifo)
127
if(plifo==0)return 0;
128
/* get the highest non-empty lifo */
129
while(plifo->lifo_start==0 && plifo->next!=0)plifo=plifo->next;
133
static void lifop_list(t_lifop *x, t_symbol *s, int argc, t_atom *argv)
135
t_lifop_prioritylist*plifo=0;
137
if(!(plifo=lifop_genprioritylist(x, x->priority))) {
138
error("[lifop]: couldn't get priority lifo");
141
if(!add2lifo(plifo, argc, argv))
147
static void lifop_bang(t_lifop *x)
149
t_lifop_prioritylist*plifo=0;
154
if(!(plifo=getLifo(x->lifo_list))){
155
outlet_bang(x->x_infout);
158
if(!(lifo=plifo->lifo_start)){
159
outlet_bang(x->x_infout);
165
plifo->lifo_start=lifo->next;
167
/* get the list from the entry */
175
/* destroy the lifo-entry (important for recursion! */
176
freebytes(lifo, sizeof(t_lifop_list));
178
/* output the list */
179
outlet_list(x->x_out, &s_list, argc, argv);
182
freebytes(argv, argc*sizeof(t_atom));
184
static void lifop_query(t_lifop*x)
186
z_verbose(1, "%d elements in lifo", (int)x->counter);
188
outlet_float(x->x_infout, (t_float)x->counter);
190
static void lifop_clear(t_lifop *x)
192
t_lifop_prioritylist *lifo_list=x->lifo_list;
194
t_lifop_prioritylist *lifo_list2=lifo_list;
196
t_lifop_list*lifo=lifo_list2->lifo_start;
197
lifo_list=lifo_list->next;
200
t_lifop_list*lifo2=lifo;
203
if(lifo2->argv)freebytes(lifo2->argv, lifo2->argc*sizeof(t_atom));
207
freebytes(lifo2, sizeof(t_lifop_list));
209
lifo_list2->priority =0;
210
lifo_list2->lifo_start=0;
212
freebytes(lifo_list2, sizeof( t_lifop_prioritylist));
218
/* this is NOT re-entrant! */
219
static void lifop_dump(t_lifop*x)
221
t_lifop_prioritylist*plifo=getLifo(x->lifo_list);
223
if(!plifo||!plifo->lifo_start) {
224
outlet_bang(x->x_infout);
229
t_lifop_list*lifo=plifo->lifo_start;
231
t_atom*argv=lifo->argv;
234
/* output the list */
235
outlet_list(x->x_out, &s_list, argc, argv);
243
static void lifop_free(t_lifop *x)
247
outlet_free(x->x_out);
248
outlet_free(x->x_infout);
251
static void *lifop_new(void)
253
t_lifop *x = (t_lifop *)pd_new(lifop_class);
255
floatinlet_new(&x->x_obj, &x->priority);
256
x->x_out=outlet_new(&x->x_obj, gensym("list"));
257
x->x_infout=outlet_new(&x->x_obj, &s_float);
265
static void lifop_help(t_lifop*x)
267
post("\n%c lifop\t\t:: a Last-In-First-Out queue with priorities", HEARTSYMBOL);
269
void lifop_setup(void)
271
lifop_class = class_new(gensym("lifop"), (t_newmethod)lifop_new,
272
(t_method)lifop_free, sizeof(t_lifop), 0, A_NULL);
274
class_addbang (lifop_class, lifop_bang);
275
class_addlist (lifop_class, lifop_list);
277
class_addmethod (lifop_class, (t_method)lifop_clear, gensym("clear"), A_NULL);
278
class_addmethod (lifop_class, (t_method)lifop_dump, gensym("dump"), A_NULL);
280
class_addmethod (lifop_class, (t_method)lifop_query, gensym("info"), A_NULL);
281
class_addmethod (lifop_class, (t_method)lifop_help, gensym("help"), A_NULL);
283
zexy_register("lifop");