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