From: Baptiste L. <bl...@us...> - 2004-08-05 20:52:58
|
Update of /cvsroot/cpptool/CppParser/include/cpputtools/configuration In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20897/include/cpputtools/configuration Added Files: description.h errors.h forwards.h parser.h simplertti.h validator.h value.h values.h Log Message: * upgraded to current cppunit 2 cvs --- NEW FILE: value.h --- #ifndef CPPUTTOOLS_CONFIGURATION_VALUE_H_INCUDED # define CPPUTTOOLS_CONFIGURATION_VALUE_H_INCUDED # include "simplertti.h" # include "validator.h" # include <cpputtools/value.h> namespace CppUTTools { namespace CommandLineOptions { class OptionHandler { public: virtual ~OptionHandler() {} virtual Value validate( const Parameters ¶meters ) const = 0; }; template<class TheOptionType> class SimpleOptionHandler : public OptionHandler { public: typedef TheOptionType OptionType; SimpleOptionHandler(); SimpleOptionHandler( Validator *validator ); SimpleOptionHandler( Validator *validator, OptionType *storage ); ~SimpleOptionHandler(); public: // overridden from OptionHandler Value validate( const Parameters ¶meters ) const; private: Validator *validator_; }; // template class SimpleOptionHandler // ////////////////////////////////////////////////////////////////// template<class TheOptionType> SimpleOptionHandler<TheOptionType>::SimpleOptionHandler() : storage_( 0 ) , validator_( new StringStreamValidator<TheOptionType>() ) { } template<class TheOptionType> SimpleOptionHandler<TheOptionType>::SimpleOptionHandler( OptionType *storage ) : storage_( storage ) , validator_( new StringStreamValidator<TheOptionType>() ) { } template<class TheOptionType> SimpleOptionHandler<TheOptionType>::SimpleOptionHandler( Validator *validator ) : storage_( 0 ) , validator_( validator ) { } template<class TheOptionType> SimpleOptionHandler<TheOptionType>::SimpleOptionHandler( Validator *validator, OptionType *storage ) : storage_( storage ) , validator_( validator ) { } template<class TheOptionType> SimpleOptionHandler<TheOptionType>::~SimpleOptionHandler() { delete validator_; } template<class TheOptionType> bool SimpleOptionHandler<TheOptionType>::hasStorage() const { return storage_ != 0; } template<class TheOptionType> void SimpleOptionHandler<TheOptionType>::storeValue( const Value &value ) const { if ( hasStorage() ) *storage_ = get<TheOptionType>( value ); } template<class TheOptionType> Value SimpleOptionHandler<TheOptionType>::validate( const Parameters ¶meters ) const { return validator_->validate( parameters ); } } } // namespace CommandLineOptions #endif // CPPUTTOOLS_CONFIGURATION_VALUE_H_INCUDED --- NEW FILE: validator.h --- #ifndef CPPUTTOOLS_CONFIGURATION_VALIDATOR_H_INCUDED # define CPPUTTOOLS_CONFIGURATION_VALIDATOR_H_INCUDED # include "errors.h" # include <cpputtools/value.h> // <cpputtools/forwards.h> namespace CppUTTools { namespace CommandLineOptions { class Validator : public ReferenceCountedPolicy { public: virtual ~Validator() {} virtual Value validate( const Parameters ¶meters ) const = 0; }; template<class OptionType> class StringStreamValidator : public Validator { public: // overridden from Validator Value validate( const Parameters ¶meters ) const; }; template<class OptionType> ValidatorPtr defaultValidator(); template<class OptionType> class EnumerationValidator : public Validator { public: void add( const String &text, const OptionType &value, const String &help = "" ); std::deque<String> inputs() const; String inputHelp( const String &text ) const; ValidatorPtr clone() const; public: // overridden from Validator Value validate( const Parameters ¶meters ) const; private: struct ValueData { OptionType value_; String help_; }; typedef std::map<String,ValueData> Values; Values values_; std::deque<String> inputs_; }; template<class Functor> ValidatorPtr makeValidator( Functor functor ); template<class OptionType> std::string validatorAdditionalMessage(); #undef COMMANDLINEOPTIONS_VALIDATOR_MESSAGE #define COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( OptionType, message ) \ template<> \ inline std::string validatorAdditionalMessage<OptionType>() \ { \ return message; \ } COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( int, "is not an integer." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( unsigned int, "is not an integer." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( short, "is not an integer." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( unsigned short, "is not an integer." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( long, "is not an integer." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( unsigned long, "is not an integer." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( float, "is not a real number." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( double, "is not a real number." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( long double, "is not a real number." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( char, "is not a character." ); COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( std::string, "is not a string." ); //COMMANDLINEOPTIONS_VALIDATOR_MESSAGE( wchar_t, "is not a character." ); // Template StringStreamValidator // ////////////////////////////////////////////////////////////////// template<class OptionType> Value StringStreamValidator<OptionType>::validate( const Parameters ¶meters ) const { IStringStream is( parameters.at(0) ); OptionType optionValue; is >> optionValue; is >> std::ws; if ( !is.eof() ) // input not completly consumed { std::ostringstream os; os << "parameter '" << parameters.at(0) << "', "; os << validatorAdditionalMessage<OptionType>(); throw ValidatorError( ValidatorError::badParameterValue, os.str() ); } return value( optionValue ); } template<class OptionType> ValidatorPtr defaultValidator() { return ValidatorPtr( new StringStreamValidator<OptionType>() ); } // Template EnumerationValidator // ////////////////////////////////////////////////////////////////// template<class OptionType> ValidatorPtr EnumerationValidator<OptionType>::clone() const { return ValidatorPtr( new EnumerationValidator<OptionType>( *this ) ); } template<class OptionType> void EnumerationValidator<OptionType>::add( const String &text, const OptionType &value, const String &help ) { ValueData data; data.value_ = value; data.help_ = help; values_.insert( Values::value_type( text, data ) ); inputs_.push_back( text ); } template<class OptionType> std::deque<String> EnumerationValidator<OptionType>::inputs() const { return inputs_; } template<class OptionType> String EnumerationValidator<OptionType>::inputHelp( const String &text ) const { Values::const_iterator it = values_.find( text ); if ( it == values_.end() ) return ""; return it->second.help_; } template<class OptionType> Value EnumerationValidator<OptionType>::validate( const Parameters ¶meters ) const { String text = parameters.at(0); Values::const_iterator it = values_.find( text ); if ( it == values_.end() ) throw ValidatorError( ValidatorError::badParameterValue, "value must be..." ); return value( it->second.value_ ); } // Function makeValidator // ////////////////////////////////////////////////////////////////// template<class Functor> class ValidatorImpl : public Validator { public: ValidatorImpl( Functor functor ) : functor_( functor ) { } // overridden from Validator Value validate( const Parameters ¶meters ) const { return functor_( parameters ); } private: Functor functor_; }; template<class Functor> ValidatorPtr validator( Functor functor ) { return ValidatorPtr( new ValidatorImpl<Functor>( functor ) ); } } } // namespace CommandLineOptions #endif // CPPUTTOOLS_CONFIGURATION_VALIDATOR_H_INCUDED --- NEW FILE: description.h --- #ifndef CPPUTTOOLS_CONFIGURATION_DESCRIPTION_H_INCUDED # define CPPUTTOOLS_CONFIGURATION_DESCRIPTION_H_INCUDED # include "forwards.h" # include "errors.h" # include "validator.h" # include <cpputtools/valuebinder.h> # include <iostream> # include <map> # include <set> namespace CppUTTools { namespace CommandLineOptions { class OptionDescription // not copyable { public: enum ParameterRequirement { noParameter, // | optionalParameter, // ? requiredParameter, // : oneOrMoreParameter, // + zeroOrMoreParameter // * }; OptionDescription( const Char &shortName, const String &longName, const String &description, const ValidatorPtr &validator ); // @param packedName Has the following format: "longName,shortName". // ShortName must be a single letter. Example: "exclude,x" // Will match --exclude or -x on the command line. OptionDescription( const String &packedName, const String &description, const ValidatorPtr &validator ); ~OptionDescription(); OptionDescription &setValidator( const ValidatorPtr &validator ); // Switch parameter requirement as follow: // * if value is empty: // optionalParameter -> requiredParameter // * if value is not empty: // noParameter, requiredParameter -> optionalParameter // oneOrMoreParameter -> zeroOrMoreParameter OptionDescription &setDefaultValue( const Value &value ); OptionDescription &setStorage( const ValueBinder &storage ); const Value &defaultValue() const; bool hasDefaultValue() const; bool hasStorage() const; bool hasShortName() const; bool hasLongName() const; String shortName() const; String longName() const; String name() const; String description() const; bool hasNoParameter() const; bool mayHaveParameter() const; bool requireParameter() const; // @exception ValidatorError if validation fail. Value validate( const Parameters ¶meters ) const; // Store the final value into the location specified by the user if any. void store( const Value &value ) const; private: void setDefaultParameterRequirement(); Value defaultValue_; String shortName_; String longName_; ValueBinder storage_; String description_; ParameterRequirement parameter_; ValidatorPtr validator_; }; class OptionsDescription { public: OptionsDescription( const String &caption ); virtual ~OptionsDescription(); /// @exception OptionsDescriptionError if an option has already been registered with conflicting /// names. OptionsDescription &add( const OptionDescription &description ); /// @exception OptionsDescriptionError if an option has already been registered with conflicting /// names. OptionsDescription &add( const String &optionName, const String &description ); #if 0 /// @exception OptionsDescriptionError if an option has already been registered with conflicting /// names. OptionsDescription &add( const String &optionName, const OptionHandlerHelper &handlerHelper, const String &description ); /// @exception OptionsDescriptionError if an option has already been registered with conflicting /// names. OptionsDescription &add( const String &optionName, const OptionHandlerHelper &handlerHelper, Validator *validator, const String &description ); /// @exception OptionsDescriptionError if an option has already been registered with conflicting /// names. OptionsDescription &add( const String &optionName, Validator *validator, const String &description ); /// @exception OptionsDescriptionError if an option has already been registered with conflicting /// names. OptionsDescription &add( const String &optionName, OptionHandler *handler, const String &description ); /// @exception OptionsDescriptionError if an option has already been registered with conflicting /// names. OptionsDescription &add( const String &optionName, OptionHandler *handler, Validator *validator, const String &description ); #endif std::set<String> optionNames() const; bool hasOption( const String &optionName ) const; // long name or -shortName const OptionDescription &description( const String &optionName ) const; friend std::ostream &operator <<( std::ostream &os, const OptionsDescription &options ); private: typedef std::deque<OptionDescription> Options; Options options_; String caption_; typedef std::map<String,int> OptionIndexes; OptionIndexes shortNameIndexes_; OptionIndexes longNameIndexes_; OptionIndexes nameIndexes_; }; template<class ValueType> OptionDescription option( const std::string &optionName, const std::string &description ); template<class DefaultValueType> OptionDescription optionDefault( const std::string &optionName, const DefaultValueType &defaultValue, const std::string &description ); template<class StorageValueType> OptionDescription option( const std::string &optionName, StorageValueType &storageValue, const std::string &description ); template<class StorageValueType ,class DefaultValueType> OptionDescription option( const std::string &optionName, StorageValueType &storageValue, const DefaultValueType &defaultValue, const std::string &description ); template<class ValueType> OptionDescription validatedOption( const std::string &optionName, const std::string &description, const ValidatorPtr &validator ); template<class DefaultValueType> OptionDescription validatedOptionDefault( const std::string &optionName, const DefaultValueType &defaultValue, const std::string &description, const ValidatorPtr &validator ); template<class StorageValueType> OptionDescription validatedOption( const std::string &optionName, StorageValueType &storageValue, const std::string &description, const ValidatorPtr &validator ); template<class StorageValueType ,class DefaultValueType> OptionDescription validatedOption( const std::string &optionName, StorageValueType &storageValue, const DefaultValueType &defaultValue, const std::string &description, const ValidatorPtr &validator ); // class OptionDescription // ////////////////////////////////////////////////////////////////// inline OptionDescription::OptionDescription( const String &packedName, const String &description, const ValidatorPtr &validator ) : description_( description ) , validator_( validator ) { unsigned int commaPos = packedName.find( ',' ); String parameter( "|?:+*" ); String cleanPackedName = packedName; Char parameterRequirement = cleanPackedName.at( cleanPackedName.length()-1 ); int pos = parameter.find( parameterRequirement ); if ( pos != String::npos ) { static ParameterRequirement parameters[] = { noParameter, optionalParameter, requiredParameter, oneOrMoreParameter, zeroOrMoreParameter }; parameter_ = parameters[pos]; cleanPackedName.resize( cleanPackedName.length()-1 ); } else setDefaultParameterRequirement(); if ( commaPos != String::npos ) { longName_ = cleanPackedName.substr(0,commaPos); shortName_ = cleanPackedName.substr(commaPos+1,1); } else longName_ = cleanPackedName; } inline OptionDescription::OptionDescription( const Char &shortName, const String &longName, const String &description, const ValidatorPtr &validator ) : shortName_( String(1,shortName) ) , longName_( longName ) , description_( description ) , validator_( validator ) { setDefaultParameterRequirement(); } inline void OptionDescription::setDefaultParameterRequirement() { if ( hasStorage() || hasDefaultValue() ) parameter_ = hasDefaultValue() ? optionalParameter : requiredParameter; else parameter_ = noParameter; } inline OptionDescription::~OptionDescription() { } inline OptionDescription & OptionDescription::setValidator( const ValidatorPtr &validator ) { validator_ = validator; return *this; } inline OptionDescription & OptionDescription::setDefaultValue( const Value &value ) { defaultValue_ = value; if ( value.isEmpty() ) { if ( parameter_ == optionalParameter ) parameter_ = requiredParameter; } else { if ( parameter_ == noParameter || parameter_ == requiredParameter ) parameter_ = optionalParameter; else if ( parameter_ == oneOrMoreParameter ) parameter_ = zeroOrMoreParameter; } return *this; } inline OptionDescription & OptionDescription::setStorage( const ValueBinder &storage ) { storage_ = storage; return *this; } inline const Value & OptionDescription::defaultValue() const { return defaultValue_; } inline bool OptionDescription::hasDefaultValue() const { return !defaultValue_.isEmpty(); } inline bool OptionDescription::hasStorage() const { return !storage_.isEmpty(); } inline bool OptionDescription::hasShortName() const { return !shortName_.empty(); } inline bool OptionDescription::hasLongName() const { return !longName_.empty(); } inline String OptionDescription::shortName() const { return shortName_; } inline String OptionDescription::longName() const { return longName_; } inline String OptionDescription::name() const { return longName_.empty() ? "-" + shortName() : longName_; } inline String OptionDescription::description() const { return description_; } inline bool OptionDescription::hasNoParameter() const { return parameter_ == noParameter; } inline bool OptionDescription::mayHaveParameter() const { return parameter_ == optionalParameter || parameter_ == zeroOrMoreParameter; } inline bool OptionDescription::requireParameter() const { return parameter_ == requiredParameter || parameter_ == oneOrMoreParameter; } inline Value OptionDescription::validate( const Parameters ¶meters ) const { if ( requireParameter() && parameters.empty() ) throw ValidatorError( ValidatorError::missingParameter, "required parameter is missing." ); if ( requireParameter() || ( mayHaveParameter() && !parameters.empty() ) ) { if ( !validator_ ) throw ValidatorError( ValidatorError::undefinedValidator, "no validator set for this option." ); return validator_->validate( parameters ); } return defaultValue(); } inline void OptionDescription::store( const Value &value ) const { if ( hasStorage() ) storage_.set( value ); } // class OptionsDescription // ////////////////////////////////////////////////////////////////// inline OptionsDescription::OptionsDescription( const String &caption ) : caption_( caption ) { } inline OptionsDescription::~OptionsDescription() { } inline OptionsDescription & OptionsDescription::add( const OptionDescription &description ) { int index = options_.size(); options_.push_back( description ); if ( longNameIndexes_.count( description.longName() ) > 0 ) throw OptionsDescriptionError( "More than one option registered with long name '" + description.longName() + "'." ); if ( shortNameIndexes_.count( description.shortName() ) > 0 ) throw OptionsDescriptionError( "More than one option registered with short name '" + description.shortName() + "'." ); if ( description.hasLongName() ) { longNameIndexes_.insert( OptionIndexes::value_type( description.longName(), index ) ); nameIndexes_.insert( OptionIndexes::value_type( description.longName(), index ) ); } if ( description.hasShortName() ) { shortNameIndexes_.insert( OptionIndexes::value_type( description.shortName(), index ) ); nameIndexes_.insert( OptionIndexes::value_type( "-" + description.shortName(), index ) ); } return *this; } inline OptionsDescription & OptionsDescription::add( const String &optionName, const String &description ) { return add( option<std::string>( optionName, description ) ); } inline std::set<String> OptionsDescription::optionNames() const { std::set<String> optionNames; Options::const_iterator it = options_.begin(); for ( ; it != options_.end(); ++it ) { const OptionDescription &option = *it; optionNames.insert( option.name() ); } return optionNames; } inline bool OptionsDescription::hasOption( const String &optionName ) const { return nameIndexes_.count( optionName) > 0; } inline const OptionDescription & OptionsDescription::description( const String &optionName ) const { OptionIndexes::const_iterator it = nameIndexes_.find( optionName ); if ( it == nameIndexes_.end() ) { std::ostringstream os; os << "No option registered for name '" + optionName + "'."; throw OptionsDescriptionError( os.str() ); } return options_[it->second]; } // template function option // ////////////////////////////////////////////////////////////////// template<class ValueType> OptionDescription option( const std::string &optionName, const std::string &description ) { return OptionDescription( optionName, description, defaultValidator<ValueType>() ); } template<class DefaultValueType> OptionDescription optionDefault( const std::string &optionName, const DefaultValueType &defaultValue, const std::string &description ) { Value value; set( value, defaultValue ); OptionDescription option( optionName, description, defaultValidator<DefaultValueType>() ); return option.setDefaultValue( value ); } template<class StorageValueType> OptionDescription option( const std::string &optionName, StorageValueType &storageValue, const std::string &description ) { OptionDescription option( optionName, description, defaultValidator<StorageValueType>() ); return option.setStorage( valueBinder( storageValue ) ); } template<class StorageValueType ,class DefaultValueType> OptionDescription option( const std::string &optionName, StorageValueType &storageValue, const DefaultValueType &defaultValue, const std::string &description ) { Value value; set( value, StorageValueType( defaultValue ) ); OptionDescription option( optionName, description, defaultValidator<StorageValueType>() ); option.setDefaultValue( value ); return option.setStorage( valueBinder( storageValue ) ); } template<class ValueType> OptionDescription validatedOption( const std::string &optionName, const std::string &description, const ValidatorPtr &validator ) { return OptionDescription( optionName, description, validator ); } template<class DefaultValueType> OptionDescription validatedOptionDefault( const std::string &optionName, const DefaultValueType &defaultValue, const std::string &description, const ValidatorPtr &validator ) { Value value; set( value, defaultValue ); OptionDescription option( optionName, description, validator ); return option.setDefaultValue( value ); } template<class StorageValueType> OptionDescription validatedOption( const std::string &optionName, StorageValueType &storageValue, const std::string &description, const ValidatorPtr &validator ) { OptionDescription option( optionName, description, validator ); return option.setStorage( valueBinder( storageValue ) ); } template<class StorageValueType ,class DefaultValueType> OptionDescription validatedOption( const std::string &optionName, StorageValueType &storageValue, const DefaultValueType &defaultValue, const std::string &description, const ValidatorPtr &validator ) { Value value; set( value, StorageValueType( defaultValue ) ); OptionDescription option( optionName, description, validator ); option.setDefaultValue( value ); return option.setStorage( valueBinder( storageValue ) ); } } } // namespace CommandLineOptions #endif // CPPUTTOOLS_CONFIGURATION_DESCRIPTION_H_INCUDED --- NEW FILE: values.h --- #ifndef CPPUTTOOLS_CONFIGURATION_VALUES_H_INCUDED # define CPPUTTOOLS_CONFIGURATION_VALUES_H_INCUDED # include "description.h" namespace CppUTTools { namespace CommandLineOptions { class OptionsValues { public: virtual ~OptionsValues(); const Value &operator[]( const String &name ) const; Value &operator[]( const String &name ); const Value &optionValue( const String &name ) const; Value &optionValue( const String &name ); bool hasOption( const String &name ) const; void setOption( const String &optionKey ); void setOptionAlias( const String &alias, const String &optionKey ); const String &optionName( const String &name ) const; Parameters optionParameters( const String &name ) const; void addOptionParameter( const String &optionKey, const String ¶meter ); void validate( const OptionsDescription &description ); void store( const OptionsDescription &description ); private: typedef std::map<String,Value> Values; Values values_; typedef std::map< String, std::deque<String> > OptionParameters; OptionParameters parameters_; typedef std::map<String, String> NameByAliases; NameByAliases nameByAliases_; }; // class OptionValues // /////////////////////////////////////////////////////////////////// inline OptionsValues::~OptionsValues() { } inline const Value & OptionsValues::operator[]( const String &name ) const { return optionValue( name ); } inline Value & OptionsValues::operator[]( const String &name ) { return optionValue( name ); } inline const Value & OptionsValues::optionValue( const String &name ) const { Values::const_iterator it = values_.find( optionName(name) ); if ( it == values_.end() ) throw std::invalid_argument( "No option named: " + name ); return it->second; } inline Value & OptionsValues::optionValue( const String &name ) { Values::iterator it = values_.find( optionName(name) ); if ( it == values_.end() ) throw std::invalid_argument( "No option named: " + name ); return it->second; } inline bool OptionsValues::hasOption( const String &name ) const { return parameters_.count( optionName(name) ) > 0; } inline void OptionsValues::setOption( const String &optionKey ) { parameters_[ optionKey ]; } inline void OptionsValues::setOptionAlias( const String &alias, const String &optionKey ) { nameByAliases_.insert( NameByAliases::value_type( alias, optionKey ) ); } inline const std::string & OptionsValues::optionName( const String &name ) const { NameByAliases::const_iterator it = nameByAliases_.find( name ); if ( it == nameByAliases_.end() ) throw std::invalid_argument( "OptionsValues::optionName: " + name + " is not an option." ); return it->second; } inline Parameters OptionsValues::optionParameters( const String &name ) const { OptionParameters::const_iterator it = parameters_.find( optionName(name) ); if ( it == parameters_.end() ) return Parameters(); return it->second; } inline void OptionsValues::addOptionParameter( const String &optionKey, const String ¶meter ) { parameters_[ optionKey ].push_back( parameter ); } inline void OptionsValues::validate( const OptionsDescription &description ) { OptionParameters::iterator it = parameters_.begin(); for ( ; it != parameters_.end(); ++it ) { const String &name = it->first; const OptionDescription &option = description.description( name ); try { /// @todo real parameters stuff for sequence support const Parameters ¶meters = it->second; Value value = option.validate( parameters ); values_[name] = value; } catch ( ValidatorError &e ) { e.setOptionName( name ); throw; } } } inline void OptionsValues::store( const OptionsDescription &description ) { Values::iterator it = values_.begin(); for ( ; it != values_.end(); ++it ) { const String &name = it->first; const OptionDescription &option = description.description( name ); const Value &value = it->second; option.store( value ); } } } } // namespace CommandLineOptions #endif // CPPUTTOOLS_CONFIGURATION_VALUES_H_INCUDED --- NEW FILE: errors.h --- #ifndef CPPUTTOOLS_CONFIGURATION_ERRORS_H_INCUDED # define CPPUTTOOLS_CONFIGURATION_ERRORS_H_INCUDED # include "forwards.h" # include <sstream> # include <stdexcept> namespace CppUTTools { namespace CommandLineOptions { class OptionError : public std::runtime_error { public: OptionError( const std::string &message ) : std::runtime_error( message ) { } }; class ValidatorError : public std::runtime_error { public: typedef std::runtime_error SuperClass; enum Cause { missingParameter = 1, badParameterValue, undefinedValidator }; ValidatorError( Cause cause, const std::string &message ) : std::runtime_error( message ) , cause_( cause ) { } void setOptionName( const String &name ) { name_ = name; } String optionName() const { return name_; } Cause cause() const { return cause_; } const char *what() const throw() { std::ostringstream os; os << "In option '"; if ( name_[0] != '-' ) os << "--"; os << name_ << "':" << SuperClass::what(); message_ = os.str(); return message_.c_str(); } private: std::string name_; mutable std::string message_; Cause cause_; }; class OptionsDescriptionError : public std::runtime_error { public: OptionsDescriptionError( const std::string &message ) : std::runtime_error( message ) { } }; class BadCastOptionError : public OptionError { public: BadCastOptionError( const std::string &message ) : OptionError( message ) { } }; class CommandLineParseError : public std::runtime_error { public: enum Cause { invalidOptionName = 1, syntaxError }; CommandLineParseError( Cause cause, const String &optionName ); Cause cause() const; String optionName() const; const char *what() const throw(); private: String optionName_; Cause cause_; mutable std::string message_; }; // class CommandLineParseError // ////////////////////////////////////////////////////////////////// inline CommandLineParseError::CommandLineParseError( Cause cause, const String &optionName ) : cause_( cause ) , optionName_( optionName ) , std::runtime_error( "CommandLineParseError" ) { } inline CommandLineParseError::Cause CommandLineParseError::cause() const { return cause_; } inline String CommandLineParseError::optionName() const { return optionName_; } inline const char * CommandLineParseError::what() const throw() { if ( message_.empty() ) { std::ostringstream os; switch ( cause_ ) { case invalidOptionName: os << "Invalid option name: "; break; case syntaxError: os << "Syntax error: "; break; } if ( !optionName_.empty() ) os << optionName_; message_ = os.str(); } return message_.c_str(); } } } // namespace CommandLineOptions #endif // CPPUTTOOLS_CONFIGURATION_ERRORS_H_INCUDED --- NEW FILE: simplertti.h --- #ifndef CPPUTTOOLS_CONFIGURATION_SIMPLERTTI_H_INCUDED # define CPPUTTOOLS_CONFIGURATION_SIMPLERTTI_H_INCUDED # include "errors.h" # include <typeinfo> namespace CppUTTools { namespace CommandLineOptions { typedef const std::type_info *OptionTypeId; template<class TheType> struct Type {}; template<class OptionType> OptionTypeId optionTypeId( Type<OptionType> ); void checkBadCast( const OptionTypeId &type1, const OptionTypeId &type2 ); // RTTI functions // ////////////////////////////////////////////////////////////////// template<class OptionType> OptionTypeId optionTypeId( Type<OptionType> ) { return &typeid( OptionType ); } inline void checkBadCast( const OptionTypeId &type1, const OptionTypeId &type2 ) { if ( *type1 != *type2 ) throw BadCastOptionError( "Incorrect get or set call on option value." ); } } } // namespace CommandLineOptions #endif // CPPUTTOOLS_CONFIGURATION_SIMPLERTTI_H_INCUDED --- NEW FILE: forwards.h --- #ifndef CPPUTTOOLS_CONFIGURATION_FORWARDS_H_INCUDED # define CPPUTTOOLS_CONFIGURATION_FORWARDS_H_INCUDED # include <cpput/config.h> // to be moved partially in cpputtools # include <cpputtools/refcountptr.h> # include <deque> # include <sstream> # include <string> namespace CppUTTools { namespace CommandLineOptions { typedef char Char; typedef std::string String; typedef std::deque<String> StringList; typedef std::istringstream IStringStream; class CommandLineParseError; class CommandLineParser; class OptionDescription; class OptionsDescription; class OptionsDescriptionError; class OptionError; class OptionHandler; class OptionHandlerHelper; template<class TheOptionType> class OptionValueStorage; class OptionsValues; template<class TheOptionType> class SimpleOptionHandler; class Validator; typedef RefCountPtr<Validator> ValidatorPtr; typedef ReferenceCountedNoThread ReferenceCountedPolicy; class ValidatorError; typedef std::deque<String> Parameters; } } // namespace CommandLineOptions #endif // CPPUTTOOLS_CONFIGURATION_FORWARDS_H_INCUDED --- NEW FILE: parser.h --- #ifndef CPPUTTOOLS_CONFIGURATION_PARSER_H_INCUDED # define CPPUTTOOLS_CONFIGURATION_PARSER_H_INCUDED # include "values.h" # include <algorithm> # include <iterator> # include <vector> namespace CppUTTools { namespace CommandLineOptions { bool parseCommandLine( int argc, const Char *argv[], const OptionsDescription &description, OptionsValues &values ); class CommandLineParser { public: enum ParseState { parseNewOption = 1, nextParameter }; enum OptionStyle { noOptionStyle = 0, shortOption, longOption }; CommandLineParser( const std::vector<String> &arguments, const OptionsDescription &description ) : arguments_( arguments ) , parseState_( parseNewOption ) , tokenIndex_( 0 ) , description_( description ) , currentOption_( 0 ) { } // @exception CommandLineParseError if invalid option name OptionsValues parse(); void processToken(); String currentToken() const; void consumeToken(); bool hasMoreToken() const; OptionStyle optionStyle( const std::string &token ) const; // @exception CommandLineParseError if invalid option name void checkOptionNameIsValid( const std::string &optionName, const std::string &optionToken ) const; private: void setOptionAliases(); typedef std::vector<String> Arguments; Arguments arguments_; OptionsValues values_; const OptionsDescription &description_; ParseState parseState_; int tokenIndex_; const OptionDescription *currentOption_; }; // Function parseCommandLine // ////////////////////////////////////////////////////////////////// inline bool parseCommandLine( int argc, const Char *argv[], const OptionsDescription &description, OptionsValues &values ) { std::vector<String> args; if ( argc > 0 ) std::copy( argv+1, argv+argc, std::back_inserter( args ) ); CommandLineParser parser( args, description ); values = parser.parse(); return true; } // class CommandLineParser // ////////////////////////////////////////////////////////////////// inline OptionsValues CommandLineParser::parse() { setOptionAliases(); while ( hasMoreToken() ) processToken(); return values_; } inline void CommandLineParser::processToken() { String token = currentToken(); switch ( parseState_ ) { case parseNewOption: { switch ( optionStyle( token ) ) { case shortOption: { String name = token.substr(1,1); String shortOptionKey = "-" + name; checkOptionNameIsValid( shortOptionKey, token ); consumeToken(); const OptionDescription &option = description_.description( shortOptionKey ); values_.setOption( option.name() ); if ( option.hasNoParameter() ) break; // if ( option.mayHaveParameter() // && optionStyle( currentToken() ) != noOption ) // break; std::string parameter = token.substr(2); if ( !parameter.empty() ) values_.addOptionParameter( option.name(), parameter ); else { parseState_ = nextParameter; currentOption_ = &option; } // if ( parameter.empty() && option.hasDefaultValue() ) // option.applyDefaultValue( values_[ optionKey ] ); } break; case longOption: { String name = token.substr(2); String parameter; int equalPos = name.find( '=' ); if ( equalPos != String::npos ) { parameter = name.substr( equalPos + 1 ); name = name.substr(0,equalPos); } checkOptionNameIsValid( name, token ); values_.setOption( name ); consumeToken(); const OptionDescription &option = description_.description( name ); if ( option.hasNoParameter() ) break; if ( equalPos != String::npos ) values_.addOptionParameter( name, parameter ); else { parseState_ = nextParameter; currentOption_ = &option; } } break; default: throw CommandLineParseError( CommandLineParseError::syntaxError, token ); break; } } break; case nextParameter: { if ( optionStyle( token ) == noOptionStyle ) { values_.addOptionParameter( currentOption_->name(), token ); consumeToken(); } parseState_ = parseNewOption; } break; default: throw CommandLineParseError( CommandLineParseError::syntaxError, token ); } } inline void CommandLineParser::checkOptionNameIsValid( const std::string &optionName, const std::string &optionToken ) const { if ( !description_.hasOption( optionName ) ) throw CommandLineParseError( CommandLineParseError::invalidOptionName, optionToken ); } inline std::string CommandLineParser::currentToken() const { return tokenIndex_ < arguments_.size() ? arguments_[tokenIndex_] : std::string(); } inline void CommandLineParser::consumeToken() { ++tokenIndex_; } inline bool CommandLineParser::hasMoreToken() const { return tokenIndex_ < arguments_.size(); } inline CommandLineParser::OptionStyle CommandLineParser::optionStyle( const std::string &token ) const { if ( token.substr(0,2) == "--" && token.length() > 2 ) return longOption; if ( token.substr(0,1) == "-" && token.length() > 1 ) return shortOption; return noOptionStyle; } inline void CommandLineParser::setOptionAliases() { std::set<String> optionNames = description_.optionNames(); std::set<String>::iterator it = optionNames.begin(); for ( ; it != optionNames.end(); ++it ) { const OptionDescription &description = description_.description( *it ); String optionKey = description.name(); values_.setOptionAlias( optionKey, optionKey ); if ( description.hasLongName() && description.hasShortName() ) values_.setOptionAlias( "-" + description.shortName(), optionKey ); } } } } // namespace CommandLineOptions #endif // CPPUTTOOLS_CONFIGURATION_PARSER_H_INCUDED |