if (tokens.size() != 1)
throw SyntaxErrorException("parameter syntax error");
- EnumTable::left_map::const_iterator i (table.left.find(tokens.begin()[0].value()));
- if (i == table.left.end())
- throw SyntaxErrorException("parameter syntax error: invalid enum value");
- return i->second;
+ std::string sym (tokens.begin()[0].value());
+ boost::algorithm::to_lower(sym);
+ EnumTable::left_map::const_iterator i1 (table.left.lower_bound(sym));
+ EnumTable::left_map::const_iterator i2 (table.left.lower_bound(sym+"\xff"));
+ if (i1 == i2)
+ throw SyntaxErrorException("parameter syntax error: invalid enum value: ")
+ << tokens.begin()[0].value();
+ long v (i1->second);
+ if (boost::algorithm::to_lower_copy(i1->first) == sym)
+ return v;
+ ++i1;
+ if (i1 != i2)
+ throw SyntaxErrorException("parameter syntax error: ambiguous enum value: ")
+ << tokens.begin()[0].value();
+ return v;
}
prefix_ std::string senf::console::detail::formatEnum(EnumTable const & table, long value)
#include <boost/preprocessor/facilities/empty.hpp>
#include <boost/bimap.hpp>
#include <boost/assign/list_inserter.hpp>
+#include <boost/algorithm/string/case_conv.hpp>
#include "../../Utils/singleton.hh"
///////////////////////////////ih.p////////////////////////////////////////
namespace detail {
#ifndef DOXYGEN
+ struct StringILess
+ {
+ bool operator()(std::string const & left, std::string const & right) const
+ { return boost::algorithm::to_lower_copy(left)
+ < boost::algorithm::to_lower_copy(right); }
+ };
- typedef boost::bimap<std::string, long> EnumTable;
+ typedef boost::bimap<boost::bimaps::set_of<std::string, StringILess>, long> EnumTable;
long parseEnum(EnumTable const & table, ParseCommandInfo::TokensRange const & tokens);
std::string formatEnum(EnumTable const & table, long value);
- template <class EnumType>
- struct EnumTraits : public senf::singleton< EnumTraits<EnumType> >
- {
- using senf::singleton< EnumTraits<EnumType> >::instance;
- EnumTable table;
- };
-
# define SENF_CONSOLE_REGISTER_ENUM_ELT(r,d,e) \
- (BOOST_PP_STRINGIZE(e), static_cast<long>(d e))
+ ( BOOST_PP_STRINGIZE(e), static_cast<long>(d e) )
# define SENF_CONSOLE_REGISTER_ENUM_(Prefix, Type, Values) \
- void senf_console_init_enum_table(Prefix Type) \
+ senf::console::detail::EnumTable & senf_console_enum_table(Prefix Type) \
{ \
- senf::console::detail::EnumTraits<Prefix Type> & traits ( \
- senf::console::detail::EnumTraits<Prefix Type>::instance() ); \
- if (traits.table.empty()) \
- boost::assign::insert(traits.table) \
+ static senf::console::detail::EnumTable table; \
+ if (table.empty()) \
+ boost::assign::insert(table) \
BOOST_PP_SEQ_FOR_EACH( SENF_CONSOLE_REGISTER_ENUM_ELT, Prefix, Values ); \
+ return table; \
} \
void senf_console_parse_argument( \
senf::console::ParseCommandInfo::TokensRange const & tokens, Prefix Type & out) \
{ \
- senf_console_init_enum_table( Prefix Type() ); \
out = static_cast<Prefix Type>( \
senf::console::detail::parseEnum( \
- senf::console::detail::EnumTraits<Prefix Type>::instance().table, tokens)); \
+ senf_console_enum_table( Prefix Type() ), tokens) ); \
} \
void senf_console_format_value(Prefix Type value, std::ostream & os) \
{ \
- senf_console_init_enum_table( Prefix Type() ); \
os << senf::console::detail::formatEnum( \
- senf::console::detail::EnumTraits<Prefix Type>::instance().table, \
- static_cast<long>(value) ); \
+ senf_console_enum_table( Prefix Type() ), static_cast<long>(value) ); \
}
#endif
///////////////////////////////cc.p////////////////////////////////////////
namespace {
- enum TestEnum { Foo, Bar };
- SENF_CONSOLE_REGISTER_ENUM( TestEnum, (Foo)(Bar) );
+ enum TestEnum { Foo, Bar, FooBar };
+ SENF_CONSOLE_REGISTER_ENUM( TestEnum, (Foo)(Bar)(FooBar) );
TestEnum test (TestEnum value) { return value; }
parser.parse("test/member MemberBar",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
BOOST_CHECK_EQUAL( ss.str(), "MemberBar\n" );
+
+ ss.str("");
+ SENF_CHECK_NO_THROW(
+ parser.parse("test/test foob",
+ boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+ BOOST_CHECK_EQUAL( ss.str(), "FooBar\n" );
+
+ ss.str("");
+ SENF_CHECK_NO_THROW(
+ parser.parse("test/test b",
+ boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+ BOOST_CHECK_EQUAL( ss.str(), "Bar\n" );
+
+ ss.str("");
+ SENF_CHECK_NO_THROW(
+ parser.parse("test/test foo",
+ boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
+ BOOST_CHECK_EQUAL( ss.str(), "Foo\n" );
}