diff --git a/include/external/clara.hpp b/include/external/clara.hpp index 3f2d13bf..88a5e9fe 100644 --- a/include/external/clara.hpp +++ b/include/external/clara.hpp @@ -1,4 +1,4 @@ -// v1.0 +// v1.0-develop.2 // See https://github.com/philsquared/Clara #ifndef CATCH_CLARA_HPP_INCLUDED @@ -409,6 +409,14 @@ namespace detail { std::string token; }; + inline auto isOptPrefix( char c ) -> bool { + return c == '-' +#ifdef CATCH_PLATFORM_WINDOWS + || c == '/' +#endif + ; + } + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled class TokenStream { using Iterator = std::vector::const_iterator; @@ -425,7 +433,7 @@ namespace detail { if( it != itEnd ) { auto const &next = *it; - if( next[0] == '-' || next[0] == '/' ) { + if( isOptPrefix( next[0] ) ) { auto delimiterPos = next.find_first_of( " :=" ); if( delimiterPos != std::string::npos ) { m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); @@ -915,9 +923,11 @@ namespace detail { }; inline auto normaliseOpt( std::string const &optName ) -> std::string { +#ifdef CATCH_PLATFORM_WINDOWS if( optName[0] == '/' ) return "-" + optName.substr( 1 ); else +#endif return optName; } @@ -958,11 +968,7 @@ namespace detail { } auto isMatch( std::string const &optToken ) const -> bool { -#ifdef CATCH_PLATFORM_WINDOWS auto normalisedToken = normaliseOpt( optToken ); -#else - auto const &normalisedToken = optToken; -#endif for( auto const &name : m_optNames ) { if( normaliseOpt( name ) == normalisedToken ) return true; @@ -1012,8 +1018,13 @@ namespace detail { for( auto const &name : m_optNames ) { if( name.empty() ) return Result::logicError( "Option name cannot be empty" ); +#ifdef CATCH_PLATFORM_WINDOWS if( name[0] != '-' && name[0] != '/' ) return Result::logicError( "Option name must begin with '-' or '/'" ); +#else + if( name[0] != '-' ) + return Result::logicError( "Option name must begin with '-'" ); +#endif } return ParserRefImpl::validate(); } diff --git a/third_party/clara.hpp b/third_party/clara.hpp index 83c4c514..aa429e7a 100644 --- a/third_party/clara.hpp +++ b/third_party/clara.hpp @@ -1,4 +1,4 @@ -// v1.0 +// v1.0-develop.2 // See https://github.com/philsquared/Clara #ifndef CLARA_HPP_INCLUDED @@ -409,6 +409,14 @@ namespace detail { std::string token; }; + inline auto isOptPrefix( char c ) -> bool { + return c == '-' +#ifdef CLARA_PLATFORM_WINDOWS + || c == '/' +#endif + ; + } + // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled class TokenStream { using Iterator = std::vector::const_iterator; @@ -425,7 +433,7 @@ namespace detail { if( it != itEnd ) { auto const &next = *it; - if( next[0] == '-' || next[0] == '/' ) { + if( isOptPrefix( next[0] ) ) { auto delimiterPos = next.find_first_of( " :=" ); if( delimiterPos != std::string::npos ) { m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } ); @@ -915,9 +923,11 @@ namespace detail { }; inline auto normaliseOpt( std::string const &optName ) -> std::string { +#ifdef CLARA_PLATFORM_WINDOWS if( optName[0] == '/' ) return "-" + optName.substr( 1 ); else +#endif return optName; } @@ -958,11 +968,7 @@ namespace detail { } auto isMatch( std::string const &optToken ) const -> bool { -#ifdef CLARA_PLATFORM_WINDOWS auto normalisedToken = normaliseOpt( optToken ); -#else - auto const &normalisedToken = optToken; -#endif for( auto const &name : m_optNames ) { if( normaliseOpt( name ) == normalisedToken ) return true; @@ -1012,8 +1018,13 @@ namespace detail { for( auto const &name : m_optNames ) { if( name.empty() ) return Result::logicError( "Option name cannot be empty" ); +#ifdef CLARA_PLATFORM_WINDOWS if( name[0] != '-' && name[0] != '/' ) return Result::logicError( "Option name must begin with '-' or '/'" ); +#else + if( name[0] != '-' ) + return Result::logicError( "Option name must begin with '-'" ); +#endif } return ParserRefImpl::validate(); } @@ -1142,10 +1153,15 @@ namespace detail { size_t count = 0; }; const size_t totalParsers = m_options.size() + m_args.size(); - ParserInfo parseInfos[totalParsers]; - size_t i = 0; - for( auto const& opt : m_options ) parseInfos[i++].parser = &opt; - for( auto const& arg : m_args ) parseInfos[i++].parser = &arg; + assert( totalParsers < 512 ); + // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do + ParserInfo parseInfos[512]; + + { + size_t i = 0; + for (auto const &opt : m_options) parseInfos[i++].parser = &opt; + for (auto const &arg : m_args) parseInfos[i++].parser = &arg; + } m_exeName.set( exeName ); @@ -1153,7 +1169,8 @@ namespace detail { while( result.value().remainingTokens() ) { bool tokenParsed = false; - for( auto& parseInfo : parseInfos ) { + for( size_t i = 0; i < totalParsers; ++i ) { + auto& parseInfo = parseInfos[i]; if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) { result = parseInfo.parser->parse(exeName, result.value().remainingTokens()); if (!result)