From 35b0e1055da40101ba544d31771427e352c41e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= <klinkjak@fjfi.cvut.cz> Date: Sat, 17 Nov 2018 13:23:05 +0100 Subject: [PATCH] Moved stuff from ConfigDescription.cpp and ParameterContainer.cpp into header files --- src/TNL/Config/CMakeLists.txt | 22 +-- src/TNL/Config/ConfigDescription.cpp | 146 ------------------ src/TNL/Config/ConfigDescription.h | 135 ++++++++++++++-- src/TNL/Config/ParameterContainer.h | 144 ++++++++++++----- src/TNL/Config/make_unique.h | 15 ++ ...ameterContainer.cpp => parseCommandLine.h} | 146 +++++------------- 6 files changed, 275 insertions(+), 333 deletions(-) delete mode 100644 src/TNL/Config/ConfigDescription.cpp create mode 100644 src/TNL/Config/make_unique.h rename src/TNL/Config/{ParameterContainer.cpp => parseCommandLine.h} (63%) diff --git a/src/TNL/Config/CMakeLists.txt b/src/TNL/Config/CMakeLists.txt index 3e11699a7f..b88a173fe8 100644 --- a/src/TNL/Config/CMakeLists.txt +++ b/src/TNL/Config/CMakeLists.txt @@ -1,25 +1,13 @@ -SET( headers +SET( headers ConfigEntryType.h ConfigEntryBase.h ConfigEntry.h ConfigEntryList.h ConfigDelimiter.h - ConfigDescription.h + ConfigDescription.h + make_unique.h ParameterContainer.h - ) - -SET( CURRENT_DIR ${CMAKE_SOURCE_DIR}/src/TNL/Config ) -set( common_SOURCES - ${CURRENT_DIR}/ConfigDescription.cpp - ${CURRENT_DIR}/ParameterContainer.cpp ) -SET( tnl_config_SOURCES - ${common_SOURCES} - PARENT_SCOPE ) - -if( BUILD_CUDA ) -SET( tnl_config_CUDA__SOURCES - ${common_SOURCES} - PARENT_SCOPE ) -endif() + parseCommandLine.h +) INSTALL( FILES ${headers} DESTINATION ${TNL_TARGET_INCLUDE_DIRECTORY}/Config ) diff --git a/src/TNL/Config/ConfigDescription.cpp b/src/TNL/Config/ConfigDescription.cpp deleted file mode 100644 index e8859523cc..0000000000 --- a/src/TNL/Config/ConfigDescription.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/*************************************************************************** - Config::ConfigDescription.cpp - description - ------------------- - begin : 2007/06/09 - copyright : (C) 2007 by Tomas Oberhuber - email : tomas.oberhuber@fjfi.cvut.cz - ***************************************************************************/ - -/* See Copyright Notice in tnl/Copyright */ - -#include <fstream> -#include <iomanip> -#include <string> - -#include <TNL/Config/ConfigDescription.h> -#include <TNL/Config/ParameterContainer.h> - -namespace TNL { -namespace Config { - -void -ConfigDescription:: -printUsage( const char* program_name ) const -{ - std::cout << "Usage of: " << program_name << std::endl << std::endl; - const int entries_num = entries.size(); - int max_name_length( 0 ); - int max_type_length( 0 ); - for( int j = 0; j < entries_num; j++ ) - if( ! entries[ j ]->isDelimiter() ) - { - max_name_length = std::max( max_name_length, - entries[ j ] -> name. getLength() ); - max_type_length = std::max( max_type_length, - entries[ j ] -> getUIEntryType().getLength() ); - } - max_name_length += 2; // this is for '--' - - for( int j = 0; j < entries_num; j++ ) - { - if( entries[ j ]->isDelimiter() ) - { - std::cout << std::endl; - std::cout << entries[ j ]->description; - std::cout << std::endl << std::endl; - } - else - { - std::cout << std::setw( max_name_length + 3 ) << String( "--" ) + entries[ j ]->name - << std::setw( max_type_length + 5 ) << entries[ j ] -> getUIEntryType() - << " " << entries[ j ]->description; - if( entries[ j ] -> required ) - std::cout << " *** REQUIRED ***"; - if( entries[ j ]->hasEnumValues() ) - { - std::cout << std::endl - << std::setw( max_name_length + 3 ) << "" - << std::setw( max_type_length + 5 ) << "" - << " "; - entries[ j ]->printEnumValues(); - } - if( entries[ j ]->hasDefaultValue ) - { - std::cout << std::endl - << std::setw( max_name_length + 3 ) << "" - << std::setw( max_type_length + 5 ) << "" - << " "; - std::cout << "- Default value is: " << entries[ j ]->printDefaultValue(); - } - std::cout << std::endl; - } - } - std::cout << std::endl; -} - -void -ConfigDescription:: -addMissingEntries( Config::ParameterContainer& parameter_container ) const -{ - const int size = entries.size(); - for( int i = 0; i < size; i++ ) - { - const char* entry_name = entries[ i ]->name.getString(); - if( entries[ i ]->hasDefaultValue && - ! parameter_container.checkParameter( entry_name ) ) - { - if( entries[ i ]->getEntryType() == "String" ) - { - ConfigEntry< String >& entry = dynamic_cast< ConfigEntry< String >& >( *entries[ i ] ); - parameter_container.addParameter< String >( entry_name, entry.defaultValue ); - continue; - } - if( entries[ i ]->getEntryType() == "bool" ) - { - ConfigEntry< bool >& entry = dynamic_cast< ConfigEntry< bool >& >( *entries[ i ] ); - parameter_container.addParameter< bool >( entry_name, entry.defaultValue ); - continue; - } - if( entries[ i ]->getEntryType() == "int" ) - { - ConfigEntry< int >& entry = dynamic_cast< ConfigEntry< int >& >( *entries[ i ] ); - parameter_container.addParameter< int >( entry_name, entry.defaultValue ); - continue; - } - if( entries[ i ]->getEntryType() == "double" ) - { - ConfigEntry< double >& entry = dynamic_cast< ConfigEntry< double >& >( *entries[ i ] ); - parameter_container.addParameter< double >( entry_name, entry.defaultValue ); - continue; - } - } - } -} - -bool -Config::ConfigDescription:: -checkMissingEntries( Config::ParameterContainer& parameter_container, - bool printUsage, - const char* programName ) const -{ - const int size = entries.size(); - std::vector< std::string > missingParameters; - for( int i = 0; i < size; i++ ) - { - const char* entry_name = entries[ i ] -> name.getString(); - if( entries[ i ] -> required && - ! parameter_container.checkParameter( entry_name ) ) - missingParameters.push_back( entry_name ); - } - if( missingParameters.size() > 0 ) - { - std::cerr << "Some mandatory parameters are misssing. They are listed at the end. " << std::endl; - if( printUsage ) - this->printUsage( programName ); - std::cerr << "Add the following missing parameters to the command line: " << std::endl << " "; - for( int i = 0; i < (int) missingParameters.size(); i++ ) - std::cerr << "--" << missingParameters[ i ] << " ... "; - std::cerr << std::endl; - return false; - } - return true; -} - -} // namespace Config -} // namespace TNL - diff --git a/src/TNL/Config/ConfigDescription.h b/src/TNL/Config/ConfigDescription.h index 6aa1c52f8e..7d05b09763 100644 --- a/src/TNL/Config/ConfigDescription.h +++ b/src/TNL/Config/ConfigDescription.h @@ -10,20 +10,11 @@ #pragma once +#include <iomanip> +#include <string> #include <vector> #include <memory> - -// std::make_unique does not exist until C++14 -// https://stackoverflow.com/a/9657991 -#if __cplusplus < 201402L -namespace std { - template<typename T, typename ...Args> - std::unique_ptr<T> make_unique( Args&& ...args ) - { - return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) ); - } -} -#endif +#include "make_unique.h" #include <TNL/Assert.h> #include <TNL/String.h> @@ -32,12 +23,11 @@ namespace std { #include <TNL/Config/ConfigEntry.h> #include <TNL/Config/ConfigEntryList.h> #include <TNL/Config/ConfigDelimiter.h> +#include <TNL/Config/ParameterContainer.h> namespace TNL { namespace Config { -class ParameterContainer; - class ConfigDescription { public: @@ -245,21 +235,130 @@ public: * If there is missing entry with defined default value in the Config::ParameterContainer it is going to be added. * \param parameter_container Name of the ParameterContainer object. */ - void addMissingEntries( Config::ParameterContainer& parameter_container ) const; + void addMissingEntries( Config::ParameterContainer& parameter_container ) const + { + const int size = entries.size(); + for( int i = 0; i < size; i++ ) + { + const char* entry_name = entries[ i ]->name.getString(); + if( entries[ i ]->hasDefaultValue && + ! parameter_container.checkParameter( entry_name ) ) + { + if( entries[ i ]->getEntryType() == "String" ) + { + ConfigEntry< String >& entry = dynamic_cast< ConfigEntry< String >& >( *entries[ i ] ); + parameter_container.addParameter< String >( entry_name, entry.defaultValue ); + continue; + } + if( entries[ i ]->getEntryType() == "bool" ) + { + ConfigEntry< bool >& entry = dynamic_cast< ConfigEntry< bool >& >( *entries[ i ] ); + parameter_container.addParameter< bool >( entry_name, entry.defaultValue ); + continue; + } + if( entries[ i ]->getEntryType() == "int" ) + { + ConfigEntry< int >& entry = dynamic_cast< ConfigEntry< int >& >( *entries[ i ] ); + parameter_container.addParameter< int >( entry_name, entry.defaultValue ); + continue; + } + if( entries[ i ]->getEntryType() == "double" ) + { + ConfigEntry< double >& entry = dynamic_cast< ConfigEntry< double >& >( *entries[ i ] ); + parameter_container.addParameter< double >( entry_name, entry.defaultValue ); + continue; + } + } + } + } //! Check for all entries with the flag 'required'. /*! Returns false if any parameter is missing. */ bool checkMissingEntries( Config::ParameterContainer& parameter_container, bool printUsage, - const char* programName ) const; + const char* programName ) const + { + const int size = entries.size(); + std::vector< std::string > missingParameters; + for( int i = 0; i < size; i++ ) + { + const char* entry_name = entries[ i ] -> name.getString(); + if( entries[ i ] -> required && + ! parameter_container.checkParameter( entry_name ) ) + missingParameters.push_back( entry_name ); + } + if( missingParameters.size() > 0 ) + { + std::cerr << "Some mandatory parameters are misssing. They are listed at the end. " << std::endl; + if( printUsage ) + this->printUsage( programName ); + std::cerr << "Add the following missing parameters to the command line: " << std::endl << " "; + for( int i = 0; i < (int) missingParameters.size(); i++ ) + std::cerr << "--" << missingParameters[ i ] << " ... "; + std::cerr << std::endl; + return false; + } + return true; + } /** * \brief Prints configuration description with the \e program_name at the top. * * \param program_name Name of the program */ - void printUsage( const char* program_name ) const; + void printUsage( const char* program_name ) const + { + std::cout << "Usage of: " << program_name << std::endl << std::endl; + const int entries_num = entries.size(); + int max_name_length( 0 ); + int max_type_length( 0 ); + for( int j = 0; j < entries_num; j++ ) + if( ! entries[ j ]->isDelimiter() ) + { + max_name_length = std::max( max_name_length, + entries[ j ] -> name. getLength() ); + max_type_length = std::max( max_type_length, + entries[ j ] -> getUIEntryType().getLength() ); + } + max_name_length += 2; // this is for '--' + + for( int j = 0; j < entries_num; j++ ) + { + if( entries[ j ]->isDelimiter() ) + { + std::cout << std::endl; + std::cout << entries[ j ]->description; + std::cout << std::endl << std::endl; + } + else + { + std::cout << std::setw( max_name_length + 3 ) << String( "--" ) + entries[ j ]->name + << std::setw( max_type_length + 5 ) << entries[ j ] -> getUIEntryType() + << " " << entries[ j ]->description; + if( entries[ j ] -> required ) + std::cout << " *** REQUIRED ***"; + if( entries[ j ]->hasEnumValues() ) + { + std::cout << std::endl + << std::setw( max_name_length + 3 ) << "" + << std::setw( max_type_length + 5 ) << "" + << " "; + entries[ j ]->printEnumValues(); + } + if( entries[ j ]->hasDefaultValue ) + { + std::cout << std::endl + << std::setw( max_name_length + 3 ) << "" + << std::setw( max_type_length + 5 ) << "" + << " "; + std::cout << "- Default value is: " << entries[ j ]->printDefaultValue(); + } + std::cout << std::endl; + } + } + std::cout << std::endl; + } //bool parseConfigDescription( const char* file_name ); @@ -270,3 +369,5 @@ protected: } //namespace Config } //namespace TNL + +#include <TNL/Config/parseCommandLine.h> diff --git a/src/TNL/Config/ParameterContainer.h b/src/TNL/Config/ParameterContainer.h index 632865f0d2..209b77a7c4 100644 --- a/src/TNL/Config/ParameterContainer.h +++ b/src/TNL/Config/ParameterContainer.h @@ -12,8 +12,8 @@ #include <vector> #include <memory> +#include "make_unique.h" -#include <TNL/Config/ConfigDescription.h> #include <TNL/param-types.h> //#include <TNL/Debugging/StackBacktrace.h> @@ -58,14 +58,25 @@ public: */ template< class T > bool addParameter( const String& name, - const T& value ); + const T& value ) + { + parameters.push_back( std::make_unique< Parameter< T > >( name, TNL::getType< T >(), value ) ); + return true; + } /** * \brief Checks whether the parameter \e name already exists in ParameterContainer. * * \param name Name of the parameter. */ - bool checkParameter( const String& name ) const; + bool checkParameter( const String& name ) const + { + const int size = parameters.size(); + for( int i = 0; i < size; i++ ) + if( parameters[ i ]->name == name ) + return true; + return false; + } /** * \brief Assigns new \e value to the parameter \e name. @@ -76,7 +87,25 @@ public: */ template< class T > bool setParameter( const String& name, - const T& value ); + const T& value ) + { + for( int i = 0; i < (int) parameters.size(); i++ ) { + if( parameters[ i ]->name == name ) { + if( parameters[ i ]->type == TNL::getType< T >() ) { + Parameter< T >& parameter = dynamic_cast< Parameter< T >& >( *parameters[ i ] ); + parameter.value = value; + return true; + } + else { + std::cerr << "Parameter " << name << " already exists with different type " + << parameters[ i ]->type << " not " + << TNL::getType< T >() << std::endl; + throw 0; + } + } + } + return addParameter< T >( name, value ); + } /** * \brief Checks whether the parameter \e name is given the \e value. @@ -133,49 +162,80 @@ public: throw 0; } +/* //! Broadcast to other nodes in MPI cluster - //void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ); - -protected: - std::vector< std::unique_ptr< ParameterBase > > parameters; -}; - -bool parseCommandLine( int argc, char* argv[], - const ConfigDescription& config_description, - ParameterContainer& parameters, - bool printUsage = true ); - -template< class T > -bool -ParameterContainer:: -addParameter( const String& name, const T& value ) -{ - parameters.push_back( std::make_unique< Parameter< T > >( name, TNL::getType< T >(), value ) ); - return true; -}; - -template< class T > -bool -ParameterContainer:: -setParameter( const String& name, - const T& value ) -{ - for( int i = 0; i < (int) parameters.size(); i++ ) { - if( parameters[ i ]->name == name ) { - if( parameters[ i ]->type == TNL::getType< T >() ) { - Parameter< T >& parameter = dynamic_cast< Parameter< T >& >( *parameters[ i ] ); - parameter.value = value; - return true; + void MPIBcast( int root, MPI_Comm mpi_comm = MPI_COMM_WORLD ) + { + #ifdef USE_MPI + int i; + int size = parameters. getSize(); + :: MPIBcast( size, 1, root, mpi_comm ); + for( i = 0; i < size; i ++ ) + { + if( MPIGetRank() == root ) + { + tnlParameterBase* param = parameters[ i ]; + param -> type. MPIBcast( root, MPI_COMM_WORLD ); + param -> name. MPIBcast( root, MPI_COMM_WORLD ); + if( param -> type == "String" ) + { + ( ( tnlParameter< String >* ) param ) -> value. MPIBcast( root, mpi_comm ); + } + if( param -> type == "bool" ) + { + :: MPIBcast( ( ( tnlParameter< bool >* ) param ) -> value, 1, root, mpi_comm ); + } + if( param -> type == "int" ) + { + :: MPIBcast( ( ( tnlParameter< int >* ) param ) -> value, 1, root, mpi_comm ); + } + if( param -> type == "double" ) + { + :: MPIBcast( ( ( tnlParameter< double >* ) param ) -> value, 1, root, mpi_comm ); + } } - else { - std::cerr << "Parameter " << name << " already exists with different type " - << parameters[ i ]->type << " not " - << TNL::getType< T >() << std::endl; - throw 0; + else + { + String param_type, param_name; + param_type. MPIBcast( root, MPI_COMM_WORLD ); + param_name. MPIBcast( root, MPI_COMM_WORLD ); + if( param_type == "mString" ) + { + String val; + val. MPIBcast( root, mpi_comm ); + addParameter< String >( param_name. getString(), + val ); + } + if( param_type == "bool" ) + { + bool val; + :: MPIBcast( val, 1, root, mpi_comm ); + addParameter< bool >( param_name. getString(), + val ); + } + if( param_type == "int" ) + { + int val; + :: MPIBcast( val, 1, root, mpi_comm ); + addParameter< int >( param_name. getString(), + val ); + } + if( param_type == "double" ) + { + double val; + :: MPIBcast( val, 1, root, mpi_comm ); + addParameter< double >( param_name. getString(), + val ); + } + } } + #endif } - return addParameter< T >( name, value ); +*/ + +protected: + std::vector< std::unique_ptr< ParameterBase > > parameters; }; } // namespace Config diff --git a/src/TNL/Config/make_unique.h b/src/TNL/Config/make_unique.h new file mode 100644 index 0000000000..4a4078a028 --- /dev/null +++ b/src/TNL/Config/make_unique.h @@ -0,0 +1,15 @@ +#pragma once + +// std::make_unique does not exist until C++14 +// https://stackoverflow.com/a/9657991 +#if __cplusplus < 201402L +#include <memory> + +namespace std { + template<typename T, typename ...Args> + std::unique_ptr<T> make_unique( Args&& ...args ) + { + return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) ); + } +} +#endif diff --git a/src/TNL/Config/ParameterContainer.cpp b/src/TNL/Config/parseCommandLine.h similarity index 63% rename from src/TNL/Config/ParameterContainer.cpp rename to src/TNL/Config/parseCommandLine.h index f318acabb4..2c8c62090a 100644 --- a/src/TNL/Config/ParameterContainer.cpp +++ b/src/TNL/Config/parseCommandLine.h @@ -1,5 +1,5 @@ /*************************************************************************** - Config::ParameterContainer.cpp - description + parseCommandLine.h - description ------------------- begin : 2007/06/15 copyright : (C) 2007 by Tomas Oberhuber @@ -8,121 +8,47 @@ /* See Copyright Notice in tnl/Copyright */ -#include <ctype.h> +#pragma once + #include <cstring> -#include <stdio.h> +#include <string> -#include "ParameterContainer.h" -#include <TNL/Object.h> +//#include <TNL/Object.h> +#include <TNL/Config/ConfigDescription.h> +#include <TNL/Config/ParameterContainer.h> namespace TNL { -namespace Config { - -bool matob( const char* value, bool& ret_val ) -{ - if( strcasecmp( value, "yes" ) == 0 || - strcasecmp( value, "true" ) == 0 ) - { - ret_val = true; - return true; - } - if( strcasecmp( value, "no" ) == 0 || - strcasecmp( value, "false" ) == 0 ) - { - ret_val = false; - return true; - } - return false; -} - -bool -Config::ParameterContainer:: -checkParameter( const String& name ) const -{ - const int size = parameters.size(); - for( int i = 0; i < size; i++ ) - if( parameters[ i ]->name == name ) - return true; - return false; -} - -/*void ParameterContainer::MPIBcast( int root, MPI_Comm mpi_comm ) -{ -#ifdef USE_MPI - int i; - int size = parameters. getSize(); - :: MPIBcast( size, 1, root, mpi_comm ); - for( i = 0; i < size; i ++ ) - { - if( MPIGetRank() == root ) - { - tnlParameterBase* param = parameters[ i ]; - param -> type. MPIBcast( root, MPI_COMM_WORLD ); - param -> name. MPIBcast( root, MPI_COMM_WORLD ); - if( param -> type == "String" ) - { - ( ( tnlParameter< String >* ) param ) -> value. MPIBcast( root, mpi_comm ); - } - if( param -> type == "bool" ) - { - :: MPIBcast( ( ( tnlParameter< bool >* ) param ) -> value, 1, root, mpi_comm ); - } - if( param -> type == "int" ) - { - :: MPIBcast( ( ( tnlParameter< int >* ) param ) -> value, 1, root, mpi_comm ); - } - if( param -> type == "double" ) - { - :: MPIBcast( ( ( tnlParameter< double >* ) param ) -> value, 1, root, mpi_comm ); - } - } - else - { - String param_type, param_name; - param_type. MPIBcast( root, MPI_COMM_WORLD ); - param_name. MPIBcast( root, MPI_COMM_WORLD ); - if( param_type == "mString" ) - { - String val; - val. MPIBcast( root, mpi_comm ); - addParameter< String >( param_name. getString(), - val ); - } - if( param_type == "bool" ) - { - bool val; - :: MPIBcast( val, 1, root, mpi_comm ); - addParameter< bool >( param_name. getString(), - val ); - } - if( param_type == "int" ) - { - int val; - :: MPIBcast( val, 1, root, mpi_comm ); - addParameter< int >( param_name. getString(), - val ); - } - if( param_type == "double" ) - { - double val; - :: MPIBcast( val, 1, root, mpi_comm ); - addParameter< double >( param_name. getString(), - val ); - } - } - } -#endif -} -*/ +std::vector< String > +parseObjectType( const String& objectType ); +namespace Config { -bool +inline bool parseCommandLine( int argc, char* argv[], const Config::ConfigDescription& config_description, Config::ParameterContainer& parameters, - bool printUsage ) + bool printUsage = true ) { + auto iequals = []( const std::string& a, const std::string& b ) + { + if( a.size() != b.size() ) + return false; + for( unsigned int i = 0; i < a.size(); i++ ) + if( std::tolower(a[i]) != std::tolower(b[i]) ) + return false; + return true; + }; + + auto matob = [iequals]( const char* value ) + { + if( iequals( value, "yes" ) || iequals( value, "true" ) ) + return true; + if( iequals( value, "no" ) || iequals( value, "false" ) ) + return true; + return false; + }; + int i; bool parse_error( false ); for( i = 1; i < argc; i ++ ) @@ -177,13 +103,12 @@ parseCommandLine( int argc, char* argv[], } if( parsedEntryType[ 1 ] == "bool" ) { - bool bool_val; - if( ! matob( value, bool_val ) ) + if( ! matob( value ) ) { std::cerr << "Yes/true or no/false is required for the parameter " << option << "." << std::endl; parse_error = true; } - else bool_list.push_back( bool_val ); + else bool_list.push_back( true ); } if( parsedEntryType[ 1 ] == "int" ) { @@ -216,13 +141,12 @@ parseCommandLine( int argc, char* argv[], } if( parsedEntryType[ 0 ] == "bool" ) { - bool bool_val; - if( ! matob( value, bool_val ) ) + if( ! matob( value ) ) { std::cerr << "Yes/true or no/false is required for the parameter " << option << "." << std::endl; parse_error = true; } - else parameters.addParameter< bool >( option, bool_val ); + else parameters.addParameter< bool >( option, true ); continue; } if( parsedEntryType[ 0 ] == "int" ) -- GitLab