root/library/bdm/mex/mex_parser.h @ 933

Revision 933, 9.2 kB (checked in by smidl, 14 years ago)

bdmtoolbox updated for new loggers

  • Property svn:eol-style set to native
Line 
1#ifndef MXPARSE_H
2#define MXPARSE_H
3
4
5#include "base/libconfig/lib/libconfig.h++"
6#include <itpp/itbase.h>
7#include <itpp/itmex.h>
8#include <stdlib.h>
9
10
11using namespace itpp;
12using namespace std;
13using namespace libconfig;
14
15//! Class for writing Settings into Matlab's mxArray
16class UImxArray : public Config {
17public:
18        //! Build an instance of Config with fields filled from the given \a mxarray
19        UImxArray ( const mxArray *mxarray ) : Config() {
20                Setting & setting = this->getRoot(); //setting is a group
21                if ( !mxIsStruct ( mxarray ) ) {
22                        mexErrMsgTxt ( "Given mxArray is not a struct." );
23                };
24
25                //mexCallMATLAB(0, NULL, 1, (mxArray **) &mxarray, "dump");
26                fillGroup ( setting, mxarray );
27                setAutoConvert ( true );
28        }
29        UImxArray() : Config() {
30                setAutoConvert ( true );
31        }
32        //! Add libconfig's \c list to the structure
33        void addList ( const mxArray *mxarray, const char* name ) {
34                Setting & setting = this->getRoot(); //setting is a group
35                Setting & child = setting.add ( name, Setting::TypeList );
36                fillList ( child, mxarray );
37        }
38        //! Add libconfig's \c group to the structure
39        void addGroup ( const mxArray *mxarray, const char* name ) {
40                Setting & setting = this->getRoot(); //setting is a group
41                Setting & child = setting.add ( name, Setting::TypeGroup );
42                fillGroup ( child, mxarray );
43        }
44        //! Operator for more convenient access to this Config
45        operator Setting&() {
46                return getRoot();
47        }
48
49private:
50        void storeNumeric ( Setting &setting, const mxArray *value, string key = "" ) {
51                //TODO: integer matrices
52                if ( !mxIsNumeric ( value ) ) {
53                        mexErrMsgTxt ( "Given mxArray is not numeric." );
54                };
55                //treat empty matrices independently
56                mat val;
57                if ( mxGetM ( value ) > 0 && mxGetN(value)>0) {
58                        val = mxArray2mat ( value );
59                }
60                if ( ( val.rows() == 1 ) && ( val.cols() == 1 ) ) {
61                        Setting &child = ( key == "" ) ? setting.add ( Setting::TypeFloat )
62                                         : setting.add ( key, Setting::TypeFloat );
63                        child = val ( 0, 0 );
64                } else {
65                        Setting &child = ( key == "" ) ? setting.add ( Setting::TypeList )
66                                         : setting.add ( key, Setting::TypeList );
67                        Setting &label = child.add ( Setting::TypeString );
68                        label = "matrix";
69                        Setting &rows = child.add ( Setting::TypeInt );
70                        Setting &cols = child.add ( Setting::TypeInt );
71                        Setting &elements = child.add ( Setting::TypeArray );
72                        cols = val.cols();
73                        rows = val.rows();
74                        for ( int i = 0; i < val.rows(); i++ ) {
75                                for ( int j = 0; j < val.cols(); j++ ) {
76                                        Setting &el = elements.add ( Setting::TypeFloat );
77                                        el = val ( i, j );
78                                }
79                        }
80                }
81        }
82
83        void fillGroup ( Setting &setting, const mxArray *mxarray ) {
84                if ( !mxIsStruct ( mxarray ) ) {
85                        mexErrMsgTxt ( "Given mxArray is not a struct." );
86                };
87                for ( int i = 0; i < mxGetNumberOfFields ( mxarray ); i++ ) {
88                        const char *key = mxGetFieldNameByNumber ( mxarray, i );
89                        mxArray *value = mxGetField ( mxarray, 0, key );
90                        if ( mxIsChar ( value ) ) {
91                                Setting &child = setting.add ( key, Setting::TypeString );
92                                child = mxArray2string ( value );
93                                } else {
94                        if ( mxIsLogical ( value ) ) {
95                                Setting &child = setting.add ( key, Setting::TypeBoolean );
96                                child = ( bool ) mxArray2bin ( value );
97                        } else {
98                        if ( mxIsStruct ( value ) ) {
99                                Setting &child = setting.add ( key, Setting::TypeGroup );
100                                fillGroup ( child, value );
101                        } else {
102                        if ( mxIsCell ( value ) ) {
103                                Setting &child = setting.add ( key, Setting::TypeList );
104                                fillList ( child, value );
105                        } else {
106                        if ( mxIsNumeric ( value ) ) {
107                                storeNumeric ( setting, value, ( string ) key );
108                        } else {
109                        // it is neither of above - treat it as an address
110                        // if (mxIsObject(value)){ <== should be tested but it is broken in matlab...
111                       
112                                Setting &child = setting.add(key, Setting::TypeInt64);
113                                child = (long)value;
114                        }
115                        }
116                        }
117                        }
118                                }
119                }
120        }
121
122        void fillList ( Setting &setting, const mxArray *mxarray ) {
123                if ( !mxIsCell ( mxarray ) ) {
124                        mexErrMsgTxt ( "Given mxArray is not a cell." );
125                };
126                for ( unsigned int i = 0; i < ( unsigned int ) mxGetNumberOfElements ( mxarray ); i++ ) {
127                        mxArray *value = mxGetCell ( mxarray, i );
128                        if ( mxIsChar ( value ) ) {
129                                Setting &child = setting.add ( Setting::TypeString );
130                                child = mxArray2string ( value );
131                        }
132                        if ( mxIsLogical ( value ) ) {
133                                Setting &child = setting.add ( Setting::TypeBoolean );
134                                child = ( bool ) mxArray2bin ( value );
135                        }
136                        if ( mxIsStruct ( value ) ) {
137                                Setting &child = setting.add ( Setting::TypeGroup );
138                                fillGroup ( child, value );
139                        }
140                        if ( mxIsCell ( value ) ) {
141                                Setting &child = setting.add ( Setting::TypeList );
142                                fillList ( child, value );
143                        }
144                        if ( mxIsNumeric ( value ) ) {
145                                storeNumeric ( setting, value );
146                        }
147                }
148        }
149
150public:
151        //! Convert existing Setting to Matlab arrays
152        static mxArray * create_mxArray( const Setting &setting )
153        {
154                return group2mxstruct ( setting );
155        }
156
157        //! Convert existing Setting to Matlab arrays
158        mxArray * create_mxArray(  )
159        {
160                return group2mxstruct ( *this );
161        }
162
163private:
164        //! Convert libconfig's array to Matlab vector
165        static mxArray* array2mxvector ( const Setting &setting )  {
166                if ( !setting.isArray() ) mexErrMsgTxt ( "Given setting is not an array" );
167                mxArray *result = mxCreateDoubleMatrix ( 1, setting.getLength(), mxREAL );
168                double *elements = mxGetPr ( result );
169                for ( int i = 0; i < setting.getLength(); i++ ) {
170                        if ( setting.getType() == Setting::TypeInt ) { //TODO: tady je chyba -- zaporna cisla nejsou TypeInt
171                                elements[i] = ( int ) setting[i];
172                        } else {
173                                elements[i] =  setting[i];
174                        }
175                }
176                return result;
177        }
178
179        //! Convert libconfig's array to Matlab matrix
180        static mxArray* list2mxmatrix ( const Setting &setting )  {
181                if ( !setting.isList() || ( strcmp ( "matrix", setting[0] ) != 0 ) )
182                        mexErrMsgTxt ( "Given setting is not a matrix" );
183                int rows = setting[1];
184                int cols = setting[2];
185                if ( setting[3].getLength() != rows*cols )
186                        mexErrMsgTxt ( "Matrix elements do not fit to rows*cols" );
187                double *elements = new double[rows*cols];
188                for ( int i = 0; i < rows*cols; i++ ) {
189                        elements[i] = setting[3][i];
190                }
191                mat &m = * ( new mat ( elements, rows, cols ) );
192                mxArray *result = mxCreateDoubleMatrix ( rows, cols, mxREAL );
193                mat2mxArray ( m, result );
194                delete &m;
195                delete [] elements;
196                return result;
197        }
198
199        //! Convert libconfig's gourp to Matlab structure
200        static mxArray* group2mxstruct ( const Setting &setting ) {
201                if ( !setting.isGroup() ) mexErrMsgTxt ( "Given setting is not a group." );
202                const char ** keys = new const char*[setting.getLength() ];
203                for ( int i = 0; i < setting.getLength(); i++ ) {
204                        keys[i] = setting[i].getName();
205                }
206                mxArray *result = mxCreateStructMatrix ( 1, 1, setting.getLength(), keys );
207                delete keys;
208                for ( int i = 0; i < setting.getLength(); i++ ) {
209                        Setting &value = setting[i];
210                        mxArray *old = mxGetFieldByNumber ( result, 0, i );
211                        if ( old ) mxDestroyArray ( old );
212                        switch ( value.getType() ) {
213                        case Setting::TypeString:
214                                mxSetFieldByNumber ( result, 0, i, mxCreateString ( value ) );
215                                break;
216                        case Setting::TypeBoolean:
217                                mxSetFieldByNumber ( result, 0, i, mxCreateLogicalScalar ( value ) );
218                                break;
219                        case Setting::TypeGroup:
220                                mxSetFieldByNumber ( result, 0, i, group2mxstruct ( value ) );
221                                break;
222                        case Setting::TypeList:
223                                mxSetFieldByNumber ( result, 0, i, list2mxcell ( value ) );
224                                break;
225                        case Setting::TypeArray:
226                                mxSetFieldByNumber ( result, 0, i, array2mxvector ( value ) );
227                                break;
228                        case Setting::TypeInt:
229                        case Setting::TypeInt64:
230                                mxSetFieldByNumber ( result, 0, i, mxCreateDoubleScalar ( ( int ) value ) );
231                                break;
232                        case Setting::TypeFloat:
233                                mxSetFieldByNumber ( result, 0, i, mxCreateDoubleScalar ( value ) );
234                                break;
235                        default:
236                                //this should never happen
237                                mexErrMsgTxt ( "Unknown type of a setting." );
238                        }
239                }
240                return result;
241
242        }
243        //! Convert libconfig's list  to Matlab cell
244        static mxArray* list2mxcell ( const Setting &setting )  {
245                if ( !setting.isList() ) mexErrMsgTxt ( "Given setting is not a list." );
246                if ( setting.getLength() == 0 ) {
247                        mxArray *result = mxCreateCellMatrix ( 1, 0 );
248                        return result;
249                }
250
251                if ( ( setting[0].getType() == Setting::TypeString ) ) {
252                        string s = ( setting[0] );
253                        if ( s == "matrix" ) {
254                                return list2mxmatrix ( setting );
255                        }
256                }
257                mxArray *result = mxCreateCellMatrix ( 1, setting.getLength() );
258                for ( int i = 0; i < setting.getLength(); i++ ) {
259                        Setting &value = setting[i];
260                        mxArray *old = mxGetCell ( result, i );
261                        if ( old ) mxDestroyArray ( old );
262                        switch ( value.getType() ) {
263                        case Setting::TypeString:
264                                mxSetCell ( result, i, mxCreateString ( value ) );
265                                break;
266                        case Setting::TypeBoolean:
267                                mxSetCell ( result, i, mxCreateLogicalScalar ( value ) );
268                                break;
269                        case Setting::TypeGroup:
270                                mxSetCell ( result, i, group2mxstruct ( value ) );
271                                break;
272                        case Setting::TypeList:
273                                mxSetCell ( result, i, list2mxcell ( value ) );
274                                break;
275                        case Setting::TypeArray:
276                                mxSetCell ( result, i, array2mxvector ( value ) );
277                                break;
278                        case Setting::TypeInt:
279                        case Setting::TypeInt64:
280                                mxSetCell ( result, i, mxCreateDoubleScalar ( ( int ) value ) );
281                                break;
282                        case Setting::TypeFloat:
283                                mxSetCell ( result, i, mxCreateDoubleScalar ( value ) );
284                                break;
285                        default:
286                                //this should never happen
287                                mexErrMsgTxt ( "Unknown type of a setting." );
288                        }
289                }
290                return result;
291        }
292};
293
294#endif //MXPARSE_H
Note: See TracBrowser for help on using the browser.