AceUtils  0.5.0
Useful Arduino utilties which are too small as separate libraries, but complex enough to be shared among multiple projects, and often have external dependencies to other libraries.
CommandDispatcher.h
1 /*
2 MIT License
3 
4 Copyright (c) 2018 Brian T. Park
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12 
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15 
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 
25 #ifndef ACE_UTILS_CLI_COMMAND_DISPATCHER_H
26 #define ACE_UTILS_CLI_COMMAND_DISPATCHER_H
27 
28 #include <AceRoutine.h> // Coroutine, Channel
29 #include "CommandHandler.h"
30 #include "InputLine.h"
31 
32 class Print;
33 class __FlashStringHelper;
34 
35 namespace ace_utils {
36 namespace cli {
37 
52 class CommandDispatcher: public ace_routine::Coroutine {
53  public:
69  ace_routine::Channel<InputLine>& channel,
70  Print& printer,
71  const CommandHandler* const* commands,
72  uint8_t numCommands,
73  const char** argv,
74  uint8_t argvSize,
75  const char* prompt):
76  mChannel(channel),
77  mPrinter(printer),
78  mCommands(commands),
79  mNumCommands(numCommands),
80  mArgv(argv),
81  mArgvSize(argvSize),
82  mPrompt(prompt) {}
83 
85  virtual ~CommandDispatcher() {}
86 
95  static uint8_t tokenize(char* line, const char** argv, uint8_t argvSize) {
96  char* token = strtok(line, DELIMS);
97  int argc = 0;
98  while (token != nullptr && argc < argvSize) {
99  argv[argc] = token;
100  argc++;
101  token = strtok(nullptr, DELIMS);
102  }
103  return argc;
104  }
105 
106  int runCoroutine() override {
107  InputLine input;
108  COROUTINE_LOOP() {
109  if (mPrompt != nullptr) {
110  mPrinter.print(mPrompt);
111  }
112  COROUTINE_CHANNEL_READ(mChannel, input);
113 
114  if (input.status == InputLine::kStatusOverflow) {
115  printLineError(input.line, STATUS_BUFFER_OVERFLOW);
116  continue;
117  }
118 
119  if (mPrompt != nullptr) {
120  mPrinter.print(input.line); // line includes the \n
121  }
122  runCommand(input.line);
123  }
124  }
125 
135  const CommandHandler* findCommand(const char* cmd) const {
136  for (uint8_t i = 0; i < mNumCommands; i++) {
137  const CommandHandler* command = mCommands[i];
138  if (command->getName().compareTo(ace_common::FCString(cmd)) == 0) {
139  return command;
140  }
141  }
142  return nullptr;
143  }
144 
145  protected:
146  // Disable copy-constructor and assignment operator
147  CommandDispatcher(const CommandDispatcher&) = delete;
148  CommandDispatcher& operator=(const CommandDispatcher&) = delete;
149 
151  void printLineError(const char* line, uint8_t statusCode) const;
152 
154  void helpCommandHandler(Print& printer, int argc, const char* const* argv)
155  const;
156 
158  void helpAll(Print& printer) const;
159 
161  bool helpSpecific(Print& printer, const char* cmd) const;
162 
164  static void printHelp(Print& printer, const CommandHandler* command);
165 
167  void runCommand(char* line) const;
168 
170  void findAndRunCommand(const char* cmd, int argc, const char* const* argv)
171  const;
172 
173  static const uint8_t STATUS_SUCCESS = 0;
174  static const uint8_t STATUS_BUFFER_OVERFLOW = 1;
175  static const uint8_t STATUS_FLUSH_TO_EOL = 2;
176  static const char DELIMS[];
177 
178  ace_routine::Channel<InputLine>& mChannel;
179  Print& mPrinter;
180  const CommandHandler* const* const mCommands;
181  uint8_t const mNumCommands;
182  const char** const mArgv;
183  uint8_t const mArgvSize;
184  const char* const mPrompt;
185 };
186 
187 } // cli
188 } // ace_utils
189 
190 #endif
ace_utils::cli::InputLine
Message sent from StreamLineReader to CommandDispatcher coroutines through Channel<InputLine> channel...
Definition: InputLine.h:36
ace_utils::cli::CommandHandler::getName
ace_common::FCString getName() const
Return the name of the command.
Definition: CommandHandler.h:59
ace_utils::cli::CommandHandler
Signature for a command handler.
Definition: CommandHandler.h:38
ace_utils::cli::CommandDispatcher::findAndRunCommand
void findAndRunCommand(const char *cmd, int argc, const char *const *argv) const
Find and run the given command.
Definition: CommandDispatcher.cpp:122
ace_utils::cli::CommandDispatcher::runCommand
void runCommand(char *line) const
Tokenize the given line and run the command handler.
Definition: CommandDispatcher.cpp:107
ace_utils::cli::CommandDispatcher::printHelp
static void printHelp(Print &printer, const CommandHandler *command)
Print help string for the given command.
Definition: CommandDispatcher.cpp:95
ace_utils::cli::CommandDispatcher::helpCommandHandler
void helpCommandHandler(Print &printer, int argc, const char *const *argv) const
Handle the 'help' command.
Definition: CommandDispatcher.cpp:55
ace_utils::cli::CommandDispatcher::~CommandDispatcher
virtual ~CommandDispatcher()
Destructor.
Definition: CommandDispatcher.h:85
ace_utils::cli::CommandDispatcher::helpAll
void helpAll(Print &printer) const
Print help on all commands.
Definition: CommandDispatcher.cpp:77
ace_utils::cli::CommandDispatcher::findCommand
const CommandHandler * findCommand(const char *cmd) const
Find the CommandHandler of the given command name.
Definition: CommandDispatcher.h:135
ace_utils::cli::CommandDispatcher::tokenize
static uint8_t tokenize(char *line, const char **argv, uint8_t argvSize)
Tokenize the line, separating tokens delimited by whitespace (space, formfeed, carriage return,...
Definition: CommandDispatcher.h:95
ace_utils::cli::CommandDispatcher
A coroutine that reads lines from the Serial port, tokenizes the line on whitespace boundaries,...
Definition: CommandDispatcher.h:52
ace_utils::cli::CommandDispatcher::helpSpecific
bool helpSpecific(Print &printer, const char *cmd) const
Print helpString of specific cmd.
Definition: CommandDispatcher.cpp:85
ace_utils::cli::CommandDispatcher::CommandDispatcher
CommandDispatcher(ace_routine::Channel< InputLine > &channel, Print &printer, const CommandHandler *const *commands, uint8_t numCommands, const char **argv, uint8_t argvSize, const char *prompt)
Constructor.
Definition: CommandDispatcher.h:68
ace_utils::cli::CommandDispatcher::printLineError
void printLineError(const char *line, uint8_t statusCode) const
Print the input line that caused an error along with its status code.
Definition: CommandDispatcher.cpp:39