[cli] simplify argument processing (#6767)

This commit changes `ParseCmd()` such that as `aArgs` array entries
are populated with parsed arguments from a command line string, the
remaining unused `aArgs` entries in the array are marked as "empty".
We also ensure that the `aArgs[]` array always end with an "empty"
`Arg` which  indicates end of the list (this is similar to how C
string ends with a null '\0' character). This commit also changes
different methods of `Arg` class (`Arg::ParseAs{Type}()` or overload
of operator `==`, etc) to check and handle when `Arg` is marked
as "empty".

These changes help simplify how the arguments are processed in CLI
modules. In `Cli::Process{Command}()` methods we can just pass the
`aArgs[]` array and do not need to pass a separate args length
parameter. In many cases the args length checks can be removed since
it will be checked from `ParseAs{Type}()` call.
This commit is contained in:
Abtin Keshavarzian
2021-06-29 13:56:41 -07:00
committed by GitHub
parent 57d072d352
commit 0a6a0b6604
23 changed files with 1288 additions and 1418 deletions
+30 -36
View File
@@ -51,9 +51,8 @@ UdpExample::UdpExample(Interpreter &aInterpreter)
memset(&mSocket, 0, sizeof(mSocket));
}
otError UdpExample::ProcessHelp(uint8_t aArgsLength, Arg aArgs[])
otError UdpExample::ProcessHelp(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
for (const Command &command : sCommands)
@@ -64,15 +63,14 @@ otError UdpExample::ProcessHelp(uint8_t aArgsLength, Arg aArgs[])
return OT_ERROR_NONE;
}
otError UdpExample::ProcessBind(uint8_t aArgsLength, Arg aArgs[])
otError UdpExample::ProcessBind(Arg aArgs[])
{
otError error;
otSockAddr sockaddr;
VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = aArgs[0].ParseAsIp6Address(sockaddr.mAddress));
SuccessOrExit(error = aArgs[1].ParseAsUint16(sockaddr.mPort));
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
error = otUdpBind(mInterpreter.mInstance, &mSocket, &sockaddr);
@@ -80,15 +78,14 @@ exit:
return error;
}
otError UdpExample::ProcessConnect(uint8_t aArgsLength, Arg aArgs[])
otError UdpExample::ProcessConnect(Arg aArgs[])
{
otError error;
otSockAddr sockaddr;
VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = aArgs[0].ParseAsIp6Address(sockaddr.mAddress));
SuccessOrExit(error = aArgs[1].ParseAsUint16(sockaddr.mPort));
VerifyOrExit(aArgs[2].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
error = otUdpConnect(mInterpreter.mInstance, &mSocket, &sockaddr);
@@ -96,17 +93,15 @@ exit:
return error;
}
otError UdpExample::ProcessClose(uint8_t aArgsLength, Arg aArgs[])
otError UdpExample::ProcessClose(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
return otUdpClose(mInterpreter.mInstance, &mSocket);
}
otError UdpExample::ProcessOpen(uint8_t aArgsLength, Arg aArgs[])
otError UdpExample::ProcessOpen(Arg aArgs[])
{
OT_UNUSED_VARIABLE(aArgsLength);
OT_UNUSED_VARIABLE(aArgs);
otError error;
@@ -118,12 +113,11 @@ exit:
return error;
}
otError UdpExample::ProcessSend(uint8_t aArgsLength, Arg aArgs[])
otError UdpExample::ProcessSend(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
otMessage * message = nullptr;
otMessageInfo messageInfo;
uint8_t argIndex = 0;
otMessageSettings messageSettings = {mLinkSecurityEnabled, OT_MESSAGE_PRIORITY_NORMAL};
memset(&messageInfo, 0, sizeof(messageInfo));
@@ -135,47 +129,43 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, Arg aArgs[])
// send <ip> <port> <text>
// send <ip> <port> <type> <value>
VerifyOrExit(aArgsLength >= 1 && aArgsLength <= 4, error = OT_ERROR_INVALID_ARGS);
if (aArgsLength > 2)
if (!aArgs[2].IsEmpty())
{
SuccessOrExit(error = aArgs[argIndex++].ParseAsIp6Address(messageInfo.mPeerAddr));
SuccessOrExit(error = aArgs[argIndex++].ParseAsUint16(messageInfo.mPeerPort));
SuccessOrExit(error = aArgs[0].ParseAsIp6Address(messageInfo.mPeerAddr));
SuccessOrExit(error = aArgs[1].ParseAsUint16(messageInfo.mPeerPort));
aArgs += 2;
}
message = otUdpNewMessage(mInterpreter.mInstance, &messageSettings);
VerifyOrExit(message != nullptr, error = OT_ERROR_NO_BUFS);
if (aArgs[argIndex] == "-s")
if (aArgs[0] == "-s")
{
// Auto-generated payload with a given length
uint16_t payloadLength;
argIndex++;
VerifyOrExit(argIndex < aArgsLength, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = aArgs[argIndex].ParseAsUint16(payloadLength));
SuccessOrExit(error = aArgs[1].ParseAsUint16(payloadLength));
SuccessOrExit(error = PrepareAutoGeneratedPayload(*message, payloadLength));
}
else if (aArgs[argIndex] == "-x")
else if (aArgs[0] == "-x")
{
// Binary hex data payload
argIndex++;
VerifyOrExit(argIndex < aArgsLength, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = PrepareHexStringPaylod(*message, aArgs[argIndex].GetCString()));
VerifyOrExit(!aArgs[1].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = PrepareHexStringPaylod(*message, aArgs[1].GetCString()));
}
else
{
// Text payload (same as without specifying the type)
if (aArgs[argIndex] == "-t")
if (aArgs[0] == "-t")
{
argIndex++;
aArgs++;
}
VerifyOrExit(argIndex < aArgsLength, error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = otMessageAppend(message, aArgs[argIndex].GetCString(), aArgs[argIndex].GetLength()));
VerifyOrExit(!aArgs[0].IsEmpty(), error = OT_ERROR_INVALID_ARGS);
SuccessOrExit(error = otMessageAppend(message, aArgs[0].GetCString(), aArgs[0].GetLength()));
}
SuccessOrExit(error = otUdpSend(mInterpreter.mInstance, &mSocket, message, &messageInfo));
@@ -191,11 +181,11 @@ exit:
return error;
}
otError UdpExample::ProcessLinkSecurity(uint8_t aArgsLength, Arg aArgs[])
otError UdpExample::ProcessLinkSecurity(Arg aArgs[])
{
otError error = OT_ERROR_NONE;
if (aArgsLength == 0)
if (aArgs[0].IsEmpty())
{
mInterpreter.OutputEnabledDisabledStatus(mLinkSecurityEnabled);
}
@@ -264,17 +254,21 @@ exit:
return error;
}
otError UdpExample::Process(uint8_t aArgsLength, Arg aArgs[])
otError UdpExample::Process(Arg aArgs[])
{
otError error = OT_ERROR_INVALID_ARGS;
const Command *command;
VerifyOrExit(aArgsLength != 0, IgnoreError(ProcessHelp(0, nullptr)));
if (aArgs[0].IsEmpty())
{
IgnoreError(ProcessHelp(aArgs));
ExitNow();
}
command = Utils::LookupTable::Find(aArgs[0].GetCString(), sCommands);
VerifyOrExit(command != nullptr, error = OT_ERROR_INVALID_COMMAND);
error = (this->*command->mHandler)(aArgsLength - 1, aArgs + 1);
error = (this->*command->mHandler)(aArgs + 1);
exit:
return error;