~ubuntu-branches/ubuntu/natty/pd-zexy/natty

« back to all changes in this revision

Viewing changes to src/liststorage.c

  • Committer: Bazaar Package Importer
  • Author(s): Jonas Smedegaard, IOhannes m zmölnig, Jonas Smedegaard
  • Date: 2010-08-20 12:17:41 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100820121741-4kxozn8b9rhee9fr
Tags: 2.2.3-1
* New upstream version

[ IOhannes m zmölnig ]
* Adopt package, on behalf of Multimedia Team.
  Closes: #546964
* Simply debian/rules with CDBS, and don't unconditionally strip
  binaries.
  Closes: #437763
* Install into /usr/lib/pd/extra/zexy/. Document usage in REAME.Debian
  and warn about change in NEWS.
* git'ify package. Add Vcs-* stanzas to control file.
* Use dpkg source format 3.0 (quilt). Drop build-dependency on quilt.

[ Jonas Smedegaard ]
* Enable CDBS copyright-check routine.
* Add copyright and licensing header to debian/rules.
* Add myself as uploader.
* Rewrite debian/copyright using rev. 135 of draft DEP5 format.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************
 
2
 *
 
3
 * zexy - implementation file
 
4
 *
 
5
 * copyleft (c) IOhannes m zm�lnig
 
6
 *
 
7
 *   1999:forum::f�r::uml�ute:2004
 
8
 *
 
9
 *   institute of electronic music and acoustics (iem)
 
10
 *
 
11
 ******************************************************
 
12
 *
 
13
 * license: GNU General Public License v.2
 
14
 *
 
15
 ******************************************************/
 
16
 
 
17
 
 
18
/*  
 
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
 
22
*/
 
23
 
 
24
#include "zexy.h"
 
25
 
 
26
#ifdef __WIN32__
 
27
# include <io.h>
 
28
#else
 
29
# include <unistd.h>
 
30
#endif
 
31
 
 
32
#include <stdio.h>
 
33
#include <fcntl.h>
 
34
#include <string.h>
 
35
 
 
36
 
 
37
 
 
38
/* ****************************************************************************** */
 
39
/* liststorage : store several lists in a slots (array of lists of lists) */
 
40
 
 
41
 
 
42
/* a list of lists  */
 
43
typedef struct _msglist {
 
44
  int argc;
 
45
  t_atom *argv;
 
46
  struct _msglist *next;
 
47
} t_msglist;
 
48
 
 
49
typedef struct _liststorage
 
50
{
 
51
  t_object x_obj;              /* everything */
 
52
 
 
53
  t_outlet*x_dataout; /* where the data appears */
 
54
  t_outlet*x_infoout; /* where meta-information appears */
 
55
 
 
56
  t_inlet*x_slotin;   /* setting the current slot */
 
57
 
 
58
  int x_numslots, x_defaultnumslots;
 
59
  int x_currentslot;
 
60
 
 
61
  t_msglist**x_slots;
 
62
} t_liststorage;
 
63
 
 
64
static t_class *liststorage_class;
 
65
 
 
66
 
 
67
/* ************************************************************************ */
 
68
/* helper functions                                                           */
 
69
 
 
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];
 
74
}
 
75
 
 
76
static void _liststorage_deletemsglist(t_msglist*list) {
 
77
  t_msglist*x=list;
 
78
  while(x) {
 
79
    t_msglist*y=x;
 
80
    int i=0;
 
81
    x=x->next;
 
82
 
 
83
    freebytes(y->argv, y->argc*sizeof(t_atom));
 
84
    y->argc=0;
 
85
    y->argv=NULL;
 
86
    y->next=NULL;
 
87
    freebytes(y, sizeof(t_msglist));
 
88
  }
 
89
}
 
90
 
 
91
static void _liststorage_deleteslot(t_liststorage*x, int slot) {
 
92
  t_msglist*list=_liststorage_getslot(x, slot);
 
93
  if(list) {
 
94
    _liststorage_deletemsglist(list);
 
95
    x->x_slots[slot]=NULL;
 
96
  }
 
97
}
 
98
 
 
99
static t_msglist*_liststorage_newslot(int argc, t_atom*argv) {
 
100
  t_msglist*slot=getbytes(sizeof(t_msglist));
 
101
  int i=0;
 
102
 
 
103
  slot->argv=getbytes(sizeof(t_atom)*argc);
 
104
  for(i=0; i<argc; i++) {
 
105
    slot->argv[i]=argv[i];
 
106
  }
 
107
 
 
108
  slot->argc=argc;
 
109
  slot->next=NULL;
 
110
 
 
111
  return slot;
 
112
}
 
113
 
 
114
 
 
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);
 
118
  if(NULL==slot) {
 
119
    //    post("no data yet: new data is %x", newlist);
 
120
    return newlist;
 
121
  }
 
122
 
 
123
  while(dummy->next) {
 
124
    dummy=dummy->next;
 
125
  }
 
