aboutsummaryrefslogtreecommitdiff
path: root/tabfind/tabfind.c
blob: e6dbd22595f78725e1c36b143a21946964af8d99 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/* ---------- tabfind: return the index of the input (float or list of floats)in the given table */
/* based on tabread in d_array.c */
/* Started 20081120 by Martin Peach (mrpeach) */

#include "m_pd.h"

#if (PD_MINOR_VERSION > 40)
#define USE_GETFLOATWORDS *//* if garray_getfloatwords is implemented */
#endif
/* garray_getfloatwords uses t_word but doesn't exist in some versions of pd */
/* garray_getfloatarray uses t_float but is not 64-bit */

static t_class *tabfind_class;

typedef struct _tabfind
{
    t_object    x_obj;
    t_symbol    *x_arrayname;
    t_int       x_nth; /* which match to find */
} t_tabfind;

static void tabfind_float(t_tabfind *x, t_float f);
static void tabfind_list(t_tabfind *x, t_symbol *s, int argc, t_atom *argv);
static void tabfind_nth(t_tabfind *x, t_float nth);
static void tabfind_set(t_tabfind *x, t_symbol *s);
static void *tabfind_new(t_symbol *s);
void tabfind_setup(void);

static void tabfind_nth(t_tabfind *x, t_float fnth)
{
/* set to find the nth instance of the key */
    int inth;
    if (fnth >= 1) inth = (int)fnth;
    else
    {
        inth = 1;
        pd_error(x, "tabfind: nth must be at least 1");
    }
    x->x_nth = inth;
}

static void tabfind_list(t_tabfind *x, t_symbol *s, int argc, t_atom *argv)
{
    /* find the nth occurrence of the list of floats argv in the array */
    t_garray    *a;
    int         npoints;
#ifdef USE_GETFLOATWORDS
    t_word      *vec;
#else
    t_float     *vec;
#endif
    int         n, count = 0;
    int         i, j;

    /* first check the list for floatness... */
    for (i = 0; i < argc; ++i)
    {
        if (argv[i].a_type != A_FLOAT)
        {
            pd_error(x, "tabfind: list must be all floats");
            return;
        }
    }

    /* then find the array again... */
    if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
        pd_error(x, "tabfind: %s: no such array", x->x_arrayname->s_name);
#ifdef USE_GETFLOATWORDS
    else if (!garray_getfloatwords(a, &npoints, &vec))
#else
    else if (!garray_getfloatarray(a, &npoints, &vec))
#endif
        pd_error(x, "tabfind: %s: bad template for tabread", x->x_arrayname->s_name);
    else
    /* try to find the nth instance of the list in a and output its index */
    {
        for (n = 0; n < npoints; ++n)
        {
            for (i = 0; ((i < argc) && ((n+i) < npoints)); ++i)
#ifdef USE_GETFLOATWORDS
                if (vec[n+i].w_float != argv[i].a_w.w_float) break;
#else
                if (vec[n+i] != argv[i].a_w.w_float) break;
#endif
            if ((i == argc) && (x->x_nth == ++count)) break;
        }
        outlet_float(x->x_obj.ob_outlet, n);
    }
}

static void tabfind_float(t_tabfind *x, t_float f)
{
    /* find the nth occurrence of the float f in the array */
    t_garray    *a;
    int         npoints;
#ifdef USE_GETFLOATWORDS
    t_word      *vec;
#else
    t_float     *vec;
#endif
    int         n, count = 0;

    if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
        pd_error(x, "tabfind: %s: no such array", x->x_arrayname->s_name);
#ifdef USE_GETFLOATWORDS
    else if (!garray_getfloatwords(a, &npoints, &vec))
#else
    else if (!garray_getfloatarray(a, &npoints, &vec))
#endif
        pd_error(x, "tabfind: %s: bad template for tabread", x->x_arrayname->s_name);
    else
    /* find the nth instance of f in a and output its index */
    {
        for (n = 0; n < npoints; ++n)
        {
#ifdef USE_GETFLOATWORDS
            if (vec[n].w_float == f)
#else
            if (vec[n] == f)
#endif
                if (x->x_nth == ++count) break;
        }
        outlet_float(x->x_obj.ob_outlet, n);
    }
}

static void tabfind_set(t_tabfind *x, t_symbol *s)
{
    /* set the name of the array we're working on */
    x->x_arrayname = s;
}

static void *tabfind_new(t_symbol *s)
{
    t_tabfind *x = (t_tabfind *)pd_new(tabfind_class);
    x->x_arrayname = s;
    outlet_new(&x->x_obj, &s_float);
    x->x_nth = 1;
    return (x);
}

void tabfind_setup(void)
{
    tabfind_class = class_new(gensym("tabfind"), (t_newmethod)tabfind_new,
        0, sizeof(t_tabfind), 0, A_DEFSYM, 0);
    class_addfloat(tabfind_class, (t_method)tabfind_float);
    class_addlist(tabfind_class, (t_method)tabfind_list); 
    class_addmethod(tabfind_class, (t_method)tabfind_nth, gensym("nth"), A_FLOAT, 0);
    class_addmethod(tabfind_class, (t_method)tabfind_set, gensym("set"), A_SYMBOL, 0);
}