AceUtils  0.3
Useful Arduino utilties which are too small as separate libraries, but complex enough to 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 CLI_COMMAND_DISPATCHER_H
26 #define 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 cli {
36 
51 class CommandDispatcher: public ace_routine::Coroutine {
52  public:
68  ace_routine::Channel<InputLine>& channel,
69  Print& printer,
70  const CommandHandler* const* commands,
71  uint8_t numCommands,
72  const char** argv,
73  uint8_t argvSize,
74  const char* prompt):
75  mChannel(channel),
76  mPrinter(printer),
77  mCommands(commands),
78  mNumCommands(numCommands),
79  mArgv(argv),
80  mArgvSize(argvSize),
81  mPrompt(prompt) {}
82 
84  virtual ~CommandDispatcher() {}
85 
94  static uint8_t tokenize(char* line, const char** argv, uint8_t argvSize) {
95  char* token = strtok(line, DELIMS);
96  int argc = 0;
97  while (token != nullptr && argc < argvSize) {
98  argv[argc] = token;
99  argc++;
100  token = strtok(nullptr, DELIMS);
101  }
102  return argc;
103  }
104 
105  int runCoroutine() override {
106  InputLine input;
107  COROUTINE_LOOP() {
108  if (mPrompt != nullptr) {
109  mPrinter.print(mPrompt);
110  }
111  COROUTINE_CHANNEL_READ(mChannel, input);
112 
113  if (input.status == InputLine::kStatusOverflow) {
114  printLineError(input.line, STATUS_BUFFER_OVERFLOW);
115  continue;
116  }
117 
118  if (mPrompt != nullptr) {
119  mPrinter.print(input.line); // line includes the \n
120  }
121  runCommand(input.line);
122  }
123  }
124 
134  const CommandHandler* findCommand(const char* cmd) const {
135  for (uint8_t i = 0; i < mNumCommands; i++) {
136  const CommandHandler* command = mCommands[i];
137  if (command->getName().compareTo(ace_common::FCString(cmd)) == 0) {
138  return command;
139  }
140  }
141  return nullptr;
142  }
143 
144  protected:
145  // Disable copy-constructor and assignment operator
146  CommandDispatcher(const CommandDispatcher&) = delete;
147  CommandDispatcher& operator=(const CommandDispatcher&) = delete;
148 
150  void printLineError(const char* line, uint8_t statusCode) const;
151 
153  void helpCommandHandler(Print& printer, int argc, const char* const* argv)
154  const;
155 
157  void helpAll(Print& printer) const;
158 
160  bool helpSpecific(Print& printer, const char* cmd) const;
161 
163  static void printHelp(Print& printer, const CommandHandler* command);
164 
166  void runCommand(char* line) const;
167 
169  void findAndRunCommand(const char* cmd, int argc, const char* const* argv)
170  const;
171 
172  static const uint8_t STATUS_SUCCESS = 0;
173  static const uint8_t STATUS_BUFFER_OVERFLOW = 1;
174  static const uint8_t STATUS_FLUSH_TO_EOL = 2;
175  static const char DELIMS[];
176 
177  ace_routine::Channel<InputLine>& mChannel;
178  Print& mPrinter;
179  const CommandHandler* const* const mCommands;
180  uint8_t const mNumCommands;
181  const char** const mArgv;
182  uint8_t const mArgvSize;
183  const char* const mPrompt;
184 };
185 
186 }
187 
188 #endif
cli::CommandDispatcher
A coroutine that reads lines from the Serial port, tokenizes the line on whitespace boundaries,...
Definition: CommandDispatcher.h:51
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:94
cli::CommandDispatcher::printHelp
static void printHelp(Print &printer, const CommandHandler *command)
Print help string for the given command.
Definition: CommandDispatcher.cpp:94
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:38
cli::CommandDispatcher::helpSpecific
bool helpSpecific(Print &printer, const char *cmd) const
Print helpString of specific cmd.
Definition: CommandDispatcher.cpp:84
cli::CommandDispatcher::runCommand
void runCommand(char *line) const
Tokenize the given line and run the command handler.
Definition: CommandDispatcher.cpp:106
cli::CommandDispatcher::~CommandDispatcher
virtual ~CommandDispatcher()
Destructor.
Definition: CommandDispatcher.h:84
cli::CommandHandler
Signature for a command handler.
Definition: CommandHandler.h:46
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:67
cli::InputLine
Message sent from StreamLineReader to CommandDispatcher coroutines through Channel<InputLine> channel...
Definition: InputLine.h:35
cli::CommandDispatcher::findAndRunCommand
void findAndRunCommand(const char *cmd, int argc, const char *const *argv) const
Find and run the given command.
Definition: CommandDispatcher.cpp:121
cli::CommandDispatcher::helpAll
void helpAll(Print &printer) const
Print help on all commands.
Definition: CommandDispatcher.cpp:76
cli::CommandDispatcher::findCommand
const CommandHandler * findCommand(const char *cmd) const
Find the CommandHandler of the given command name.
Definition: CommandDispatcher.h:134
cli::CommandDispatcher::helpCommandHandler
void helpCommandHandler(Print &printer, int argc, const char *const *argv) const
Handle the 'help' command.
Definition: CommandDispatcher.cpp:54
cli::CommandHandler::getName
ace_common::FCString getName() const
Return the name of the command.
Definition: CommandHandler.h:67