126
  dummy->next=newlist;
 
127
  //  post("added data to slot @ %x", slot);
 
128
  return slot;
 
129
}
 
130
 
 
131
 
 
132
static int _liststorage_resize(t_liststorage*x, int size) {
 
133
  t_msglist**newarray=NULL;
 
134
  int i=0;
 
135
 
 
136
  if(size<0) {
 
137
    pd_error(x, "[liststorage]: refusing to resize for negative amount of slots");
 
138
    return 0;
 
139
  }
 
140
 
 
141
  if(size==x->x_numslots) {
 
142
    verbose(1, "[liststorate] no need to resize array");
 
143
    return size;
 
144
  }
 
145
 
 
146
  /* create a new array */
 
147
  newarray=getbytes(sizeof(t_msglist*)*size);
 
148
  for(i=0; i<size; i++) {
 
149
    newarray[i]=NULL;
 
150
  }
 
151
 
 
152
  /* copy over all the data from the old array (if there was one */
 
153
  i=(size<x->x_numslots)?size:x->x_numslots;
 
154
  while(i-->0) {
 
155
    newarray[i]=x->x_slots[i];
 
156
    x->x_slots[i]=NULL;
 
157
  }
 
158
 
 
159
  /* delete the old array */
 
160
  for(i=0; i<x->x_numslots; i++) {
 
161
    _liststorage_deleteslot(x, i);
 
162
  }
 
163
  freebytes(x->x_slots, sizeof(t_msglist*));
 
164
 
 
165
  /* make the new array the current */
 
166
  x->x_slots=newarray;
 
167
  x->x_numslots=size;
 
168
 
 
169
  return size;
 
170
}
 
171
 
 
172
static int _liststorage_checkslot(t_liststorage*x, const char*string, const int resize) {
 
173
  int slot=x->x_currentslot;
 
174
  t_atom atom;
 
175
  SETFLOAT(&atom, (t_float)slot);
 
176
 
 
177
  if(slot<0) { 
 
178
    if(NULL!=string)pd_error(x, "[liststorage]: %s %d", string, slot); 
 
179
    outlet_anything(x->x_infoout, gensym("invalidslot"), 1, &atom);
 
180
    return -1;
 
181
  }
 
182
  if(slot>=x->x_numslots) {
 
183
    if(resize) {
 
184
      _liststorage_resize(x, slot+1);
 
185
    } else {
 
186
      if(NULL!=string)pd_error(x, "[liststorage]: %s %d", string, slot);
 
187
      outlet_anything(x->x_infoout, gensym("invalidslot"), 1, &atom);
 
188
      return -1;
 
189
    }
 
190
  }
 
191
  return slot;
 
192
}
 
193
/* ************************************************************************ */
 
194
/* object methods                                                           */
 
195
 
 
196
  /* recall all lists from the current slot */
 
197
static void liststorage_bang(t_liststorage *x)
 
198
 
199
  t_atom atom;
 
200
  t_msglist*list=NULL;
 
201
 
 
202
  int slot=_liststorage_checkslot(x, "attempting to read data from invalid slot", 0);
 
203
  if(slot<0)return;
 
204
  list=_liststorage_getslot(x, slot);
 
205
 
 
206
  while(list) {
 
207
    outlet_list(x->x_dataout, gensym("list"), list->argc, list->argv);
 
208
    list=list->next;
 
209
  }
 
210
  SETFLOAT(&atom, (t_float)slot);
 
211
 
 
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);
 
214
}
 
215
 
 
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)
 
218
{
 
219
  t_msglist*list=NULL;
 
220
  int slot=_liststorage_checkslot(x, "attempting to add data to invalid slot", 1);
 
221
  if(slot<0)return;
 
222
  list=_liststorage_getslot(x, slot);
 
223
  x->x_slots[slot]=_liststorage_add2slot(x->x_slots[slot], ac, av);
 
224
}
 
225
 
 
226
  /* clear the current slot */
 
227
static void liststorage_clear(t_liststorage *x)
 
228
{
 
229
  int slot=_liststorage_checkslot(x, "attempting to clear invalid slot", 0);
 
230
  if(slot<0)return;
 
231
 
 
232
  _liststorage_deleteslot(x, slot);
 
233
}
 
234
 
 
235
  /* clear all slots */
 
236
static void liststorage_clearall(t_liststorage *x)
 
237
{
 
238
  int i=0;
 
239
  for(i=0; i<x->x_numslots; i++) {
 
240
    _liststorage_deleteslot(x, i);
 
241
  }
 
242
}
 
243
 
 
244
  /* insert an empty slot at (before) given position */
 
245
static void liststorage_insert(t_liststorage *x, t_floatarg f)
 
