blob: 4df64da61492c0257ef30af2de8af8f597bf57b7 [file] [log] [blame]
Patrick Benavolicfb64dd2011-10-24 18:50:03 +02001#pragma once
2
3#include <vector>
4#include "RemoteCommandHandler.h"
5
6template <class CCommandParser>
7class TRemoteCommandHandlerTemplate : public IRemoteCommandHandler
8{
9public:
Kevin Rocard325bf972013-07-18 09:13:51 +020010 /** Remote command parser execution return status */
Patrick Benavolicfb64dd2011-10-24 18:50:03 +020011 enum CommandStatus {
Kevin Rocard2c2b20a2013-09-06 11:50:27 +020012 EDone, /**< Command succeded, return "Done" */
13 ESucceeded, /**< Command succeeded */
14 EFailed, /**< Command failed */
15 EShowUsage /**< Command failed, show usage */
Patrick Benavolicfb64dd2011-10-24 18:50:03 +020016 };
17
Kevin Rocard325bf972013-07-18 09:13:51 +020018 /** Type of the remote command callbacks
19 *
20 * @param[in] remoteCommand contains the arguments of the received command.
21 * @param[out] strResult a string containing the result of the command.
22 *
23 * @return the command execution status, @see CommandStatus
24 */
Patrick Benavolicfb64dd2011-10-24 18:50:03 +020025 typedef CommandStatus (CCommandParser::*RemoteCommandParser)(const IRemoteCommand& remoteCommand, std::string& strResult);
26
27private:
28 // Parser descriptions
29 class CRemoteCommandParserItem
30 {
31 public:
32 CRemoteCommandParserItem(const std::string& strCommandName,
33 RemoteCommandParser pfnParser,
34 uint32_t uiMinArgumentCount,
35 const std::string& strHelp,
36 const std::string& strDescription)
37 : _strCommandName(strCommandName),
38 _pfnParser(pfnParser),
39 _uiMinArgumentCount(uiMinArgumentCount),
40 _strHelp(strHelp),
41 _strDescription(strDescription) {}
42
43 const std::string& getCommandName() const
44 {
45 return _strCommandName;
46 }
47
48 const std::string& getDescription() const
49 {
50 return _strDescription;
51 }
52
53 // Usage
54 std::string usage() const
55 {
56 return _strCommandName + " " + _strHelp;
57 }
58
59 bool parse(CCommandParser* pCommandParser, const IRemoteCommand& remoteCommand, std::string& strResult) const
60 {
61 // Check enough arguments supplied
62 if (remoteCommand.getArgumentCount() < _uiMinArgumentCount) {
63
64 strResult = std::string("Not enough arguments supplied\nUsage:\n") + usage();
65
66 return false;
67 }
68
69 switch ((pCommandParser->*_pfnParser)(remoteCommand, strResult)) {
70 case EDone:
71 strResult = "Done";
72 // Fall through intentionally
73 case ESucceeded:
74 return true;
75 case EShowUsage:
76 strResult = usage();
77 // Fall through intentionally
78 case EFailed:
79 return false;
80 }
81
82 return false;
83 }
84
85 private:
86 std::string _strCommandName;
87 RemoteCommandParser _pfnParser;
88 uint32_t _uiMinArgumentCount;
89 std::string _strHelp;
90 std::string _strDescription;
91 };
92
93public:
94 TRemoteCommandHandlerTemplate(CCommandParser* pCommandParser) : _pCommandParser(pCommandParser), _uiMaxCommandUsageLength(0)
95 {
96 // Help Command
97 addCommandParser("help", NULL, 0, "", "Show commands description and usage");
98 }
99 ~TRemoteCommandHandlerTemplate()
100 {
101 uint32_t uiIndex;
102
103 for (uiIndex = 0; uiIndex < _remoteCommandParserVector.size(); uiIndex++) {
104
105 delete _remoteCommandParserVector[uiIndex];
106 }
107 }
108
109 // Parsers
110 bool addCommandParser(const std::string& strCommandName,
111 RemoteCommandParser pfnParser,
112 uint32_t uiMinArgumentCount,
113 const std::string& strHelp,
114 const std::string& strDescription)
115 {
116 if (findCommandParserItem(strCommandName)) {
117
118 // Already exists
119 return false;
120 }
121
122 // Add command
123 _remoteCommandParserVector.push_back(new CRemoteCommandParserItem(strCommandName, pfnParser, uiMinArgumentCount, strHelp, strDescription));
124
125 return true;
126 }
127
128private:
129 // Command processing
130 bool remoteCommandProcess(const IRemoteCommand& remoteCommand, std::string& strResult)
131 {
132 // Dispatch
133 const CRemoteCommandParserItem* pRemoteCommandParserItem = findCommandParserItem(remoteCommand.getCommand());
134
135 if (!pRemoteCommandParserItem) {
136
137 // Not found
138 strResult = "Command not found!";
139
140 return false;
141 }
142
143 if (remoteCommand.getCommand() == "help") {
144
145 helpCommandProcess(strResult);
146
147 return true;
148 }
149
150 return pRemoteCommandParserItem->parse(_pCommandParser, remoteCommand, strResult);
151 }
152
153 // Max command usage length, use for formatting
154 void initMaxCommandUsageLength()
155 {
156 if (!_uiMaxCommandUsageLength) {
157 // Show usages
158 uint32_t uiIndex;
159
160 for (uiIndex = 0; uiIndex < _remoteCommandParserVector.size(); uiIndex++) {
161
162 const CRemoteCommandParserItem* pRemoteCommandParserItem = _remoteCommandParserVector[uiIndex];
163
164 uint32_t uiRemoteCommandUsageLength = pRemoteCommandParserItem->usage().length();
165
166 if (uiRemoteCommandUsageLength > _uiMaxCommandUsageLength) {
167
168 _uiMaxCommandUsageLength = uiRemoteCommandUsageLength;
169 }
170 }
171 }
172 }
173
174 /////////////////// Remote command parsers
175 /// Help
176 void helpCommandProcess(std::string& strResult)
177 {
178 initMaxCommandUsageLength();
179
180 strResult = "\n";
181
182 // Show usages
183 uint32_t uiIndex;
184
185 for (uiIndex = 0; uiIndex < _remoteCommandParserVector.size(); uiIndex++) {
186
187 const CRemoteCommandParserItem* pRemoteCommandParserItem = _remoteCommandParserVector[uiIndex];
188
189 std::string strUsage = pRemoteCommandParserItem->usage();
190
191 strResult += strUsage;
192
193 // Align
194 uint32_t uiToSpacesAdd = _uiMaxCommandUsageLength + 5 - strUsage.length();
195
196 while (uiToSpacesAdd--) {
197
198 strResult += " ";
199 }
200
201 strResult += std::string("=> ") + std::string(pRemoteCommandParserItem->getDescription()) + "\n";
202 }
203 }
204
205 const CRemoteCommandParserItem* findCommandParserItem(const std::string& strCommandName) const
206 {
207 uint32_t uiIndex;
208
209 for (uiIndex = 0; uiIndex < _remoteCommandParserVector.size(); uiIndex++) {
210
211 const CRemoteCommandParserItem* pRemoteCommandParserItem = _remoteCommandParserVector[uiIndex];
212
213 if (pRemoteCommandParserItem->getCommandName() == strCommandName) {
214
215 return pRemoteCommandParserItem;
216 }
217 }
218 return NULL;
219 }
220
221private:
222 CCommandParser* _pCommandParser;
223 std::vector<CRemoteCommandParserItem*> _remoteCommandParserVector;
224 uint32_t _uiMaxCommandUsageLength;
225};
Sebastien Gonzalved7e48442013-03-12 14:30:27 +0100226