From 6938888b0524384a78b67d27ca5feccbca9fef16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 18 May 2005 16:51:41 +0000 Subject: added lifop (Last-In-First-Out with Priorities) and fifop (First-In-First-Out with Priorities) svn path=/trunk/externals/zexy/; revision=3018 --- src/fifop.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lifop.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 457 insertions(+) create mode 100644 src/fifop.c create mode 100644 src/lifop.c (limited to 'src') diff --git a/src/fifop.c b/src/fifop.c new file mode 100644 index 0000000..898d7f0 --- /dev/null +++ b/src/fifop.c @@ -0,0 +1,233 @@ +/****************************************************** + * + * zexy - implementation file + * + * copyleft (c) IOhannes m zmölnig + * + * 1999:forum::für::umläute:2004 + * + * institute of electronic music and acoustics (iem) + * + ****************************************************** + * + * license: GNU General Public License v.2 + * + ******************************************************/ + +/* 2305:forum::für::umläute:2001 */ + + +#include "zexy.h" +#include + +/* ------------------------- fifop ------------------------------- */ + +/* + * a FIFO (first-in first-out) with priorities + * + * an incoming list is added to a fifo (based on its priority) + * "bang" outputs the next element of the non-empty fifo with the highest priority + * + * high priority means low numeric value + */ + +static t_class *fifop_class; + +typedef struct _fifop_list { + int argc; + t_atom *argv; + struct _fifop_list *next; +} t_fifop_list; + +typedef struct _fifop_prioritylist { + t_float priority; + t_fifop_list *fifo_start; + struct _fifop_prioritylist *next; +} t_fifop_prioritylist; + +typedef struct _fifop +{ + t_object x_obj; + t_fifop_prioritylist *fifo_list; + t_float priority; /* current priority */ +} t_fifop; + +static t_fifop_prioritylist*fifop_genprioritylist(t_fifop*x, t_float priority) +{ + t_fifop_prioritylist*result=0, *dummy=0; + + if(x->fifo_list!=0) + { + /* + * do we already have this priority ? + * if so, just return a pointer to that fifo + * else set the dummy-pointer to the fifo BEFORE the new one + */ + dummy=x->fifo_list; + while(dummy!=0){ + t_float prio=dummy->priority; + if(prio==priority)return dummy; + if(prio>priority)break; + result=dummy; + dummy=dummy->next; + } + dummy=result; + } + /* create a new priority list */ + result = (t_fifop_prioritylist*)getbytes(sizeof( t_fifop_prioritylist*)); + result->priority=priority; + result->fifo_start=0; + + /* insert it into the list of priority lists */ + if(dummy!=0){ + result->next=dummy->next; + dummy->next =result; + } else { + result->next=0; + } + if(x->fifo_list==0){ + x->fifo_list=result; + } + + /* return the result */ + return result; +} + +static int add2fifo(t_fifop_prioritylist*fifoprio, int argc, t_atom *argv) +{ + t_atom*buffer=0; + t_fifop_list*fifo=0; + t_fifop_list*entry=0; + + if(fifoprio==0){ + error("pfifo: no fifos available"); + return -1; + } + + /* create an entry for the fifo */ + if(!(entry = (t_fifop_list*)getbytes(sizeof(t_fifop_list)))) + { + error("pfifo: couldn't add entry to end of fifo"); + return -1; + } + if(!(entry->argv=(t_atom*)getbytes(argc*sizeof(t_atom)))){ + error("pfifo: couldn't add list to fifo!"); + return -1; + } + memcpy(entry->argv, argv, argc*sizeof(t_atom)); + entry->argc=argc; + entry->next=0; + + /* go to end of fifo */ + fifo=fifoprio->fifo_start; + if(fifo){ + while(fifo->next!=0)fifo=fifo->next; + /* add new entry to end of fifo */ + fifo->next=entry; + } else { + /* the new entry is the 1st entry of the fifo */ + fifoprio->fifo_start=entry; + } +} +static t_fifop_prioritylist*getFifo(t_fifop_prioritylist*pfifo) +{ + if(pfifo==0)return 0; + /* get the highest non-empty fifo */ + while(pfifo->fifo_start==0 && pfifo->next!=0)pfifo=pfifo->next; + return pfifo; +} + +static void fifop_list(t_fifop *x, t_symbol *s, int argc, t_atom *argv) +{ + t_fifop_prioritylist*pfifo=0; + if(!(pfifo=fifop_genprioritylist(x, x->priority))) { + error("[fifop]: couldn't get priority fifo"); + return; + } + add2fifo(pfifo, argc, argv); +} +static void fifop_bang(t_fifop *x) +{ + t_fifop_prioritylist*pfifo=0; + t_fifop_list*fifo=0; + t_atom*argv=0; + int argc=0; + + if(!(pfifo=getFifo(x->fifo_list))){ + return; + } + if(!(fifo=pfifo->fifo_start)){ + return; + } + + pfifo->fifo_start=fifo->next; + + /* get the list from the entry */ + argc=fifo->argc; + argv=fifo->argv; + + fifo->argc=0; + fifo->argv=0; + fifo->next=0; + + /* destroy the fifo-entry (important for recursion! */ + freebytes(fifo, sizeof(t_fifop_list)); + + /* output the list */ + outlet_list(x->x_obj.ob_outlet, &s_list, argc, argv); + + /* free the list */ + freebytes(argv, argc*sizeof(t_atom)); +} + +static void fifop_free(t_fifop *x) +{ + t_fifop_prioritylist *fifo_list=x->fifo_list; + while(fifo_list){ + t_fifop_prioritylist *fifo_list2=fifo_list; + + t_fifop_list*fifo=fifo_list2->fifo_start; + fifo_list=fifo_list->next; + + while(fifo){ + t_fifop_list*fifo2=fifo; + fifo=fifo->next; + + if(fifo2->argv)freebytes(fifo2->argv, fifo2->argc*sizeof(t_atom)); + fifo2->argv=0; + fifo2->argc=0; + fifo2->next=0; + freebytes(fifo2, sizeof(t_fifop_list)); + } + fifo_list2->priority =0; + fifo_list2->fifo_start=0; + fifo_list2->next =0; + freebytes(fifo_list2, sizeof( t_fifop_prioritylist)); + } + x->fifo_list=0; +} + +static void *fifop_new(t_symbol *s, int argc, t_atom *argv) +{ + t_fifop *x = (t_fifop *)pd_new(fifop_class); + + outlet_new(&x->x_obj, 0); + floatinlet_new(&x->x_obj, &x->priority); + + x->fifo_list = 0; + x->priority=0; + + return (x); +} + +void fifop_setup(void) +{ + fifop_class = class_new(gensym("fifop"), (t_newmethod)fifop_new, + (t_method)fifop_free, sizeof(t_fifop), 0, A_GIMME, 0); + + class_addbang (fifop_class, fifop_bang); + class_addlist (fifop_class, fifop_list); + + class_sethelpsymbol(fifop_class, gensym("zexy/fifop")); + zexy_register("fifop"); +} diff --git a/src/lifop.c b/src/lifop.c new file mode 100644 index 0000000..1e2431e --- /dev/null +++ b/src/lifop.c @@ -0,0 +1,224 @@ +/****************************************************** + * + * zexy - implementation file + * + * copyleft (c) IOhannes m zmölnig + * + * 1999:forum::für::umläute:2004 + * + * institute of electronic music and acoustics (iem) + * + ****************************************************** + * + * license: GNU General Public License v.2 + * + ******************************************************/ + +/* 2305:forum::für::umläute:2001 */ + + +#include "zexy.h" +#include + +/* ------------------------- lifop ------------------------------- */ + +/* + * a LIFO (last-in first-out) with priorities + * + * an incoming list is added to a lifo (based on its priority) + * "bang" outputs the last element of the non-empty lifo with the highest priority + * + * high priority means low numeric value + */ + +static t_class *lifop_class; + +typedef struct _lifop_list { + int argc; + t_atom *argv; + struct _lifop_list *next; +} t_lifop_list; + +typedef struct _lifop_prioritylist { + t_float priority; + t_lifop_list *lifo_start; + struct _lifop_prioritylist *next; +} t_lifop_prioritylist; +typedef struct _lifop +{ + t_object x_obj; + t_lifop_prioritylist *lifo_list; + t_float priority; /* current priority */ +} t_lifop; + +static t_lifop_prioritylist*lifop_genprioritylist(t_lifop*x, t_float priority) +{ + t_lifop_prioritylist*result=0, *dummy=0; + + if(x->lifo_list!=0) + { + /* + * do we already have this priority ? + * if so, just return a pointer to that lifo + * else set the dummy-pointer to the lifo BEFORE the new one + */ + dummy=x->lifo_list; + while(dummy!=0){ + t_float prio=dummy->priority; + if(prio==priority)return dummy; + if(prio>priority)break; + result=dummy; + dummy=dummy->next; + } + dummy=result; + } + /* create a new priority list */ + result = (t_lifop_prioritylist*)getbytes(sizeof( t_lifop_prioritylist)); + result->priority=priority; + result->lifo_start=0; + + /* insert it into the list of priority lists */ + if(dummy!=0){ + result->next=dummy->next; + dummy->next =result; + } else { + result->next=0; + } + if(x->lifo_list==0){ + x->lifo_list=result; + } + + /* return the result */ + return result; +} + +static int add2lifo(t_lifop_prioritylist*lifoprio, int argc, t_atom *argv) +{ + t_atom*buffer=0; + t_lifop_list*lifo=0; + t_lifop_list*entry=0; + + if(lifoprio==0){ + error("plifo: no lifos available"); + return -1; + } + + /* create an entry for the lifo */ + if(!(entry = (t_lifop_list*)getbytes(sizeof(t_lifop_list)))) + { + error("plifo: couldn't add entry to end of lifo"); + return -1; + } + if(!(entry->argv=(t_atom*)getbytes(argc*sizeof(t_atom)))){ + error("plifo: couldn't add list to lifo!"); + return -1; + } + memcpy(entry->argv, argv, argc*sizeof(t_atom)); + entry->argc=argc; + entry->next=0; + + entry->next=lifoprio->lifo_start; + lifoprio->lifo_start=entry; +} +static t_lifop_prioritylist*getLifo(t_lifop_prioritylist*plifo) +{ + if(plifo==0)return 0; + /* get the highest non-empty lifo */ + while(plifo->lifo_start==0 && plifo->next!=0)plifo=plifo->next; + return plifo; +} + +static void lifop_list(t_lifop *x, t_symbol *s, int argc, t_atom *argv) +{ + t_lifop_prioritylist*plifo=0; + if(!(plifo=lifop_genprioritylist(x, x->priority))) { + error("[lifop]: couldn't get priority lifo"); + return; + } + add2lifo(plifo, argc, argv); +} +static void lifop_bang(t_lifop *x) +{ + t_lifop_prioritylist*plifo=0; + t_lifop_list*lifo=0; + t_atom*argv=0; + int argc=0; + + if(!(plifo=getLifo(x->lifo_list))){ + return; + } + if(!(lifo=plifo->lifo_start)){ + return; + } + + plifo->lifo_start=lifo->next; + + /* get the list from the entry */ + argc=lifo->argc; + argv=lifo->argv; + + lifo->argc=0; + lifo->argv=0; + lifo->next=0; + + /* destroy the lifo-entry (important for recursion! */ + freebytes(lifo, sizeof(t_lifop_list)); + + /* output the list */ + outlet_list(x->x_obj.ob_outlet, &s_list, argc, argv); + + /* free the list */ + freebytes(argv, argc*sizeof(t_atom)); +} + +static void lifop_free(t_lifop *x) +{ + t_lifop_prioritylist *lifo_list=x->lifo_list; + while(lifo_list){ + t_lifop_prioritylist *lifo_list2=lifo_list; + + t_lifop_list*lifo=lifo_list2->lifo_start; + lifo_list=lifo_list->next; + + while(lifo){ + t_lifop_list*lifo2=lifo; + lifo=lifo->next; + + if(lifo2->argv)freebytes(lifo2->argv, lifo2->argc*sizeof(t_atom)); + lifo2->argv=0; + lifo2->argc=0; + lifo2->next=0; + freebytes(lifo2, sizeof(t_lifop_list)); + } + lifo_list2->priority =0; + lifo_list2->lifo_start=0; + lifo_list2->next =0; + freebytes(lifo_list2, sizeof( t_lifop_prioritylist)); + } + x->lifo_list=0; +} + +static void *lifop_new(t_symbol *s, int argc, t_atom *argv) +{ + t_lifop *x = (t_lifop *)pd_new(lifop_class); + + outlet_new(&x->x_obj, 0); + floatinlet_new(&x->x_obj, &x->priority); + + x->lifo_list = 0; + x->priority=0; + + return (x); +} + +void lifop_setup(void) +{ + lifop_class = class_new(gensym("lifop"), (t_newmethod)lifop_new, + (t_method)lifop_free, sizeof(t_lifop), 0, A_GIMME, 0); + + class_addbang (lifop_class, lifop_bang); + class_addlist (lifop_class, lifop_list); + + class_sethelpsymbol(lifop_class, gensym("zexy/lifop")); + zexy_register("lifop"); +} -- cgit v1.2.1