From faada59567f8cb252f4a909116595ce309ff5828 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Fri, 23 May 2003 12:29:55 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r647, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/miXed/; revision=648 --- cyclone/hammer/substitute.c | 340 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 340 insertions(+) create mode 100644 cyclone/hammer/substitute.c (limited to 'cyclone/hammer/substitute.c') diff --git a/cyclone/hammer/substitute.c b/cyclone/hammer/substitute.c new file mode 100644 index 0000000..48a9b9d --- /dev/null +++ b/cyclone/hammer/substitute.c @@ -0,0 +1,340 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include +#include "m_pd.h" +#include "common/grow.h" + +#define SUBSTITUTE_INISIZE 32 /* LATER rethink */ +#define SUBSTITUTE_MAXSIZE 256 + +typedef struct _substitute +{ + t_object x_ob; + t_pd *x_proxy; + t_atom x_match; + t_atom x_repl; + int x_size; /* as allocated */ + t_atom *x_message; + t_atom x_messini[SUBSTITUTE_INISIZE]; + int x_entered; + t_atom x_auxmatch; + t_atom x_auxrepl; + t_outlet *x_passout; +} t_substitute; + +typedef struct _substitute_proxy +{ + t_object p_ob; + t_atom *p_match; /* pointing to parent's (aux)match */ + t_atom *p_repl; +} t_substitute_proxy; + +static t_class *substitute_class; +static t_class *substitute_proxy_class; + +/* LATER rethink */ +static void substitute_dooutput(t_substitute *x, + t_symbol *s, int ac, t_atom *av, int pass) +{ + t_outlet *out = (pass ? x->x_passout : ((t_object *)x)->ob_outlet); + if (s == &s_float) + { + if (ac > 1) + outlet_list(out, &s_list, ac, av); + else + outlet_float(out, av->a_w.w_float); + } + else if (s == &s_bang && !ac) /* CHECKED */ + outlet_bang(out); + else if (s == &s_symbol && ac == 1 && av->a_type == A_SYMBOL) + outlet_symbol(out, av->a_w.w_symbol); + else if (s) + outlet_anything(out, s, ac, av); + else if (ac) + outlet_list(out, &s_list, ac, av); +} + +static int substitute_check(t_substitute *x, t_symbol *s, int ac, t_atom *av) +{ + if (x->x_repl.a_type == A_NULL) + return (-2); + /* see substitute_proxy_validate() for possible types and values */ + if (x->x_match.a_type == A_FLOAT) + { + t_float f = x->x_match.a_w.w_float; + int i; + for (i = 0; i < ac; i++, av++) + if (av->a_type == A_FLOAT && av->a_w.w_float == f) + return (i); + } + else if (x->x_match.a_type == A_SYMBOL) + { + /* match symbol is validated -- never null */ + t_symbol *match = x->x_match.a_w.w_symbol; + int i; + if (s == match) + return (-1); + for (i = 0; i < ac; i++, av++) + if (av->a_type == A_SYMBOL && av->a_w.w_symbol == match) + return (i); + } + return (-2); +} + +static void substitute_doit(t_substitute *x, + t_symbol *s, int ac, t_atom *av, int startndx) +{ + int cnt = ac - startndx; + if (cnt > 0) + { + t_atom *ap = av + startndx; + if (x->x_match.a_type == A_FLOAT) + { + t_float f = x->x_match.a_w.w_float; + while (cnt--) + { + if (ap->a_type == A_FLOAT && ap->a_w.w_float == f) + *ap = x->x_repl; + ap++; + } + } + else if (x->x_match.a_type == A_SYMBOL) + { + t_symbol *match = x->x_match.a_w.w_symbol; + while (cnt--) + { + if (ap->a_type == A_SYMBOL && ap->a_w.w_symbol == match) + *ap = x->x_repl; + ap++; + } + } + } + substitute_dooutput(x, s, ac, av, 0); +} + +static void substitute_anything(t_substitute *x, + t_symbol *s, int ac, t_atom *av) +{ + int matchndx = substitute_check(x, s, ac, av); + if (matchndx < -1) + substitute_dooutput(x, s, ac, av, 1); + else + { + int reentered = x->x_entered; + int prealloc = !reentered; + int ntotal = ac; + t_atom *buf; + t_substitute_proxy *proxy = (t_substitute_proxy *)x->x_proxy; + x->x_entered = 1; + proxy->p_match = &x->x_auxmatch; + proxy->p_repl = &x->x_auxrepl; + if (s == &s_) s = 0; + if (matchndx == -1) + { + if (x->x_repl.a_type == A_FLOAT) + { + ntotal++; + if (ac) s = &s_list; + else s = &s_float; + } + else if (x->x_repl.a_type == A_SYMBOL) + { + s = x->x_repl.a_w.w_symbol; + matchndx = 0; + } + } + else if (matchndx == 0 + && (!s || s == &s_list || s == &s_float) + && av->a_type == A_FLOAT + && x->x_repl.a_type == A_SYMBOL) + { + s = x->x_repl.a_w.w_symbol; + ac--; + av++; + ntotal = ac; + } + if (prealloc && ac > x->x_size) + { + if (ntotal > SUBSTITUTE_MAXSIZE) + prealloc = 0; + else + x->x_message = grow_nodata(&ntotal, &x->x_size, x->x_message, + SUBSTITUTE_INISIZE, x->x_messini, + sizeof(*x->x_message)); + } + if (prealloc) buf = x->x_message; + else + /* LATER consider using the stack if ntotal <= MAXSTACK */ + buf = getbytes(ntotal * sizeof(*buf)); + if (buf) + { + int ncopy = ntotal; + t_atom *bp = buf; + if (matchndx == -1) + { + SETFLOAT(bp++, x->x_repl.a_w.w_float); + ncopy--; + } + if (ncopy) + memcpy(bp, av, ncopy * sizeof(*buf)); + substitute_doit(x, s, ntotal, buf, matchndx); + if (buf != x->x_message) + freebytes(buf, ntotal * sizeof(*buf)); + } + if (!reentered) + { + x->x_entered = 0; + if (x->x_auxmatch.a_type != A_NULL) + { + x->x_match = x->x_auxmatch; + x->x_auxmatch.a_type = A_NULL; + } + if (x->x_auxrepl.a_type != A_NULL) + { + x->x_repl = x->x_auxrepl; + x->x_auxrepl.a_type = A_NULL; + } + proxy->p_match = &x->x_match; + proxy->p_repl = &x->x_repl; + } + } +} + +static void substitute_bang(t_substitute *x) +{ + substitute_anything(x, &s_bang, 0, 0); +} + +static void substitute_float(t_substitute *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + substitute_anything(x, 0, 1, &at); +} + +/* CHECKED (but LATER rethink) */ +static void substitute_symbol(t_substitute *x, t_symbol *s) +{ + t_atom at; + SETSYMBOL(&at, s); + substitute_anything(x, &s_symbol, 1, &at); +} + +/* LATER gpointer */ + +static void substitute_list(t_substitute *x, t_symbol *s, int ac, t_atom *av) +{ + substitute_anything(x, 0, ac, av); +} + +static int substitute_atomvalidate(t_atom *ap) +{ + return (ap->a_type == A_FLOAT + || (ap->a_type == A_SYMBOL + && ap->a_w.w_symbol && ap->a_w.w_symbol != &s_)); +} + +/* CHECKED: 'set' is ignored, single '' does not modify a replacement */ +static void substitute_proxy_anything(t_substitute_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + if (s == &s_) s = 0; + if (s) + { + SETSYMBOL(x->p_match, s); + if (ac && substitute_atomvalidate(av)) + *x->p_repl = *av; + } + else if (ac && substitute_atomvalidate(av)) + { + *x->p_match = *av++; + if (ac > 1 && substitute_atomvalidate(av)) + *x->p_repl = *av; + } +} + +static void substitute_proxy_bang(t_substitute_proxy *x) +{ + SETSYMBOL(x->p_match, &s_bang); +} + +static void substitute_proxy_float(t_substitute_proxy *x, t_float f) +{ + SETFLOAT(x->p_match, f); +} + +/* CHECKED (but LATER rethink) */ +static void substitute_proxy_symbol(t_substitute_proxy *x, t_symbol *s) +{ + SETSYMBOL(x->p_match, &s_symbol); + SETSYMBOL(x->p_repl, s); +} + +/* LATER gpointer */ + +static void substitute_proxy_list(t_substitute_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + substitute_proxy_anything(x, 0, ac, av); +} + +static void substitute_free(t_substitute *x) +{ + if (x->x_proxy) pd_free(x->x_proxy); + if (x->x_message != x->x_messini) + freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); +} + +static void *substitute_new(t_symbol *s, int ac, t_atom *av) +{ + t_substitute *x = 0; + t_substitute_proxy *proxy = + (t_substitute_proxy *)pd_new(substitute_proxy_class); + if (proxy) + { + x = (t_substitute *)pd_new(substitute_class); + proxy->p_match = &x->x_match; + proxy->p_repl = &x->x_repl; + x->x_proxy = (t_pd *)proxy; + x->x_size = SUBSTITUTE_INISIZE; + x->x_message = x->x_messini; + x->x_entered = 0; + /* CHECKED: everything is to be passed unchanged, until both are set */ + /* CHECKED: max crashes if a match has been set, but not a replacement, + and there is a match */ + x->x_match.a_type = x->x_repl.a_type = A_NULL; + x->x_auxmatch.a_type = x->x_auxrepl.a_type = A_NULL; + inlet_new((t_object *)x, (t_pd *)proxy, 0, 0); + outlet_new((t_object *)x, &s_anything); + /* CHECKED (refman error: 'a bang is sent') */ + x->x_passout = outlet_new((t_object *)x, &s_anything); + substitute_proxy_anything(proxy, 0, ac, av); + } + return (x); +} + +void substitute_setup(void) +{ + substitute_class = class_new(gensym("substitute"), + (t_newmethod)substitute_new, + (t_method)substitute_free, + sizeof(t_substitute), 0, + A_GIMME, 0); + class_addbang(substitute_class, substitute_bang); + class_addfloat(substitute_class, substitute_float); + class_addsymbol(substitute_class, substitute_symbol); + class_addlist(substitute_class, substitute_list); + class_addanything(substitute_class, substitute_anything); + substitute_proxy_class = class_new(gensym("_substitute_proxy"), 0, 0, + sizeof(t_substitute_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(substitute_proxy_class, substitute_proxy_bang); + class_addfloat(substitute_proxy_class, substitute_proxy_float); + class_addsymbol(substitute_proxy_class, substitute_proxy_symbol); + class_addlist(substitute_proxy_class, substitute_proxy_list); + class_addanything(substitute_proxy_class, substitute_proxy_anything); + class_addmethod(substitute_proxy_class, (t_method)substitute_proxy_list, + gensym("set"), A_GIMME, 0); +} -- cgit v1.2.1