diff --git a/cmd/traffic_cache_tool/CacheTool.cc b/cmd/traffic_cache_tool/CacheTool.cc index 332e019fb1e..11adc3be551 100644 --- a/cmd/traffic_cache_tool/CacheTool.cc +++ b/cmd/traffic_cache_tool/CacheTool.cc @@ -1151,7 +1151,7 @@ struct option Options[] = {{"help", 0, nullptr, 'h'}, } Errata -List_Stripes(Cache::SpanDumpDepth depth, int argc, char *argv[]) +List_Stripes(Cache::SpanDumpDepth depth) { Errata zret; Cache cache; @@ -1241,9 +1241,9 @@ main(int argc, char *argv[]) Commands .add("list", "List elements of the cache", - [](int argc, char *argv[]) { return List_Stripes(Cache::SpanDumpDepth::SPAN, argc, argv); }) + []() { return List_Stripes(Cache::SpanDumpDepth::SPAN); }) .subCommand(std::string("stripes"), std::string("List the stripes"), - [](int argc, char *argv[]) { return List_Stripes(Cache::SpanDumpDepth::STRIPE, argc, argv); }); + []() { return List_Stripes(Cache::SpanDumpDepth::STRIPE); }); Commands.add(std::string("clear"), std::string("Clear spans"), &Clear_Spans); Commands.add(std::string("volumes"), std::string("Volumes"), &Simulate_Span_Allocation); Commands.add(std::string("alloc"), std::string("Storage allocation")) diff --git a/cmd/traffic_cache_tool/Command.cc b/cmd/traffic_cache_tool/Command.cc index f4b64492ce4..c7a98d1310f 100644 --- a/cmd/traffic_cache_tool/Command.cc +++ b/cmd/traffic_cache_tool/Command.cc @@ -42,37 +42,45 @@ ERR_COMMAND_TAG_NOT_FOUND(char const *tag) return ts::Errata(s.str()); } -CommandTable::Command::Command() +CommandTable::Command::Command() {} + +CommandTable::Command::Command(std::string const &name, std::string const &help) : _name(name), _help(help) { } -CommandTable::Command::Command(std::string const &name, std::string const &help) : _name(name), _help(help) +CommandTable::Command::Command(std::string const &name, std::string const &help, LeafAction const &f) + : _name(name), _help(help) { + _action = f; } -CommandTable::Command::Command(std::string const &name, std::string const &help, CommandFunction const &f) - : _name(name), _help(help), _func(f) +CommandTable::Command::Command(std::string const &name, std::string const &help, NullaryAction const &f) + : _name(name), _help(help) { + _action = f; } -auto -CommandTable::Command::set(CommandFunction const &f) -> self & +CommandTable::Command::~Command() { +} + +CommandTable::Command & +CommandTable::Command::subCommand(std::string const &name, std::string const &help, LeafAction const &f) { - _func = f; - return *this; + _group.push_back(Command(name, help, f)); + return _group.back(); } CommandTable::Command & -CommandTable::Command::subCommand(std::string const &name, std::string const &help, CommandFunction const &f) +CommandTable::Command::subCommand(std::string const &name, std::string const &help, NullaryAction const &f) { - _group.emplace_back(Command(name, help, f)); + _group.push_back(Command(name, help, f)); return _group.back(); } auto CommandTable::Command::subCommand(std::string const &name, std::string const &help) -> self & { - _group.emplace_back(Command(name, help)); + _group.push_back(Command(name, help)); return _group.back(); } @@ -81,10 +89,11 @@ CommandTable::Command::invoke(int argc, char *argv[]) { ts::Errata zret; - if (CommandTable::_opt_idx >= argc || argv[CommandTable::_opt_idx][0] == '-') { - // Tail of command keywords, try to invoke. - if (_func) { - zret = _func(argc - CommandTable::_opt_idx, argv + CommandTable::_opt_idx); + if (_action.is_leaf()) { + zret = _action.invoke(argc - CommandTable::_opt_idx, argv + CommandTable::_opt_idx); + } else if (CommandTable::_opt_idx >= argc || argv[CommandTable::_opt_idx][0] == '-') { + if (_action.is_nullary()) { + zret = _action.invoke(); } else { std::ostringstream s; s << "Incomplete command, additional keyword required"; @@ -132,10 +141,6 @@ CommandTable::Command::helpMessage(int argc, char *argv[], std::ostream &out, st } } -CommandTable::Command::~Command() -{ -} - CommandTable::CommandTable() { } @@ -147,7 +152,13 @@ CommandTable::add(std::string const &name, std::string const &help) -> Command & } auto -CommandTable::add(std::string const &name, std::string const &help, CommandFunction const &f) -> Command & +CommandTable::add(std::string const &name, std::string const &help, LeafAction const &f) -> Command & +{ + return _top.subCommand(name, help, f); +} + +auto +CommandTable::add(std::string const &name, std::string const &help, NullaryAction const &f) -> Command & { return _top.subCommand(name, help, f); } diff --git a/cmd/traffic_cache_tool/Command.h b/cmd/traffic_cache_tool/Command.h index bd9d08b17c9..582f46766e7 100644 --- a/cmd/traffic_cache_tool/Command.h +++ b/cmd/traffic_cache_tool/Command.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #if !defined(CACHE_TOOL_COMMAND_H) @@ -44,8 +45,10 @@ class CommandTable { typedef CommandTable self; ///< Self reference type. public: - /// Signature for actual command implementation. - typedef std::function CommandFunction; + /// Signature for a leaf command. + using LeafAction = std::function; + /// Signature for a argumentless command. + using NullaryAction = std::function; CommandTable(); @@ -56,6 +59,7 @@ class CommandTable { typedef Command self; ///< Self reference type. public: + Command(Command && that) = default; ~Command(); /** Add a subcommand to this command. @@ -65,11 +69,11 @@ class CommandTable /** Add a subcommand to this command. @return The new sub command instance. */ - Command &subCommand(std::string const &name, std::string const &help, CommandFunction const &f); + Command &subCommand(std::string const &name, std::string const &help, NullaryAction const &f); /** Add a leaf command. @return This new sub command instance. */ - Command &set(CommandFunction const &f); + Command &subCommand(std::string const &name, std::string const &help, LeafAction const &f); /** Invoke a command. @return The return value of the executed command, or an error value if the command was not found. @@ -83,8 +87,70 @@ class CommandTable std::string _name; ///< Command name. std::string _help; ///< Help message. - /// Command to execute if no more keywords. - CommandFunction _func; + + /** Class to hold varying types of functions. + + @internal A bit ugly, I need to do better wrapping and type erasure. + */ + class Action { + public: + /// Type of the function stored. + enum Type { + NIL, ///< Nothing / empty + LEAF, ///< Leaf action (arguments) + NULLARY, ///< Nullary action. + }; + Action() { } + Action(Action && that) { + _type = that._type; + memcpy(_data, that._data, sizeof(_data)); + that._type = NIL; + } + ~Action() { this->clear(); } + + Action& operator = (LeafAction const& a) { + this->clear(); + _type = LEAF; + new (_data) LeafAction(a); + return *this; + } + + Action& operator = (NullaryAction const& a) { + this->clear(); + _type = NULLARY; + new (_data) NullaryAction(a); + return *this; + } + + Errata invoke(int argc, char *argv[]) { + assert(LEAF == _type); + return (*reinterpret_cast(_data))(argc, argv); + } + + Errata invoke() { + assert(NULLARY == _type); + return (*reinterpret_cast(_data))(); + } + + bool is_leaf() const { return LEAF == _type; } + bool is_nullary() const { return NULLARY == _type; } + + protected: + + void clear() { + switch (_type) { + case NIL: break; + case LEAF: reinterpret_cast(_data)->~LeafAction(); break; + case NULLARY: reinterpret_cast(_data)->~NullaryAction(); break; + } + _type = NIL; + } + + Type _type = NIL; ///< Type of function stored. + /// Raw storage for the function. + char _data[sizeof(NullaryAction) > sizeof(LeafAction) ? sizeof(NullaryAction) : sizeof(LeafAction)]; + } _action; + /// Next command for current keyword. CommandGroup _group; @@ -93,7 +159,9 @@ class CommandTable /// Construct with a function for this command. Command(std::string const &name, std::string const &help); /// Construct with a function for this command. - Command(std::string const &name, std::string const &help, CommandFunction const &f); + Command(std::string const &name, std::string const &help, LeafAction const &f); + /// Construct with a function for this command. + Command(std::string const &name, std::string const &help, NullaryAction const &f); friend class CommandTable; }; @@ -101,7 +169,12 @@ class CommandTable /** Add a direct command. @return The created @c Command instance. */ - Command &add(std::string const &name, std::string const &help, CommandFunction const &f); + Command &add(std::string const &name, std::string const &help, LeafAction const &f); + + /** Add a direct command. + @return The created @c Command instance. + */ + Command &add(std::string const &name, std::string const &help, NullaryAction const &f); /** Add a parent command. @return The created @c Command instance.