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

Revision 1064, 11.5 kB (checked in by mido, 14 years ago)

astyle applied all over the library

  • 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 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.