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
|
/*
flext - C++ layer for Max/MSP and pd (pure data) externals
Copyright (c) 2001-2005 Thomas Grill (gr@grrrr.org)
For information on usage and redistribution, and for a DISCLAIMER OF ALL
WARRANTIES, see the file, "license.txt," in this distribution.
*/
/*! \file flmeth.cpp
\brief Method processing of flext base class.
*/
#include "flext.h"
#include <string.h>
#include <stdarg.h>
#include "flinternal.h"
flext_base::MethItem::MethItem(AttrItem *conn):
Item(conn),index(0),
argc(0),args(NULL)
,fun(NULL)
{}
flext_base::MethItem::~MethItem()
{
if(args) delete[] args;
}
void flext_base::MethItem::SetArgs(methfun _fun,int _argc,metharg *_args)
{
fun = _fun;
if(args) delete[] args;
argc = _argc,args = _args;
}
/*! \brief Add a method to the queue
*/
void flext_base::AddMethod(ItemCont *ma,int inlet,const t_symbol *tag,methfun fun,metharg tp,...)
{
va_list marker;
// at first just count the arg type list (in argc)
int argc = 0;
va_start(marker,tp);
metharg *args = NULL,arg = tp;
for(; arg != a_null; ++argc) arg = (metharg)va_arg(marker,int); //metharg);
va_end(marker);
if(argc > 0) {
if(argc > FLEXT_MAXMETHARGS) {
error("flext - method %s: only %i arguments are type-checkable: use variable argument list for more",tag?GetString(tag):"?",FLEXT_MAXMETHARGS);
argc = FLEXT_MAXMETHARGS;
}
args = new metharg[argc];
va_start(marker,tp);
metharg a = tp;
for(int ix = 0; ix < argc; ++ix) {
#ifdef FLEXT_DEBUG
if(a == a_list && ix > 0) {
ERRINTERNAL();
}
#endif
#if FLEXT_SYS == FLEXT_SYS_PD
if(a == a_pointer && flext_base::compatibility) {
post("Pointer arguments are not allowed in compatibility mode");
}
#endif
args[ix] = a;
a = (metharg)va_arg(marker,int); //metharg);
}
va_end(marker);
}
MethItem *mi = new MethItem;
mi->index = ma->Members();
mi->SetArgs(fun,argc,args);
ma->Add(mi,tag,inlet);
}
void flext_base::ListMethods(AtomList &la,int inlet) const
{
typedef TablePtrMap<int,const t_symbol *,32> MethList;
MethList list[2];
ItemCont *clmethhead = ClMeths(thisClassId());
int i;
for(i = 0; i <= 1; ++i) {
ItemCont *a = i?methhead:clmethhead;
if(a && a->Contained(inlet)) {
ItemSet &ai = a->GetInlet(inlet);
for(ItemSet::iterator as(ai); as; ++as) {
for(Item *al = as.data(); al; al = al->nxt) {
MethItem *aa = (MethItem *)al;
// check it's not related to an attribute
if(!aa->IsAttr()) {
list[i].insert(aa->index,as.key());
break;
}
}
}
}
}
la((int)list[0].size()+(int)list[1].size());
int ix = 0;
for(i = 0; i <= 1; ++i)
for(MethList::iterator it(list[i]); it; ++it)
SetSymbol(la[ix++],it.data());
}
bool flext_base::cb_ListMethods(flext_base *c,int argc,const t_atom *argv)
{
if(c->HasAttributes() && (argc == 0 || (argc == 1 && CanbeInt(argv[0])))) {
// defined in flsupport.cpp
int inlet = argc?GetAInt(argv[0]):0;
AtomListStatic<32> la;
c->ListMethods(la,inlet);
c->ToOutAnything(c->GetOutAttr(),sym_methods,la.Count(),la.Atoms());
return true;
}
else
return false;
}
|