00001 #ifndef UIBUILD
00002 #define UIBUILD
00003
00004 #include <itpp/itbase.h>
00005 #include "stat/libBM.h"
00006 #include "libconfig/libconfig.h++"
00007
00008 namespace bdm {
00009
00010 using namespace libconfig;
00011 using namespace std;
00012
00013 #define CHECK_UITYPE(S,Type) it_assert_debug(S.getType()==Setting::Type, string("Wrong input path \"")+string(S.getPath())+string("\""));
00014 #define UIREGISTER(UI) UI* UI##_global_instance = new UI();
00015
00017
00018 class UIbuilder;
00020 typedef map<const string, const UIbuilder*> UImap;
00021 extern UImap __uimap__;
00022
00023 class UIFile : public Config {
00024 public:
00025 UIFile ( const char * fname ) :Config() {
00026 try{Config::readFile ( fname );}
00027 catch ( ParseException& P ) {
00028 char msg[200];
00029 sprintf ( msg,"Error in file %s on line %d.", fname, P.getLine() );
00030 it_error ( msg );
00031 }
00032 catch ( FileIOException f ) {it_error ( "File " + string ( fname ) + " not found" );}
00033 }
00034 };
00035
00040 class UIbuilder {
00041 protected:
00042 const vec getvec ( Setting& S ) const {
00043 CHECK_UITYPE ( S,TypeArray );
00044 vec tmp;
00045 tmp.set_size ( S.getLength() );
00046 for ( int i=0;i<S.getLength();i++ ) {
00047 switch ( S[i].getType() ) {
00048 case Setting::TypeFloat :
00049 tmp[i]=double ( S[i] );break;
00050 case Setting::TypeInt :
00051 tmp[i]=int ( S[i] );break;
00052 case Setting::TypeBoolean :
00053 tmp[i]=bool ( S[i] );break;
00054 default: it_error ( "libconfig error?" );
00055 }
00056 }
00057 return tmp;
00058 };
00059 const mat getmat ( Setting& S , int ncols) const {
00060 CHECK_UITYPE ( S,TypeArray );
00061 mat tmp;
00062 int nrows=S.getLength()/ncols;
00063 int r=0,c=0;
00064 tmp.set_size ( nrows, ncols );
00065
00066 for ( int i=0;i<S.getLength();i++ ) {
00067 switch ( S[i].getType() ) {
00068 case Setting::TypeFloat :
00069 tmp(r,c)=double ( S[i] );break;
00070 case Setting::TypeInt :
00071 tmp(r,c)=int ( S[i] );break;
00072 case Setting::TypeBoolean :
00073 tmp(r,c)=bool ( S[i] );break;
00074 default: it_error ( "libconfig error?" );
00075 }
00076 c++; if (c==ncols) {c=0;r++;}
00077 }
00078 return tmp;
00079 };
00080 const vec getivec ( Setting& S ) const {
00081 CHECK_UITYPE ( S,TypeArray );
00082 vec tmp;
00083 tmp.set_size ( S.getLength() );
00084 for ( int i=0;i<S.getLength();i++ ) {
00085 switch ( S[i].getType() ) {
00086 case Setting::TypeFloat :
00087 tmp[i]=double ( S[i] );break;
00088 case Setting::TypeInt :
00089 tmp[i]=int ( S[i] );break;
00090 case Setting::TypeBoolean :
00091 tmp[i]=bool ( S[i] );break;
00092 default: it_error ( "libconfig error?" );
00093 }
00094 }
00095 return tmp;
00096 };
00097 public:
00099 UIbuilder ( const string &typ ) {__uimap__.insert ( make_pair ( typ,this ) );}
00101 virtual bdmroot* build ( Setting &S ) const =0;
00102 };
00103
00104 class UIexternal:public UIbuilder {
00105 public:
00106 UIexternal() :UIbuilder ( "external" ) {}
00107 bdmroot* build ( Setting &S ) const;
00108 };
00109
00110 class UIinternal:public UIbuilder {
00111 public:
00112 UIinternal() :UIbuilder ( "internal" ) {}
00113 bdmroot* build ( Setting &S ) const;
00114 };
00115
00117 void UI_DBG ( Setting &S, const string &spc );
00118
00120 template<class T>
00121 void UIbuild ( Setting &S, T* &ret ) {
00122 CHECK_UITYPE ( S,TypeGroup );
00123
00124 it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
00125
00126 const string typ=S["type"];
00127
00128 UImap::const_iterator iter = __uimap__.find ( typ );
00129 if ( iter == __uimap__.end() ) {
00130 it_error ( "UI of type \"" + typ + "\" is not registered!" );
00131 }
00132
00133
00134 try {
00135 ret = dynamic_cast<T*> ( iter->second->build ( S ) );
00136 }
00137 catch ( SettingTypeException e ) {
00138 UI_DBG(S,"");
00139 it_error ( "Setting " +string ( e.getPath() ) +" is of incorrect Type" );}
00140 catch ( SettingNotFoundException e ) {
00141 UI_DBG(S,"");
00142 it_error ( "Setting " + string ( e.getPath() ) +" was not found" );}
00143 };
00144
00146 template<class T>
00147 void UIcall ( Setting &S, void ( *func ) ( Setting&, T ), T Tmp ) {
00148 CHECK_UITYPE ( S,TypeGroup );
00149
00150 it_assert_debug ( S.exists ( "type" ), string ( S.getPath() ) +" is not a valid UI!" );
00151
00152 const string typ=S["type"];
00153 if ( typ=="internal" ) {
00154 try {
00155 Setting* Stmp = &S;
00156 do {Stmp=& ( Stmp->getParent() );}
00157 while ( !Stmp->isRoot() );
00158 Setting& intS=Stmp->lookup ( ( const char* ) S["path"] );
00159 func ( intS, Tmp );
00160 return;
00161 }
00162 catch ( ... ) {
00163 it_error ( "Internal field " + string ( S.getPath() ) + " not valid" );
00164 }
00165 }
00166 if ( typ=="external" ) {
00167 UIFile C(S["filename"]);
00168 try {
00169 func ( C.lookup ( ( const char* ) S["path"] ), Tmp );
00170 }
00171 catch ( ... ) {
00172 it_error ( "External field " + string ( S.getPath() ) + " not valid" );
00173 }
00174 return;
00175 }
00176
00177
00178 func ( S, Tmp );
00179 };
00180
00181 }
00182 #endif //UIBUILD