user_info.h
Go to the documentation of this file.00001 00015 #ifndef USER_INFO_H 00016 #define USER_INFO_H 00017 00018 #include <stdio.h> 00019 #include <string> 00020 #include <typeinfo> 00021 #include <map> 00022 #include <stdexcept> 00023 00024 #include "../bdmroot.h" 00025 #include "../shared_ptr.h" 00026 #include "itpp/itbase.h" 00027 #include "../math/square_mat.h" 00028 #include "../math/chmat.h" 00029 00030 using std::string; 00031 using namespace std; 00032 using namespace libconfig; 00033 00034 namespace bdm { 00035 00039 class UIException : public std::exception { 00040 private: 00042 const string message; 00043 00044 public: 00049 UIException ( const string &message ) : 00050 message ( message ) { 00051 } 00052 00054 virtual const char* what() const throw() { 00055 return message.c_str(); 00056 } 00057 00058 ~UIException() throw() {}; 00059 00060 protected: 00065 static string format_message ( const string &reason, const string &path ); 00066 }; 00067 00071 class UISettingException : public UIException { 00072 public: 00074 UISettingException ( const string &message, const Setting &element ) : 00075 UIException ( format_message ( message, string ( element.getPath() ) ) ) { 00076 } 00077 00079 UISettingException ( const string &message, const string &path ) : 00080 UIException ( format_message ( message, path ) ) { 00081 } 00082 00083 ~UISettingException() throw() {}; 00084 }; 00085 00089 class UIClassException : public UIException { 00090 public: 00092 UIClassException ( const string &message, const Setting &element ) : 00093 UIException ( format_message ( message, string ( element.getPath() ) ) ) { 00094 } 00095 00097 UIClassException ( const string &message, const string &path ) : 00098 UIException ( format_message ( message, path ) ) { 00099 } 00100 00101 ~UIClassException() throw() {}; 00102 }; 00103 00128 class UIFile : public Config { 00129 public: 00131 UIFile(); 00132 00134 UIFile ( const string &file_name ); 00135 00137 void save ( const string &file_name ); 00138 00140 operator Setting&(); 00141 }; 00142 00209 class SettingResolver : root { 00210 private: 00212 UIFile *file; 00213 00219 const Setting &initialize_reference ( UIFile* &file, const Setting &potential_link ); 00220 00221 public: 00223 const Setting &result; 00224 00226 SettingResolver ( const Setting &potential_link ); 00227 00229 ~SettingResolver(); 00230 }; 00231 00232 00233 00244 class UI { 00245 private: 00251 class MappedUI { 00252 private: 00254 typedef map< const string, const UI* const > StringToUIMap; 00255 00257 typedef map< const type_info * const, const string > TypeInfoToStringMap; 00258 00260 static StringToUIMap& mapped_strings(); 00261 00263 static TypeInfoToStringMap& mapped_type_infos(); 00264 00266 static void unregistered_class_error ( const string &unregistered_class_name ); 00267 00268 public: 00270 static void add_class ( const string &class_name, const type_info * const class_type_info, const UI* const ui ); 00271 00273 static const UI& retrieve_ui ( const string &class_name ); 00274 00276 static const string& retrieve_class_name ( const type_info* const class_type_info ); 00277 }; 00278 00280 static void assert_type ( const Setting &element, Setting::Type type ); 00281 00290 virtual root* new_instance() const = 0; 00291 00293 static const Setting& to_child_setting ( const Setting &element, const int index ); 00294 00296 static const Setting& to_child_setting ( const Setting &element, const string &name ); 00297 00299 static void call_from_setting( root &instance, const Setting &set, string class_name = "unknown"); 00300 00302 static void call_to_setting( const root &instance, Setting &set, string class_name = "unknown" ); 00303 00305 static void from_setting ( mat& matrix, const Setting &element ); 00307 static void from_setting ( ldmat& matrix, const Setting &element ); 00309 static void from_setting ( ivec &vector, const Setting &element ); 00311 static void from_setting ( string &str, const Setting &element ); 00313 static void from_setting ( vec &vector, const Setting &element ); 00315 static void from_setting ( int &integer, const Setting &element ); 00317 static void from_setting ( double &real, const Setting &element ); 00319 static void from_setting ( root &instance, const Setting &element ); 00325 static void from_setting ( log_level_base &log_level, const Setting &element ); 00327 template<class T> static void from_setting ( T* &instance, const Setting &element ) { 00328 const SettingResolver link ( element ); 00329 assert_type( link.result, Setting::TypeGroup ); 00330 00331 // we get a value stored in the "class" attribute 00332 string class_name; 00333 if ( !link.result.lookupValue ( "class", class_name ) ) 00334 throw UIClassException ( "UIException: the obligatory \"class\" identifier is missing.", link.result ); 00335 00336 // then we find a user-info related to this type 00337 const UI& related_UI = MappedUI::retrieve_ui ( class_name ); 00338 00339 root *typeless_instance = related_UI.new_instance(); 00340 bdm_assert ( typeless_instance, "UI::new_instance failed" ); 00341 00342 instance = dynamic_cast<T*> ( typeless_instance ); 00343 if ( !instance ) { 00344 delete typeless_instance; 00345 throw UIClassException ( "UIException: class " + class_name + " is not a descendant of the desired output class. Try to call the UI::build<T> function with a different type parameter.", link.result ); 00346 } 00347 00348 try { 00349 call_from_setting( *instance, link.result, class_name ); 00350 } catch ( ... ) { 00351 delete instance; 00352 instance = 0; 00353 throw; 00354 } 00355 } 00356 00359 template<class T> static void from_setting ( bdm::shared_ptr<T> &instance, const Setting &element ) { 00360 T *tmp_inst = 0; 00361 from_setting ( tmp_inst, element ); 00362 bdm_assert ( tmp_inst, "UI::from_setting failed" ); 00363 instance = tmp_inst; 00364 } 00365 00367 template<class T> static void from_setting ( Array<T> &array_to_load, const Setting &element ) { 00368 const SettingResolver link ( element ); 00369 00370 assert_type ( link.result, Setting::TypeList ); 00371 00372 int len = link.result.getLength(); 00373 array_to_load.set_length ( len ); 00374 if ( len == 0 ) return; 00375 00376 for ( int i = 0; i < len; i++ ) 00377 from_setting ( array_to_load ( i ), link.result[i] ); 00378 } 00379 00380 protected: 00382 UI ( const string& class_name, const type_info * const class_type_info ) { 00383 MappedUI::add_class ( class_name, class_type_info, this ); 00384 } 00385 00386 public: 00387 00389 enum SettingPresence { optional, compulsory } ; 00390 00394 00399 template<class T> 00400 static bdm::shared_ptr<T> build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) { 00401 if ( !element.exists ( name ) ) { 00402 if ( settingPresence == optional ) 00403 return bdm::shared_ptr<T>(); 00404 else 00405 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element ); 00406 } 00407 00408 bdm::shared_ptr<T> instance; 00409 from_setting<T> ( instance, to_child_setting ( element, name ) ); 00410 return instance; 00411 } 00412 00417 template<class T> 00418 static bdm::shared_ptr<T> build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) { 00419 if ( element.getLength() <= index ) { 00420 if ( settingPresence == optional ) 00421 return bdm::shared_ptr<T>(); 00422 else { 00423 stringstream stream; 00424 stream << index; 00425 throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element ); 00426 } 00427 } 00428 00429 bdm::shared_ptr<T> instance; 00430 from_setting<T> ( instance, to_child_setting ( element, index ) ); 00431 return instance; 00432 } 00433 00437 template<class T> 00438 static bdm::shared_ptr<T> build ( const Setting &element, SettingPresence settingPresence = optional ) { 00439 bdm::shared_ptr<T> instance; 00440 from_setting<T> ( instance, element ); 00441 return instance; 00442 } 00443 00445 00449 00452 template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { 00453 if ( !element.exists ( name ) ) { 00454 if ( settingPresence == optional ) 00455 return false; 00456 else 00457 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element ); 00458 } 00459 00460 from_setting ( instance, to_child_setting ( element, name ) ); 00461 return true; 00462 } 00463 00466 template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) { 00467 if ( element.getLength() <= index ) { 00468 if ( settingPresence == optional ) 00469 return false; 00470 else { 00471 stringstream stream; 00472 stream << "UIException: the compulsory Setting with the index " << index << " is missing."; 00473 stream << index; 00474 throw UISettingException ( stream.str(), element ); 00475 } 00476 } 00477 00478 from_setting ( instance, to_child_setting ( element, index ) ); 00479 return true; 00480 } 00481 00483 template<class T> static bool get ( T &instance, const Setting &element ) { 00484 from_setting ( instance, element ); 00485 return true; 00486 } 00488 00492 00495 template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { 00496 if ( !element.exists ( name ) ) { 00497 if ( settingPresence == optional ) 00498 return false; 00499 else 00500 throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element ); 00501 } 00502 00503 from_setting ( array_to_load, to_child_setting ( element, name ) ); 00504 return true; 00505 } 00506 00509 template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const int index, SettingPresence settingPresence = optional ) { 00510 if ( element.getLength() <= index ) { 00511 if ( settingPresence == optional ) 00512 return bdm::shared_ptr<T>(); 00513 else { 00514 stringstream stream; 00515 stream << index; 00516 throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element ); 00517 } 00518 } 00519 00520 from_setting ( array_to_load, to_child_setting ( element, index ) ); 00521 return true; 00522 } 00523 00525 template<class T> static bool get ( Array<T> &array_to_load, const Setting &element ) { 00526 from_setting ( array_to_load, element ); 00527 return true; 00528 } 00530 00535 00537 static void save ( const root &instance, Setting &element, const string &name = "" ); 00538 00540 static void save ( const root * const instance, Setting &element, const string &name = "" ); 00541 00543 template< class T> static void save ( const bdm::shared_ptr<T> &instance, Setting &element, const string &name = "" ) { 00544 save( instance.get(), element, name ); 00545 } 00546 00548 template<class T> static void save ( const Array<T> &array_to_save, Setting &element, const string &name = "" ) { 00549 assert_type ( element, Setting::TypeGroup ); 00550 Setting &list = ( name == "" ) ? element.add ( Setting::TypeList ) 00551 : element.add ( name, Setting::TypeList ); 00552 for ( int i = 0; i < array_to_save.length(); i++ ) 00553 save ( array_to_save ( i ), list ); 00554 } 00555 00557 static void save ( const mat &matrix, Setting &element, const string &name = "" ); 00558 00560 static void save ( const ldmat &matrix, Setting &element, const string &name = "" ); 00561 00563 static void save ( const ivec &vec, Setting &element, const string &name = "" ); 00564 00566 static void save ( const vec &vector, Setting &element, const string &name = "" ); 00567 00569 static void save ( const string &str, Setting &element, const string &name = "" ); 00570 00572 static void save ( const int &integer, Setting &element, const string &name = "" ); 00573 00575 static void save ( const double &real, Setting &element, const string &name = "" ); 00576 00577 // The only difference from classical UserInfo approach here is the fact 00578 // that the actual UI element related to log_level_base could possibly exists yet. In this case, 00579 // we do not want to throw an exception as usually. We rather append current data into the existig element. This way, it is 00580 // possible that more instances of log_level_base (templated with different classes) 00581 // can be stored in only one line in a configuration file 00582 static void save ( const log_level_base &log_level, Setting &element ); 00583 00585 00587 virtual ~UI() {} 00588 }; 00589 00590 00593 template<typename T> class ParticularUI : private UI { 00594 public: 00596 ParticularUI<T> ( const string &class_name ) : UI ( class_name, &typeid ( T ) ) {}; 00597 00599 root* new_instance() const { 00600 return new T(); 00601 } 00602 }; 00603 00604 } 00605 00615 #ifndef BDMLIB 00616 #define UIREGISTER(class_name) static bdm::ParticularUI<class_name> UI##class_name(#class_name) 00617 #else 00618 #define UIREGISTER(class_name) 00619 #endif 00620 00622 #define QUOTEME(x) #x 00623 00632 #ifndef BDMLIB 00633 #define UIREGISTER2(class_name, temp_name) static bdm::ParticularUI<class_name<temp_name> > UI##class_name##_##temp_name( QUOTEME(class_name<temp_name>) ) 00634 #else 00635 #define UIREGISTER2(class_name,temp_name) 00636 #endif 00637 00638 #endif // #ifndef USER_INFO_H
Generated on 2 Dec 2013 for mixpp by 1.4.7