root/bdm/uibuilder.h @ 334

Revision 334, 6.5 kB (checked in by miro, 15 years ago)

getvec and getmat are compatible with mxstruct2config output
not yet tested, but the former functionality should be unchanged

  • Property svn:eol-style set to native
Line 
1#ifndef UIBUILD
2#define UIBUILD
3
4#include <itpp/itbase.h>
5#include "stat/libBM.h"
6#include "libconfig/libconfig.h++"
7
8namespace bdm {
9
10using namespace libconfig;
11using namespace std;
12
13#define CHECK_UITYPE(S,Type) it_assert_debug(S.getType()==Setting::Type, string("Wrong input path \"")+string(S.getPath())+string("\""));
14#define UIREGISTER(UI) UI* UI##_global_instance = new UI();
15
16//!Standard catches for UIs, use as: catch UICATCH
17#define UICATCH  ( SettingTypeException e ) {it_error ( "Setting " +string ( e.getPath() ) +" is of incorrect Type" );} catch ( SettingNotFoundException e ) {it_error ( "Setting " + string ( e.getPath() ) +" was not found" );}
18
19////////// GLOBAL VAriables
20
21class UIbuilder;
22//! Internal structure mapping strings to UIBuilder objects
23typedef map<const string, const UIbuilder*> UImap;
24extern UImap __uimap__;
25
26class UIFile : public Config {
27public:
28        UIFile ( const char * fname ) :Config() {
29                try{Config::readFile ( fname );}
30                catch ( FileIOException f ) {it_error ( "File " + string ( fname ) + " not found" );}
31                catch ( ParseException& P ) {
32                        char msg[200];
33                        sprintf ( msg,"Error in file %s  on line %d.", fname, P.getLine() );
34                        it_error ( msg );
35                }
36        }
37};
38
39//! \name elem Elementary build functions
40//!@{
41
42//! construct itpp::vec from Setting of type Array
43inline vec getvec ( Setting& S ) {
44        vec vector;
45        if (S.getType() == Setting::TypeArray) {       
46                vector.set_size ( S.getLength() );
47                for ( int i=0;i<S.getLength();i++ ) {
48                        switch ( S[i].getType() ) {
49                                case Setting::TypeFloat :
50                                        vector[i]=double ( S[i] );break;
51                                case Setting::TypeInt :
52                                        vector[i]=int ( S[i] );break;
53                                case Setting::TypeBoolean :
54                                        vector[i]=bool ( S[i] );break;
55                                default: it_error ( "libconfig error?" );
56                        }
57                }
58        } else if (S.getType() == Setting::TypeGroup) {
59                vector = getvec(S["elements"]);
60                int cols = S["cols"];
61                if (vector.length() != cols) { 
62                        it_error("requested vector is a matrix");
63                }
64        } else {
65                it_error("requested vector has invalid type");
66        }
67        return vector;
68};
69
70//! construct itpp::mat from Setting of type Array, number of columns must be given
71inline mat getmat ( Setting& S , int ncols ) {
72        CHECK_UITYPE ( S,TypeArray );
73        mat tmp;
74        int nrows=S.getLength() /ncols;
75        int r=0,c=0;
76        tmp.set_size ( nrows, ncols );
77        // Build matrix row-wise
78        for ( int i=0;i<S.getLength();i++ ) {
79                switch ( S[i].getType() ) {
80                        case Setting::TypeFloat :
81                                tmp ( r,c ) =double ( S[i] );break;
82                        case Setting::TypeInt :
83                                tmp ( r,c ) =int ( S[i] );break;
84                        case Setting::TypeBoolean :
85                                tmp ( r,c ) =bool ( S[i] );break;
86                        default: it_error ( "libconfig error?" );
87                }
88                c++; if ( c==ncols ) {c=0;r++;}
89        }
90        return tmp;
91};
92
93//! construct itpp::mat from Setting of type Group containing settings
94//! "elements" and "cols"
95inline mat getmat (Setting & S) {
96        CHECK_UITYPE (S, TypeGroup);
97        return getmat(S["elements"], S["cols"]);
98}
99
100//! construct itpp::ivec from Setting of type Array
101
102inline ivec getivec ( Setting& S ) {
103        CHECK_UITYPE ( S,TypeArray );
104        ivec tmp;
105        tmp.set_size ( S.getLength() );
106        for ( int i=0;i<S.getLength();i++ ) {
107                switch ( S[i].getType() ) {
108                        case Setting::TypeFloat :
109                                tmp[i]=double ( S[i] );break;
110                        case Setting::TypeInt :
111                                tmp[i]=int ( S[i] );break;
112                        case Setting::TypeBoolean :
113                                tmp[i]=bool ( S[i] );break;
114                        default: it_error ( "libconfig error?" );
115                }
116        }
117        return tmp;
118};
119
120//! construct itpp::Array<string> from Setting of type Array
121
122inline Array<string> get_as ( Setting& S ) {
123        CHECK_UITYPE ( S,TypeArray );
124        Array<string> tmp;
125        tmp.set_size ( S.getLength() );
126        for ( int i=0;i<S.getLength();i++ ) {tmp ( i ) = ( const char* ) S[i];}
127        return tmp;
128};
129
130//!@}
131
132/*!\brief Builds computational object from a UserInfo structure
133
134Return value is a pointer to the created object (memory management issue?)
135*/
136class UIbuilder {
137protected:
138public:
139        //!Constructor needs to be run only once macro UIREGISTER
140        UIbuilder ( const string &typ ) {__uimap__.insert ( make_pair ( typ,this ) );}
141        //! Function building the computational object
142        virtual bdmroot* build ( Setting &S ) const =0;
143        //! Virtual destructor for future use;
144        virtual ~UIbuilder(){};
145};
146
147/*! Recursive build of objects defined in external file
148
149\code
150{type="external";
151filename="my_file.cfg";       // name of file from which to read
152path="system.profile.[0]";    // Path in the external file
153};
154\endcode
155*/
156class UIexternal:public UIbuilder {
157public:
158        UIexternal() :UIbuilder ( "external" ) {}
159        bdmroot* build ( Setting &S ) const;
160};
161
162/*! Recursive build of objects defined in the same file
163
164\code
165{type="internal";
166path="system.profile.[0]";    // Path from the root
167};
168\endcode
169 */
170class UIinternal:public UIbuilder {
171public:
172        UIinternal() :UIbuilder ( "internal" ) {}
173        bdmroot* build ( Setting &S ) const;
174};
175
176//! [Debugging] Print values in current S to cout
177void UI_DBG ( Setting &S, const string &spc );
178
179//! Prototype of a UI builder. Return value is by the second argument since it type checking via \c dynamic_cast.
180template<class T>
181void UIbuild ( Setting &S, T* &ret ) {
182        CHECK_UITYPE ( S,TypeGroup );
183        // Check if field "type" is present, if not it is not a valid UI
184        it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
185
186        const string typ=S["type"];
187        // Find "type" in list of registred UI builders
188        UImap::const_iterator iter = __uimap__.find ( typ );
189        if ( iter == __uimap__.end() ) {
190                it_error ( "UI of type \"" + typ + "\" is not registered!" );
191        }
192
193        //BUILD the result
194        try {
195                ret = dynamic_cast<T*> ( iter->second->build ( S ) );
196        }
197        catch UICATCH
198};
199
200//! Auxiliary function allowing recursivity in S (too complex, remove?)
201template<class T>
202void UIcall ( Setting &S, void ( *func ) ( Setting&, T ), T Tmp ) {
203        CHECK_UITYPE ( S,TypeGroup );
204        // Check if field "type" is present, if not it is not a valid UI
205        it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
206
207        const string typ=S["type"];
208        if ( typ=="internal" ) {
209                try {
210                        Setting* Stmp = &S;
211                        do {Stmp=& ( Stmp->getParent() );}
212                        while ( !Stmp->isRoot() );
213                        Setting& intS=Stmp->lookup ( ( const char* ) S["path"] );
214                        func ( intS, Tmp ); // <======== calling func
215                        return;
216                }
217                catch ( ... ) {
218                        it_error ( "Internal field " + string ( S.getPath() ) + " not valid" );
219                }
220        }
221        if ( typ=="external" ) {
222                UIFile C ( S["filename"] );
223                try {
224                        func ( C.lookup ( ( const char* ) S["path"] ), Tmp );
225                }
226                catch ( ... ) {
227                        it_error ( "External field " + string ( S.getPath() ) + " not valid" );
228                }
229                return;
230        }
231
232        // v======================= calling final func
233        func ( S, Tmp );
234};
235
236}
237#endif //UIBUILD
Note: See TracBrowser for help on using the browser.