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

Revision 796, 9.0 kB (checked in by smidl, 14 years ago)

UI changes for MixEF_init

  • 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                        }
94                        if ( mxIsLogical ( value ) ) {
95                                Setting &child = setting.add ( key, Setting::TypeBoolean );
96                                child = ( bool ) mxArray2bin ( value );
97                        }
98                        if ( mxIsStruct ( value ) ) {
99                                Setting &child = setting.add ( key, Setting::TypeGroup );
100                                fillGroup ( child, value );
101                        }
102                        if ( mxIsCell ( value ) ) {
103                                Setting &child = setting.add ( key, Setting::TypeList );
104                                fillList ( child, value );
105                        }
106                        if ( mxIsNumeric ( value ) ) {
107                                storeNumeric ( setting, value, ( string ) key );
108                        }
109                }
110        }
111
112        void fillList ( Setting &setting, const mxArray *mxarray ) {
113                if ( !mxIsCell ( mxarray ) ) {
114                        mexErrMsgTxt ( "Given mxArray is not a cell." );
115                };
116                for ( unsigned int i = 0; i < ( unsigned int ) mxGetNumberOfElements ( mxarray ); i++ ) {
117                        mxArray *value = mxGetCell ( mxarray, i );
118                        if ( mxIsChar ( value ) ) {
119                                Setting &child = setting.add ( Setting::TypeString );
120                                child = mxArray2string ( value );
121                        }
122                        if ( mxIsLogical ( value ) ) {
123                                Setting &child = setting.add ( Setting::TypeBoolean );
124                                child = ( bool ) mxArray2bin ( value );
125                        }
126                        if ( mxIsStruct ( value ) ) {
127                                Setting &child = setting.add ( Setting::TypeGroup );
128                                fillGroup ( child, value );
129                        }
130                        if ( mxIsCell ( value ) ) {
131                                Setting &child = setting.add ( Setting::TypeList );
132                                fillList ( child, value );
133                        }
134                        if ( mxIsNumeric ( value ) ) {
135                                storeNumeric ( setting, value );
136                        }
137                }
138        }
139
140public:
141        //! Convert existing Setting to Matlab arrays
142        static mxArray * create_mxArray( const Setting &setting )
143        {
144                return group2mxstruct ( setting );
145        }
146
147        //! Convert existing Setting to Matlab arrays
148        mxArray * create_mxArray(  )
149        {
150                return group2mxstruct ( *this );
151        }
152
153private:
154        //! Convert libconfig's array to Matlab vector
155        static mxArray* array2mxvector ( const Setting &setting )  {
156                if ( !setting.isArray() ) mexErrMsgTxt ( "Given setting is not an array" );
157                mxArray *result = mxCreateDoubleMatrix ( 1, setting.getLength(), mxREAL );
158                double *elements = mxGetPr ( result );
159                for ( int i = 0; i < setting.getLength(); i++ ) {
160                        if ( setting.getType() == Setting::TypeInt ) { //TODO: tady je chyba -- zaporna cisla nejsou TypeInt
161                                elements[i] = ( int ) setting[i];
162                        } else {
163                                elements[i] =  setting[i];
164                        }
165                }
166                return result;
167        }
168
169        //! Convert libconfig's array to Matlab matrix
170        static mxArray* list2mxmatrix ( const Setting &setting )  {
171                if ( !setting.isList() || ( strcmp ( "matrix", setting[0] ) != 0 ) )
172                        mexErrMsgTxt ( "Given setting is not a matrix" );
173                int rows = setting[1];
174                int cols = setting[2];
175                if ( setting[3].getLength() != rows*cols )
176                        mexErrMsgTxt ( "Matrix elements do not fit to rows*cols" );
177                double *elements = new double[rows*cols];
178                for ( int i = 0; i < rows*cols; i++ ) {
179                        elements[i] = setting[3][i];
180                }
181                mat &m = * ( new mat ( elements, rows, cols ) );
182                mxArray *result = mxCreateDoubleMatrix ( rows, cols, mxREAL );
183                mat2mxArray ( m, result );
184                delete &m;
185                delete [] elements;
186                return result;
187        }
188
189        //! Convert libconfig's gourp to Matlab structure
190        static mxArray* group2mxstruct ( const Setting &setting ) {
191                if ( !setting.isGroup() ) mexErrMsgTxt ( "Given setting is not a group." );
192                const char ** keys = new const char*[setting.getLength() ];
193                for ( int i = 0; i < setting.getLength(); i++ ) {
194                        keys[i] = setting[i].getName();
195                }
196                mxArray *result = mxCreateStructMatrix ( 1, 1, setting.getLength(), keys );
197                delete keys;
198                for ( int i = 0; i < setting.getLength(); i++ ) {
199                        Setting &value = setting[i];
200                        mxArray *old = mxGetFieldByNumber ( result, 0, i );
201                        if ( old ) mxDestroyArray ( old );
202                        switch ( value.getType() ) {
203                        case Setting::TypeString:
204                                mxSetFieldByNumber ( result, 0, i, mxCreateString ( value ) );
205                                break;
206                        case Setting::TypeBoolean:
207                                mxSetFieldByNumber ( result, 0, i, mxCreateLogicalScalar ( value ) );
208                                break;
209                        case Setting::TypeGroup:
210                                mxSetFieldByNumber ( result, 0, i, group2mxstruct ( value ) );
211                                break;
212                        case Setting::TypeList:
213                                mxSetFieldByNumber ( result, 0, i, list2mxcell ( value ) );
214                                break;
215                        case Setting::TypeArray:
216                                mxSetFieldByNumber ( result, 0, i, array2mxvector ( value ) );
217                                break;
218                        case Setting::TypeInt:
219                        case Setting::TypeInt64:
220                                mxSetFieldByNumber ( result, 0, i, mxCreateDoubleScalar ( ( int ) value ) );
221                                break;
222                        case Setting::TypeFloat:
223                                mxSetFieldByNumber ( result, 0, i, mxCreateDoubleScalar ( value ) );
224                                break;
225                        default:
226                                //this should never happen
227                                mexErrMsgTxt ( "Unknown type of a setting." );
228                        }
229                }
230                return result;
231
232        }
233        //! Convert libconfig's list  to Matlab cell
234        static mxArray* list2mxcell ( const Setting &setting )  {
235                if ( !setting.isList() ) mexErrMsgTxt ( "Given setting is not a list." );
236                if ( setting.getLength() == 0 ) {
237                        mxArray *result = mxCreateCellMatrix ( 1, 0 );
238                        return result;
239                }
240
241                if ( ( setting[0].getType() == Setting::TypeString ) ) {
242                        string s = ( setting[0] );
243                        if ( s == "matrix" ) {
244                                return list2mxmatrix ( setting );
245                        }
246                }
247                mxArray *result = mxCreateCellMatrix ( 1, setting.getLength() );
248                for ( int i = 0; i < setting.getLength(); i++ ) {
249                        Setting &value = setting[i];
250                        mxArray *old = mxGetCell ( result, i );
251                        if ( old ) mxDestroyArray ( old );
252                        switch ( value.getType() ) {
253                        case Setting::TypeString:
254                                mxSetCell ( result, i, mxCreateString ( value ) );
255                                break;
256                        case Setting::TypeBoolean:
257                                mxSetCell ( result, i, mxCreateLogicalScalar ( value ) );
258                                break;
259                        case Setting::TypeGroup:
260                                mxSetCell ( result, i, group2mxstruct ( value ) );
261                                break;
262                        case Setting::TypeList:
263                                mxSetCell ( result, i, list2mxcell ( value ) );
264                                break;
265                        case Setting::TypeArray:
266                                mxSetCell ( result, i, array2mxvector ( value ) );
267                                break;
268                        case Setting::TypeInt:
269                        case Setting::TypeInt64:
270                                mxSetCell ( result, i, mxCreateDoubleScalar ( ( int ) value ) );
271                                break;
272                        case Setting::TypeFloat:
273                                mxSetCell ( result, i, mxCreateDoubleScalar ( value ) );
274                                break;
275                        default:
276                                //this should never happen
277                                mexErrMsgTxt ( "Unknown type of a setting." );
278                        }
279                }
280                return result;
281        }
282};
283
284#endif //MXPARSE_H
Note: See TracBrowser for help on using the browser.