forked from fieldtrip/fieldtrip
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathft_getopt.c
126 lines (110 loc) · 3.86 KB
/
ft_getopt.c
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
/*
* MEX file implementation of ft_getopt: this function is called very frequently
* and therefore worthwile to speed up with a compiled version.
*
* Use as
* val = ft_getopt(s, key, default)
* where s is a structure or a cell-array.
*
* It will return the value of the option, or an empty array if the option was
* not present.
*
* The optional fourth argument allows you to specify whether
* or not an empty value in the configuration structure/cell-array should be
* interpreted as meaningful. If emptymeaningful = 1, then an empty
* configuration option will be returned if present. If emptymeaningful = 0,
* then the specified default will be returned if an empty value is
* encountered. The default value for emptymeaningful = 0.
*
* Copyright (C) 2011, Robert Oostenveld
*
*/
#include "mex.h"
#include "compiler.h"
#if defined (COMPILER_LCC)
#include <string.h>
#define strcasecmp strcmpi
#elif defined (COMPILER_MSVC)
#include <string.h>
#define strcasecmp stricmp
#else
#include <strings.h>
#endif
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
int num, i, emptymeaningful;
char *key = NULL, *str = NULL;
mxArray *field = NULL, *defaultval = NULL;
int index;
if (nrhs<2 || nrhs>4)
mexErrMsgTxt("incorrect number of input arguments");
if (!mxIsChar(prhs[1]))
mexErrMsgTxt("the key should be specified as a string");
if (nrhs == 4 && !(mxIsLogical(prhs[3]) || mxIsNumeric(prhs[3]))) {
mexErrMsgTxt("if specified, input argument emptymeaningful should be a logical or numeric value");
}
if (nrhs < 4) {
emptymeaningful = 0;
} else {
emptymeaningful = (int)mxGetScalar(prhs[3]);
}
key = mxArrayToString(prhs[1]);
num = mxGetNumberOfElements(prhs[0]);
/* the default output will be dealt with later */
plhs[0] = NULL;
if (mxIsClass(prhs[0], "config")) {
/* the config object has to be converted to a struct object */
/* this fixes bug 885 */
mexPutVariable("caller", "bcks4i37yr3_cwb", prhs[0]);
mexEvalString("bcks4i37yr3_cwb = struct(bcks4i37yr3_cwb);");
prhs[0] = mexGetVariable("caller", "bcks4i37yr3_cwb");
mexEvalString("clear bcks4i37yr3_cwb;");
}
if (mxIsStruct(prhs[0])) {
/* it will also end up here if the input is an object, in which case this code fails */
if (num!=1)
mexErrMsgTxt("the first input should be a single structure");
field = mxGetField(prhs[0], 0, key);
if (field)
plhs[0] = mxDuplicateArray(field);
}
else if (mxIsCell(prhs[0])) {
if ((num % 2)!=0)
mexErrMsgTxt("the first input should contain key-value pairs");
for (i=0; i<num; i+=2) {
if ((str = mxArrayToString(mxGetCell(prhs[0], i)))==NULL) {
mexErrMsgTxt("the first input should contain key-value pairs");
}
else {
if (strcasecmp(str, key)==0) {
field = mxGetCell(prhs[0], i+1);
if (field)
plhs[0] = mxDuplicateArray(field);
break;
}
}
}
}
else if (mxIsEmpty(prhs[0])) {
/* do nothing, the default value will be assigned below */
}
else {
mexErrMsgTxt("the first input argument should be a cell-array or structure");
}
if (plhs[0]!=NULL && mxIsEmpty(plhs[0]) && !emptymeaningful) {
/* use the default value instead of the empty input that was specified:
this applies for example if you do functionname('key', []), where
the empty is meant to indicate that the user does not know or care
what the value is */
mxDestroyArray(plhs[0]);
plhs[0] = NULL;
}
if (plhs[0]==NULL) {
/* the output value has not yet been assigned */
if (nrhs>=3)
/* return the default value */
plhs[0] = mxDuplicateArray(prhs[2]);
else
/* return an empty array */
plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL);
}
}