Skip to content
Snippets Groups Projects
Commit 5b9f5300 authored by g0dil's avatar g0dil
Browse files

Utils/Console: Implement FlagCollection as special argument type

parent bd7d3296
No related branches found
No related tags found
No related merge requests found
......@@ -208,17 +208,18 @@ namespace senf {
The watchdog is controlled using the watchdogTimeout(), watchdogEvents() and watchdogAbort().
functions.
The watchdog is implemented using a free running interval timer. The watchdog signal must \e not
be blocked. If signals need to be blocked for some reason, those regions will not be checked by
the watchdog. If a callback blocks, the watchdog has no chance to interrupt the process.
The watchdog is implemented using a free running interval timer. The watchdog signal (\c SIGURG)
must \e not be blocked. If signals need to be blocked for some reason, those regions will not be
checked by the watchdog. If a callback blocks, the watchdog has no chance to interrupt the
process.
\warning Since the watchdog is free running for performance reasons, every callback must expect
signals to happen. Signals \e will certainly happen since the watchdog signal is generated
periodically (which does not necessarily generate a watchdog event ...)
Additional signals may occur when using using hires timers on kernel/glibc combinations which do
not support timerfd(). On such systems, hires timers are implemented using POSIX timers which
generate a considerable number of additional signals.
Additional signals (\c SIGALRM) may occur when using using hires timers on kernel/glibc
combinations which do not support timerfd(). On such systems, hires timers are implemented using
POSIX timers which generate a considerable number of additional signals.
\todo Fix the file support to use threads (?) fork (?) and a pipe so it works reliably even
over e.g. NFS.
......
......@@ -46,6 +46,57 @@ senf::console::senf_console_parse_argument(ParseCommandInfo::TokensRange const &
}
}
///////////////////////////////////////////////////////////////////////////
// senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >
template <class Enum>
prefix_ void senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >::
parse(ParseCommandInfo::TokensRange const & tokens, type & out)
{
CheckedArgumentIteratorWrapper arg (tokens);
out.value = 0;
while (arg) {
Enum v;
senf::console::parse( *(arg++), v);
out.value |= v;
}
}
template <class Enum>
prefix_ std::string
senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >::description()
{
return ArgumentTraits<Enum>::description();
}
template <class Enum>
prefix_ std::string
senf::console::ArgumentTraits< senf::console::FlagCollection<Enum> >::str(type const & value)
{
std::stringstream ss;
senf::console::format(value, ss);
return ss.str();
}
///////////////////////////////////////////////////////////////////////////
// senf::console::ReturnValueTraits< senf::console::FlagCollection<Enum> >
template <class Enum>
prefix_ void senf::console::ReturnValueTraits< senf::console::FlagCollection<Enum> >::
format(type const & value, std::ostream & os)
{
unsigned n (0);
std::stringstream ss;
for (unsigned bit (0); bit<sizeof(value.value)*CHAR_BIT; ++bit) {
unsigned long flag (1<<bit);
if (value.value & flag) {
if (n++) ss << " ";
senf::console::format(static_cast<Enum>(flag), ss);
}
}
os << (n != 1 ? "(" + ss.str() + ")" : ss.str());
}
///////////////////////////////ct.e////////////////////////////////////////
#undef prefix_
......
......@@ -211,6 +211,32 @@ namespace console {
# define SENF_CONSOLE_REGISTER_ENUM_MEMBER(Class, Type, Values) \
SENF_CONSOLE_REGISTER_ENUM_(Class::, Type, Values)
template <class Enum>
struct FlagCollection
{
operator unsigned long() const { return value; }
FlagCollection() : value (0) {}
FlagCollection(unsigned long value_) : value (value_) {}
FlagCollection(Enum value_) : value (value_) {}
unsigned long value;
};
template <class Enum>
struct ArgumentTraits< FlagCollection<Enum> >
{
typedef FlagCollection<Enum> type;
static void parse(ParseCommandInfo::TokensRange const & tokens, type & out);
static std::string description();
static std::string str(type const & value);
};
template <class Enum>
struct ReturnValueTraits< FlagCollection<Enum> >
{
typedef FlagCollection<Enum> type;
static void format(type const & value, std::ostream & os);
};
}}
///////////////////////////////hh.e////////////////////////////////////////
......
......@@ -40,7 +40,7 @@
///////////////////////////////cc.p////////////////////////////////////////
namespace {
enum TestEnum { Foo, Bar, FooBar };
enum TestEnum { Foo=1, Bar=2, FooBar=4 };
SENF_CONSOLE_REGISTER_ENUM( TestEnum, (Foo)(Bar)(FooBar) );
TestEnum test (TestEnum value) { return value; }
......@@ -52,6 +52,9 @@ namespace {
SENF_CONSOLE_REGISTER_ENUM_MEMBER( TestClass, MemberEnum, (MemberFoo)(MemberBar) );
bool boolTest(bool value) { return value; }
senf::console::FlagCollection<TestEnum> collectionTest(
senf::console::FlagCollection<TestEnum> flags) { return flags; }
}
BOOST_AUTO_UNIT_TEST(boolTraits)
......@@ -159,6 +162,34 @@ BOOST_AUTO_UNIT_TEST(enumSupport)
BOOST_CHECK_EQUAL( ss.str(), "Foo\n" );
}
BOOST_AUTO_UNIT_TEST(flagCollection)
{
senf::console::Executor executor;
senf::console::CommandParser parser;
senf::console::ScopedDirectory<> dir;
senf::console::root().add("test", dir);
std::stringstream ss;
dir.add("test",&collectionTest);
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" );
ss.str("");
SENF_CHECK_NO_THROW(
parser.parse("test/test (foo bar)",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
BOOST_CHECK_EQUAL( ss.str(), "(Foo Bar)\n" );
ss.str("");
SENF_CHECK_NO_THROW(
parser.parse("test/test ()",
boost::bind<void>( boost::ref(executor), boost::ref(ss), _1 )) );
BOOST_CHECK_EQUAL( ss.str(), "()\n" );
}
///////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment