[PD-dev] 0.48.0 release status

Miller Puckette msp at ucsd.edu
Fri Jul 21 19:58:56 CEST 2017


OK... for now, I renamed "range" to "get" (did it right away to avoid the
necessity of keeping the other name for compatibility).  We can mess with the
other stuff later.

Not sure about the pointer issues, will just hope that doesn't bite us before
I can look closer at it.

Meanwhile, yeah, I can think of losts of cool things to try (e.g., "sort")

cheers
Miller

On Fri, Jul 21, 2017 at 06:20:49PM +0200, Christof Ressi wrote:
> Thanks for your answer! I guess it doesn't have high priority but anyway, the thing is this:
> 
> I'm really happy about [list store] but I think it can be way more expressive. My idea was to take the interface of [text] and [array] to add more methods. 
> 
> First, I renamed [range( to [get( (but kept the old method around as an alias) because it's structurally very similar to [text get] and [array get].
> 
> Then I added a method [set <f> ...( which lets you overwrite atoms, just like [text set] and [array set]. the first float is the index, followed by the atoms you want to copy.
> 
> Then I added a general [insert <f> ...( method which lets you insert atoms, where the first float is the index, followed by the atoms you want to insert *before* that index. A large index lets you append atoms. I kept [prepend ...( and [append ...( as shortcuts for those two special cases.
> 
> Finally I added a [delete <f> <f>( method where the first float is the index to start deleting and the second float is the number of floats to delete.
> 
> ---
> 
> These methods would turn [list store] into a powerful dynamically sized type-agnostic array - which we don't have in Pd yet! [text] comes closest, but it doesn't handle pointers and it bashes everything to binbufs which sometimes leads to unexpected or undesired behaviour.
> 
> Please find my version of x_list.c(which also includes the bug fix that you've already applied) and a messy test patch attached. I didn't have much time...
> 
> The methods works well with floats and symbols but there are mysterious bugs with pointers. Not only with my new method but also with your [range( method (which I didn't change). For example, sequencing a list of pointers creates 'consistency check failed' errors with [print] and sometimes there are crashes with segmentation faults. 
> 
> Also, I'm wondering if memmove() and realloc() is really safe with arrays of t_listelem because a gpointer atom l_a inside t_listelem points to l_a. when the array changes location in memory, won't the pointer point to the wrong location?
> 
> I know there are more important things to do right now. Just have look when you have time. 
> 
> Thanks!
> 
> Christof
> 
> 
> 
> 
> 
> 
> > Gesendet: Freitag, 21. Juli 2017 um 17:26 Uhr
> > Von: "Miller Puckette" <msp at ucsd.edu>
> > An: "Christof Ressi" <christof.ressi at gmx.at>
> > Cc: "Dan Wilcox" <danomatika at gmail.com>, pd-dev at iem.at
> > Betreff: Re: [PD-dev] 0.48.0 release status
> >
> > Always open to bug reports (although swamped right now I'm afraid, will only
> > get to things that are either urgent or easy :)
> > 
> > I've already fixed "list_store_range" following your earlier report, thanks.
> > 
> > Miller
> > 
> > On Fri, Jul 21, 2017 at 01:05:15PM +0200, Christof Ressi wrote:
> > > I got some more feedback/code for [list store], apart from the list_store_range bug I've already reported on the list. Is there some time left for you guys to review it? I can send it in a couple of hours. I'm travelling right now. 
> > > 
> > > Christof
> > > 
> > > > Gesendet: Freitag, 21. Juli 2017 um 11:54 Uhr
> > > > Von: "Dan Wilcox" <danomatika at gmail.com>
> > > > An: pd-dev at iem.at
> > > > Cc: "Miller Puckette" <msp at ucsd.edu>
> > > > Betreff: [PD-dev] 0.48.0 release status
> > > >
> > > > Ok all, at this point we've nailed most of the bugs and feedback so far. The latest PR is https://github.com/pure-data/pure-data/pull/123 <https://github.com/pure-data/pure-data/pull/123>
> > > > 
> > > > As far as I can tell, the only remaining things which could be done/included for the release are:
> > > > 
> > > > Small Stuff
> > > > 
> > > > * Remove midiin & sysexin Windows warnings in x_midi.c (& update help file)
> > > > 
> > > > (Optional) Big Stuff
> > > > 
> > > > * Adopt DejaVu Sans Mono a the default font -> this is in the dejavu branch https://github.com/pure-data/pure-data/pull/42 <https://github.com/pure-data/pure-data/pull/42>
> > > >   This is mainly for mac & Linux, Windows support will need to be added later as mentioned in the discussion. It also fixes the bad Monaco rendering on
> > > >   retina screens at small font sizes.
> > > > * Update the icon -> see my pd-icon repo https://github.com/pure-data/pd-icon <https://github.com/pure-data/pd-icon> & the recent thread on the pd-list
> > > > 
> > > > There may be more things, but I think I'm done on my end for now. We could do one final test release after this, but hopefully the feedback bugs will all have been fixed.
> > > > 
> > > > --------
> > > > Dan Wilcox
> > > > @danomatika <http://twitter.com/danomatika>
> > > > danomatika.com <http://danomatika.com/>
> > > > robotcowboy.com <http://robotcowboy.com/>
> > > > 
> > > > 
> > > > 
> > > > _______________________________________________
> > > > Pd-dev mailing list
> > > > Pd-dev at lists.iem.at
> > > > https://lists.puredata.info/listinfo/pd-dev
> > > >
> > > 
> > > _______________________________________________
> > > Pd-dev mailing list
> > > Pd-dev at lists.iem.at
> > > https://lists.puredata.info/listinfo/pd-dev
> > 


> /* Copyright (c) 1997- Miller Puckette and others.
> * For information on usage and redistribution, and for a DISCLAIMER OF ALL
> * WARRANTIES, see the file, "LICENSE.txt," in this distribution.  */
> 
> #include "m_pd.h"
> #include <string.h>
> 
> #ifdef _WIN32
> # include <malloc.h> /* MSVC or mingw on windows */
> #elif defined(__linux__) || defined(__APPLE__)
> # include <alloca.h> /* linux, mac, mingw, cygwin */
> #else
> # include <stdlib.h> /* BSDs for example */
> #endif
> 
> #ifndef HAVE_ALLOCA     /* can work without alloca() but we never need it */
> #define HAVE_ALLOCA 1
> #endif
> 
> #define LIST_NGETBYTE 100 /* bigger that this we use alloc, not alloca */
> 
> /* the "list" object family.
> 
>     list append - append a list to another
>     list prepend - prepend a list to another
>     list split - first n elements to first outlet, rest to second outlet
>     list trim - trim off "list" selector
>     list length - output number of items in list
>     list fromsymbol - "explode" a symbol into a list of character codes
> 
> Need to think more about:
>     list foreach - spit out elements of a list one by one (also in reverse?)
>     list reverse - permute elements of a list back to front
>     list cat - build a list by accumulating elements
> 
> Probably don't need:
>     list first - output first n elements.
>     list last - output last n elements
>     list nth - nth item in list, counting from zero
>     list array - get items from a named array as a list
>     list pack - synonym for 'pack'
>     list unpack - synonym for 'unpack'
> */
> 
> /* -------------- utility functions: storage, copying  -------------- */
>     /* List element for storage.  Keep an atom and, in case it's a pointer,
>         an associated 'gpointer' to protect against stale pointers. */
> typedef struct _listelem
> {
>     t_atom l_a;
>     t_gpointer l_p;
> } t_listelem;
> 
> typedef struct _alist
> {
>     t_pd l_pd;          /* object to point inlets to */
>     int l_n;            /* number of items */
>     int l_npointer;     /* number of pointers */
>     t_listelem *l_vec;  /* pointer to items */
> } t_alist;
> 
> #if HAVE_ALLOCA
> #define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)((n) < LIST_NGETBYTE ?  \
>         alloca((n) * sizeof(t_atom)) : getbytes((n) * sizeof(t_atom))))
> #define ATOMS_FREEA(x, n) ( \
>     ((n) < LIST_NGETBYTE || (freebytes((x), (n) * sizeof(t_atom)), 0)))
> #else
> #define ATOMS_ALLOCA(x, n) ((x) = (t_atom *)getbytes((n) * sizeof(t_atom)))
> #define ATOMS_FREEA(x, n) (freebytes((x), (n) * sizeof(t_atom)))
> #endif
> 
> static void atoms_copy(int argc, t_atom *from, t_atom *to)
> {
>     int i;
>     for (i = 0; i < argc; i++)
>         to[i] = from[i];
> }
> 
> /* ------------- fake class to divert inlets to ----------------- */
> 
> t_class *alist_class;
> 
> static void alist_init(t_alist *x)
> {
>     x->l_pd = alist_class;
>     x->l_n = x->l_npointer = 0;
>     x->l_vec = 0;
> }
> 
> static void alist_clear(t_alist *x)
> {
>     int i;
>     for (i = 0; i < x->l_n; i++)
>     {
>         if (x->l_vec[i].l_a.a_type == A_POINTER)
>             gpointer_unset(x->l_vec[i].l_a.a_w.w_gpointer);
>     }
>     if (x->l_vec)
>         freebytes(x->l_vec, x->l_n * sizeof(*x->l_vec));
> }
> 
> static void alist_copyin(t_alist *x, t_symbol *s, int argc, t_atom *argv,
>     int where)
> {
>     int i, j;
>     for (i = 0, j = where; i < argc; i++, j++)
>     {
>         x->l_vec[j].l_a = argv[i];
>         if (x->l_vec[j].l_a.a_type == A_POINTER)
>         {
>             x->l_npointer++;
>             gpointer_copy(x->l_vec[j].l_a.a_w.w_gpointer, &x->l_vec[j].l_p);
>             x->l_vec[j].l_a.a_w.w_gpointer = &x->l_vec[j].l_p;
>         }
>     }
> }
> 
>     /* set contents to a list */
> static void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv)
> {
>     alist_clear(x);
>     if (!(x->l_vec = (t_listelem *)getbytes(argc * sizeof(*x->l_vec))))
>     {
>         x->l_n = 0;
>         error("list: out of memory");
>         return;
>     }
>     x->l_n = argc;
>     x->l_npointer = 0;
>     alist_copyin(x, s, argc, argv, 0);
> }
> 
>     /* set contents to an arbitrary non-list message */
> static void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv)
> {
>     int i;
>     alist_clear(x);
>     if (!(x->l_vec = (t_listelem *)getbytes((argc+1) * sizeof(*x->l_vec))))
>     {
>         x->l_n = 0;
>         error("list_alloc: out of memory");
>         return;
>     }
>     x->l_n = argc+1;
>     x->l_npointer = 0;
>     SETSYMBOL(&x->l_vec[0].l_a, s);
>     for (i = 0; i < argc; i++)
>     {
>         x->l_vec[i+1].l_a = argv[i];
>         if (x->l_vec[i+1].l_a.a_type == A_POINTER)
>         {
>             x->l_npointer++;
>             gpointer_copy(x->l_vec[i+1].l_a.a_w.w_gpointer, &x->l_vec[i+1].l_p);
>             x->l_vec[i+1].l_a.a_w.w_gpointer = &x->l_vec[i+1].l_p;
>         }
>     }
> }
> 
> static void alist_toatoms(t_alist *x, t_atom *to, int onset, int count)
> {
>     int i;
>     for (i = 0; i < count; i++)
>         to[i] = x->l_vec[onset + i].l_a;
> }
> 
> 
> static void alist_clone(t_alist *x, t_alist *y, int onset, int count)
> {
>     int i;
>     y->l_pd = alist_class;
>     y->l_n = count;
>     y->l_npointer = 0;
>     if (!(y->l_vec = (t_listelem *)getbytes(y->l_n * sizeof(*y->l_vec))))
>     {
>         y->l_n = 0;
>         error("list_alloc: out of memory");
>     }
>     else for (i = 0; i < count; i++)
>     {
>         y->l_vec[i].l_a = x->l_vec[onset + i].l_a;
>         if (y->l_vec[i].l_a.a_type == A_POINTER)
>         {
>             gpointer_copy(y->l_vec[i].l_a.a_w.w_gpointer, &y->l_vec[i].l_p);
>             y->l_vec[i].l_a.a_w.w_gpointer = &y->l_vec[i].l_p;
>             y->l_npointer++;
>         }
>     }
> }
> 
> static void alist_setup(void)
> {
>     alist_class = class_new(gensym("list inlet"),
>         0, 0, sizeof(t_alist), 0, 0);
>     class_addlist(alist_class, alist_list);
>     class_addanything(alist_class, alist_anything);
> }
> 
> /* ------------- list append --------------------- */
> 
> t_class *list_append_class;
> 
> typedef struct _list_append
> {
>     t_object x_obj;
>     t_alist x_alist;
> } t_list_append;
> 
> static void *list_append_new(t_symbol *s, int argc, t_atom *argv)
> {
>     t_list_append *x = (t_list_append *)pd_new(list_append_class);
>     alist_init(&x->x_alist);
>     alist_list(&x->x_alist, 0, argc, argv);
>     outlet_new(&x->x_obj, &s_list);
>     inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0);
>     return (x);
> }
> 
> static void list_append_list(t_list_append *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     t_atom *outv;
>     int n, outc = x->x_alist.l_n + argc;
>     ATOMS_ALLOCA(outv, outc);
>     atoms_copy(argc, argv, outv);
>     if (x->x_alist.l_npointer)
>     {
>         t_alist y;
>         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
>         alist_toatoms(&y, outv+argc, 0, x->x_alist.l_n);
>         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
>         alist_clear(&y);
>     }
>     else
>     {
>         alist_toatoms(&x->x_alist, outv+argc, 0, x->x_alist.l_n);
>         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
>     }
>     ATOMS_FREEA(outv, outc);
> }
> 
> static void list_append_anything(t_list_append *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     t_atom *outv;
>     int n, outc = x->x_alist.l_n + argc + 1;
>     ATOMS_ALLOCA(outv, outc);
>     SETSYMBOL(outv, s);
>     atoms_copy(argc, argv, outv + 1);
>     if (x->x_alist.l_npointer)
>     {
>         t_alist y;
>         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
>         alist_toatoms(&y, outv + 1 + argc, 0, x->x_alist.l_n);
>         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
>         alist_clear(&y);
>     }
>     else
>     {
>         alist_toatoms(&x->x_alist, outv + 1 + argc, 0, x->x_alist.l_n);
>         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
>     }
>     ATOMS_FREEA(outv, outc);
> }
> 
> static void list_append_append(t_list_append *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
>         (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
>         (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec))))
>     {
>         x->x_alist.l_n = 0;
>         error("list: out of memory");
>         return;
>     }
>     alist_copyin(&x->x_alist, s, argc, argv, x->x_alist.l_n);
>     x->x_alist.l_n += argc;
> }
> 
> static void list_append_prepend(t_list_append *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
>         (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
>         (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec))))
>     {
>         x->x_alist.l_n = 0;
>         error("list: out of memory");
>         return;
>     }
>     memmove(x->x_alist.l_vec + argc, x->x_alist.l_vec,
>         x->x_alist.l_n * sizeof(*x->x_alist.l_vec));
>     alist_copyin(&x->x_alist, s, argc, argv, 0);
>     x->x_alist.l_n += argc;
> }
> 
> static void list_append_free(t_list_append *x)
> {
>     alist_clear(&x->x_alist);
> }
> 
> static void list_append_setup(void)
> {
>     list_append_class = class_new(gensym("list append"),
>         (t_newmethod)list_append_new, (t_method)list_append_free,
>         sizeof(t_list_append), 0, A_GIMME, 0);
>     class_addlist(list_append_class, list_append_list);
>     class_addanything(list_append_class, list_append_anything);
>     class_sethelpsymbol(list_append_class, &s_list);
> }
> 
> /* ------------- list prepend --------------------- */
> 
> t_class *list_prepend_class;
> 
> typedef t_list_append t_list_prepend;
> 
> static void *list_prepend_new(t_symbol *s, int argc, t_atom *argv)
> {
>     t_list_prepend *x = (t_list_prepend *)pd_new(list_prepend_class);
>     alist_init(&x->x_alist);
>     alist_list(&x->x_alist, 0, argc, argv);
>     outlet_new(&x->x_obj, &s_list);
>     inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0);
>     return (x);
> }
> 
> static void list_prepend_list(t_list_prepend *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     t_atom *outv;
>     int n, outc = x->x_alist.l_n + argc;
>     ATOMS_ALLOCA(outv, outc);
>     atoms_copy(argc, argv, outv + x->x_alist.l_n);
>     if (x->x_alist.l_npointer)
>     {
>         t_alist y;
>         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
>         alist_toatoms(&y, outv, 0, x->x_alist.l_n);
>         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
>         alist_clear(&y);
>     }
>     else
>     {
>         alist_toatoms(&x->x_alist, outv, 0, x->x_alist.l_n);
>         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
>     }
>     ATOMS_FREEA(outv, outc);
> }
> 
> static void list_prepend_anything(t_list_prepend *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     t_atom *outv;
>     int n, outc = x->x_alist.l_n + argc + 1;
>     ATOMS_ALLOCA(outv, outc);
>     SETSYMBOL(outv + x->x_alist.l_n, s);
>     atoms_copy(argc, argv, outv + x->x_alist.l_n + 1);
>     if (x->x_alist.l_npointer)
>     {
>         t_alist y;
>         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
>         alist_toatoms(&y, outv, 0, x->x_alist.l_n);
>         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
>         alist_clear(&y);
>     }
>     else
>     {
>         alist_toatoms(&x->x_alist, outv, 0, x->x_alist.l_n);
>         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
>     }
>     ATOMS_FREEA(outv, outc);
> }
> 
> static void list_prepend_free(t_list_prepend *x)
> {
>     alist_clear(&x->x_alist);
> }
> 
> static void list_prepend_setup(void)
> {
>     list_prepend_class = class_new(gensym("list prepend"),
>         (t_newmethod)list_prepend_new, (t_method)list_prepend_free,
>         sizeof(t_list_prepend), 0, A_GIMME, 0);
>     class_addlist(list_prepend_class, list_prepend_list);
>     class_addanything(list_prepend_class, list_prepend_anything);
>     class_sethelpsymbol(list_prepend_class, &s_list);
> }
> 
> /* ------------- list store --------------------- */
> 
> t_class *list_store_class;
> 
> typedef struct _list_store
> {
>     t_object x_obj;
>     t_alist x_alist;
>     t_outlet *x_out1;
>     t_outlet *x_out2;
> } t_list_store;
> 
> static void *list_store_new(t_symbol *s, int argc, t_atom *argv)
> {
>     t_list_store *x = (t_list_store *)pd_new(list_store_class);
>     alist_init(&x->x_alist);
>     alist_list(&x->x_alist, 0, argc, argv);
>     x->x_out1 = outlet_new(&x->x_obj, &s_list);
>     x->x_out2 = outlet_new(&x->x_obj, &s_bang);
>     inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0);
>     return (x);
> }
> 
> static void list_store_list(t_list_store *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     t_atom *outv;
>     int n, outc = x->x_alist.l_n + argc;
>     ATOMS_ALLOCA(outv, outc);
>     atoms_copy(argc, argv, outv);
>     if (x->x_alist.l_npointer)
>     {
>         t_alist y;
>         alist_clone(&x->x_alist, &y, 0, x->x_alist.l_n);
>         alist_toatoms(&y, outv+argc, 0, x->x_alist.l_n);
>         outlet_list(x->x_out1, &s_list, outc, outv);
>         alist_clear(&y);
>     }
>     else
>     {
>         alist_toatoms(&x->x_alist, outv+argc, 0, x->x_alist.l_n);
>         outlet_list(x->x_out1, &s_list, outc, outv);
>     }
>     ATOMS_FREEA(outv, outc);
> }
> 
> /* insert atoms before a given index */
> static void list_store_doinsert(t_list_store *x, int index, t_symbol *s, 
>     int argc, t_atom *argv)
> {
> 	if (index < 0) index = 0; /* index = 0 -> prepend */
> 	if (index > x->x_alist.l_n) index = x->x_alist.l_n; /* index >= length -> append */
> 	
> 	if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
>         (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
>         (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec))))
>     {
>         x->x_alist.l_n = 0;
>         error("list: out of memory");
>         return;
>     }
> 	/* we don't need memmove for appending */
> 	if (index < x->x_alist.l_n){
>         memmove(x->x_alist.l_vec + index + argc, x->x_alist.l_vec + index, (x->x_alist.l_n - index) * sizeof(*x->x_alist.l_vec));
> 	}
>     alist_copyin(&x->x_alist, s, argc, argv, index);
>     x->x_alist.l_n += argc;
> }	
> 
> static void list_store_insert(t_list_store *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     if (argc < 2) return;
> 	
> 	/* first atom is the index where to start inserting atoms. */
> 	int index = atom_getfloat(argv);
> 	argc--; argv++;
> 	/* insert remaining atoms */
> 	list_store_doinsert(x, index, s, argc, argv);
> }
> 
> static void list_store_append(t_list_store *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     list_store_doinsert(x, 1e+009, s, argc, argv);
> }
> 
> static void list_store_prepend(t_list_store *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
> 	list_store_doinsert(x, 0, s, argc, argv);
> }
> 
> static void list_store_delete(t_list_store *x, float f1, float f2)
> {
>     int index = f1;
> 	int ndelete = f2;
> 	
> 	if (index < 0) index = 0; 
> 	if (index >= x->x_alist.l_n) return; /* out of range: nothing to delete */
> 	
> 	int maxlength = x->x_alist.l_n - index;
> 	if (ndelete > maxlength) ndelete = maxlength;
> 	
> 	/* first unset pointers */
> 	if (x->x_alist.l_npointer)
>     {
> 	    t_listelem *vec = x->x_alist.l_vec;
> 		for (int i = 0; i < ndelete; i++)
>         {
>             if (vec[index + i].l_a.a_type == A_POINTER)
>             {
>         	    gpointer_unset(vec[i].l_a.a_w.w_gpointer);
> 				x->x_alist.l_npointer--;
> 				post("remaining number of pointers: %d", x->x_alist.l_npointer);
> 			}
>         }
> 	}
> 	
> 	/* then move atoms */
>     memmove(x->x_alist.l_vec + index, x->x_alist.l_vec + index + ndelete, 
>         (x->x_alist.l_n - index - ndelete) * sizeof(*x->x_alist.l_vec));
> 	
> 	x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
>         (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
>         (x->x_alist.l_n - ndelete) * sizeof(*x->x_alist.l_vec));
> 	
>     x->x_alist.l_n -= ndelete;
> }
> 
> static void list_store_set(t_list_store *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     if (argc < 2) return;
> 	
> 	/* first atom is the index where to start copying the atoms */
> 	int index = atom_getfloat(argv);
> 	if (index < 0) index = 0;
> 	if (index > x->x_alist.l_n - 1) index = x->x_alist.l_n - 1;
> 	argc--; argv++;
> 	
> 	/* copy remaining atoms */
> 	int maxlength = x->x_alist.l_n - index;
> 	/* for now we truncate. we could also append remaining atoms... */
> 	if (argc > maxlength) argc = maxlength;
> 	
> 	/* first unset pointers */
> 	if (x->x_alist.l_npointer)
>     {
>         t_listelem *vec = x->x_alist.l_vec;
> 		for (int i = 0; i < argc; i++)
>         {
>             if (vec[index + i].l_a.a_type == A_POINTER)
> 			{
> 				gpointer_unset(vec[i+index].l_a.a_w.w_gpointer);
> 				x->x_alist.l_npointer--;
> 			}
>         }			
>     }
> 	/* then copy */
>     alist_copyin(&x->x_alist, s, argc, argv, index);
> }
> 
> static void list_store_get(t_list_store *x, float f1, float f2)
> {
>     t_atom *outv;
>     int onset = f1, outc = f2;
>     if (onset < 0 || outc < 0)
>     {
>         pd_error(x, "list_store_range: negative range (%d %d)", onset, outc);
>         return;
>     }
>     if (onset + outc > x->x_alist.l_n)
>     {
>         outlet_bang(x->x_out2);
>         return;
>     }
>     ATOMS_ALLOCA(outv, outc);
>     if (x->x_alist.l_npointer)
>     {
>         t_alist y;
>         alist_clone(&x->x_alist, &y, onset, outc);
>         alist_toatoms(&y, outv, onset, outc);
>         outlet_list(x->x_out1, &s_list, outc, outv);
>         alist_clear(&y);
>     }
>     else
>     {
>         alist_toatoms(&x->x_alist, outv, onset, outc);
>         outlet_list(x->x_out1, &s_list, outc, outv);
>     }
>     ATOMS_FREEA(outv, outc);
> }
> 
> static void list_store_range(t_list_store *x, float f1, float f2)
> {
>     list_store_get(x, f1, f2);    
> }
> 
> static void list_store_free(t_list_store *x)
> {
>     alist_clear(&x->x_alist);
> }
> 
> static void list_store_setup(void)
> {
>     list_store_class = class_new(gensym("list store"),
>         (t_newmethod)list_store_new, (t_method)list_store_free,
>         sizeof(t_list_store), 0, A_GIMME, 0);
>     class_addlist(list_store_class, list_store_list);
> 	class_addmethod(list_store_class, (t_method)list_store_set,
>         gensym("set"), A_GIMME, 0);
>     class_addmethod(list_store_class, (t_method)list_store_get,
>         gensym("get"), A_FLOAT, A_FLOAT, 0);
> 	class_addmethod(list_store_class, (t_method)list_store_range,
>         gensym("range"), A_FLOAT, A_FLOAT, 0); /* alias for "get" */
> 	class_addmethod(list_store_class, (t_method)list_store_insert,
>         gensym("insert"), A_GIMME, 0);
>     class_addmethod(list_store_class, (t_method)list_store_append,
>         gensym("append"), A_GIMME, 0);
>     class_addmethod(list_store_class, (t_method)list_store_prepend,
>         gensym("prepend"), A_GIMME, 0);
> 	class_addmethod(list_store_class, (t_method)list_store_delete,
>         gensym("delete"), A_FLOAT, A_FLOAT, 0);
> 	
>     class_sethelpsymbol(list_store_class, &s_list);
> }
> 
> /* ------------- list split --------------------- */
> 
> t_class *list_split_class;
> 
> typedef struct _list_split
> {
>     t_object x_obj;
>     t_float x_f;
>     t_outlet *x_out1;
>     t_outlet *x_out2;
>     t_outlet *x_out3;
> } t_list_split;
> 
> static void *list_split_new(t_floatarg f)
> {
>     t_list_split *x = (t_list_split *)pd_new(list_split_class);
>     x->x_out1 = outlet_new(&x->x_obj, &s_list);
>     x->x_out2 = outlet_new(&x->x_obj, &s_list);
>     x->x_out3 = outlet_new(&x->x_obj, &s_list);
>     floatinlet_new(&x->x_obj, &x->x_f);
>     x->x_f = f;
>     return (x);
> }
> 
> static void list_split_list(t_list_split *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     int n = x->x_f;
>     if (n < 0)
>         n = 0;
>     if (argc >= n)
>     {
>         outlet_list(x->x_out2, &s_list, argc-n, argv+n);
>         outlet_list(x->x_out1, &s_list, n, argv);
>     }
>     else outlet_list(x->x_out3, &s_list, argc, argv);
> }
> 
> static void list_split_anything(t_list_split *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     t_atom *outv;
>     ATOMS_ALLOCA(outv, argc+1);
>     SETSYMBOL(outv, s);
>     atoms_copy(argc, argv, outv + 1);
>     list_split_list(x, &s_list, argc+1, outv);
>     ATOMS_FREEA(outv, argc+1);
> }
> 
> static void list_split_setup(void)
> {
>     list_split_class = class_new(gensym("list split"),
>         (t_newmethod)list_split_new, 0,
>         sizeof(t_list_split), 0, A_DEFFLOAT, 0);
>     class_addlist(list_split_class, list_split_list);
>     class_addanything(list_split_class, list_split_anything);
>     class_sethelpsymbol(list_split_class, &s_list);
> }
> 
> /* ------------- list trim --------------------- */
> 
> t_class *list_trim_class;
> 
> typedef struct _list_trim
> {
>     t_object x_obj;
> } t_list_trim;
> 
> static void *list_trim_new( void)
> {
>     t_list_trim *x = (t_list_trim *)pd_new(list_trim_class);
>     outlet_new(&x->x_obj, &s_list);
>     return (x);
> }
> 
> static void list_trim_list(t_list_trim *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     if (argc < 1 || argv[0].a_type != A_SYMBOL)
>         outlet_list(x->x_obj.ob_outlet, &s_list, argc, argv);
>     else outlet_anything(x->x_obj.ob_outlet, argv[0].a_w.w_symbol,
>         argc-1, argv+1);
> }
> 
> static void list_trim_anything(t_list_trim *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     outlet_anything(x->x_obj.ob_outlet, s, argc, argv);
> }
> 
> static void list_trim_setup(void)
> {
>     list_trim_class = class_new(gensym("list trim"),
>         (t_newmethod)list_trim_new, 0,
>         sizeof(t_list_trim), 0, 0);
>     class_addlist(list_trim_class, list_trim_list);
>     class_addanything(list_trim_class, list_trim_anything);
>     class_sethelpsymbol(list_trim_class, &s_list);
> }
> 
> /* ------------- list length --------------------- */
> 
> t_class *list_length_class;
> 
> typedef struct _list_length
> {
>     t_object x_obj;
> } t_list_length;
> 
> static void *list_length_new( void)
> {
>     t_list_length *x = (t_list_length *)pd_new(list_length_class);
>     outlet_new(&x->x_obj, &s_float);
>     return (x);
> }
> 
> static void list_length_list(t_list_length *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     outlet_float(x->x_obj.ob_outlet, (t_float)argc);
> }
> 
> static void list_length_anything(t_list_length *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     outlet_float(x->x_obj.ob_outlet, (t_float)argc+1);
> }
> 
> static void list_length_setup(void)
> {
>     list_length_class = class_new(gensym("list length"),
>         (t_newmethod)list_length_new, 0,
>         sizeof(t_list_length), 0, 0);
>     class_addlist(list_length_class, list_length_list);
>     class_addanything(list_length_class, list_length_anything);
>     class_sethelpsymbol(list_length_class, &s_list);
> }
> 
> /* ------------- list fromsymbol --------------------- */
> 
> t_class *list_fromsymbol_class;
> 
> typedef struct _list_fromsymbol
> {
>     t_object x_obj;
> } t_list_fromsymbol;
> 
> static void *list_fromsymbol_new( void)
> {
>     t_list_fromsymbol *x = (t_list_fromsymbol *)pd_new(list_fromsymbol_class);
>     outlet_new(&x->x_obj, &s_list);
>     return (x);
> }
> 
> static void list_fromsymbol_symbol(t_list_fromsymbol *x, t_symbol *s)
> {
>     t_atom *outv;
>     int n, outc = strlen(s->s_name);
>     ATOMS_ALLOCA(outv, outc);
>     for (n = 0; n < outc; n++)
>         SETFLOAT(outv + n, (unsigned char)s->s_name[n]);
>     outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
>     ATOMS_FREEA(outv, outc);
> }
> 
> static void list_fromsymbol_setup(void)
> {
>     list_fromsymbol_class = class_new(gensym("list fromsymbol"),
>         (t_newmethod)list_fromsymbol_new, 0, sizeof(t_list_fromsymbol), 0, 0);
>     class_addsymbol(list_fromsymbol_class, list_fromsymbol_symbol);
>     class_sethelpsymbol(list_fromsymbol_class, &s_list);
> }
> 
> /* ------------- list tosymbol --------------------- */
> 
> t_class *list_tosymbol_class;
> 
> typedef struct _list_tosymbol
> {
>     t_object x_obj;
> } t_list_tosymbol;
> 
> static void *list_tosymbol_new( void)
> {
>     t_list_tosymbol *x = (t_list_tosymbol *)pd_new(list_tosymbol_class);
>     outlet_new(&x->x_obj, &s_symbol);
>     return (x);
> }
> 
> static void list_tosymbol_list(t_list_tosymbol *x, t_symbol *s,
>     int argc, t_atom *argv)
> {
>     int i;
> #if HAVE_ALLOCA
>     char *str = alloca(argc + 1);
> #else
>     char *str = getbytes(argc + 1);
> #endif
>     for (i = 0; i < argc; i++)
>         str[i] = (char)atom_getfloatarg(i, argc, argv);
>     str[argc] = 0;
>     outlet_symbol(x->x_obj.ob_outlet, gensym(str));
> #if HAVE_ALLOCA
> #else
>     freebytes(str, argc+1);
> #endif
> }
> 
> static void list_tosymbol_setup(void)
> {
>     list_tosymbol_class = class_new(gensym("list tosymbol"),
>         (t_newmethod)list_tosymbol_new, 0, sizeof(t_list_tosymbol), 0, 0);
>     class_addlist(list_tosymbol_class, list_tosymbol_list);
>     class_sethelpsymbol(list_tosymbol_class, &s_list);
> }
> 
> /* ------------- list ------------------- */
> 
> static void *list_new(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
> {
>     if (!argc || argv[0].a_type != A_SYMBOL)
>         pd_this->pd_newest = list_append_new(s, argc, argv);
>     else
>     {
>         t_symbol *s2 = argv[0].a_w.w_symbol;
>         if (s2 == gensym("append"))
>             pd_this->pd_newest = list_append_new(s, argc-1, argv+1);
>         else if (s2 == gensym("prepend"))
>             pd_this->pd_newest = list_prepend_new(s, argc-1, argv+1);
>         else if (s2 == gensym("split"))
>             pd_this->pd_newest =
>                 list_split_new(atom_getfloatarg(1, argc, argv));
>         else if (s2 == gensym("trim"))
>             pd_this->pd_newest = list_trim_new();
>         else if (s2 == gensym("length"))
>             pd_this->pd_newest = list_length_new();
>         else if (s2 == gensym("fromsymbol"))
>             pd_this->pd_newest = list_fromsymbol_new();
>         else if (s2 == gensym("tosymbol"))
>             pd_this->pd_newest = list_tosymbol_new();
>         else if (s2 == gensym("store"))
>             pd_this->pd_newest = list_store_new(s, argc-1, argv+1);
>         else
>         {
>             error("list %s: unknown function", s2->s_name);
>             pd_this->pd_newest = 0;
>         }
>     }
>     return (pd_this->pd_newest);
> }
> 
> void x_list_setup(void)
> {
>     alist_setup();
>     list_append_setup();
>     list_prepend_setup();
>     list_store_setup();
>     list_split_setup();
>     list_trim_setup();
>     list_length_setup();
>     list_fromsymbol_setup();
>     list_tosymbol_setup();
>     class_addcreator((t_newmethod)list_new, &s_list, A_GIMME, 0);
> }

> _______________________________________________
> Pd-dev mailing list
> Pd-dev at lists.iem.at
> https://lists.puredata.info/listinfo/pd-dev




More information about the Pd-dev mailing list