From: g0dil Date: Wed, 4 Mar 2009 11:50:10 +0000 (+0000) Subject: Utils/Console: Implement FlagCollection as special argument type X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=7a4fb9b49e6eccd19a1ea48a31175245b6dadb61;p=senf.git Utils/Console: Implement FlagCollection as special argument type git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1143 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/Scheduler/Scheduler.hh b/Scheduler/Scheduler.hh index 29ba555..779e04b 100644 --- a/Scheduler/Scheduler.hh +++ b/Scheduler/Scheduler.hh @@ -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. diff --git a/Utils/Console/Traits.ct b/Utils/Console/Traits.ct index d9d5a98..f3e0a72 100644 --- a/Utils/Console/Traits.ct +++ b/Utils/Console/Traits.ct @@ -46,6 +46,57 @@ senf::console::senf_console_parse_argument(ParseCommandInfo::TokensRange const & } } +/////////////////////////////////////////////////////////////////////////// +// senf::console::ArgumentTraits< senf::console::FlagCollection > + +template +prefix_ void senf::console::ArgumentTraits< senf::console::FlagCollection >:: +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 +prefix_ std::string +senf::console::ArgumentTraits< senf::console::FlagCollection >::description() +{ + return ArgumentTraits::description(); +} + +template +prefix_ std::string +senf::console::ArgumentTraits< senf::console::FlagCollection >::str(type const & value) +{ + std::stringstream ss; + senf::console::format(value, ss); + return ss.str(); +} + +/////////////////////////////////////////////////////////////////////////// +// senf::console::ReturnValueTraits< senf::console::FlagCollection > + +template +prefix_ void senf::console::ReturnValueTraits< senf::console::FlagCollection >:: +format(type const & value, std::ostream & os) +{ + unsigned n (0); + std::stringstream ss; + for (unsigned bit (0); bit(flag), ss); + } + } + os << (n != 1 ? "(" + ss.str() + ")" : ss.str()); +} + ///////////////////////////////ct.e//////////////////////////////////////// #undef prefix_ diff --git a/Utils/Console/Traits.hh b/Utils/Console/Traits.hh index df2a6a8..2e84882 100644 --- a/Utils/Console/Traits.hh +++ b/Utils/Console/Traits.hh @@ -211,6 +211,32 @@ namespace console { # define SENF_CONSOLE_REGISTER_ENUM_MEMBER(Class, Type, Values) \ SENF_CONSOLE_REGISTER_ENUM_(Class::, Type, Values) + template + 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 + struct ArgumentTraits< FlagCollection > + { + typedef FlagCollection type; + static void parse(ParseCommandInfo::TokensRange const & tokens, type & out); + static std::string description(); + static std::string str(type const & value); + }; + + template + struct ReturnValueTraits< FlagCollection > + { + typedef FlagCollection type; + static void format(type const & value, std::ostream & os); + }; + }} ///////////////////////////////hh.e//////////////////////////////////////// diff --git a/Utils/Console/Traits.test.cc b/Utils/Console/Traits.test.cc index 2e54245..17ba545 100644 --- a/Utils/Console/Traits.test.cc +++ b/Utils/Console/Traits.test.cc @@ -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 collectionTest( + senf::console::FlagCollection 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( 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( 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( boost::ref(executor), boost::ref(ss), _1 )) ); + BOOST_CHECK_EQUAL( ss.str(), "()\n" ); +} ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_