diff --git a/pd/src/s_stuff.h.in b/pd/src/s_stuff.h.in index 0fb85a58a9024504c115fb3d5655f23cad1b2890..5e48f33cec95e009f10a2e67922c3f901c2ae98d 100644 --- a/pd/src/s_stuff.h.in +++ b/pd/src/s_stuff.h.in @@ -440,7 +440,7 @@ EXTERN void alist_init(t_alist *x); EXTERN void alist_clear(t_alist *x); EXTERN void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv); EXTERN void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv); -EXTERN void alist_toatoms(t_alist *x, t_atom *to); -EXTERN void alist_clone(t_alist *x, t_alist *y); +EXTERN void alist_toatoms(t_alist *x, t_atom *to, int onset, int count); +EXTERN void alist_clone(t_alist *x, t_alist *y, int onset, int count); #endif /* __s_stuff_h_ */ diff --git a/pd/src/x_list.c b/pd/src/x_list.c index d43378a2191d50ed063a0ab1d303873aa3e287c8..e03829441cb2800ad4c5df064d248a3a241a426a 100644 --- a/pd/src/x_list.c +++ b/pd/src/x_list.c @@ -79,21 +79,33 @@ void alist_init(t_alist *x) void alist_clear(t_alist *x) { - if (x->l_n) + int i; + for (i = 0; i < x->l_n; i++) { - 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) { - if (x->l_vec[i].l_a.a_type == A_POINTER) - gpointer_unset(x->l_vec[i].l_a.a_w.w_gpointer); + 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; } - if (x->l_vec) - freebytes(x->l_vec, x->l_n * sizeof(*x->l_vec)); } - x->l_n = 0; - x->l_npointer = 0; } + /* set contents to a list */ void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv) { int i; @@ -118,6 +130,7 @@ void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv) } } + /* set contents to an arbitrary non-list message */ void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv) { int i; @@ -143,32 +156,32 @@ void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv) } } -void alist_toatoms(t_alist *x, t_atom *to) +void alist_toatoms(t_alist *x, t_atom *to, int onset, int count) { int i; - for (i = 0; i < x->l_n; i++) - to[i] = x->l_vec[i].l_a; + for (i = 0; i < count; i++) + to[i] = x->l_vec[onset + i].l_a; } - -void alist_clone(t_alist *x, t_alist *y) +void alist_clone(t_alist *x, t_alist *y, int onset, int count) { int i; y->l_pd = alist_class; - y->l_n = x->l_n; - y->l_npointer = x->l_npointer; + 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 < x->l_n; i++) + else for (i = 0; i < count; i++) { - y->l_vec[i].l_a = x->l_vec[i].l_a; + 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++; } } } @@ -205,20 +218,22 @@ static void list_append_list(t_list_append *x, t_symbol *s, int argc, t_atom *argv) { t_atom *outv; - int outc = x->x_alist.l_n + argc; + int n, outc; + n = x->x_alist.l_n; + outc = n + argc; XL_ATOMS_ALLOCA(outv, outc); atoms_copy(argc, argv, outv); if (x->x_alist.l_npointer) { t_alist y; - alist_clone(&x->x_alist, &y); - alist_toatoms(&y, outv+argc); + alist_clone(&x->x_alist, &y, 0, n); + alist_toatoms(&y, outv+argc, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); alist_clear(&y); } else { - alist_toatoms(&x->x_alist, outv+argc); + alist_toatoms(&x->x_alist, outv+argc, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); } XL_ATOMS_FREEA(outv, outc); @@ -228,21 +243,23 @@ static void list_append_anything(t_list_append *x, t_symbol *s, int argc, t_atom *argv) { t_atom *outv; - int outc = x->x_alist.l_n + argc + 1; + int n, outc; + n = x->x_alist.l_n; + outc = n + argc + 1; XL_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); - alist_toatoms(&y, outv + 1 + argc); + alist_clone(&x->x_alist, &y, 0, n); + alist_toatoms(&y, outv + 1 + argc, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); alist_clear(&y); } else { - alist_toatoms(&x->x_alist, outv + 1 + argc); + alist_toatoms(&x->x_alist, outv + 1 + argc, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); } XL_ATOMS_FREEA(outv, outc); @@ -309,20 +326,22 @@ static void list_cat_list(t_list_cat *x, t_symbol *s, int argc, t_atom *argv) { t_atom *outv; - int outc = x->x_alist.l_n + argc; + int n, outc; + n = x->x_alist.l_n; + outc = n + argc; XL_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); - alist_toatoms(&y, outv); + alist_clone(&x->x_alist, &y, 0, n); + alist_toatoms(&y, outv, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); alist_clear(&y); } else { - alist_toatoms(&x->x_alist, outv); + alist_toatoms(&x->x_alist, outv, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); } alist_list(&x->x_alist, s, outc, outv); @@ -333,21 +352,23 @@ static void list_cat_anything(t_list_cat *x, t_symbol *s, int argc, t_atom *argv) { t_atom *outv; - int outc = x->x_alist.l_n + argc + 1; + int n, outc; + n = x->x_alist.l_n; + outc = n + argc + 1; XL_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); - alist_toatoms(&y, outv); + alist_clone(&x->x_alist, &y, 0, n); + alist_toatoms(&y, outv, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); alist_clear(&y); } else { - alist_toatoms(&x->x_alist, outv); + alist_toatoms(&x->x_alist, outv, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); } if (x->x_alist.l_n <= 1) @@ -406,20 +427,22 @@ static void list_prepend_list(t_list_prepend *x, t_symbol *s, int argc, t_atom *argv) { t_atom *outv; - int outc = x->x_alist.l_n + argc; + int n, outc; + n = x->x_alist.l_n; + outc = n + argc; XL_ATOMS_ALLOCA(outv, outc); - atoms_copy(argc, argv, outv + x->x_alist.l_n); + atoms_copy(argc, argv, outv + n); if (x->x_alist.l_npointer) { t_alist y; - alist_clone(&x->x_alist, &y); - alist_toatoms(&y, outv); + alist_clone(&x->x_alist, &y, 0, n); + alist_toatoms(&y, outv, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); alist_clear(&y); } else { - alist_toatoms(&x->x_alist, outv); + alist_toatoms(&x->x_alist, outv, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); } XL_ATOMS_FREEA(outv, outc); @@ -431,21 +454,23 @@ static void list_prepend_anything(t_list_prepend *x, t_symbol *s, int argc, t_atom *argv) { t_atom *outv; - int outc = x->x_alist.l_n + argc + 1; + int n, outc; + n = x->x_alist.l_n; + outc = n + argc + 1; XL_ATOMS_ALLOCA(outv, outc); - SETSYMBOL(outv + x->x_alist.l_n, s); - atoms_copy(argc, argv, outv + x->x_alist.l_n + 1); + SETSYMBOL(outv + n, s); + atoms_copy(argc, argv, outv + n + 1); if (x->x_alist.l_npointer) { t_alist y; - alist_clone(&x->x_alist, &y); - alist_toatoms(&y, outv); + alist_clone(&x->x_alist, &y, 0, n); + alist_toatoms(&y, outv, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); alist_clear(&y); } else { - alist_toatoms(&x->x_alist, outv); + alist_toatoms(&x->x_alist, outv, 0, n); outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv); } XL_ATOMS_FREEA(outv, outc); @@ -468,6 +493,162 @@ static void list_prepend_setup(void) } +/* ------------- 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; + n = x->x_alist.l_n; + outc = 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, n); + alist_toatoms(&y, outv+argc, 0, n); + outlet_list(x->x_out1, &s_list, outc, outv); + alist_clear(&y); + } + else + { + alist_toatoms(&x->x_alist, outv+argc, 0, n); + outlet_list(x->x_out1, &s_list, outc, outv); + } + ATOMS_FREEA(outv, outc); +} + +/* function to restore gpointers after the list has moved in memory */ +static void list_store_restore_gpointers(t_list_store *x, int offset, int count) +{ + t_listelem *vec = x->x_alist.l_vec + offset; + while (count--) + { + if (vec->l_a.a_type == A_POINTER) + vec->l_a.a_w.w_gpointer = &vec->l_p; + vec++; + } +} + +static void list_store_append(t_list_store *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_listelem *oldptr = x->x_alist.l_vec; + + 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; + } + + /* fix gpointers if resizebytes() has moved the alist in memory */ + if (x->x_alist.l_vec != oldptr && x->x_alist.l_npointer) + list_store_restore_gpointers(x, 0, x->x_alist.l_n); + + alist_copyin(&x->x_alist, s, argc, argv, x->x_alist.l_n); + x->x_alist.l_n += argc; +} + +static void list_store_prepend(t_list_store *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)); + + /* we always have to fix gpointers because of memmove() */ + if (x->x_alist.l_npointer) + list_store_restore_gpointers(x, argc, x->x_alist.l_n); + + alist_copyin(&x->x_alist, s, argc, argv, 0); + x->x_alist.l_n += argc; +} + +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_get: 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, 0, 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_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_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_get, + gensym("get"), A_FLOAT, A_FLOAT, 0); + class_sethelpsymbol(list_store_class, &s_list); +} + /* ------------- list split --------------------- */ t_class *list_split_class; @@ -709,6 +890,8 @@ static void *list_new(t_pd *dummy, t_symbol *s, int argc, t_atom *argv) newest = list_fromsymbol_new(); else if (s2 == gensym("tosymbol")) newest = list_tosymbol_new(); + else if (s2 == gensym("store")) + newest = list_store_new(s, argc-1, argv+1); else { error("list %s: unknown function", s2->s_name); @@ -724,6 +907,7 @@ void x_list_setup(void) list_append_setup(); list_cat_setup(); list_prepend_setup(); + list_store_setup(); list_split_setup(); list_trim_setup(); list_length_setup(); diff --git a/pd/src/x_preset.c b/pd/src/x_preset.c index d618696a8942e074c1a94002910bf5ebd3bf4a1f..e4224c43c40cfadfb1550cc6c1a311fcc8bdf41f 100644 --- a/pd/src/x_preset.c +++ b/pd/src/x_preset.c @@ -614,9 +614,9 @@ void preset_node_set_and_output_value(t_preset_node *x, t_alist val) if (val.l_n > 0) { alist_clear(&x->pn_val); - alist_clone(&val, &x->pn_val); + alist_clone(&val, &x->pn_val, 0, val.l_n); XL_ATOMS_ALLOCA(outv, x->pn_val.l_n); - alist_toatoms(&x->pn_val, outv); + alist_toatoms(&x->pn_val, outv, 0, x->pn_val.l_n); outlet_list(x->pn_outlet, &s_list, x->pn_val.l_n, outv); if(PH_DEBUG) { @@ -1199,7 +1199,8 @@ void preset_hub_store(t_preset_hub *h, t_float f) } } alist_clear(&np2->np_val); - alist_clone(&hd1->phd_node->pn_val, &np2->np_val); + alist_clone(&hd1->phd_node->pn_val, &np2->np_val, + 0, hd1->phd_node->pn_val.l_n); if (PH_DEBUG) { fprintf(stderr," node data len = %d, "