Audio Processing Framework (APF) version 0.5.0
mextools.h
Go to the documentation of this file.
1/******************************************************************************
2 Copyright (c) 2012-2016 Institut für Nachrichtentechnik, Universität Rostock
3 Copyright (c) 2006-2012 Quality & Usability Lab
4 Deutsche Telekom Laboratories, TU Berlin
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 THE SOFTWARE.
23*******************************************************************************/
24
25// https://AudioProcessingFramework.github.io/
26
29
30#ifndef APF_MEXTOOLS_H
31#define APF_MEXTOOLS_H
32
33#include <mex.h>
34#include <string>
35#include <map>
36#include <cmath> // for std::floor()
37#include <vector>
38
39#include "apf/stringtools.h" // for A2S()
40
41#define APF_MEX_ERROR_NO_OUTPUT_SUPPORTED(name) \
42(void)plhs; \
43if (nlhs > 0) { \
44 std::string msg("No output parameters are supported for " \
45 + std::string(name) + "!"); \
46 mexErrMsgTxt(msg.c_str()); }
47
48#define APF_MEX_ERROR_EXACTLY_ONE_OUTPUT(name) \
49(void)plhs; \
50if (nlhs != 1) { \
51 std::string msg("Exactly one output parameter is supported for " \
52 + std::string(name) + "!"); \
53 mexErrMsgTxt(msg.c_str()); }
54
55#define APF_MEX_ERROR_ONE_OPTIONAL_OUTPUT(name) \
56(void)plhs; \
57if (nlhs > 1) { \
58 std::string msg("No more than one output parameter is supported for " \
59 + std::string(name) + "!"); \
60 mexErrMsgTxt(msg.c_str()); }
61
62#define APF_MEX_ERROR_NO_FURTHER_INPUTS(name) \
63(void)prhs; \
64if (nrhs > 0) { \
65 std::string msg("No further input parameters are supported for " \
66 + std::string(name) + "!"); \
67 mexErrMsgTxt(msg.c_str()); }
68
69#define APF_MEX_ERROR_FURTHER_INPUT_NEEDED(text) \
70(void)prhs; \
71if (nrhs < 1) { \
72 std::string msg(std::string(text) + " needs a further input parameter!"); \
73 mexErrMsgTxt(msg.c_str()); }
74
75#define APF_MEX_ERROR_NUMERIC_INPUT(text) \
76(void)prhs; \
77if (!mxIsNumeric(prhs[0])) { \
78 std::string msg(std::string(text) + " must be a numeric matrix!"); \
79 mexErrMsgTxt(msg.c_str()); }
80
81#define APF_MEX_ERROR_REAL_INPUT(text) \
82(void)prhs; \
83APF_MEX_ERROR_NUMERIC_INPUT(text); \
84if (mxIsComplex(prhs[0])) { \
85 std::string msg(std::string(text) + " must not be complex!"); \
86 mexErrMsgTxt(msg.c_str()); }
87
88#define APF_MEX_ERROR_SAME_NUMBER_OF_ROWS(value, text) \
89(void)prhs; \
90if (static_cast<mwSize>(mxGetM(prhs[0])) != (value)) { \
91 std::string msg("Number of rows must be the same " \
92 + std::string(text) + "!"); \
93 mexErrMsgTxt(msg.c_str()); }
94
95#define APF_MEX_ERROR_SAME_NUMBER_OF_COLUMNS(value, text) \
96(void)prhs; \
97if (static_cast<mwSize>(mxGetN(prhs[0])) != (value)) { \
98 std::string msg("Number of columns must be the same " \
99 + std::string(text) + "!"); \
100 mexErrMsgTxt(msg.c_str()); }
101
102namespace apf
103{
105namespace mex
106{
107
108// TODO: check if (and how) user-specified overloads of convert() work
109// TODO: use a traits class, if necessary
110
112bool convert(const mxArray* in, std::string& out)
113{
114 if (!mxIsChar(in)) return false;
115 if (mxGetM(in) != 1 && mxGetN(in) > 0) return false;
116
117 char* temp = mxArrayToString(in);
118 out = temp;
119 mxFree(temp);
120 return true;
121}
122
124bool convert(const mxArray* in, double& out)
125{
126 if (!mxIsDouble(in) || mxIsComplex(in)) return false;
127 if (mxGetNumberOfElements(in) != 1) return false;
128 out = mxGetScalar(in);
129 return true;
130}
131
133bool convert(const mxArray* in, int& out)
134{
135 if (!mxIsDouble(in) || mxIsComplex(in)) return false;
136 if (mxGetNumberOfElements(in) != 1) return false;
137 double temp = mxGetScalar(in);
138 if (temp != std::floor(temp)) return false;
139 out = temp;
140 return true;
141}
142
144bool convert(const mxArray* in, long int& out)
145{
146 if (!mxIsDouble(in) || mxIsComplex(in)) return false;
147 if (mxGetNumberOfElements(in) != 1) return false;
148 double temp = mxGetScalar(in);
149 if (temp != std::floor(temp)) return false;
150 out = temp;
151 return true;
152}
153
155bool convert(const mxArray* in, bool& out)
156{
157 if (mxIsComplex(in) || (!mxIsLogical(in) && !mxIsNumeric(in))) return false;
158 if (mxGetNumberOfElements(in) != 1) return false;
159 out = mxGetScalar(in); // returns only the real part of complex numbers
160 return true;
161}
162
164bool convert(const mxArray* in, size_t& out)
165{
166 if (!mxIsDouble(in) || mxIsComplex(in)) return false;
167 if (mxGetNumberOfElements(in) != 1) return false;
168 double temp = mxGetScalar(in);
169 if (temp < 0 || temp != std::floor(temp)) return false;
170 out = temp;
171 return true;
172}
173
178// TODO: allow wstring?
179bool convert(const mxArray* in, std::map<std::string, std::string>& out)
180{
181 if (!mxIsStruct(in)) return false;
182 if (mxGetNumberOfElements(in) != 1) return false;
183
184 for (int i = 0; i < mxGetNumberOfFields(in); ++i)
185 {
186 auto fieldname = std::string(mxGetFieldNameByNumber(in, i));
187
188 // Second argument: number of element (we expect only one):
189 mxArray* field = mxGetFieldByNumber(in, 0, i);
190
191 double doublevalue;
192 std::string stringvalue;
193
194 // TODO: check for size_t and int?
195
196 if (convert(field, doublevalue))
197 {
198 stringvalue = apf::str::A2S(doublevalue);
199 }
200 else if (convert(field, stringvalue))
201 {
202 // do nothing
203 }
204 else
205 {
206 mexPrintf("Trying to convert '%s' ...\n", fieldname.c_str());
207 mexErrMsgTxt("Value must be a real scalar number or a string!");
208 }
209 out[fieldname] = stringvalue;
210 }
211 return true;
212}
213
217bool convert(const mxArray* in, std::vector<std::string>& out)
218{
219 if (!mxIsCell(in)) return false;
220
221 for (size_t i = 0; i < mxGetNumberOfElements(in); ++i)
222 {
223 mxArray* cell = mxGetCell(in, i);
224 std::string stringvalue;
225
226 if (convert(cell, stringvalue))
227 {
228 out.push_back(stringvalue);
229 }
230 else
231 {
232 mexErrMsgTxt("Element of cell array must be a string!");
233 }
234
235 }
236 return true;
237}
238
239namespace internal
240{
241
242template<bool optional, typename T>
243bool next_arg_helper(int& n, const mxArray**& p, T& data)
244{
245 if (n < 1) return optional;
246 bool result = convert(p[0], data);
247 if (result)
248 {
249 --n; ++p;
250 }
251 return result;
252}
253
254} // namespace internal
255
264template<typename T>
265bool next_arg(int& n, const mxArray**& p, T& data)
266{
267 return internal::next_arg_helper<false>(n, p, data);
268}
269
280template<typename T>
281bool next_optarg(int& n, const mxArray**& p, T& data)
282{
283 return internal::next_arg_helper<true>(n, p, data);
284}
285
289template<typename T>
290void next_arg(int& n, const mxArray**& p, T& data, const std::string& error)
291{
292 if (!next_arg(n, p, data)) mexErrMsgTxt(error.c_str());
293}
294
298template<typename T>
299void next_optarg(int& n, const mxArray**& p, T& data, const std::string& error)
300{
301 if (!next_optarg(n, p, data)) mexErrMsgTxt(error.c_str());
302}
303
304} // namespace mex
305} // namespace apf
306
307#endif
bool next_arg(int &n, const mxArray **&p, T &data)
Get next argument, converted to T.
Definition: mextools.h:265
bool convert(const mxArray *in, std::string &out)
Convert mxArray to std::string.
Definition: mextools.h:112
bool next_optarg(int &n, const mxArray **&p, T &data)
Get next optional argument, converted to T.
Definition: mextools.h:281
std::string A2S(const T &input)
Converter "Anything to String".
Definition: stringtools.h:52
Audio Processing Framework.
Definition: iterator.h:61
Helper functions for string conversion.