ISIS Core Library 0.7.2 (api 3.0.0)

/scr/tee1/isis/lib/Core/CoreUtils/progparameter.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (C) 2010  reimer@cbs.mpg.de
00003 
00004     This program is free software: you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation, either version 3 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program.  If !, see <http://www.gnu.org/licenses/>.
00016 
00017 */
00018 
00019 #include "progparameter.hpp"
00020 #include <boost/foreach.hpp>
00021 
00022 namespace isis
00023 {
00024 namespace util
00025 {
00026 
00027 ProgParameter::ProgParameter(): m_hidden( false ), m_set( false )
00028 {
00029     needed() = true;
00030 }
00031 
00032 bool ProgParameter::isHidden() const
00033 {
00034     return m_hidden;
00035 }
00036 bool &ProgParameter::hidden()
00037 {
00038     return m_hidden;
00039 }
00040 
00041 bool ProgParameter::parse( const Value<std::string> &props )
00042 {
00043     ValueBase &me = **this;
00044     bool ret = false;
00045 
00046     if ( ( ( std::string )props ).empty() ) {
00047         if ( me.is<bool>() ) {
00048             me.castTo<bool>() = true;
00049             ret = true;
00050         }
00051     } else {
00052         ret = ValueBase::convert( props, me );
00053     }
00054 
00055     LOG_IF( ret, Debug, info ) << "Parsed " << MSubject( props.toString() ) << " as " << me.toString( true );
00056 
00057     if( ret )m_set = true;
00058 
00059     return ret;
00060 }
00061 bool ProgParameter::parse_list( const isis::util::Value< slist >& props_list )
00062 {
00063     ValueBase &me = **this;
00064     bool ret = false;
00065     const util::slist &theList = props_list.castTo<util::slist>();
00066 
00067     if ( theList.empty() ) {
00068         //there is nothing like a bool-list (yet)
00069     } else {
00070         ret = ValueBase::convert( props_list, me );
00071     }
00072 
00073     LOG_IF( ret, Debug, info )
00074             << "Parsed parameter list " << MSubject( util::listToString( theList.begin(), theList.end(), " ", "", "" ) ) << " as " << me.toString( true );
00075 
00076     if( ret )m_set = true;
00077 
00078     return ret;
00079 }
00080 
00081 
00082 const std::string &ProgParameter::description()const
00083 {
00084     return m_description;
00085 }
00086 void ProgParameter::setDescription( const std::string &desc )
00087 {
00088     m_description = desc;
00089 }
00090 bool ProgParameter::isSet() const
00091 {
00092     return m_set;
00093 }
00094 
00095 
00096 ParameterMap::ParameterMap(): parsed( false ) {}
00097 
00098 bool ParameterMap::parse( int argc, char **argv )
00099 {
00100     parsed = true;
00101     std::string pName;
00102 
00103     for ( int i = 1; i < argc; ) { // scan through the command line, to find next parameter
00104         if ( argv[i][0] == '-' ) { //seems like we found a new parameter here
00105             pName = argv[i];
00106             pName.erase( 0, pName.find_first_not_of( '-' ) );
00107         } else {
00108             LOG( Runtime, error ) << "Ignoring unexpected non-parameter " << MSubject( argv[i] );
00109         }
00110 
00111         i++;
00112 
00113         if( !pName.empty() ) { // if we got a parameter before
00114             const int start = i;
00115 
00116             while( i < argc && argv[i][0] != '-' ) { //collect its properties, while there are some ..
00117                 i++;
00118             }
00119 
00120             std::list<std::string> matchingStrings;
00121             BOOST_FOREACH( ParameterMap::const_reference parameterRef, *this ) {
00122                 if( parameterRef.first.find( pName ) == 0 ) {
00123                     if( parameterRef.first.length() == pName.length() ) { //if its an exact match
00124                         matchingStrings = std::list<std::string>( 1, pName ); //use that
00125                         break;// and stop searching for partial matches
00126                     } else
00127                         matchingStrings.push_back( parameterRef.first );
00128                 }
00129             }
00130 
00131             if( matchingStrings.size() > 1 ) {
00132                 std::stringstream matchingStringStream;
00133                 BOOST_FOREACH( std::list<std::string>::const_reference stringRef, matchingStrings ) {
00134                     matchingStringStream << stringRef << " ";
00135                 }
00136                 LOG( Runtime, warning )
00137                         << "The parameter \"" << pName << "\" is ambiguous. The parameters \""
00138                         << matchingStringStream.str().erase( matchingStringStream.str().size() - 1, 1 )
00139                         << "\" are possible. Ignoring this parameter!";
00140             } else if ( !matchingStrings.size() ) {
00141                 LOG( Runtime, warning ) << "Ignoring unknown parameter " << MSubject( std::string( "-" ) + pName + " " + listToString( argv + start, argv + i, " ", "", "" ) );
00142             } else {
00143                 if( at( matchingStrings.front() ).is<util::slist>() &&
00144                     at( matchingStrings.front() ).parse_list( util::slist( argv + start, argv + i ) )
00145                   ) { //dont do tokenizing if the target is an slist (is already done by the shell)
00146                     at( matchingStrings.front() ).needed() = false; //remove needed flag, because the value is set (aka "not needed anymore")
00147                 } else if ( at( matchingStrings.front() ).parse( listToString( argv + start, argv + i, ",", "", "" ) ) ) { // parse the collected properties
00148                     at( matchingStrings.front() ).needed() = false; //remove needed flag, because the value is set (aka "not needed anymore")
00149                 } else {
00150                     LOG( Runtime, error )
00151                             << "Failed to parse the parameter " << MSubject( std::string( "-" ) + matchingStrings.front() ) << ": "
00152                             << ( start == i ? "nothing" : listToString( argv + start, argv + i, " ", "\"", "\"" ) )
00153                             << " was given, but a " << at( matchingStrings.front() ).getTypeName() << " was expected.";
00154                     parsed = false;
00155                 }
00156 
00157             }
00158         }
00159     }
00160 
00161     return parsed ;
00162 }
00163 bool ParameterMap::isComplete()const
00164 {
00165     LOG_IF( ! parsed, Debug, error ) << "You did not run parse() yet. This is very likely an error";
00166     return std::find_if( begin(), end(), neededP() ) == end();
00167 }
00168 
00169 const ProgParameter ParameterMap::operator[] ( const std::string key ) const
00170 {
00171     std::map<std::string, ProgParameter>::const_iterator at = find( key );
00172 
00173     if( at != end() )
00174         return at->second;
00175     else {
00176         LOG( Debug, error ) << "The requested parameter " << util::MSubject( key ) << " does not exist";
00177         return ProgParameter();
00178     }
00179 }
00180 ProgParameter &ParameterMap::operator[] ( const std::string key ) {return std::map<std::string, ProgParameter>::operator[]( key );}
00181 
00182 ProgParameter::operator boost::scoped_ptr<ValueBase>::unspecified_bool_type()const
00183 {
00184     boost::scoped_ptr<ValueBase> dummy;
00185 
00186     if( ( *this ).castTo<bool>() )dummy.reset( new Value<int16_t> );
00187 
00188     return  dummy;
00189 }
00190 
00191 }
00192 }