246 | | //! Class with state shared across all its instances ("monostate"), encapsulating two maps, one mapping names to UI instances and the other mapping type_infos to class names |
247 | | //! |
248 | | //! The key property of this class is that it initializes the internal maps on global init, |
249 | | //! before the instance is used for a first time. Therefore, we do not have to care about initialization |
250 | | //! during a call of UIREGISTER macro operating with both these mappings. |
251 | | class MappedUI { |
252 | | private: |
253 | | //! Type definition of mapping which transforms class names to the related UI instances |
254 | | typedef map< const string, const UI* const > StringToUIMap; |
255 | | |
256 | | //! Type definition of mapping which transforms RTTI type_infos to the related class names |
257 | | typedef map< const type_info * const, const string > TypeInfoToStringMap; |
258 | | |
259 | | //! Immediately initialized instance of type StringToUIMap |
260 | | static StringToUIMap& mapped_strings(); |
261 | | |
262 | | //! Immediately initialized instance of type TypeInfoToStringMap |
263 | | static TypeInfoToStringMap& mapped_type_infos(); |
264 | | |
265 | | //! Method for reporting a error when an attempt to operate with an unregistered class occures |
266 | | static void unregistered_class_error ( const string &unregistered_class_name ); |
267 | | |
268 | | public: |
269 | | //! Add a pair key-userinfo into the internal map |
270 | | static void add_class ( const string &class_name, const type_info * const class_type_info, const UI* const ui ); |
271 | | |
272 | | //! Search for an userinfo related to the passed class name within the internal map |
273 | | static const UI& retrieve_ui ( const string &class_name ); |
274 | | |
275 | | //! Search for an class name related to the passed type_info within the internal map |
276 | | static const string& retrieve_class_name ( const type_info* const class_type_info ); |
277 | | }; |
278 | | |
279 | | //! Function assertting that the setting element is of the SettingType type |
280 | | static void assert_type ( const Setting &element, Setting::Type type ); |
281 | | |
282 | | /*! |
283 | | \brief Method constructing a configured instance |
284 | | |
285 | | The returned pointer must be allocated using operator new |
286 | | (it's deleted at the end of its life cycle). The method is |
287 | | implemented in descendant class ParticularUI<T>, which knows |
288 | | the correct type T. |
289 | | */ |
290 | | virtual root* new_instance() const = 0; |
291 | | |
292 | | //! Method switching from the \a element to its child Setting according the passed \a index, it also does all the necessary error-checking |
293 | | static const Setting& to_child_setting ( const Setting &element, const int index ); |
294 | | |
295 | | //! Method switching from the \a element to its child Setting according the passed \a name, it also does all the necessary error-checking |
296 | | static const Setting& to_child_setting ( const Setting &element, const string &name ); |
297 | | |
298 | | //! A shortcut for calling instance.from_setting( set ); with some error catches added |
299 | | static void call_from_setting( root &instance, const Setting &set, string class_name = "unknown"); |
300 | | |
301 | | //! A shortcut for calling instance.to_setting( set ); with some error catches added |
302 | | static void call_to_setting( const root &instance, Setting &set, string class_name = "unknown" ); |
303 | | |
304 | | //! This method converts a Setting into a matrix |
305 | | static void from_setting ( mat& matrix, const Setting &element ); |
306 | | //! This method converts a Setting into a ldmat |
307 | | static void from_setting ( ldmat& matrix, const Setting &element ); |
308 | | //! This method converts a Setting into an integer vector |
309 | | static void from_setting ( ivec &vector, const Setting &element ); |
310 | | //! This method converts a Setting into a string |
311 | | static void from_setting ( string &str, const Setting &element ); |
312 | | //! This method converts a Setting into a real vector |
313 | | static void from_setting ( vec &vector, const Setting &element ); |
314 | | //! This method converts a Setting into a integer scalar |
315 | | static void from_setting ( int &integer, const Setting &element ); |
316 | | //! This method converts a Setting into a real scalar |
317 | | static void from_setting ( double &real, const Setting &element ); |
318 | | //! This method converts a Setting into a staticallly allocated root descendant |
319 | | static void from_setting ( root &instance, const Setting &element ); |
320 | | //! This method converts a Setting into a log_level |
321 | | //! |
322 | | //! Data is stored in string which has different meaning than usally. For that reason, a specialized |
323 | | //! method is necessary here to avoid the default call of "const SettingResolver link ( element );", |
324 | | //! which would lead to erroneous behaviour in this case |
325 | | static void from_setting ( log_level_base &log_level, const Setting &element ); |
326 | | //! This method converts a Setting into a dynamically allocated root descendant |
327 | | template<class T> static void from_setting ( T* &instance, const Setting &element ) { |
328 | | const SettingResolver link ( element ); |
329 | | assert_type( link.result, Setting::TypeGroup ); |
330 | | |
331 | | // we get a value stored in the "class" attribute |
332 | | string class_name; |
333 | | if ( !link.result.lookupValue ( "class", class_name ) ) |
334 | | throw UIClassException ( "UIException: the obligatory \"class\" identifier is missing.", link.result ); |
335 | | |
336 | | // then we find a user-info related to this type |
337 | | const UI& related_UI = MappedUI::retrieve_ui ( class_name ); |
338 | | |
339 | | root *typeless_instance = related_UI.new_instance(); |
340 | | bdm_assert ( typeless_instance, "UI::new_instance failed" ); |
341 | | |
342 | | instance = dynamic_cast<T*> ( typeless_instance ); |
343 | | if ( !instance ) { |
344 | | delete typeless_instance; |
345 | | 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 ); |
346 | | } |
347 | | |
348 | | try { |
349 | | call_from_setting( *instance, link.result, class_name ); |
350 | | } catch ( ... ) { |
351 | | delete instance; |
352 | | instance = 0; |
353 | | throw; |
354 | | } |
355 | | } |
356 | | |
357 | | //! This method converts a Setting into a descendant of class |
358 | | //! T, wrapped in an instance of bdm::shared_ptr<T> . |
359 | | template<class T> static void from_setting ( bdm::shared_ptr<T> &instance, const Setting &element ) { |
360 | | T *tmp_inst = 0; |
361 | | from_setting ( tmp_inst, element ); |
362 | | bdm_assert ( tmp_inst, "UI::from_setting failed" ); |
363 | | instance = tmp_inst; |
364 | | } |
365 | | |
366 | | //! This methods converts a Setting into a new templated array of type Array<T> |
367 | | template<class T> static void from_setting ( Array<T> &array_to_load, const Setting &element ) { |
368 | | const SettingResolver link ( element ); |
369 | | |
370 | | assert_type ( link.result, Setting::TypeList ); |
371 | | |
372 | | int len = link.result.getLength(); |
373 | | array_to_load.set_length ( len ); |
374 | | if ( len == 0 ) return; |
375 | | |
376 | | for ( int i = 0; i < len; i++ ) |
377 | | from_setting ( array_to_load ( i ), link.result[i] ); |
378 | | } |
| 246 | //! Class with state shared across all its instances ("monostate"), encapsulating two maps, one mapping names to UI instances and the other mapping type_infos to class names |
| 247 | //! |
| 248 | //! The key property of this class is that it initializes the internal maps on global init, |
| 249 | //! before the instance is used for a first time. Therefore, we do not have to care about initialization |
| 250 | //! during a call of UIREGISTER macro operating with both these mappings. |
| 251 | class MappedUI { |
| 252 | private: |
| 253 | //! Type definition of mapping which transforms class names to the related UI instances |
| 254 | typedef map< const string, const UI* const > StringToUIMap; |
| 255 | |
| 256 | //! Type definition of mapping which transforms RTTI type_infos to the related class names |
| 257 | typedef map< const type_info * const, const string > TypeInfoToStringMap; |
| 258 | |
| 259 | //! Immediately initialized instance of type StringToUIMap |
| 260 | static StringToUIMap& mapped_strings(); |
| 261 | |
| 262 | //! Immediately initialized instance of type TypeInfoToStringMap |
| 263 | static TypeInfoToStringMap& mapped_type_infos(); |
| 264 | |
| 265 | //! Method for reporting a error when an attempt to operate with an unregistered class occures |
| 266 | static void unregistered_class_error ( const string &unregistered_class_name ); |
| 267 | |
| 268 | public: |
| 269 | //! Add a pair key-userinfo into the internal map |
| 270 | static void add_class ( const string &class_name, const type_info * const class_type_info, const UI* const ui ); |
| 271 | |
| 272 | //! Search for an userinfo related to the passed class name within the internal map |
| 273 | static const UI& retrieve_ui ( const string &class_name ); |
| 274 | |
| 275 | //! Search for an class name related to the passed type_info within the internal map |
| 276 | static const string& retrieve_class_name ( const type_info* const class_type_info ); |
| 277 | }; |
| 278 | |
| 279 | //! Function assertting that the setting element is of the SettingType type |
| 280 | static void assert_type ( const Setting &element, Setting::Type type ); |
| 281 | |
| 282 | /*! |
| 283 | \brief Method constructing a configured instance |
| 284 | |
| 285 | The returned pointer must be allocated using operator new |
| 286 | (it's deleted at the end of its life cycle). The method is |
| 287 | implemented in descendant class ParticularUI<T>, which knows |
| 288 | the correct type T. |
| 289 | */ |
| 290 | virtual root* new_instance() const = 0; |
| 291 | |
| 292 | //! Method switching from the \a element to its child Setting according the passed \a index, it also does all the necessary error-checking |
| 293 | static const Setting& to_child_setting ( const Setting &element, const int index ); |
| 294 | |
| 295 | //! Method switching from the \a element to its child Setting according the passed \a name, it also does all the necessary error-checking |
| 296 | static const Setting& to_child_setting ( const Setting &element, const string &name ); |
| 297 | |
| 298 | //! A shortcut for calling instance.from_setting( set ); with some error catches added |
| 299 | static void call_from_setting( root &instance, const Setting &set, string class_name = "unknown"); |
| 300 | |
| 301 | //! A shortcut for calling instance.to_setting( set ); with some error catches added |
| 302 | static void call_to_setting( const root &instance, Setting &set, string class_name = "unknown" ); |
| 303 | |
| 304 | //! This method converts a Setting into a matrix |
| 305 | static void from_setting ( mat& matrix, const Setting &element ); |
| 306 | //! This method converts a Setting into a ldmat |
| 307 | static void from_setting ( ldmat& matrix, const Setting &element ); |
| 308 | //! This method converts a Setting into an integer vector |
| 309 | static void from_setting ( ivec &vector, const Setting &element ); |
| 310 | //! This method converts a Setting into a string |
| 311 | static void from_setting ( string &str, const Setting &element ); |
| 312 | //! This method converts a Setting into a real vector |
| 313 | static void from_setting ( vec &vector, const Setting &element ); |
| 314 | //! This method converts a Setting into a integer scalar |
| 315 | static void from_setting ( int &integer, const Setting &element ); |
| 316 | //! This method converts a Setting into a real scalar |
| 317 | static void from_setting ( double &real, const Setting &element ); |
| 318 | //! This method converts a Setting into a staticallly allocated root descendant |
| 319 | static void from_setting ( root &instance, const Setting &element ); |
| 320 | //! This method converts a Setting into a log_level |
| 321 | //! |
| 322 | //! Data is stored in string which has different meaning than usally. For that reason, a specialized |
| 323 | //! method is necessary here to avoid the default call of "const SettingResolver link ( element );", |
| 324 | //! which would lead to erroneous behaviour in this case |
| 325 | static void from_setting ( log_level_base &log_level, const Setting &element ); |
| 326 | //! This method converts a Setting into a dynamically allocated root descendant |
| 327 | template<class T> static void from_setting ( T* &instance, const Setting &element ) { |
| 328 | const SettingResolver link ( element ); |
| 329 | assert_type( link.result, Setting::TypeGroup ); |
| 330 | |
| 331 | // we get a value stored in the "class" attribute |
| 332 | string class_name; |
| 333 | if ( !link.result.lookupValue ( "class", class_name ) ) |
| 334 | throw UIClassException ( "UIException: the obligatory \"class\" identifier is missing.", link.result ); |
| 335 | |
| 336 | // then we find a user-info related to this type |
| 337 | const UI& related_UI = MappedUI::retrieve_ui ( class_name ); |
| 338 | |
| 339 | root *typeless_instance = related_UI.new_instance(); |
| 340 | bdm_assert ( typeless_instance, "UI::new_instance failed" ); |
| 341 | |
| 342 | instance = dynamic_cast<T*> ( typeless_instance ); |
| 343 | if ( !instance ) { |
| 344 | delete typeless_instance; |
| 345 | 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 ); |
| 346 | } |
| 347 | |
| 348 | try { |
| 349 | call_from_setting( *instance, link.result, class_name ); |
| 350 | } catch ( ... ) { |
| 351 | delete instance; |
| 352 | instance = 0; |
| 353 | throw; |
| 354 | } |
| 355 | } |
| 356 | |
| 357 | //! This method converts a Setting into a descendant of class |
| 358 | //! T, wrapped in an instance of bdm::shared_ptr<T> . |
| 359 | template<class T> static void from_setting ( bdm::shared_ptr<T> &instance, const Setting &element ) { |
| 360 | T *tmp_inst = 0; |
| 361 | from_setting ( tmp_inst, element ); |
| 362 | bdm_assert ( tmp_inst, "UI::from_setting failed" ); |
| 363 | instance = tmp_inst; |
| 364 | } |
| 365 | |
| 366 | //! This methods converts a Setting into a new templated array of type Array<T> |
| 367 | template<class T> static void from_setting ( Array<T> &array_to_load, const Setting &element ) { |
| 368 | const SettingResolver link ( element ); |
| 369 | |
| 370 | assert_type ( link.result, Setting::TypeList ); |
| 371 | |
| 372 | int len = link.result.getLength(); |
| 373 | array_to_load.set_length ( len ); |
| 374 | if ( len == 0 ) return; |
| 375 | |
| 376 | for ( int i = 0; i < len; i++ ) |
| 377 | from_setting ( array_to_load ( i ), link.result[i] ); |
| 378 | } |
388 | | //! Enum type used to determine whether the data for concrete Settingis is compulsory or optional |
389 | | enum SettingPresence { optional, compulsory } ; |
390 | | |
391 | | //! \name Initialization of classes |
392 | | //!@{ |
393 | | //! The type T has to be a #bdm::root descendant class |
394 | | |
395 | | //! The new instance of type T* is constructed and initialized with values stored in the Setting element[name] |
396 | | //! |
397 | | //! If there does not exist any sub-element named name and settingPresence is optional, an empty bdm::shared_ptr<T> is returned. |
398 | | //! When settingPresence is compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). |
399 | | template<class T> |
400 | | static bdm::shared_ptr<T> build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) { |
401 | | if ( !element.exists ( name ) ) { |
402 | | if ( settingPresence == optional ) |
403 | | return bdm::shared_ptr<T>(); |
404 | | else |
405 | | throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element ); |
406 | | } |
407 | | |
408 | | bdm::shared_ptr<T> instance; |
409 | | from_setting<T> ( instance, to_child_setting ( element, name ) ); |
410 | | return instance; |
411 | | } |
412 | | |
413 | | //! The new instance of type T* is constructed and initialized with values stored in the Setting element[index] |
414 | | //! |
415 | | //! If there does not exist any sub-element indexed by index, and settingPresence is optional, an empty bdm::shared_ptr<T> is returned. |
416 | | //! When settingPresence is compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). |
417 | | template<class T> |
418 | | static bdm::shared_ptr<T> build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) { |
419 | | if ( element.getLength() <= index ) { |
420 | | if ( settingPresence == optional ) |
421 | | return bdm::shared_ptr<T>(); |
422 | | else { |
423 | | stringstream stream; |
424 | | stream << index; |
425 | | throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element ); |
426 | | } |
427 | | } |
428 | | |
429 | | bdm::shared_ptr<T> instance; |
430 | | from_setting<T> ( instance, to_child_setting ( element, index ) ); |
431 | | return instance; |
432 | | } |
| 388 | //! Enum type used to determine whether the data for concrete Settingis is compulsory or optional |
| 389 | enum SettingPresence { optional, compulsory } ; |
| 390 | |
| 391 | //! \name Initialization of classes |
| 392 | //!@{ |
| 393 | //! The type T has to be a #bdm::root descendant class |
| 394 | |
| 395 | //! The new instance of type T* is constructed and initialized with values stored in the Setting element[name] |
| 396 | //! |
| 397 | //! If there does not exist any sub-element named name and settingPresence is optional, an empty bdm::shared_ptr<T> is returned. |
| 398 | //! When settingPresence is compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). |
| 399 | template<class T> |
| 400 | static bdm::shared_ptr<T> build ( const Setting &element, const string &name, SettingPresence settingPresence = optional ) { |
| 401 | if ( !element.exists ( name ) ) { |
| 402 | if ( settingPresence == optional ) |
| 403 | return bdm::shared_ptr<T>(); |
| 404 | else |
| 405 | throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element ); |
| 406 | } |
| 407 | |
| 408 | bdm::shared_ptr<T> instance; |
| 409 | from_setting<T> ( instance, to_child_setting ( element, name ) ); |
| 410 | return instance; |
| 411 | } |
| 412 | |
| 413 | //! The new instance of type T* is constructed and initialized with values stored in the Setting element[index] |
| 414 | //! |
| 415 | //! If there does not exist any sub-element indexed by index, and settingPresence is optional, an empty bdm::shared_ptr<T> is returned. |
| 416 | //! When settingPresence is compulsory, the returned bdm::shared_ptr<T> is never empty (an exception is thrown when the object isn't found). |
| 417 | template<class T> |
| 418 | static bdm::shared_ptr<T> build ( const Setting &element, const int index, SettingPresence settingPresence = optional ) { |
| 419 | if ( element.getLength() <= index ) { |
| 420 | if ( settingPresence == optional ) |
| 421 | return bdm::shared_ptr<T>(); |
| 422 | else { |
| 423 | stringstream stream; |
| 424 | stream << index; |
| 425 | throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element ); |
| 426 | } |
| 427 | } |
| 428 | |
| 429 | bdm::shared_ptr<T> instance; |
| 430 | from_setting<T> ( instance, to_child_setting ( element, index ) ); |
| 431 | return instance; |
| 432 | } |
437 | | template<class T> |
438 | | static bdm::shared_ptr<T> build ( const Setting &element, SettingPresence settingPresence = optional ) { |
439 | | bdm::shared_ptr<T> instance; |
440 | | from_setting<T> ( instance, element ); |
441 | | return instance; |
442 | | } |
443 | | |
444 | | //!@} |
445 | | |
446 | | //! \name Initialization of structures |
447 | | //!@{ |
448 | | //! The type T has to be int, double, string, vec, ivec or mat. |
449 | | |
450 | | //! The existing instance of type T is initialized with values stored in the Setting element[name] |
451 | | //! If there does not exist any sub-element named name, this method returns false. |
452 | | template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { |
453 | | if ( !element.exists ( name ) ) { |
454 | | if ( settingPresence == optional ) |
455 | | return false; |
456 | | else |
457 | | throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element ); |
458 | | } |
459 | | |
460 | | from_setting ( instance, to_child_setting ( element, name ) ); |
461 | | return true; |
462 | | } |
463 | | |
464 | | //! The existing instance of type T is initialized with values stored in the Setting element[index] |
465 | | //! If there does not exist any sub-element indexed by index, this method returns false. |
466 | | template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) { |
467 | | if ( element.getLength() <= index ) { |
468 | | if ( settingPresence == optional ) |
469 | | return false; |
470 | | else { |
471 | | stringstream stream; |
472 | | stream << "UIException: the compulsory Setting with the index " << index << " is missing."; |
473 | | stream << index; |
474 | | throw UISettingException ( stream.str(), element ); |
475 | | } |
476 | | } |
477 | | |
478 | | from_setting ( instance, to_child_setting ( element, index ) ); |
479 | | return true; |
480 | | } |
481 | | |
482 | | //! The existing instance of type T is initialized with values stored in the Setting element directly |
483 | | template<class T> static bool get ( T &instance, const Setting &element ) { |
484 | | from_setting ( instance, element ); |
485 | | return true; |
486 | | } |
487 | | //!@} |
488 | | |
489 | | //! \name Initialization of arrays Array<T> |
490 | | //!@{ |
491 | | //! The type T has to be int, double, string, vec, ivec or mat, or pointer to any root descendant. |
492 | | |
493 | | //! The existing array of type T is initialized with values stored in the Setting element[name] |
494 | | //! If there is not any sub-element named name, this method returns false. |
495 | | template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { |
496 | | if ( !element.exists ( name ) ) { |
497 | | if ( settingPresence == optional ) |
498 | | return false; |
499 | | else |
500 | | throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element ); |
501 | | } |
502 | | |
503 | | from_setting ( array_to_load, to_child_setting ( element, name ) ); |
504 | | return true; |
505 | | } |
506 | | |
507 | | //! The existing array of type T is initialized with values stored in the Setting element[index] |
508 | | //! If there is not any sub-element indexed by index, this method returns false. |
509 | | template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const int index, SettingPresence settingPresence = optional ) { |
510 | | if ( element.getLength() <= index ) { |
511 | | if ( settingPresence == optional ) |
512 | | return bdm::shared_ptr<T>(); |
513 | | else { |
514 | | stringstream stream; |
515 | | stream << index; |
516 | | throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element ); |
517 | | } |
518 | | } |
519 | | |
520 | | from_setting ( array_to_load, to_child_setting ( element, index ) ); |
521 | | return true; |
522 | | } |
523 | | |
524 | | //! The existing array of type T is initialized with values stored in the Setting element |
525 | | template<class T> static bool get ( Array<T> &array_to_load, const Setting &element ) { |
526 | | from_setting ( array_to_load, element ); |
527 | | return true; |
528 | | } |
529 | | //!@} |
530 | | |
531 | | //! \name Serialization of objects and structures into a new Setting |
532 | | //!@{ |
533 | | //! The new child Setting can be accessed either by its name - if some name is passed as a parameter - |
534 | | //! or by its integer index. In that case, the new element is added at the very end of the current list of child Settings. |
535 | | |
536 | | //! A root descendant is stored in the new child Setting appended to the passed element |
537 | | static void save ( const root &instance, Setting &element, const string &name = "" ); |
538 | | |
539 | | //! A pointer to root descendant is stored in the new child Setting appended to the passed element |
540 | | static void save ( const root * const instance, Setting &element, const string &name = "" ); |
541 | | |
542 | | //! A shared pointer to root descendant is stored in the new child Setting appended to the passed element |
543 | | template< class T> static void save ( const bdm::shared_ptr<T> &instance, Setting &element, const string &name = "" ) { |
544 | | save( instance.get(), element, name ); |
545 | | } |
546 | | |
547 | | //! An Array<T> instance is stored in the new child Setting appended to the passed element |
548 | | template<class T> static void save ( const Array<T> &array_to_save, Setting &element, const string &name = "" ) { |
549 | | assert_type ( element, Setting::TypeGroup ); |
550 | | Setting &list = ( name == "" ) ? element.add ( Setting::TypeList ) |
551 | | : element.add ( name, Setting::TypeList ); |
552 | | for ( int i = 0; i < array_to_save.length(); i++ ) |
553 | | save ( array_to_save ( i ), list ); |
554 | | } |
555 | | |
556 | | //! A matrix(of type mat) is stored in the new child Setting appended to the passed element |
557 | | static void save ( const mat &matrix, Setting &element, const string &name = "" ); |
558 | | |
559 | | //! A matrix(of type mat) is stored in the new child Setting appended to the passed element |
560 | | static void save ( const ldmat &matrix, Setting &element, const string &name = "" ); |
561 | | |
562 | | //! An integer vector (of type ivec) is stored in the new child Setting appended to the passed element |
563 | | static void save ( const ivec &vec, Setting &element, const string &name = "" ); |
564 | | |
565 | | //! A double vector (of type vec) is stored in the new child Setting appended to the passed element |
566 | | static void save ( const vec &vector, Setting &element, const string &name = "" ); |
567 | | |
568 | | //! A string is stored in the new child Setting appended to the passed element |
569 | | static void save ( const string &str, Setting &element, const string &name = "" ); |
570 | | |
571 | | //! An integer is stored in the new child Setting appended to the passed element |
572 | | static void save ( const int &integer, Setting &element, const string &name = "" ); |
573 | | |
574 | | //! A double is stored in the new child Setting appended to the passed element |
575 | | static void save ( const double &real, Setting &element, const string &name = "" ); |
| 437 | template<class T> |
| 438 | static bdm::shared_ptr<T> build ( const Setting &element, SettingPresence settingPresence = optional ) { |
| 439 | bdm::shared_ptr<T> instance; |
| 440 | from_setting<T> ( instance, element ); |
| 441 | return instance; |
| 442 | } |
| 443 | |
| 444 | //!@} |
| 445 | |
| 446 | //! \name Initialization of structures |
| 447 | //!@{ |
| 448 | //! The type T has to be int, double, string, vec, ivec or mat. |
| 449 | |
| 450 | //! The existing instance of type T is initialized with values stored in the Setting element[name] |
| 451 | //! If there does not exist any sub-element named name, this method returns false. |
| 452 | template<class T> static bool get ( T &instance, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { |
| 453 | if ( !element.exists ( name ) ) { |
| 454 | if ( settingPresence == optional ) |
| 455 | return false; |
| 456 | else |
| 457 | throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element ); |
| 458 | } |
| 459 | |
| 460 | from_setting ( instance, to_child_setting ( element, name ) ); |
| 461 | return true; |
| 462 | } |
| 463 | |
| 464 | //! The existing instance of type T is initialized with values stored in the Setting element[index] |
| 465 | //! If there does not exist any sub-element indexed by index, this method returns false. |
| 466 | template<class T> static bool get ( T &instance, const Setting &element, const int index, SettingPresence settingPresence = optional ) { |
| 467 | if ( element.getLength() <= index ) { |
| 468 | if ( settingPresence == optional ) |
| 469 | return false; |
| 470 | else { |
| 471 | stringstream stream; |
| 472 | stream << "UIException: the compulsory Setting with the index " << index << " is missing."; |
| 473 | stream << index; |
| 474 | throw UISettingException ( stream.str(), element ); |
| 475 | } |
| 476 | } |
| 477 | |
| 478 | from_setting ( instance, to_child_setting ( element, index ) ); |
| 479 | return true; |
| 480 | } |
| 481 | |
| 482 | //! The existing instance of type T is initialized with values stored in the Setting element directly |
| 483 | template<class T> static bool get ( T &instance, const Setting &element ) { |
| 484 | from_setting ( instance, element ); |
| 485 | return true; |
| 486 | } |
| 487 | //!@} |
| 488 | |
| 489 | //! \name Initialization of arrays Array<T> |
| 490 | //!@{ |
| 491 | //! The type T has to be int, double, string, vec, ivec or mat, or pointer to any root descendant. |
| 492 | |
| 493 | //! The existing array of type T is initialized with values stored in the Setting element[name] |
| 494 | //! If there is not any sub-element named name, this method returns false. |
| 495 | template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const string &name, SettingPresence settingPresence = optional ) { |
| 496 | if ( !element.exists ( name ) ) { |
| 497 | if ( settingPresence == optional ) |
| 498 | return false; |
| 499 | else |
| 500 | throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element ); |
| 501 | } |
| 502 | |
| 503 | from_setting ( array_to_load, to_child_setting ( element, name ) ); |
| 504 | return true; |
| 505 | } |
| 506 | |
| 507 | //! The existing array of type T is initialized with values stored in the Setting element[index] |
| 508 | //! If there is not any sub-element indexed by index, this method returns false. |
| 509 | template<class T> static bool get ( Array<T> &array_to_load, const Setting &element, const int index, SettingPresence settingPresence = optional ) { |
| 510 | if ( element.getLength() <= index ) { |
| 511 | if ( settingPresence == optional ) |
| 512 | return bdm::shared_ptr<T>(); |
| 513 | else { |
| 514 | stringstream stream; |
| 515 | stream << index; |
| 516 | throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element ); |
| 517 | } |
| 518 | } |
| 519 | |
| 520 | from_setting ( array_to_load, to_child_setting ( element, index ) ); |
| 521 | return true; |
| 522 | } |
| 523 | |
| 524 | //! The existing array of type T is initialized with values stored in the Setting element |
| 525 | template<class T> static bool get ( Array<T> &array_to_load, const Setting &element ) { |
| 526 | from_setting ( array_to_load, element ); |
| 527 | return true; |
| 528 | } |
| 529 | //!@} |
| 530 | |
| 531 | //! \name Serialization of objects and structures into a new Setting |
| 532 | //!@{ |
| 533 | //! The new child Setting can be accessed either by its name - if some name is passed as a parameter - |
| 534 | //! or by its integer index. In that case, the new element is added at the very end of the current list of child Settings. |
| 535 | |
| 536 | //! A root descendant is stored in the new child Setting appended to the passed element |
| 537 | static void save ( const root &instance, Setting &element, const string &name = "" ); |
| 538 | |
| 539 | //! A pointer to root descendant is stored in the new child Setting appended to the passed element |
| 540 | static void save ( const root * const instance, Setting &element, const string &name = "" ); |
| 541 | |
| 542 | //! A shared pointer to root descendant is stored in the new child Setting appended to the passed element |
| 543 | template< class T> static void save ( const bdm::shared_ptr<T> &instance, Setting &element, const string &name = "" ) { |
| 544 | save( instance.get(), element, name ); |
| 545 | } |
| 546 | |
| 547 | //! An Array<T> instance is stored in the new child Setting appended to the passed element |
| 548 | template<class T> static void save ( const Array<T> &array_to_save, Setting &element, const string &name = "" ) { |
| 549 | assert_type ( element, Setting::TypeGroup ); |
| 550 | Setting &list = ( name == "" ) ? element.add ( Setting::TypeList ) |
| 551 | : element.add ( name, Setting::TypeList ); |
| 552 | for ( int i = 0; i < array_to_save.length(); i++ ) |
| 553 | save ( array_to_save ( i ), list ); |
| 554 | } |
| 555 | |
| 556 | //! A matrix(of type mat) is stored in the new child Setting appended to the passed element |
| 557 | static void save ( const mat &matrix, Setting &element, const string &name = "" ); |
| 558 | |
| 559 | //! A matrix(of type mat) is stored in the new child Setting appended to the passed element |
| 560 | static void save ( const ldmat &matrix, Setting &element, const string &name = "" ); |
| 561 | |
| 562 | //! An integer vector (of type ivec) is stored in the new child Setting appended to the passed element |
| 563 | static void save ( const ivec &vec, Setting &element, const string &name = "" ); |
| 564 | |
| 565 | //! A double vector (of type vec) is stored in the new child Setting appended to the passed element |
| 566 | static void save ( const vec &vector, Setting &element, const string &name = "" ); |
| 567 | |
| 568 | //! A string is stored in the new child Setting appended to the passed element |
| 569 | static void save ( const string &str, Setting &element, const string &name = "" ); |
| 570 | |
| 571 | //! An integer is stored in the new child Setting appended to the passed element |
| 572 | static void save ( const int &integer, Setting &element, const string &name = "" ); |
| 573 | |
| 574 | //! A double is stored in the new child Setting appended to the passed element |
| 575 | static void save ( const double &real, Setting &element, const string &name = "" ); |