Changeset 942

Show
Ignore:
Timestamp:
05/14/10 12:16:00 (14 years ago)
Author:
mido
Message:

the functionality of user info was improved, it supports an initialization of root descendant via UI::get directly, however it is save only for static attributes, for dynamically allocated attributes UI::build should be called to handle with intahrence issues

Location:
library
Files:
8 modified

Legend:

Unmodified
Added
Removed
  • library/bdm/base/bdmbase.h

    r927 r942  
    296296RV concat ( const RV &rv1, const RV &rv2 ); 
    297297 
    298  
    299 //! This class stores a details that will be logged to a logger 
    300 //! 
    301 //! This is only the first part of the whole declaration, which has to be however separated into 
    302 //! two different classes for allowing the compilation of source code. For more details 
    303 //! see logger::add_setting(...) method and mainly log_level_template<T>::template<class U> void store( const enum T::log_level_enums log_level_enum, const U data ) const 
    304 //! method. For the reason the second one is templated, it was necessary to declare this whole class.  
    305 template<class T> class log_level_intermediate : public log_level_base { 
    306 public: 
    307         //! this method adds new id to its proper position and return the name of this position 
    308         string store_id_and_give_name( enum T::log_level_enums const log_level_enum,  int enum_subindex, int id ) { 
    309 //              int ids_len = ids(log_level_enum).length(); <== compiler suggest to remove 
    310                 if( ids(log_level_enum).length() <= enum_subindex ) 
    311                         ids(log_level_enum).set_size( enum_subindex+1, true ); 
    312                 ids(log_level_enum)(enum_subindex) = id;  
    313  
    314                 // here we remove a "log" prefix from name, i.e., for instance it transforms "logevidence" to "evidence" 
    315                 ostringstream stream; 
    316                 string name_with_prefix = names()(log_level_enum); 
    317                 string possible_log_prefix = name_with_prefix.substr(0,3); 
    318                 if( possible_log_prefix == "log" ) 
    319                         stream << name_with_prefix.substr(3,name_with_prefix.length()-3); 
    320                 else  
    321                         stream << name_with_prefix; 
    322  
    323                 // add number to name only in the case there are more registered vectors with the same log_level_enum 
    324                 if( ids(log_level_enum).length() > 1 ) 
    325                         stream << "*" << enum_subindex; 
    326                  
    327                 return stream.str(); 
    328         } 
    329  
    330         log_level_intermediate( ) { 
    331                 int len = names().length(); 
    332                 ids.set_size( len ); 
    333                 for( int i = 0; i<len; i++ ) 
    334                 { 
    335                         ids(i).set_size ( 1 ); 
    336                         ids(i) = -1; 
    337                 } 
    338         } 
    339  
    340         //! string equivalents of the used enumerations which are filled with a help of #LOG_LEVEL macro within class T 
    341         const Array<string> &names() const 
    342         { 
    343                 return T::log_level_names(); 
    344         } 
    345  
    346         //! read only operator for testing individual fields of log_level 
    347         //! 
    348         //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe 
    349         bool operator [] (const enum T::log_level_enums &log_level_enum ) const 
    350         { 
    351                 return values[log_level_enum]; 
    352         } 
    353  
    354         //! operator for setting an individual field of log_level  
    355         //! 
    356         //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe 
    357         bitset<32>::reference operator [] (const enum T::log_level_enums &log_level_enum ) 
    358         { 
    359                 return values[log_level_enum]; 
    360         } 
    361 }; 
    362  
    363  
    364298/*! 
    365299@brief Class for storing results (and semi-results) of an experiment 
     
    417351        //!  
    418352        //! passing the last parameter \c enum_subindex one can store multiple vectors in the position of one enum 
    419         template<class T> void add_vector ( log_level_intermediate<T> &log_level, enum T::log_level_enums const log_level_enum, const RV &rv, const string &prefix, int enum_subindex = 0 ) 
     353        template<class T> void add_vector ( log_level_base<T> &log_level, enum T::log_level_enums const log_level_enum, const RV &rv, const string &prefix, int enum_subindex = 0 ) 
    420354        { 
    421355                if( !log_level.registered_logger ) 
     
    439373        //! It also sets a pointer to logger or justify it is correctly assigned from previous call to this procedure  
    440374        //! 
    441         //! To allow both arguments log_level and log_level_enum be templated, it was necessary to declare log_level_intermediate<T> class. 
     375        //! To allow both arguments log_level and log_level_enum be templated, it was necessary to declare log_level_base<T> class. 
    442376        //! This way we check compatibility of the passed log_level and log_level_enum, which would be impossible using just log_level_base class 
    443377        //! here.  
     
    445379        //! 
    446380        //! passing the last parameter \c enum_subindex one can store multiple settings in the position of one enum 
    447         template<class T> void add_setting ( log_level_intermediate<T> &log_level, enum T::log_level_enums const log_level_enum,  const string &prefix, int enum_subindex = 0 ) { 
     381        template<class T> void add_setting ( log_level_base<T> &log_level, enum T::log_level_enums const log_level_enum,  const string &prefix, int enum_subindex = 0 ) { 
    448382                if( !log_level.registered_logger ) 
    449383                        log_level.registered_logger = this; 
     
    471405 
    472406//! This class stores a details that will be logged to a logger 
    473 template<class T> class log_level_template : public log_level_intermediate<T> { 
     407template<class T> class log_level_template : public log_level_base<T> { 
    474408public: 
    475409        //! This method stores a vector to the proper place in registered logger  
     
    499433        //! If this method was not templated, we could store whole body of this class in cpp file without explicitly touching registered_logger->log_setting(...) here. 
    500434        //! (it would not be straightforward, though, still there are some enums which had to be converted into integers but it could be done without loosing type control) 
    501         //! This way, it would not be necessary to declare log_level_intermediate<T> class and we could declare log_level_template<T> 
     435        //! This way, it would not be necessary to declare log_level_base<T> class and we could declare log_level_template<T> 
    502436        //! before the logger class itself with a mere foroward declaration of logger. In our case, however, touching of registered_logger->log_setting 
    503         //! implies that friend declaration is not enough and we are lost in a circle. And just by cutting this circle we obtains log_level_intermediate<T> class.  
    504         //! Howg.) 
     437        //! implies that forward declaration is not enough and we are lost in a circle. And just by cutting this circle we obtains log_level_base<T> class.  
    505438        template<class U> void store( const enum T::log_level_enums log_level_enum, const U data, int enum_subindex = 0 ) const 
    506439        {                        
     
    526459  \ref ui 
    527460*/ 
    528 #define LOG_LEVEL(classname,...) public: enum log_level_enums { __VA_ARGS__ }; log_level_template<classname> log_level; private: friend class log_level_template<classname>; friend class log_level_intermediate<classname>; static const Array<string> &log_level_names() { static const Array<string> log_level_names = log_level_base::string2Array( #__VA_ARGS__ ); return log_level_names; } 
     461#define LOG_LEVEL(classname,...) public: enum log_level_enums { __VA_ARGS__ }; log_level_template<classname> log_level; private: friend class log_level_template<classname>; friend class log_level_base<classname>; static const Array<string> &log_level_names() { static const Array<string> log_level_names = log_level_base<classname>::string2Array( #__VA_ARGS__ ); return log_level_names; } 
    529462 
    530463 
  • library/bdm/base/datasources.cpp

    r927 r942  
    5151        DS::from_setting ( set ); 
    5252 
    53         string filename; 
    5453        UI::get ( filename, set, "filename", UI::compulsory ); 
    5554 
  • library/bdm/base/user_info.cpp

    r907 r942  
    176176} 
    177177 
     178void UI::call_to_setting( const root &instance, Setting &set, string class_name ) { 
     179        try { 
     180                instance.to_setting ( set ); 
     181        } catch ( SettingException &sttng_xcptn ) { 
     182                string msg = "UIException: method "; 
     183                msg += class_name; 
     184                msg += ".to_setting(Setting&) has thrown a SettingException."; 
     185                throw UISettingException ( msg, sttng_xcptn.getPath() ); 
     186        } 
     187} 
     188 
     189void UI::save ( const root &instance, Setting &element, const string &name ) { 
     190        Setting &set = ( name == "" ) ?  (element.getType()==Setting::TypeArray || element.getType()==Setting::TypeList) ? element.add ( Setting::TypeGroup ) : element  
     191                            : element.add ( name, Setting::TypeGroup ); 
     192 
     193        call_to_setting( instance, set ); 
     194} 
     195 
     196void UI::save ( const root * const instance, Setting &element, const string &name ) { 
     197        Setting &set = ( name == "" ) ?  (element.getType()==Setting::TypeArray || element.getType()==Setting::TypeList) ? element.add ( Setting::TypeGroup ) : element  
     198                            : element.add ( name, Setting::TypeGroup ); 
     199 
     200        // add attribute "class" 
     201        const string &class_name = MappedUI::retrieve_class_name ( &typeid ( *instance ) ); 
     202        Setting &type = set.add ( "class", Setting::TypeString ); 
     203        type = class_name; 
     204 
     205        call_to_setting( *instance, set, class_name ); 
     206} 
     207 
    178208void UI::save ( const int &integer, Setting &element, const string &name ) { 
    179209        Setting &set = ( name == "" ) ? element.add ( Setting::TypeInt ) 
     
    235265} 
    236266 
    237 void UI::save ( const log_level_base &log_level, Setting &element, const string &name ) { 
    238         assert_type ( element, Setting::TypeGroup ); 
    239  
    240         string string_to_write; 
    241  
    242         Setting *list; 
    243         if( element.exists( name ) )  
    244         { 
    245                 list = &element[name]; 
    246                 assert_type ( *list, Setting::TypeString ); 
    247                 string_to_write = ( const char* ) *list; 
    248         } 
    249         else 
    250                 list = &element.add ( name, Setting::TypeString );  
    251  
    252         for( unsigned int i = 0; i < log_level.values.size(); i++ ) 
    253                 if( log_level.values[i] ) // a jeste zkontrolovat zda to jmeno uz neni obsazeno?  
    254                 { 
    255                         if( string_to_write.length() > 0 ) 
    256                                 string_to_write = string_to_write + ','; 
    257                         string_to_write = string_to_write + log_level.names()(i); 
    258                 } 
    259                          
    260         *list = string_to_write; 
     267 
     268void UI::call_from_setting( root &instance, const Setting &set, string class_name) { 
     269        try { 
     270                instance.from_setting ( set ); 
     271        } catch ( SettingException &sttng_xcptn ) { 
     272                string msg = "UIException: method "; 
     273                msg += class_name; 
     274                msg += ".from_setting(Setting&) has thrown a SettingException."; 
     275                throw UISettingException ( msg, sttng_xcptn.getPath() ); 
     276        } catch ( std::runtime_error &e ) { 
     277                string msg = "UIException: method "; 
     278                msg += class_name; 
     279                msg += " says: "; 
     280                msg += e.what(); 
     281                throw UISettingException ( msg, set ); 
     282        }  
     283 
     284        // validate the new instance 
     285        instance.validate();     
     286} 
     287 
     288void UI::from_setting ( root &instance, const Setting &element ) { 
     289        const SettingResolver link ( element ); 
     290        assert_type( link.result, Setting::TypeGroup ); 
     291        call_from_setting( instance, link.result ); 
    261292} 
    262293 
     
    393424} 
    394425 
    395 void UI::from_setting ( log_level_base &log_level, const Setting &element ) 
    396 { 
    397         string raw_log_level; 
    398         UI::get( raw_log_level, element ); 
    399         Array<string> loaded_log_level = log_level_base::string2Array( raw_log_level ); 
    400          
    401         log_level.values.reset(); 
    402  
    403         for( int i = 0; i < loaded_log_level.length(); i++ ) 
    404                 for( int j = 0; j < log_level.names().length(); j++ ){ 
    405                         if( loaded_log_level(i) == log_level.names()(j)  )  
    406                         { 
    407                                 log_level.values[j] = true; 
    408                                 break; 
    409                         }  
    410                 } 
    411 } 
    412  
    413426}//namespace 
  • library/bdm/base/user_info.h

    r927 r942  
    228228}; 
    229229 
     230 
     231//! This class stores the details which will be logged to a logger 
     232//! 
     233//! This is only the first part of the whole declaration, which has to be however separated into 
     234//! two different classes for allowing the compilation of source code. For more details 
     235//! see logger::add_setting(...) method and mainly log_level_template<T>::template<class U> void store( const enum T::log_level_enums log_level_enum, const U data ) const 
     236//! method. For the reason the second one is templated, it was necessary to declare this whole class.  
     237template<class T> class log_level_base : public root { 
     238private: 
     239        //! this is necessary to allow logger to set ids vector appropriately and also to set registered_logger 
     240        friend class logger;  
     241 
     242protected: 
     243        //! boolean flags related indicating which details will be logged to a logger 
     244        bitset<32> values; 
     245         
     246        //! vector of vectors of log IDs - one element for each entry and multiple entries can be stored on the position of one enum 
     247        Vec<ivec> ids; 
     248 
     249        //! internal pointer to the logger to which this log_level is registered 
     250        //!  
     251        //! it is set to NULL at the beginning 
     252        logger * registered_logger; 
     253 
     254public: 
     255 
     256        //! default constructor 
     257        log_level_base( ) { 
     258                registered_logger = NULL; 
     259                int len = names().length(); 
     260                ids.set_size( len ); 
     261                for( int i = 0; i<len; i++ ) 
     262                { 
     263                        ids(i).set_size ( 1 ); 
     264                        ids(i) = -1; 
     265                } 
     266        } 
     267 
     268        //! a general utility transforming a comma-separated sequence of strings into an instance of Array<strings> 
     269        static Array<string> string2Array( const string &input ) 
     270        { 
     271                string result = input; 
     272                string::size_type loc; 
     273                while( loc = result.find( ',' ), loc != string::npos ) 
     274                        result[loc] = ' '; 
     275                return Array<string>("{ " + result + " }" ); 
     276        } 
     277 
     278 
     279 
     280        //! Set log_levels according to the Setting element 
     281        void from_setting ( const Setting &element ) 
     282        { 
     283                string raw_log_level; 
     284                UI::get( raw_log_level, element ); 
     285                Array<string> loaded_log_level = log_level_base::string2Array( raw_log_level ); 
     286         
     287                values.reset(); 
     288 
     289                for( int i = 0; i < loaded_log_level.length(); i++ ) 
     290                        for( int j = 0; j < names().length(); j++ ){ 
     291                                if( loaded_log_level(i) == names()(j)  )  
     292                                { 
     293                                        values[j] = true; 
     294                                        break; 
     295                                }  
     296                        } 
     297        } 
     298 
     299        //! Store log_levels into the Setting element 
     300        void to_setting ( Setting &element ) const  
     301        { 
     302                // HERE WE WANT NOT TO DELETE PREVIOUS DATA STORED BY OTHER LOG_LEVELS, SEE SPECIAL IMPLEMENTATION OF UI::GET(...) FOR THIS CLASS 
     303                string string_to_write =  ( const char* ) element; 
     304 
     305                for( unsigned int i = 0; i < values.size(); i++ ) 
     306                        if( values[i] )  
     307                        { 
     308                                if( string_to_write.length() > 0 ) 
     309                                        string_to_write = string_to_write + ','; 
     310                                string_to_write = string_to_write + names()(i); 
     311                        } 
     312                         
     313                element = string_to_write; 
     314        } 
     315 
     316        //! this method adds new id to its proper position and return the name of this position 
     317        string store_id_and_give_name( enum T::log_level_enums const log_level_enum,  int enum_subindex, int id ) { 
     318                if( ids(log_level_enum).length() <= enum_subindex ) 
     319                        ids(log_level_enum).set_size( enum_subindex+1, true ); 
     320                ids(log_level_enum)(enum_subindex) = id;  
     321 
     322                // here we remove a "log" prefix from name, i.e., for instance it transforms "logevidence" to "evidence" 
     323                ostringstream stream; 
     324                string name_with_prefix = names()(log_level_enum); 
     325                string possible_log_prefix = name_with_prefix.substr(0,3); 
     326                if( possible_log_prefix == "log" ) 
     327                        stream << name_with_prefix.substr(3,name_with_prefix.length()-3); 
     328                else  
     329                        stream << name_with_prefix; 
     330 
     331                // add number to name only in the case there are more registered vectors with the same log_level_enum 
     332                if( ids(log_level_enum).length() > 1 ) 
     333                        stream << "*" << enum_subindex; 
     334                 
     335                return stream.str(); 
     336        } 
     337 
     338        //! string equivalents of the used enumerations which are filled with a help of #LOG_LEVEL macro within class T 
     339        const Array<string> &names() const 
     340        { 
     341                return T::log_level_names(); 
     342        } 
     343 
     344        //! read only operator for testing individual fields of log_level 
     345        //! 
     346        //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe 
     347        bool operator [] (const enum T::log_level_enums &log_level_enum ) const 
     348        { 
     349                return values[log_level_enum]; 
     350        } 
     351 
     352        //! operator for setting an individual field of log_level  
     353        //! 
     354        //! it is necessary to acces it with a proper enumeration type, thus this approach is type-safe 
     355        bitset<32>::reference operator [] (const enum T::log_level_enums &log_level_enum ) 
     356        { 
     357                return values[log_level_enum]; 
     358        } 
     359}; 
     360//UIREGISTER IS FORBIDDEN FOR THIS CLASS,  AS IT SHOULD BE LOADED ONLY THROUGH THE SPECIALIZED UI::GET(...) METHOD 
     361 
    230362/*! 
    231363@brief UI is an abstract class which collects all the auxiliary functions useful to prepare some concrete 
     
    292424        static const Setting& to_child_setting ( const Setting &element, const string &name ); 
    293425 
     426        //! A shortcut for calling instance.from_setting( set ); with some error catches added 
     427        static void call_from_setting( root &instance, const Setting &set, string class_name = "unknown"); 
     428 
     429        //! A shortcut for calling instance.to_setting( set ); with some error catches added 
     430        static void call_to_setting( const root &instance, Setting &set, string class_name = "unknown" ); 
     431 
    294432        //! This method converts a Setting into a matrix 
    295433        static void from_setting ( mat& matrix, const Setting &element ); 
     
    304442        //! This method converts a Setting into a real scalar    
    305443        static void from_setting ( double &real, const Setting &element ); 
    306         //! This method converts a Setting into a log_level variant and initialize options properly 
    307         static void from_setting ( log_level_base &log_level, const Setting &element ); 
    308  
     444        //! This method converts a Setting into a class T descendant 
     445        static void from_setting ( root &instance, const Setting &element ); 
    309446        //! This method converts a Setting into a class T descendant 
    310447        template<class T> static void from_setting ( T* &instance, const Setting &element ) { 
     
    330467 
    331468                try { 
    332                         instance->from_setting ( link.result ); 
    333                 } catch ( SettingException &sttng_xcptn ) { 
    334                         delete instance; 
    335                         instance = 0; 
    336                         string msg = "UIException: method "; 
    337                         msg += class_name; 
    338                         msg += ".from_setting(Setting&) has thrown a SettingException."; 
    339                         throw UISettingException ( msg, sttng_xcptn.getPath() ); 
    340                 } catch ( std::runtime_error &e ) { 
    341                         delete instance; 
    342                         instance = 0; 
    343                         string msg = "UIException: method "; 
    344                         msg += class_name; 
    345                         msg += " says: "; 
    346                         msg += e.what(); 
    347                         throw UISettingException ( msg, link.result ); 
     469                        call_from_setting( *instance, link.result, class_name ); 
    348470                } catch ( ... ) { 
    349471                        delete instance; 
     
    351473                        throw; 
    352474                } 
    353  
    354                 // validate the new instance 
    355                 instance->validate(); 
    356475        } 
    357476 
    358477        //! This method converts a Setting into a descendant of class 
    359478        //! T, wrapped in an instance of bdm::shared_ptr<T> . 
    360         template<class T> 
    361         static void from_setting ( bdm::shared_ptr<T> &instance, const Setting &element ) { 
     479        template<class T> static void from_setting ( bdm::shared_ptr<T> &instance, const Setting &element ) { 
    362480                T *tmp_inst = 0; 
    363481                from_setting ( tmp_inst, element ); 
     
    372490                assert_type ( link.result, Setting::TypeList ); 
    373491 
    374  
    375492                int len = link.result.getLength(); 
    376493                array_to_load.set_length ( len ); 
     
    380497                        from_setting ( array_to_load ( i ), link.result[i] ); 
    381498        } 
    382 /* 
    383         //! This is dummy version of the from_setting method for other, unsupported types. It just throws an exception. 
    384         //! 
    385         //! At the moment, this is the only way how to compile the library without obtaining the compiler error c2665. 
    386         //! The exception can help to find the place where the template is misused and also to correct it. 
    387         template<class T> static void from_setting ( T &variable_to_load, const Setting &element ) { 
    388                 std::string msg = "UIException: from_setting is not implemented for type "; 
    389                 try{ 
    390                         variable_to_load.from_setting(element); 
    391                 } catch (...){ 
    392                         msg += typeid ( T ).name(); 
    393                         msg += '.'; 
    394                         throw UISettingException ( msg, element ); 
    395                 } 
    396         } 
    397 */ 
    398499 
    399500protected: 
     
    414515        //! The new instance of type T* is constructed and initialized with values stored in the Setting element[name] 
    415516        //! 
    416         //! If there is not any sub-element named #name and settingPresence is #optional, an empty bdm::shared_ptr<T> is returned. When settingPresence is #compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). 
     517        //! If there does not exist any sub-element named #name and settingPresence is #optional, an empty bdm::shared_ptr<T> is returned. When settingPresence is #compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). 
    417518        template<class T> 
    418519        static bdm::shared_ptr<T> build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) { 
     
    431532        //! The new instance of type T* is constructed and initialized with values stored in the Setting element[index] 
    432533        //! 
    433         //! If there is not any sub-element indexed by #index, and settingPresence is #optional, an empty bdm::shared_ptr<T> is returned. When settingPresence is #compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). 
     534        //! If there does not exist any sub-element indexed by #index, and settingPresence is #optional, an empty bdm::shared_ptr<T> is returned. When settingPresence is #compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). 
    434535        template<class T> 
    435536        static bdm::shared_ptr<T> build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) { 
     
    466567 
    467568        //! The existing instance of type T is initialized with values stored in the Setting element[name] 
    468         //! If there is not any sub-element named #name, this method returns false. 
     569        //! If there does not exist any sub-element named #name, this method returns false. 
    469570        template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { 
    470571                if ( !element.exists ( name ) ) { 
     
    480581 
    481582        //! The existing instance of type T is initialized with values stored in the Setting element[index] 
    482         //! If there is not any sub-element indexed by #index, this method returns false. 
     583        //! If there does not exist any sub-element indexed by #index, this method returns false. 
    483584        template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) { 
    484585                if ( element.getLength() <= index ) { 
     
    551652        //! or by its integer index. In that case, the new element is added at the very end of the current list of child Settings. 
    552653 
    553         //! A root descendant instance is stored in the new child Setting appended to the passed element 
    554         template< class T> static void save ( const T * const instance, Setting &element, const string &name = "" ) { 
    555                 Setting &set = ( name == "" ) ?  (element.getType()==Setting::TypeArray || element.getType()==Setting::TypeList) ? element.add ( Setting::TypeGroup ) : element  
    556                                : element.add ( name, Setting::TypeGroup ); 
    557  
    558                 const string &class_name = MappedUI::retrieve_class_name ( &typeid ( *instance ) ); 
    559  
    560                 // add attribute "class" 
    561                 Setting &type = set.add ( "class", Setting::TypeString ); 
    562                 type = class_name; 
    563  
    564                 try { 
    565                         instance->to_setting ( set ); 
    566                 } catch ( SettingException &sttng_xcptn ) { 
    567                         string msg = "UIException: method "; 
    568                         msg += class_name; 
    569                         msg += ".to_setting(Setting&) has thrown a SettingException."; 
    570                         throw UISettingException ( msg, sttng_xcptn.getPath() ); 
    571                 } 
    572         } 
    573  
     654        //! A root descendant is stored in the new child Setting appended to the passed element 
     655        static void save ( const root &instance, Setting &element, const string &name = "" ); 
     656 
     657        //! A pointer to root descendant is stored in the new child Setting appended to the passed element 
     658        static void save ( const root * const instance, Setting &element, const string &name = "" ); 
     659 
     660        //! A shared pointer to root descendant is stored in the new child Setting appended to the passed element 
    574661        template< class T> static void save ( const bdm::shared_ptr<T> &instance, Setting &element, const string &name = "" ) { 
    575                 save<T> ( instance.get(), element, name ); 
     662                save( instance.get(), element, name ); 
    576663        } 
    577664 
     
    603690        static void save ( const double &real, Setting &element, const string &name = "" ); 
    604691 
    605 // The only difference from classical UserInfo approach to log_level_template is the fact 
    606         // that the actual UI element related to log_level_template could possibly exists yet. In this case,  
    607         // we do not want to throw an exception like in the case of any other type being loaded 
    608         // from Setting. We rather fill the current log_level into this existig element. This way, it is  
    609         // possible that more instances of log_level_template class (templated with different classes) 
     692    // The only difference from classical UserInfo approach here is the fact 
     693        // that the actual UI element related to log_level_base could possibly exists yet. In this case,  
     694        // we do not want to throw an exception as usually. We rather append current data into the existig element. This way, it is  
     695        // possible that more instances of log_level_base  (templated with different classes) 
    610696        // can be stored in only one line in a configuration file 
    611         static void save ( const log_level_base &log_level, Setting &element, const string &name = "log_level"  ); 
     697        template<class T> static void save ( const log_level_base<T> &log_level, Setting &element ) { 
     698                assert_type ( element, Setting::TypeGroup );             
     699                string name = "log_level"; 
     700                 
     701                if( element.exists( name ) )  
     702                        assert_type ( element[name], Setting::TypeString ); 
     703                else 
     704                        element.add ( name, Setting::TypeString );  
     705 
     706                log_level.to_setting( element[name] ); 
     707        } 
    612708 
    613709        //!@} 
  • library/bdm/bdmroot.cpp

    r907 r942  
    44namespace bdm { 
    55         
    6         //! a general utility transforming a comma-separated sequence of strings into an instance of Array<strings> 
    7         Array<string> log_level_base::string2Array( const string &input ) 
    8         { 
    9                 string result = input; 
    10                 string::size_type loc; 
    11                 while( loc = result.find( ',' ), loc != string::npos ) 
    12                         result[loc] = ' '; 
    13                 return Array<string>("{ " + result + " }" ); 
    14         } 
    15  
    166        void UI_DBG (const  Setting &S, const string &spc, ostream &out =cout){ 
    177                const char *Name=S.getName(); 
  • library/bdm/bdmroot.h

    r915 r942  
    4141//! Forward class declaration 
    4242class logger; 
    43  
    44 //! base class for all log_levels 
    45 //! 
    46 //! the existence of this class is forced by the necessity of passing log_levels to user_info methods, however, the main functionality 
    47 //! is located in \c log_level_template class 
    48 class log_level_base { 
    49 private: 
    50         // UserInfo class have to be able to read all the internal  
    51         // attributes to be able to write/read log_level to/from a Setting structure 
    52         friend class UI; 
    53  
    54         //! this is necessary to allow logger to set ids vector appropriately and also to set registered_logger 
    55         friend class logger;  
    56  
    57 protected: 
    58         //! boolean flags related indicating which details will be logged to a logger 
    59         bitset<32> values; 
    60          
    61         //! vector of vectors of log IDs - one element for each entry and multiple entries can be stored on the position of one enum 
    62         Vec<ivec> ids; 
    63  
    64         //! internal pointer to the logger to which this log_level is registered 
    65         //!  
    66         //! it is set to NULL at the beginning 
    67         logger * registered_logger; 
    68  
    69 public: 
    70         //! default constructor 
    71         log_level_base() { 
    72                 registered_logger = NULL; 
    73         } 
    74  
    75  
    76         //! a general utility transforming a comma-separated sequence of strings into an instance of Array<strings> 
    77         static Array<string> string2Array( const string &input ); 
    78  
    79         //! string equivalents of the used enumerations which are filled with a help of #LOG_LEVEL macro within class T 
    80         virtual const Array<string> &names() const = 0; 
    81 }; 
    8243 
    8344//! Root class of BDM objects 
  • library/bdm/itpp_ext.cpp

    r869 r942  
    412412                long long tmp = (long long) (A * seed); 
    413413                tmp = tmp % M; 
    414                 seed = tmp; 
     414                seed = (double) tmp; 
    415415                counter++; 
    416416                return seed / M; 
  • library/tests/testsuite/user_info_test.cpp

    r722 r942  
    9595                Setting &manufacturer_setting = set.add ( "manufacturer", Setting::TypeString ); 
    9696                manufacturer_setting = manufacturer; 
     97        } 
     98 
     99        virtual string to_string() const 
     100        { 
     101                return "the method to_string() is not implemented"; 
    97102        } 
    98103}; 
     
    202207        CHECK_EQUAL ( string ( "A car made in 1998 by audi, having 25000 kilometers on the clock.The names of passengers are as follows: Karlos Novak -1_CygWin_Matlab_Aimsun Karlosik Novacek " ), pepikovo->to_string() ); 
    203208 
     209        Transport pepikovo_static; 
     210        UI::get( pepikovo_static, in, "pepikovo", UI::compulsory ); 
     211        CHECK_EQUAL ( string ( "the method to_string() is not implemented" ), pepikovo_static.to_string() ); 
     212         
    204213        shared_ptr<Transport> jardovo ( UI::build<Transport> ( in, "jardovo", UI::compulsory ) ); 
    205214        CHECK_EQUAL ( string ( "A car made in 1992 by liaz, having 1555000 kilometers on the clock." ), jardovo->to_string() );