root/bdm/uibuilder.h @ 257

Revision 257, 4.1 kB (checked in by smidl, 15 years ago)

All objects have a virtual predecessor. This allows type checking in UI, see

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////////// GLOBAL VAriables
17
18class UIbuilder;
19//! Internal structure mapping strings to UIBuilder objects
20typedef map<const string, const UIbuilder*> UImap;
21extern UImap __uimap__;
22
23class UIFile : public Config{
24        public:
25        UIFile(const char * fname):Config(){
26                try{Config::readFile(fname);} 
27                catch (ParseException& P) {
28                        char msg[200];
29                        sprintf(msg,"Error in file %s  on line %d.", fname, P.getLine());
30                        it_error(msg);
31                } 
32                catch (FileIOException f) {it_error("File " + string(fname) + " not found");} 
33        }
34};
35
36/*!\brief Builds computational object from a UserInfo structure
37
38Return value is a pointer to the created object (memory management issue?)
39*/
40class UIbuilder {
41        protected:
42                static const UIbuilder* theinstance;
43        vec getvec ( Setting& S ) {
44                CHECK_UITYPE(S,TypeArray);
45                vec tmp;
46                tmp.set_size ( S.getLength() );
47                for ( int i=0;i<S.getLength();i++ ) {
48                        switch (S[i].getType()) {
49                                case Setting::TypeFloat :
50                                        tmp[i]=double(S[i]);break;
51                                case Setting::TypeInt :
52                                        tmp[i]=int(S[i]);break;
53                                case Setting::TypeBoolean :
54                                        tmp[i]=bool(S[i]);break;
55                                default: it_error("libconfig error?");
56                        } 
57                }
58                return tmp;
59        };
60        vec getivec ( Setting& S ) {
61                CHECK_UITYPE(S,TypeArray);
62                vec tmp;
63                tmp.set_size ( S.getLength() );
64                for ( int i=0;i<S.getLength();i++ ) {
65                        switch (S[i].getType()) {
66                                case Setting::TypeFloat :
67                                        tmp[i]=double(S[i]);break;
68                                case Setting::TypeInt :
69                                        tmp[i]=int(S[i]);break;
70                                case Setting::TypeBoolean :
71                                        tmp[i]=bool(S[i]);break;
72                                        default: it_error("libconfig error?");
73                        } 
74                }
75                return tmp;
76        };
77        public:
78                //!Constructor needs to be run only once macro UIREGISTER
79                UIbuilder(const string &typ){__uimap__.insert(make_pair(typ,this));}
80                //! Function building the computational object
81                virtual bdmroot* build(Setting &S) const =0;
82};
83
84class UIexternal:public UIbuilder{
85        public:
86                UIexternal():UIbuilder("external"){}
87                bdmroot* build(Setting &S) const;
88};
89
90class UIinternal:public UIbuilder{
91        public:
92                UIinternal():UIbuilder("internal"){}
93                bdmroot* build(Setting &S) const;
94};
95
96//! Prototype of a UI builder. Return value is by the second argument since it type checking via \c dynamic_cast.
97template<class T>
98void UIbuild(Setting &S, T* &ret){
99        CHECK_UITYPE(S,TypeGroup);
100        // Check if field "type" is present, if not it is not a valid UI
101        it_assert_debug(S.exists("type"), string(S.getPath())+" is not a valid UI!");
102               
103        const string typ=S["type"];     
104        // Find "type" in list of registred UI builders
105        UImap::const_iterator iter = __uimap__.find( typ );
106        if( iter == __uimap__.end()) {
107                it_error("UI of type \"" + typ + "\" is not registered!");
108        }
109       
110        //BUILD the result
111        ret = dynamic_cast<T*>(iter->second->build(S));
112};
113
114//! Auxiliary function allowing recursivity in S
115template<class T>
116void UIcall(Setting &S, void (*func)(Setting&, T), T Tmp ){
117        CHECK_UITYPE(S,TypeGroup);
118        // Check if field "type" is present, if not it is not a valid UI
119        it_assert_debug(S.exists("type"), string(S.getPath())+" is not a valid UI!");
120               
121        const string typ=S["type"];     
122        if(typ=="internal"){
123                try {   
124                        Setting* Stmp = &S;
125                        do {Stmp=&(Stmp->getParent());} while (!Stmp->isRoot());
126                        Setting& intS=Stmp->lookup((const char*)S["path"]);
127                        func(intS, Tmp); // <======== calling UIset
128                        return;
129                }
130                catch (...) { it_error("Internal field " + string(S.getPath()) + " not valid");
131                }
132        }
133        if(typ=="extern"){
134                Config C;
135                bdmroot* tmp;
136                try{C.readFile((const char*)S["filename"]);} catch (...){
137                        it_error("File " + string((const char*)S["filename"]) + " not found or broken");
138                }
139                try {func(C.lookup((const char*)S["path"]), Tmp);} catch (...) { //<=========== calling UIset
140                        it_error("External field " + string(S.getPath()) + " not valid");
141                }
142                return;
143        }
144       
145        // v======================= calling final set
146        func(S, Tmp);
147};
148
149}
150#endif UIBUILD
Note: See TracBrowser for help on using the browser.