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
******************************************************/
19
this is heavily based on code from [textfile],
20
which is part of pd and written by Miller S. Pucket
21
pd (and thus [textfile]) come with their own license
38
/* ****************************************************************************** */
39
/* liststorage : store several lists in a slots (array of lists of lists) */
43
typedef struct _msglist {
46
struct _msglist *next;
49
typedef struct _liststorage
51
t_object x_obj; /* everything */
53
t_outlet*x_dataout; /* where the data appears */
54
t_outlet*x_infoout; /* where meta-information appears */
56
t_inlet*x_slotin; /* setting the current slot */
58
int x_numslots, x_defaultnumslots;
64
static t_class *liststorage_class;
67
/* ************************************************************************ */
68
/* helper functions */
70
static t_msglist*_liststorage_getslot(t_liststorage*x, int slot) {
71
// post("getting slot %d of %d|%d", slot, 0, x->x_numslots);
72
if(slot<0 || slot>=x->x_numslots) { pd_error(x, "[liststorage]: attempting to access invalid slot %d", slot); return NULL; }
73
return x->x_slots[slot];
76
static void _liststorage_deletemsglist(t_msglist*list) {
83
freebytes(y->argv, y->argc*sizeof(t_atom));
87
freebytes(y, sizeof(t_msglist));
91
static void _liststorage_deleteslot(t_liststorage*x, int slot) {
92
t_msglist*list=_liststorage_getslot(x, slot);
94
_liststorage_deletemsglist(list);
95
x->x_slots[slot]=NULL;
99
static t_msglist*_liststorage_newslot(int argc, t_atom*argv) {
100
t_msglist*slot=getbytes(sizeof(t_msglist));
103
slot->argv=getbytes(sizeof(t_atom)*argc);
104
for(i=0; i<argc; i++) {
105
slot->argv[i]=argv[i];
115
static t_msglist*_liststorage_add2slot(t_msglist*slot, int argc, t_atom*argv) {
116
t_msglist*dummy=slot;
117
t_msglist*newlist=_liststorage_newslot(argc, argv);
119
// post("no data yet: new data is %x", newlist);
127
// post("added data to slot @ %x", slot);
132
static int _liststorage_resize(t_liststorage*x, int size) {
133
t_msglist**newarray=NULL;
137
pd_error(x, "[liststorage]: refusing to resize for negative amount of slots");
141
if(size==x->x_numslots) {
142
verbose(1, "[liststorate] no need to resize array");
146
/* create a new array */
147
newarray=getbytes(sizeof(t_msglist*)*size);
148
for(i=0; i<size; i++) {
152
/* copy over all the data from the old array (if there was one */
153
i=(size<x->x_numslots)?size:x->x_numslots;
155
newarray[i]=x->x_slots[i];
159
/* delete the old array */
160
for(i=0; i<x->x_numslots; i++) {
161
_liststorage_deleteslot(x, i);
163
freebytes(x->x_slots, sizeof(t_msglist*));
165
/* make the new array the current */
172
static int _liststorage_checkslot(t_liststorage*x, const char*string, const int resize) {
173
int slot=x->x_currentslot;
175
SETFLOAT(&atom, (t_float)slot);
178
if(NULL!=string)pd_error(x, "[liststorage]: %s %d", string, slot);
179
outlet_anything(x->x_infoout, gensym("invalidslot"), 1, &atom);
182
if(slot>=x->x_numslots) {
184
_liststorage_resize(x, slot+1);
186
if(NULL!=string)pd_error(x, "[liststorage]: %s %d", string, slot);
187
outlet_anything(x->x_infoout, gensym("invalidslot"), 1, &atom);
193
/* ************************************************************************ */
196
/* recall all lists from the current slot */
197
static void liststorage_bang(t_liststorage *x)
202
int slot=_liststorage_checkslot(x, "attempting to read data from invalid slot", 0);
204
list=_liststorage_getslot(x, slot);
207
outlet_list(x->x_dataout, gensym("list"), list->argc, list->argv);
210
SETFLOAT(&atom, (t_float)slot);
212
/* no need for done: use [t b b b] to get beginning and end of output */
213
// outlet_anything(x->x_infoout, gensym("done"), 1, &atom);
216
/* add a new list to the current slot */
217
static void liststorage_add(t_liststorage *x, t_symbol *s, int ac, t_atom *av)
220
int slot=_liststorage_checkslot(x, "attempting to add data to invalid slot", 1);
222
list=_liststorage_getslot(x, slot);
223
x->x_slots[slot]=_liststorage_add2slot(x->x_slots[slot], ac, av);
226
/* clear the current slot */
227
static void liststorage_clear(t_liststorage *x)
229
int slot=_liststorage_checkslot(x, "attempting to clear invalid slot", 0);
232
_liststorage_deleteslot(x, slot);
235
/* clear all slots */
236
static void liststorage_clearall(t_liststorage *x)
239
for(i=0; i<x->x_numslots; i++) {
240
_liststorage_deleteslot(x, i);
244
/* insert an empty slot at (before) given position */
245
static void liststorage_insert(t_liststorage *x, t_floatarg f)
247
int current=x->x_currentslot;
252
slot=_liststorage_checkslot(x, "attempting to insert invalid slot", 1);
253
x->x_currentslot=current;
257
_liststorage_resize(x, x->x_numslots+1);
259
for(i=x->x_numslots-1; i>slot; i--) {
260
x->x_slots[i]=x->x_slots[i-1];
262
x->x_slots[slot]=NULL;
265
/* get the number of slots */
266
static void liststorage_info(t_liststorage *x)
269
SETFLOAT(&ap, (t_float)x->x_numslots);
270
outlet_anything(x->x_infoout, gensym("numslots"), 1, &ap);
274
/* get the number of slots */
275
static void liststorage_slot(t_liststorage *x, t_floatarg f)
278
x->x_currentslot=slot;
283
/* remove empty slots */
284
static void liststorage_compress(t_liststorage *x)
286
t_msglist**newarray=NULL;
289
for(i=0; i<x->x_numslots; i++) {
290
if(NULL!=x->x_slots[i]) {
296
if(size>=x->x_numslots) {
297
// post("incomressible: %d of %d", size, x->x_numslots);
301
if(size<x->x_defaultnumslots)
302
size=x->x_defaultnumslots;
304
/* create a new array */
305
newarray=getbytes(sizeof(t_msglist*)*size);
306
for(i=0; i<size; i++) {
310
/* copy over all the data from the old array (if there was one */
311
for(i=0, j=0; i<x->x_numslots; i++) {
312
if(NULL!=x->x_slots[i]) {
313
newarray[j]=x->x_slots[i];
319
/* delete the old array */
320
for(i=0; i<x->x_numslots; i++) {
321
_liststorage_deleteslot(x, i);
323
freebytes(x->x_slots, sizeof(t_msglist*));
325
/* make the new array the current */
331
/* ************************************************************************ */
332
/* constructor/destructor */
334
static void liststorage_free(t_liststorage *x)
336
liststorage_clearall(x);
337
_liststorage_resize(x, 0);
340
/* constructor: argument is initial number of slots (can grow) */
341
static void *liststorage_new(t_floatarg f)
343
t_liststorage *x = (t_liststorage *)pd_new(liststorage_class);
346
x->x_slotin=inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("slot"));
347
x->x_dataout=outlet_new(&x->x_obj, &s_list);
348
x->x_infoout=outlet_new(&x->x_obj, 0);
352
if(slots<=0)slots=20;
353
x->x_defaultnumslots=slots;
358
_liststorage_resize(x, x->x_defaultnumslots);
365
void liststorage_setup(void)
367
liststorage_class = class_new(gensym("liststorage"), (t_newmethod)liststorage_new,
368
(t_method)liststorage_free, sizeof(t_liststorage), 0, A_DEFFLOAT, 0);
370
/* recall all lists from the current slot */
371
class_addbang(liststorage_class, (t_method)liststorage_bang);
373
/* add a new list to the current slot */
374
class_addmethod(liststorage_class, (t_method)liststorage_add, gensym("add"), A_GIMME, 0);
375
/* clear the current slot */
376
class_addmethod(liststorage_class, (t_method)liststorage_clear, gensym("clear"), 0);
377
/* clear all slots */
378
class_addmethod(liststorage_class, (t_method)liststorage_clearall, gensym("clearall"), 0);
381
/* add a new list to the current slot */
382
class_addmethod(liststorage_class, (t_method)liststorage_slot, gensym("slot"), A_FLOAT, 0);
385
/* insert an empty slot at (before) given position */
386
class_addmethod(liststorage_class, (t_method)liststorage_insert, gensym("insert"), A_DEFFLOAT, 0);
388
/* remove empty slots */
389
class_addmethod(liststorage_class, (t_method)liststorage_compress, gensym("compress"), 0);
392
/* get the number of slots */
393
class_addmethod(liststorage_class, (t_method)liststorage_info, gensym("info"), 0);
395
zexy_register("liststorage");