#ifndef CFGSTR_H #define CFGSTR_H #include "../base/libconfig/libconfig.h++" #include #include #include using namespace itpp; using namespace std; using namespace libconfig; //! Reimplementation of libconfig's Config class for Matlab mxArray structures class UImxConfig : public Config { public: //! Matlab structure where the info is stored mxArray *mxconfig; //! Load file in libconfig syntax to Matlab arrays UImxConfig ( const char * filename ) { Config config; config.readFile ( filename ); mxconfig = group2mxstruct ( config.getRoot() ); } //! Convert existing Setting to Matlab arrays UImxConfig ( const Setting &setting ) { mxconfig = group2mxstruct ( setting ); } private: //! Convert libconfig's array to Matlab vector mxArray* array2mxvector ( const Setting &setting ) { if ( !setting.isArray() ) mexErrMsgTxt ( "Given setting is not an array" ); double *elements = new double[setting.getLength() ]; for ( int i = 0; i < setting.getLength(); i++ ) { if ( setting.getType() == Setting::TypeInt ) { //TODO: tady je chyba -- zaporna cisla nejsou TypeInt elements[i] = setting[i]; } else { elements[i] = ( int ) setting[i]; } } vec &v = * ( new vec ( elements, setting.getLength() ) ); mxArray *result = mxCreateDoubleMatrix ( 1, setting.getLength(), mxREAL ); vec2mxArray ( v, result ); delete &v; delete [] elements; return result; } //! Convert libconfig's array to Matlab matrix mxArray* list2mxmatrix ( const Setting &setting ) { if ( !setting.isList() || ( "matrix" != setting[0] ) ) mexErrMsgTxt ( "Given setting is not a matrix" ); int rows = setting[1]; int cols = setting[2]; if ( setting[3].getLength() != rows*cols ) mexErrMsgTxt ( "Matrix elements do not fit to rows*cols" ); double *elements = new double[rows*cols]; for ( int i = 0; i < rows*cols; i++ ) { elements[i] = setting[3][i]; } mat &m = * ( new mat ( elements, rows, cols ) ); mxArray *result = mxCreateDoubleMatrix ( rows, cols, mxREAL ); mat2mxArray ( m, result ); delete &m; delete [] elements; return result; } //! Convert libconfig's gourp to Matlab structure mxArray* group2mxstruct ( const Setting &setting ) { if ( !setting.isGroup() ) mexErrMsgTxt ( "Given setting is not a group." ); const char ** keys = new const char*[setting.getLength() ]; for ( int i = 0; i < setting.getLength(); i++ ) { keys[i] = setting[i].getName(); } mxArray *result = mxCreateStructMatrix ( 1, 1, setting.getLength(), keys ); delete keys; for ( int i = 0; i < setting.getLength(); i++ ) { Setting &value = setting[i]; mxArray *old = mxGetFieldByNumber ( result, 0, i ); if ( old ) mxDestroyArray ( old ); switch ( value.getType() ) { case Setting::TypeString: mxSetFieldByNumber ( result, 0, i, mxCreateString ( value ) ); break; case Setting::TypeBoolean: mxSetFieldByNumber ( result, 0, i, mxCreateLogicalScalar ( value ) ); break; case Setting::TypeGroup: mxSetFieldByNumber ( result, 0, i, group2mxstruct ( value ) ); break; case Setting::TypeList: mxSetFieldByNumber ( result, 0, i, list2mxcell ( value ) ); break; case Setting::TypeArray: mxSetFieldByNumber ( result, 0, i, array2mxvector ( value ) ); break; case Setting::TypeInt: case Setting::TypeInt64: mxSetFieldByNumber ( result, 0, i, mxCreateDoubleScalar ( ( int ) value ) ); break; case Setting::TypeFloat: mxSetFieldByNumber ( result, 0, i, mxCreateDoubleScalar ( value ) ); break; default: //this should never happen mexErrMsgTxt ( "Unknown type of a setting." ); } } return result; } //! Convert libconfig's list to Matlab cell mxArray* list2mxcell ( const Setting &setting ) { if ( !setting.isList() ) mexErrMsgTxt ( "Given setting is not a list." ); if ( setting.getLength() == 0 ) { mxArray *result = mxCreateCellMatrix ( 1, 0 ); return result; } if ( ( setting[0].getType() == Setting::TypeString ) && ( "matrix" == setting[0] ) ) { return list2mxmatrix ( setting ); } mxArray *result = mxCreateCellMatrix ( 1, setting.getLength() ); for ( int i = 0; i < setting.getLength(); i++ ) { Setting &value = setting[i]; mxArray *old = mxGetCell ( result, i ); if ( old ) mxDestroyArray ( old ); switch ( value.getType() ) { case Setting::TypeString: mxSetCell ( result, i, mxCreateString ( value ) ); break; case Setting::TypeBoolean: mxSetCell ( result, i, mxCreateLogicalScalar ( value ) ); break; case Setting::TypeGroup: mxSetCell ( result, i, group2mxstruct ( value ) ); break; case Setting::TypeList: mxSetCell ( result, i, list2mxcell ( value ) ); break; case Setting::TypeArray: mxSetCell ( result, i, array2mxvector ( value ) ); break; case Setting::TypeInt: case Setting::TypeInt64: mxSetCell ( result, i, mxCreateDoubleScalar ( ( int ) value ) ); break; case Setting::TypeFloat: mxSetCell ( result, i, mxCreateDoubleScalar ( value ) ); break; default: //this should never happen mexErrMsgTxt ( "Unknown type of a setting." ); } } return result; } }; #endif //CFGSTR_H