root/bdm/uibuilder.h @ 350

Revision 350, 6.5 kB (checked in by smidl, 15 years ago)

restore uibuilder.* for compatibility (CMake changes kept local)

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