246
{
 
247
  int current=x->x_currentslot;
 
248
  int slot=-1;
 
249
  int i=0;
 
250
 
 
251
  x->x_currentslot=f;
 
252
  slot=_liststorage_checkslot(x, "attempting to insert invalid slot", 1);
 
253
  x->x_currentslot=current;
 
254
 
 
255
  if(slot<0)return;
 
256
 
 
257
  _liststorage_resize(x, x->x_numslots+1); 
 
258
 
 
259
  for(i=x->x_numslots-1; i>slot; i--) {
 
260
    x->x_slots[i]=x->x_slots[i-1];
 
261
  }
 
262
  x->x_slots[slot]=NULL;  
 
263
}
 
264
 
 
265
  /* get the number of slots */
 
266
static void liststorage_info(t_liststorage *x)
 
267
{
 
268
  t_atom ap;
 
269
  SETFLOAT(&ap, (t_float)x->x_numslots);
 
270
  outlet_anything(x->x_infoout, gensym("numslots"), 1, &ap);
 
271
}
 
272
 
 
273
 
 
274
  /* get the number of slots */
 
275
static void liststorage_slot(t_liststorage *x, t_floatarg f)
 
276
{
 
277
  int slot=f;
 
278
  x->x_currentslot=slot;
 
279
 
 
280
}
 
281
 
 
282
 
 
283
  /* remove empty slots */
 
284
static void liststorage_compress(t_liststorage *x)
 
285
{
 
286
  t_msglist**newarray=NULL;
 
287
  int i=0, j=0;
 
288
  int size=0;
 
289
  for(i=0; i<x->x_numslots; i++) {
 
290
    if(NULL!=x->x_slots[i]) {
 
291
      
 
292
      size++;
 
293
    }
 
294
  }
 
295
 
 
296
  if(size>=x->x_numslots) {
 
297
    //    post("incomressible: %d of %d", size, x->x_numslots);
 
298
    return;
 
299
  }
 
300
 
 
301
  if(size<x->x_defaultnumslots)
 
302
    size=x->x_defaultnumslots;
 
303
 
 
304
  /* create a new array */
 
305
  newarray=getbytes(sizeof(t_msglist*)*size);
 
306
  for(i=0; i<size; i++) {
 
307
    newarray[i]=NULL;
 
308
  }
 
309
 
 
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];
 
314
      j++;
 
315
    }
 
316
    x->x_slots[i]=NULL;
 
317
  }
 
318
 
 
319
  /* delete the old array */
 
320
  for(i=0; i<x->x_numslots; i++) {
 
321
    _liststorage_deleteslot(x, i);
 
322
  }
 
323
  freebytes(x->x_slots, sizeof(t_msglist*));
 
324
 
 
325
  /* make the new array the current */
 
326
  x->x_slots=newarray;
 
327
  x->x_numslots=size;
 
328
}
 
329
 
 
330
 
 
331
/* ************************************************************************ */
 
332
/* constructor/destructor                                                   */
 
333
 
 
334
static void liststorage_free(t_liststorage *x)
 
335
{
 
336
  liststorage_clearall(x);
 
337
  _liststorage_resize(x, 0);
 
338
}
 
339
 
 
340
/* constructor: argument is initial number of slots (can grow) */
 
341
static void *liststorage_new(t_floatarg f)
 
342
{
 
343
  t_liststorage *x = (t_liststorage *)pd_new(liststorage_class);
 
344
  int slots=f;
 
345
 
 
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);
 
349
 
 
350
 
 
351
 
 
352
  if(slots<=0)slots=20;
 
353
  x->x_defaultnumslots=slots;
 
354
  x->x_numslots=0;
 
355
  x->x_currentslot=0;
 
356
  x->x_slots=NULL;
 
357
  
 
358
  _liststorage_resize(x, x->x_defaultnumslots);
 
359
 
 
360
 
 
361
 
 
362
  return (x);
 
363
}
 
364
 
 
365
void liststorage_setup(void)
 
366
{
 
367
  liststorage_class = class_new(gensym("liststorage"), (t_newmethod)liststorage_new,
 
368
                            (t_method)liststorage_free, sizeof(t_liststorage), 0, A_DEFFLOAT, 0);
 
369
 
 
370
  /* recall all lists from the current slot */
 
371
  class_addbang(liststorage_class, (t_method)liststorage_bang);
 
372
 
 
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);
 
379
 
 
380
 
 
381
  /* add a new list to the current slot */
 
382
  class_addmethod(liststorage_class, (t_method)liststorage_slot, gensym("slot"), A_FLOAT, 0);
 
383
 
 
384
 
 
385
  /* insert an empty slot at (before) given position */
 
386
  class_addmethod(liststorage_class, (t_method)liststorage_insert, gensym("insert"), A_DEFFLOAT, 0);
 
387
 
 
388
 /* remove empty slots */
 
389
  class_addmethod(liststorage_class, (t_method)liststorage_compress, gensym("compress"), 0);
 
390
 
 
391
 
 
392
  /* get the number of slots */
 
393
  class_addmethod(liststorage_class, (t_method)liststorage_info, gensym("info"), 0);
 
394
 
 
395
  zexy_register("liststorage");
 
396
}