aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/flext/source/flmeth.cpp
blob: 3b40cd1abbdf0be0113e705cb051cf2c8abe335d (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
/* 

flext - C++ layer for Max/MSP and pd (pure data) externals

Copyright (c) 2001-2003 Thomas Grill (xovo@gmx.net)
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>

flext_base::methitem::methitem(int in,const t_symbol *tg,attritem *conn): 
	item(tg,in,conn),
	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;
}

/*
void flext_base::AddMethItem(methitem *m)
{
	int ix = m->Hash();
	post("method index %x",ix);
	methitem *&mix = methhead[ix];

	if(mix) {
		methitem *mi;
		for(mi = mix; mi->nxt; mi = mi->nxt) {}
		mi->nxt = m;
	}
	else 
		mix = m;
}
*/
/*
const flext_base::methitem *flext_base::FindMethItem(int inlet,const t_symbol *tag,const methitem *st)
{
	const methitem *mi = st?st:mlst;
	if(inlet < 0) {
		for(; mi; mi = mi->nxt) 
			if(mi->tag == tag) break;
	}
	else {
		for(; mi; mi = mi->nxt) 
			if(mi->inlet == inlet && mi->tag == tag) break;
	}
	return mi;
}
*/

void flext_base::AddMethodDef(int inlet,const char *tag)
{
	methhead->Add(new methitem(inlet,tag?MakeSymbol(tag):NULL));
}

/*! \brief Add a method to the queue
*/
void flext_base::AddMethod(itemarr *ma,int inlet,const char *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?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(inlet,MakeSymbol(tag));

	mi->SetArgs(fun,argc,args);

	ma->Add(mi);
}