mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 17:37:46 +00:00
[cmd-parser] adding helper 'ParseAs{Type}' function (#5607)
This commit adds new helper functions under `Utils::CmdLineParser` to
parse a given ASCII string as different simple types, namely signed or
unsigned integers of different bit lengths (`uint8/16/32/64`, and
`int8/16/32`). The new functions validate that the parsed value fits
within the supported range of the expected int type. This commit also
adds different flavors of `ParseAsHexString()` to parse a hex string
into sequence of bytes (with fixed/known size or unknown size allowing
or disallowing truncation). It also moves the parse related methods
(like `ParseAsIp6Prefix`) from CLI modules in `CmdLineParser`.
The CLI modules are then updated to use the new `ParseAs{Type}`
functions simplifying the code and adding extra checks when parsing
the CLI input.
Finally, this commit adds a unit test `test_cmd_line_parser` verifying
the behavior of new `ParseAs{Type}()` functions.
This commit is contained in:
+254
-363
File diff suppressed because it is too large
Load Diff
+1
-40
@@ -126,44 +126,6 @@ public:
|
||||
*/
|
||||
void ProcessLine(char *aBuf, uint16_t aBufLength);
|
||||
|
||||
/**
|
||||
* This method parses an ASCII string as a long.
|
||||
*
|
||||
* @param[in] aString A pointer to the ASCII string.
|
||||
* @param[out] aLong A reference to where the parsed long is placed.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully parsed the ASCII string.
|
||||
* @retval OT_ERROR_INVALID_ARGS @p aString is not a valid long integer.
|
||||
*
|
||||
*/
|
||||
static otError ParseLong(char *aString, long &aLong);
|
||||
|
||||
/**
|
||||
* This method parses an ASCII string as an unsigned long.
|
||||
*
|
||||
* @param[in] aString A pointer to the ASCII string.
|
||||
* @param[out] aUnsignedLong A reference to where the parsed unsigned long is placed.
|
||||
*
|
||||
* @retval OT_ERROR_NONE Successfully parsed the ASCII string.
|
||||
* @retval OT_ERROR_INVALID_ARGS @p aString is not a valid unsigned long integer.
|
||||
*
|
||||
*/
|
||||
static otError ParseUnsignedLong(char *aString, unsigned long &aUnsignedLong);
|
||||
|
||||
/**
|
||||
* This method converts a hex string to binary.
|
||||
*
|
||||
* @param[in] aHex A pointer to the hex string.
|
||||
* @param[out] aBin A pointer to where the binary representation is placed.
|
||||
* @param[in] aBinLength Maximum length of the binary representation.
|
||||
* @param[in] aAllowTruncate TRUE if @p aBinLength may be less than what is required
|
||||
* to convert @p aHex to binary representation, FALSE otherwise.
|
||||
*
|
||||
* @returns The number of bytes in the binary representation, or -1 if @p aHex is not a valid hex string
|
||||
*
|
||||
*/
|
||||
static int Hex2Bin(const char *aHex, uint8_t *aBin, uint16_t aBinLength, bool aAllowTruncate = false);
|
||||
|
||||
/**
|
||||
* This method delivers raw characters to the client.
|
||||
*
|
||||
@@ -296,7 +258,6 @@ private:
|
||||
|
||||
otError ParsePingInterval(const char *aString, uint32_t &aInterval);
|
||||
static otError ParseJoinerDiscerner(char *aString, otJoinerDiscerner &aJoinerDiscerner);
|
||||
static otError ParseIp6Prefix(char *aString, otIp6Prefix &aPrefix);
|
||||
|
||||
otError ProcessHelp(uint8_t aArgsLength, char *aArgs[]);
|
||||
otError ProcessCcaThreshold(uint8_t aArgsLength, char *aArgs[]);
|
||||
@@ -343,7 +304,7 @@ private:
|
||||
otError ProcessContextIdReuseDelay(uint8_t aArgsLength, char *aArgs[]);
|
||||
#endif
|
||||
otError ProcessCounters(uint8_t aArgsLength, char *aArgs[]);
|
||||
otError ProcessCsl(uint8_t aArgsLength, char *argv[]);
|
||||
otError ProcessCsl(uint8_t aArgsLength, char *aArgs[]);
|
||||
#if OPENTHREAD_FTD
|
||||
otError ProcessDelayTimerMin(uint8_t aArgsLength, char *aArgs[]);
|
||||
#endif
|
||||
|
||||
+10
-17
@@ -39,6 +39,11 @@
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
#include "coap/coap_message.hpp"
|
||||
#include "utils/parse_cmdline.hpp"
|
||||
|
||||
using ot::Utils::CmdLineParser::ParseAsIp6Address;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint32;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint8;
|
||||
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
@@ -298,24 +303,12 @@ otError Coap::ProcessParameters(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long value;
|
||||
|
||||
VerifyOrExit(aArgsLength >= 6, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
SuccessOrExit(error = mInterpreter.ParseUnsignedLong(aArgs[2], value));
|
||||
txParameters->mAckTimeout = static_cast<uint32_t>(value);
|
||||
|
||||
SuccessOrExit(error = mInterpreter.ParseUnsignedLong(aArgs[3], value));
|
||||
VerifyOrExit(value <= 255, error = OT_ERROR_INVALID_ARGS);
|
||||
txParameters->mAckRandomFactorNumerator = static_cast<uint8_t>(value);
|
||||
|
||||
SuccessOrExit(error = mInterpreter.ParseUnsignedLong(aArgs[4], value));
|
||||
VerifyOrExit(value <= 255, error = OT_ERROR_INVALID_ARGS);
|
||||
txParameters->mAckRandomFactorDenominator = static_cast<uint8_t>(value);
|
||||
|
||||
SuccessOrExit(error = mInterpreter.ParseUnsignedLong(aArgs[5], value));
|
||||
VerifyOrExit(value <= 255, error = OT_ERROR_INVALID_ARGS);
|
||||
txParameters->mMaxRetransmit = static_cast<uint8_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint32(aArgs[2], txParameters->mAckTimeout));
|
||||
SuccessOrExit(error = ParseAsUint8(aArgs[3], txParameters->mAckRandomFactorNumerator));
|
||||
SuccessOrExit(error = ParseAsUint8(aArgs[4], txParameters->mAckRandomFactorDenominator));
|
||||
SuccessOrExit(error = ParseAsUint8(aArgs[5], txParameters->mMaxRetransmit));
|
||||
|
||||
VerifyOrExit(txParameters->mAckRandomFactorNumerator > txParameters->mAckRandomFactorDenominator,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
@@ -391,7 +384,7 @@ otError Coap::ProcessRequest(uint8_t aArgsLength, char *aArgs[])
|
||||
// Destination IPv6 address
|
||||
if (aArgsLength > 1)
|
||||
{
|
||||
SuccessOrExit(error = otIp6AddressFromString(aArgs[1], &coapDestinationIp));
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[1], coapDestinationIp));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -39,9 +39,14 @@
|
||||
#include <openthread/ip6.h>
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
#include "utils/parse_cmdline.hpp"
|
||||
|
||||
// header for place your x509 certificate and private key
|
||||
#include "x509_cert_key.hpp"
|
||||
|
||||
using ot::Utils::CmdLineParser::ParseAsIp6Address;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint16;
|
||||
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
|
||||
@@ -234,7 +239,7 @@ otError CoapSecure::ProcessRequest(uint8_t aArgsLength, char *aArgs[])
|
||||
// Destination IPv6 address
|
||||
if (aArgsLength > 1)
|
||||
{
|
||||
error = otIp6AddressFromString(aArgs[1], &coapDestinationIp);
|
||||
error = ParseAsIp6Address(aArgs[1], coapDestinationIp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -322,17 +327,13 @@ otError CoapSecure::ProcessConnect(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
// Destination IPv6 address
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
SuccessOrExit(error = otIp6AddressFromString(aArgs[1], &sockaddr.mAddress));
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[1], sockaddr.mAddress));
|
||||
sockaddr.mPort = OT_DEFAULT_COAP_SECURE_PORT;
|
||||
|
||||
// check for port specification
|
||||
if (aArgsLength > 2)
|
||||
{
|
||||
long value;
|
||||
|
||||
error = Interpreter::ParseLong(aArgs[2], value);
|
||||
SuccessOrExit(error);
|
||||
sockaddr.mPort = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[2], sockaddr.mPort));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = otCoapSecureConnect(mInterpreter.mInstance, &sockaddr, &CoapSecure::HandleConnected, this));
|
||||
|
||||
@@ -34,6 +34,13 @@
|
||||
#include "cli_commissioner.hpp"
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
#include "utils/parse_cmdline.hpp"
|
||||
|
||||
using ot::Utils::CmdLineParser::ParseAsHexString;
|
||||
using ot::Utils::CmdLineParser::ParseAsIp6Address;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint16;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint32;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint8;
|
||||
|
||||
#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE && OPENTHREAD_FTD
|
||||
|
||||
@@ -58,21 +65,19 @@ otError Commissioner::ProcessHelp(uint8_t aArgsLength, char *aArgs[])
|
||||
otError Commissioner::ProcessAnnounce(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error;
|
||||
long mask;
|
||||
long count;
|
||||
long period;
|
||||
uint32_t mask;
|
||||
uint8_t count;
|
||||
uint16_t period;
|
||||
otIp6Address address;
|
||||
|
||||
VerifyOrExit(aArgsLength > 4, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[1], mask));
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[2], count));
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[3], period));
|
||||
SuccessOrExit(error = otIp6AddressFromString(aArgs[4], &address));
|
||||
SuccessOrExit(error = ParseAsUint32(aArgs[1], mask));
|
||||
SuccessOrExit(error = ParseAsUint8(aArgs[2], count));
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[3], period));
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[4], address));
|
||||
|
||||
SuccessOrExit(error = otCommissionerAnnounceBegin(mInterpreter.mInstance, static_cast<uint32_t>(mask),
|
||||
static_cast<uint8_t>(count), static_cast<uint16_t>(period),
|
||||
&address));
|
||||
SuccessOrExit(error = otCommissionerAnnounceBegin(mInterpreter.mInstance, mask, count, period, &address));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -81,23 +86,21 @@ exit:
|
||||
otError Commissioner::ProcessEnergy(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error;
|
||||
long mask;
|
||||
long count;
|
||||
long period;
|
||||
long scanDuration;
|
||||
uint32_t mask;
|
||||
uint8_t count;
|
||||
uint16_t period;
|
||||
uint16_t scanDuration;
|
||||
otIp6Address address;
|
||||
|
||||
VerifyOrExit(aArgsLength > 5, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[1], mask));
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[2], count));
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[3], period));
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[4], scanDuration));
|
||||
SuccessOrExit(error = otIp6AddressFromString(aArgs[5], &address));
|
||||
SuccessOrExit(error = ParseAsUint32(aArgs[1], mask));
|
||||
SuccessOrExit(error = ParseAsUint8(aArgs[2], count));
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[3], period));
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[4], scanDuration));
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[5], address));
|
||||
|
||||
SuccessOrExit(error = otCommissionerEnergyScan(mInterpreter.mInstance, static_cast<uint32_t>(mask),
|
||||
static_cast<uint8_t>(count), static_cast<uint16_t>(period),
|
||||
static_cast<uint16_t>(scanDuration), &address,
|
||||
SuccessOrExit(error = otCommissionerEnergyScan(mInterpreter.mInstance, mask, count, period, scanDuration, &address,
|
||||
&Commissioner::HandleEnergyReport, this));
|
||||
|
||||
exit:
|
||||
@@ -121,8 +124,7 @@ otError Commissioner::ProcessJoiner(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else if ((error = Interpreter::ParseJoinerDiscerner(aArgs[2], discerner)) == OT_ERROR_NOT_FOUND)
|
||||
{
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[2], addr.m8, sizeof(addr)) == sizeof(addr),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[2], addr.m8));
|
||||
addrPtr = &addr;
|
||||
}
|
||||
else if (error != OT_ERROR_NONE)
|
||||
@@ -134,22 +136,21 @@ otError Commissioner::ProcessJoiner(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
VerifyOrExit(aArgsLength > 3, error = OT_ERROR_INVALID_ARGS);
|
||||
// Timeout parameter is optional - if not specified, use default value.
|
||||
unsigned long timeout = kDefaultJoinerTimeout;
|
||||
uint32_t timeout = kDefaultJoinerTimeout;
|
||||
|
||||
if (aArgsLength > 4)
|
||||
{
|
||||
SuccessOrExit(error = Interpreter::ParseUnsignedLong(aArgs[4], timeout));
|
||||
SuccessOrExit(error = ParseAsUint32(aArgs[4], timeout));
|
||||
}
|
||||
|
||||
if (discerner.mLength)
|
||||
{
|
||||
SuccessOrExit(error = otCommissionerAddJoinerWithDiscerner(mInterpreter.mInstance, &discerner, aArgs[3],
|
||||
static_cast<uint32_t>(timeout)));
|
||||
SuccessOrExit(
|
||||
error = otCommissionerAddJoinerWithDiscerner(mInterpreter.mInstance, &discerner, aArgs[3], timeout));
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(error = otCommissionerAddJoiner(mInterpreter.mInstance, addrPtr, aArgs[3],
|
||||
static_cast<uint32_t>(timeout)));
|
||||
SuccessOrExit(error = otCommissionerAddJoiner(mInterpreter.mInstance, addrPtr, aArgs[3], timeout));
|
||||
}
|
||||
}
|
||||
else if (strcmp(aArgs[1], "remove") == 0)
|
||||
@@ -174,10 +175,9 @@ exit:
|
||||
|
||||
otError Commissioner::ProcessMgmtGet(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error;
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint8_t tlvs[32];
|
||||
long value;
|
||||
int length = 0;
|
||||
uint8_t length = 0;
|
||||
|
||||
for (uint8_t index = 1; index < aArgsLength; index++)
|
||||
{
|
||||
@@ -201,13 +201,12 @@ otError Commissioner::ProcessMgmtGet(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else if (strcmp(aArgs[index], "-x") == 0)
|
||||
{
|
||||
uint16_t readLength;
|
||||
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
value = static_cast<long>(strlen(aArgs[index]) + 1) / 2;
|
||||
VerifyOrExit(static_cast<size_t>(value) <= (sizeof(tlvs) - static_cast<size_t>(length)),
|
||||
error = OT_ERROR_NO_BUFS);
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], tlvs + length, static_cast<uint16_t>(value)) == value,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
length += value;
|
||||
readLength = static_cast<uint16_t>(sizeof(tlvs) - length);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[index], readLength, tlvs + length));
|
||||
length += static_cast<uint8_t>(readLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -226,8 +225,7 @@ otError Commissioner::ProcessMgmtSet(uint8_t aArgsLength, char *aArgs[])
|
||||
otError error;
|
||||
otCommissioningDataset dataset;
|
||||
uint8_t tlvs[32];
|
||||
long value;
|
||||
int length = 0;
|
||||
uint8_t tlvsLength = 0;
|
||||
|
||||
VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
@@ -235,48 +233,42 @@ otError Commissioner::ProcessMgmtSet(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
for (uint8_t index = 1; index < aArgsLength; index++)
|
||||
{
|
||||
VerifyOrExit(static_cast<size_t>(length) < sizeof(tlvs), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
if (strcmp(aArgs[index], "locator") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mIsLocatorSet = true;
|
||||
SuccessOrExit(error = Interpreter::Interpreter::ParseLong(aArgs[index], value));
|
||||
dataset.mLocator = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mLocator));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "sessionid") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mIsSessionIdSet = true;
|
||||
SuccessOrExit(error = Interpreter::Interpreter::ParseLong(aArgs[index], value));
|
||||
dataset.mSessionId = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mSessionId));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "steeringdata") == 0)
|
||||
{
|
||||
uint16_t length;
|
||||
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mIsSteeringDataSet = true;
|
||||
length = static_cast<int>((strlen(aArgs[index]) + 1) / 2);
|
||||
VerifyOrExit(static_cast<size_t>(length) <= OT_STEERING_DATA_MAX_LENGTH, error = OT_ERROR_NO_BUFS);
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], dataset.mSteeringData.m8, static_cast<uint16_t>(length)) ==
|
||||
length,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
length = sizeof(dataset.mSteeringData.m8);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[index], length, dataset.mSteeringData.m8));
|
||||
dataset.mSteeringData.mLength = static_cast<uint8_t>(length);
|
||||
length = 0;
|
||||
}
|
||||
else if (strcmp(aArgs[index], "joinerudpport") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mIsJoinerUdpPortSet = true;
|
||||
SuccessOrExit(error = Interpreter::Interpreter::ParseLong(aArgs[index], value));
|
||||
dataset.mJoinerUdpPort = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mJoinerUdpPort));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "-x") == 0)
|
||||
{
|
||||
uint16_t length;
|
||||
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
length = static_cast<int>((strlen(aArgs[index]) + 1) / 2);
|
||||
VerifyOrExit(static_cast<size_t>(length) <= sizeof(tlvs), error = OT_ERROR_NO_BUFS);
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], tlvs, static_cast<uint16_t>(length)) == length,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
length = sizeof(tlvs);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[index], length, tlvs));
|
||||
tlvsLength = static_cast<uint8_t>(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -284,8 +276,7 @@ otError Commissioner::ProcessMgmtSet(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
}
|
||||
|
||||
SuccessOrExit(error =
|
||||
otCommissionerSendMgmtSet(mInterpreter.mInstance, &dataset, tlvs, static_cast<uint8_t>(length)));
|
||||
SuccessOrExit(error = otCommissionerSendMgmtSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength));
|
||||
|
||||
exit:
|
||||
return error;
|
||||
@@ -294,18 +285,17 @@ exit:
|
||||
otError Commissioner::ProcessPanId(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error;
|
||||
long panid;
|
||||
long mask;
|
||||
uint16_t panId;
|
||||
uint32_t mask;
|
||||
otIp6Address address;
|
||||
|
||||
VerifyOrExit(aArgsLength > 3, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[1], panid));
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[2], mask));
|
||||
SuccessOrExit(error = otIp6AddressFromString(aArgs[3], &address));
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[1], panId));
|
||||
SuccessOrExit(error = ParseAsUint32(aArgs[2], mask));
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[3], address));
|
||||
|
||||
SuccessOrExit(error = otCommissionerPanIdQuery(mInterpreter.mInstance, static_cast<uint16_t>(panid),
|
||||
static_cast<uint32_t>(mask), &address,
|
||||
SuccessOrExit(error = otCommissionerPanIdQuery(mInterpreter.mInstance, panId, mask, &address,
|
||||
&Commissioner::HandlePanIdConflict, this));
|
||||
|
||||
exit:
|
||||
|
||||
+55
-99
@@ -40,6 +40,14 @@
|
||||
#include <openthread/dataset_ftd.h>
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
#include "utils/parse_cmdline.hpp"
|
||||
|
||||
using ot::Utils::CmdLineParser::ParseAsHexString;
|
||||
using ot::Utils::CmdLineParser::ParseAsIp6Address;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint16;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint32;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint64;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint8;
|
||||
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
@@ -284,10 +292,7 @@ otError Dataset::ProcessActiveTimestamp(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value));
|
||||
sDataset.mActiveTimestamp = static_cast<uint64_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint64(aArgs[0], sDataset.mActiveTimestamp));
|
||||
sDataset.mComponents.mIsActiveTimestampPresent = true;
|
||||
}
|
||||
|
||||
@@ -308,10 +313,7 @@ otError Dataset::ProcessChannel(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value));
|
||||
sDataset.mChannel = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[0], sDataset.mChannel));
|
||||
sDataset.mComponents.mIsChannelPresent = true;
|
||||
}
|
||||
|
||||
@@ -332,10 +334,7 @@ otError Dataset::ProcessChannelMask(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value));
|
||||
sDataset.mChannelMask = static_cast<uint32_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint32(aArgs[0], sDataset.mChannelMask));
|
||||
sDataset.mComponents.mIsChannelMaskPresent = true;
|
||||
}
|
||||
|
||||
@@ -388,10 +387,7 @@ otError Dataset::ProcessDelay(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value));
|
||||
sDataset.mDelay = static_cast<uint32_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint32(aArgs[0], sDataset.mDelay));
|
||||
sDataset.mComponents.mIsDelayPresent = true;
|
||||
}
|
||||
|
||||
@@ -413,12 +409,7 @@ otError Dataset::ProcessExtPanId(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t extPanId[OT_EXT_PAN_ID_SIZE];
|
||||
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[0], extPanId, sizeof(extPanId)) == sizeof(extPanId),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
memcpy(sDataset.mExtendedPanId.m8, extPanId, sizeof(sDataset.mExtendedPanId));
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[0], sDataset.mExtendedPanId.m8));
|
||||
sDataset.mComponents.mIsExtendedPanIdPresent = true;
|
||||
}
|
||||
|
||||
@@ -440,12 +431,7 @@ otError Dataset::ProcessMasterKey(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t key[OT_MASTER_KEY_SIZE];
|
||||
|
||||
VerifyOrExit((Interpreter::Hex2Bin(aArgs[0], key, sizeof(key))) == OT_MASTER_KEY_SIZE,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
memcpy(sDataset.mMasterKey.m8, key, sizeof(sDataset.mMasterKey));
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[0], sDataset.mMasterKey.m8));
|
||||
sDataset.mComponents.mIsMasterKeyPresent = true;
|
||||
}
|
||||
|
||||
@@ -473,7 +459,7 @@ otError Dataset::ProcessMeshLocalPrefix(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otIp6Address prefix;
|
||||
|
||||
SuccessOrExit(error = otIp6AddressFromString(aArgs[0], &prefix));
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[0], prefix));
|
||||
|
||||
memcpy(sDataset.mMeshLocalPrefix.m8, prefix.mFields.m8, sizeof(sDataset.mMeshLocalPrefix.m8));
|
||||
sDataset.mComponents.mIsMeshLocalPrefixPresent = true;
|
||||
@@ -523,10 +509,7 @@ otError Dataset::ProcessPanId(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value));
|
||||
sDataset.mPanId = static_cast<otPanId>(value);
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[0], sDataset.mPanId));
|
||||
sDataset.mComponents.mIsPanIdPresent = true;
|
||||
}
|
||||
|
||||
@@ -547,10 +530,7 @@ otError Dataset::ProcessPendingTimestamp(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value));
|
||||
sDataset.mPendingTimestamp = static_cast<uint64_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint64(aArgs[0], sDataset.mPendingTimestamp));
|
||||
sDataset.mComponents.mIsPendingTimestampPresent = true;
|
||||
}
|
||||
|
||||
@@ -563,9 +543,7 @@ otError Dataset::ProcessMgmtSetCommand(uint8_t aArgsLength, char *aArgs[])
|
||||
otError error = OT_ERROR_NONE;
|
||||
otOperationalDataset dataset;
|
||||
uint8_t tlvs[128];
|
||||
long value;
|
||||
int length = 0;
|
||||
otIp6Address prefix;
|
||||
uint8_t tlvsLength = 0;
|
||||
|
||||
VerifyOrExit(aArgsLength > 0, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
@@ -577,85 +555,77 @@ otError Dataset::ProcessMgmtSetCommand(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsActiveTimestampPresent = true;
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value));
|
||||
dataset.mActiveTimestamp = static_cast<uint64_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint64(aArgs[index], dataset.mActiveTimestamp));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "pendingtimestamp") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsPendingTimestampPresent = true;
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value));
|
||||
dataset.mPendingTimestamp = static_cast<uint64_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint64(aArgs[index], dataset.mPendingTimestamp));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "masterkey") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsMasterKeyPresent = true;
|
||||
VerifyOrExit((length = Interpreter::Hex2Bin(aArgs[index], dataset.mMasterKey.m8,
|
||||
sizeof(dataset.mMasterKey.m8))) == OT_MASTER_KEY_SIZE,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
length = 0;
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[index], dataset.mMasterKey.m8));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "networkname") == 0)
|
||||
{
|
||||
size_t length;
|
||||
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsNetworkNamePresent = true;
|
||||
VerifyOrExit((length = static_cast<int>(strlen(aArgs[index]))) <= OT_NETWORK_NAME_MAX_SIZE,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
VerifyOrExit((length = strlen(aArgs[index])) <= OT_NETWORK_NAME_MAX_SIZE, error = OT_ERROR_INVALID_ARGS);
|
||||
memset(&dataset.mNetworkName, 0, sizeof(sDataset.mNetworkName));
|
||||
memcpy(dataset.mNetworkName.m8, aArgs[index], static_cast<size_t>(length));
|
||||
length = 0;
|
||||
memcpy(dataset.mNetworkName.m8, aArgs[index], length);
|
||||
}
|
||||
else if (strcmp(aArgs[index], "extpanid") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsExtendedPanIdPresent = true;
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], dataset.mExtendedPanId.m8,
|
||||
sizeof(dataset.mExtendedPanId.m8)) == sizeof(dataset.mExtendedPanId.m8),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[index], dataset.mExtendedPanId.m8));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "localprefix") == 0)
|
||||
{
|
||||
otIp6Address prefix;
|
||||
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsMeshLocalPrefixPresent = true;
|
||||
SuccessOrExit(error = otIp6AddressFromString(aArgs[index], &prefix));
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[index], prefix));
|
||||
memcpy(dataset.mMeshLocalPrefix.m8, prefix.mFields.m8, sizeof(dataset.mMeshLocalPrefix.m8));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "delaytimer") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsDelayPresent = true;
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value));
|
||||
dataset.mDelay = static_cast<uint32_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint32(aArgs[index], dataset.mDelay));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "panid") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsPanIdPresent = true;
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value));
|
||||
dataset.mPanId = static_cast<otPanId>(value);
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mPanId));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "channel") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsChannelPresent = true;
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value));
|
||||
dataset.mChannel = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[index], dataset.mChannel));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "channelmask") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
dataset.mComponents.mIsChannelMaskPresent = true;
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[index], value));
|
||||
dataset.mChannelMask = static_cast<uint32_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint32(aArgs[index], dataset.mChannelMask));
|
||||
}
|
||||
else if (strcmp(aArgs[index], "-x") == 0)
|
||||
{
|
||||
uint16_t length;
|
||||
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
length = static_cast<int>((strlen(aArgs[index]) + 1) / 2);
|
||||
VerifyOrExit(static_cast<size_t>(length) <= sizeof(tlvs), error = OT_ERROR_NO_BUFS);
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], tlvs, static_cast<uint16_t>(length)) == length,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
length = sizeof(tlvs);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[index], length, tlvs));
|
||||
tlvsLength = static_cast<uint8_t>(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -665,13 +635,11 @@ otError Dataset::ProcessMgmtSetCommand(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
if (strcmp(aArgs[0], "active") == 0)
|
||||
{
|
||||
SuccessOrExit(
|
||||
error = otDatasetSendMgmtActiveSet(mInterpreter.mInstance, &dataset, tlvs, static_cast<uint8_t>(length)));
|
||||
SuccessOrExit(error = otDatasetSendMgmtActiveSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength));
|
||||
}
|
||||
else if (strcmp(aArgs[0], "pending") == 0)
|
||||
{
|
||||
SuccessOrExit(
|
||||
error = otDatasetSendMgmtPendingSet(mInterpreter.mInstance, &dataset, tlvs, static_cast<uint8_t>(length)));
|
||||
SuccessOrExit(error = otDatasetSendMgmtPendingSet(mInterpreter.mInstance, &dataset, tlvs, tlvsLength));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -687,8 +655,7 @@ otError Dataset::ProcessMgmtGetCommand(uint8_t aArgsLength, char *aArgs[])
|
||||
otError error = OT_ERROR_NONE;
|
||||
otOperationalDatasetComponents datasetComponents;
|
||||
uint8_t tlvs[32];
|
||||
long value;
|
||||
int length = 0;
|
||||
uint8_t tlvsLength = 0;
|
||||
bool destAddrSpecified = false;
|
||||
otIp6Address address;
|
||||
|
||||
@@ -698,8 +665,6 @@ otError Dataset::ProcessMgmtGetCommand(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
for (uint8_t index = 1; index < aArgsLength; index++)
|
||||
{
|
||||
VerifyOrExit(static_cast<size_t>(length) < sizeof(tlvs), error = OT_ERROR_NO_BUFS);
|
||||
|
||||
if (strcmp(aArgs[index], "activetimestamp") == 0)
|
||||
{
|
||||
datasetComponents.mIsActiveTimestampPresent = true;
|
||||
@@ -738,18 +703,17 @@ otError Dataset::ProcessMgmtGetCommand(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else if (strcmp(aArgs[index], "-x") == 0)
|
||||
{
|
||||
uint16_t length;
|
||||
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
value = static_cast<long>(strlen(aArgs[index]) + 1) / 2;
|
||||
VerifyOrExit(static_cast<size_t>(value) <= (sizeof(tlvs) - static_cast<size_t>(length)),
|
||||
error = OT_ERROR_NO_BUFS);
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[index], tlvs + length, static_cast<uint16_t>(value)) == value,
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
length += value;
|
||||
length = sizeof(tlvs);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[index], length, tlvs));
|
||||
tlvsLength = static_cast<uint8_t>(length);
|
||||
}
|
||||
else if (strcmp(aArgs[index], "address") == 0)
|
||||
{
|
||||
VerifyOrExit(++index < aArgsLength, error = OT_ERROR_INVALID_ARGS);
|
||||
SuccessOrExit(error = otIp6AddressFromString(aArgs[index], &address));
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[index], address));
|
||||
destAddrSpecified = true;
|
||||
}
|
||||
else
|
||||
@@ -760,14 +724,12 @@ otError Dataset::ProcessMgmtGetCommand(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
if (strcmp(aArgs[0], "active") == 0)
|
||||
{
|
||||
SuccessOrExit(error = otDatasetSendMgmtActiveGet(mInterpreter.mInstance, &datasetComponents, tlvs,
|
||||
static_cast<uint8_t>(length),
|
||||
SuccessOrExit(error = otDatasetSendMgmtActiveGet(mInterpreter.mInstance, &datasetComponents, tlvs, tlvsLength,
|
||||
destAddrSpecified ? &address : nullptr));
|
||||
}
|
||||
else if (strcmp(aArgs[0], "pending") == 0)
|
||||
{
|
||||
SuccessOrExit(error = otDatasetSendMgmtPendingGet(mInterpreter.mInstance, &datasetComponents, tlvs,
|
||||
static_cast<uint8_t>(length),
|
||||
SuccessOrExit(error = otDatasetSendMgmtPendingGet(mInterpreter.mInstance, &datasetComponents, tlvs, tlvsLength,
|
||||
destAddrSpecified ? &address : nullptr));
|
||||
}
|
||||
else
|
||||
@@ -793,9 +755,7 @@ otError Dataset::ProcessPskc(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else if (aArgsLength == 1)
|
||||
{
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[0], sDataset.mPskc.m8, sizeof(sDataset.mPskc)) ==
|
||||
sizeof(sDataset.mPskc),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[0], sDataset.mPskc.m8));
|
||||
}
|
||||
#if OPENTHREAD_FTD
|
||||
else if (aArgsLength == 2 && !strcmp(aArgs[0], "-p"))
|
||||
@@ -862,11 +822,8 @@ otError Dataset::ProcessSecurityPolicy(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else
|
||||
{
|
||||
long value;
|
||||
|
||||
SuccessOrExit(error = Interpreter::ParseLong(aArgs[0], value));
|
||||
sDataset.mSecurityPolicy.mRotationTime = static_cast<uint16_t>(value);
|
||||
sDataset.mSecurityPolicy.mFlags = 0;
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[0], sDataset.mSecurityPolicy.mRotationTime));
|
||||
sDataset.mSecurityPolicy.mFlags = 0;
|
||||
|
||||
if (aArgsLength > 1)
|
||||
{
|
||||
@@ -911,13 +868,12 @@ otError Dataset::ProcessSet(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
otOperationalDatasetTlvs dataset;
|
||||
int tlvsLength;
|
||||
uint16_t tlvsLength;
|
||||
|
||||
VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
tlvsLength = Interpreter::Hex2Bin(aArgs[1], dataset.mTlvs, sizeof(dataset.mTlvs));
|
||||
VerifyOrExit((0 <= tlvsLength) && (static_cast<size_t>(tlvsLength) <= sizeof(dataset.mTlvs)),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
tlvsLength = sizeof(dataset.mTlvs);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[1], tlvsLength, dataset.mTlvs));
|
||||
dataset.mLength = static_cast<uint8_t>(tlvsLength);
|
||||
|
||||
if (strcmp(aArgs[0], "active") == 0)
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
#include "utils/parse_cmdline.hpp"
|
||||
|
||||
#if OPENTHREAD_CONFIG_JOINER_ENABLE
|
||||
|
||||
|
||||
@@ -38,8 +38,10 @@
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "utils/parse_cmdline.hpp"
|
||||
|
||||
using ot::Encoding::BigEndian::HostSwap16;
|
||||
using ot::Utils::CmdLineParser::ParseAsHexString;
|
||||
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
@@ -212,7 +214,7 @@ otError NetworkData::ProcessSteeringData(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
if (error == OT_ERROR_NOT_FOUND)
|
||||
{
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[1], addr.m8, sizeof(addr)) == sizeof(addr), OT_NOOP);
|
||||
SuccessOrExit(error = ParseAsHexString(aArgs[1], addr.m8));
|
||||
}
|
||||
else if (error != OT_ERROR_NONE)
|
||||
{
|
||||
|
||||
+16
-35
@@ -38,9 +38,14 @@
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "utils/parse_cmdline.hpp"
|
||||
|
||||
using ot::Encoding::BigEndian::HostSwap16;
|
||||
|
||||
using ot::Utils::CmdLineParser::ParseAsHexString;
|
||||
using ot::Utils::CmdLineParser::ParseAsIp6Address;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint16;
|
||||
|
||||
namespace ot {
|
||||
namespace Cli {
|
||||
|
||||
@@ -70,19 +75,11 @@ otError UdpExample::ProcessBind(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error;
|
||||
otSockAddr sockaddr;
|
||||
long value;
|
||||
|
||||
VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
|
||||
error = otIp6AddressFromString(aArgs[0], &sockaddr.mAddress);
|
||||
SuccessOrExit(error);
|
||||
|
||||
error = Interpreter::ParseLong(aArgs[1], value);
|
||||
SuccessOrExit(error);
|
||||
|
||||
sockaddr.mPort = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[0], sockaddr.mAddress));
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[1], sockaddr.mPort));
|
||||
|
||||
error = otUdpBind(mInterpreter.mInstance, &mSocket, &sockaddr);
|
||||
|
||||
@@ -94,19 +91,11 @@ otError UdpExample::ProcessConnect(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error;
|
||||
otSockAddr sockaddr;
|
||||
long value;
|
||||
|
||||
VerifyOrExit(aArgsLength == 2, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
memset(&sockaddr, 0, sizeof(sockaddr));
|
||||
|
||||
error = otIp6AddressFromString(aArgs[0], &sockaddr.mAddress);
|
||||
SuccessOrExit(error);
|
||||
|
||||
error = Interpreter::ParseLong(aArgs[1], value);
|
||||
SuccessOrExit(error);
|
||||
|
||||
sockaddr.mPort = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[0], sockaddr.mAddress));
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[1], sockaddr.mPort));
|
||||
|
||||
error = otUdpConnect(mInterpreter.mInstance, &mSocket, &sockaddr);
|
||||
|
||||
@@ -146,14 +135,8 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
if (aArgsLength > 2)
|
||||
{
|
||||
long value;
|
||||
error = otIp6AddressFromString(aArgs[curArg++], &messageInfo.mPeerAddr);
|
||||
SuccessOrExit(error);
|
||||
|
||||
error = Interpreter::ParseLong(aArgs[curArg++], value);
|
||||
SuccessOrExit(error);
|
||||
|
||||
messageInfo.mPeerPort = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsIp6Address(aArgs[curArg++], messageInfo.mPeerAddr));
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[curArg++], messageInfo.mPeerPort));
|
||||
}
|
||||
|
||||
if (aArgsLength == 2 || aArgsLength == 4)
|
||||
@@ -162,10 +145,8 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
if (strcmp(aArgs[typePos], "-s") == 0)
|
||||
{
|
||||
unsigned long value;
|
||||
payloadType = kTypeAutoSize;
|
||||
SuccessOrExit(error = Interpreter::ParseUnsignedLong(aArgs[curArg], value));
|
||||
payloadLength = static_cast<uint16_t>(value);
|
||||
SuccessOrExit(error = ParseAsUint16(aArgs[curArg], payloadLength));
|
||||
}
|
||||
else if (strcmp(aArgs[typePos], "-x") == 0)
|
||||
{
|
||||
@@ -192,14 +173,14 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, char *aArgs[])
|
||||
case kTypeHexString:
|
||||
{
|
||||
uint8_t buf[50];
|
||||
int16_t bufLen;
|
||||
uint16_t bufLen;
|
||||
uint16_t conversionLength = 0;
|
||||
const char *hexString = aArgs[curArg];
|
||||
|
||||
while (payloadLength > 0)
|
||||
{
|
||||
bufLen = static_cast<int16_t>(Interpreter::Hex2Bin(hexString, buf, sizeof(buf), true));
|
||||
|
||||
bufLen = sizeof(buf);
|
||||
SuccessOrExit(error = ParseAsHexString(hexString, bufLen, buf, Utils::CmdLineParser::kAllowTruncate));
|
||||
VerifyOrExit(bufLen > 0, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
conversionLength = static_cast<uint16_t>(bufLen * 2);
|
||||
@@ -211,7 +192,7 @@ otError UdpExample::ProcessSend(uint8_t aArgsLength, char *aArgs[])
|
||||
|
||||
hexString += conversionLength;
|
||||
payloadLength -= conversionLength;
|
||||
SuccessOrExit(error = otMessageAppend(message, buf, static_cast<uint16_t>(bufLen)));
|
||||
SuccessOrExit(error = otMessageAppend(message, buf, bufLen));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -31,14 +31,17 @@
|
||||
* This file implements the command line parser.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "parse_cmdline.hpp"
|
||||
|
||||
#include <limits>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/code_utils.hpp"
|
||||
#include "net/ip6_address.hpp"
|
||||
|
||||
namespace ot {
|
||||
namespace Utils {
|
||||
namespace CmdLineParser {
|
||||
|
||||
static bool IsSeparator(char aChar)
|
||||
{
|
||||
@@ -50,7 +53,38 @@ static bool IsEscapable(char aChar)
|
||||
return IsSeparator(aChar) || (aChar == '\\');
|
||||
}
|
||||
|
||||
otError CmdLineParser::ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax)
|
||||
static otError ParseDigit(char aDigitChar, uint8_t &aValue)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
VerifyOrExit(('0' <= aDigitChar) && (aDigitChar <= '9'), error = OT_ERROR_INVALID_ARGS);
|
||||
aValue = static_cast<uint8_t>(aDigitChar - '0');
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
static otError ParseHexDigit(char aHexChar, uint8_t &aValue)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
if (('A' <= aHexChar) && (aHexChar <= 'F'))
|
||||
{
|
||||
ExitNow(aValue = static_cast<uint8_t>(aHexChar - 'A' + 10));
|
||||
}
|
||||
|
||||
if (('a' <= aHexChar) && (aHexChar <= 'f'))
|
||||
{
|
||||
ExitNow(aValue = static_cast<uint8_t>(aHexChar - 'a' + 10));
|
||||
}
|
||||
|
||||
error = ParseDigit(aHexChar, aValue);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
char * cmd;
|
||||
@@ -80,5 +114,229 @@ exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
template <typename UintType> otError ParseUint(const char *aString, UintType &aUint)
|
||||
{
|
||||
otError error;
|
||||
uint64_t value;
|
||||
|
||||
SuccessOrExit(error = ParseAsUint64(aString, value));
|
||||
|
||||
VerifyOrExit(value <= std::numeric_limits<UintType>::max(), error = OT_ERROR_INVALID_ARGS);
|
||||
aUint = static_cast<UintType>(value);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError ParseAsUint8(const char *aString, uint8_t &aUint8)
|
||||
{
|
||||
return ParseUint<uint8_t>(aString, aUint8);
|
||||
}
|
||||
|
||||
otError ParseAsUint16(const char *aString, uint16_t &aUint16)
|
||||
{
|
||||
return ParseUint<uint16_t>(aString, aUint16);
|
||||
}
|
||||
|
||||
otError ParseAsUint32(const char *aString, uint32_t &aUint32)
|
||||
{
|
||||
return ParseUint<uint32_t>(aString, aUint32);
|
||||
}
|
||||
|
||||
otError ParseAsUint64(const char *aString, uint64_t &aUint64)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint64_t value = 0;
|
||||
const char *cur = aString;
|
||||
bool isHex = false;
|
||||
|
||||
enum : uint64_t
|
||||
{
|
||||
kMaxHexBeforeOveflow = (0xffffffffffffffffULL / 16),
|
||||
kMaxDecBeforeOverlow = (0xffffffffffffffffULL / 10),
|
||||
};
|
||||
|
||||
if (cur[0] == '0' && (cur[1] == 'x' || cur[1] == 'X'))
|
||||
{
|
||||
cur += 2;
|
||||
isHex = true;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
uint8_t digit;
|
||||
uint64_t newValue;
|
||||
|
||||
SuccessOrExit(error = isHex ? ParseHexDigit(*cur, digit) : ParseDigit(*cur, digit));
|
||||
VerifyOrExit(value <= (isHex ? kMaxHexBeforeOveflow : kMaxDecBeforeOverlow), error = OT_ERROR_INVALID_ARGS);
|
||||
value = isHex ? (value << 4) : (value * 10);
|
||||
newValue = value + digit;
|
||||
VerifyOrExit(newValue >= value, error = OT_ERROR_INVALID_ARGS);
|
||||
value = newValue;
|
||||
cur++;
|
||||
} while (*cur != '\0');
|
||||
|
||||
aUint64 = value;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
template <typename IntType> otError ParseInt(const char *aString, IntType &aInt)
|
||||
{
|
||||
otError error;
|
||||
int32_t value;
|
||||
|
||||
SuccessOrExit(error = ParseAsInt32(aString, value));
|
||||
|
||||
VerifyOrExit((std::numeric_limits<IntType>::min() <= value) && (value <= std::numeric_limits<IntType>::max()),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
aInt = static_cast<IntType>(value);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError ParseAsInt8(const char *aString, int8_t &aInt8)
|
||||
{
|
||||
return ParseInt<int8_t>(aString, aInt8);
|
||||
}
|
||||
|
||||
otError ParseAsInt16(const char *aString, int16_t &aInt16)
|
||||
{
|
||||
return ParseInt<int16_t>(aString, aInt16);
|
||||
}
|
||||
|
||||
otError ParseAsInt32(const char *aString, int32_t &aInt32)
|
||||
{
|
||||
otError error;
|
||||
uint64_t value;
|
||||
bool isNegavtive = false;
|
||||
|
||||
if (*aString == '-')
|
||||
{
|
||||
aString++;
|
||||
isNegavtive = true;
|
||||
}
|
||||
else if (*aString == '+')
|
||||
{
|
||||
aString++;
|
||||
}
|
||||
|
||||
SuccessOrExit(error = ParseAsUint64(aString, value));
|
||||
VerifyOrExit(value <= (isNegavtive
|
||||
? static_cast<uint64_t>(-static_cast<int64_t>(std::numeric_limits<int32_t>::min()))
|
||||
: static_cast<uint64_t>(std::numeric_limits<int32_t>::max())),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
aInt32 = isNegavtive ? -static_cast<int32_t>(value) : static_cast<int32_t>(value);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError ParseAsBool(const char *aString, bool &aBool)
|
||||
{
|
||||
otError error;
|
||||
uint32_t value;
|
||||
|
||||
SuccessOrExit(error = ParseAsUint32(aString, value));
|
||||
aBool = (value != 0);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
otError ParseAsIp6Prefix(const char *aString, otIp6Prefix &aPrefix)
|
||||
{
|
||||
enum : uint8_t
|
||||
{
|
||||
kMaxIp6AddressStringSize = 45,
|
||||
};
|
||||
|
||||
otError error = OT_ERROR_INVALID_ARGS;
|
||||
char string[kMaxIp6AddressStringSize];
|
||||
const char *prefixLengthStr;
|
||||
|
||||
prefixLengthStr = strchr(aString, '/');
|
||||
VerifyOrExit(prefixLengthStr != nullptr, OT_NOOP);
|
||||
|
||||
VerifyOrExit(prefixLengthStr - aString < static_cast<int32_t>(sizeof(string)), OT_NOOP);
|
||||
|
||||
memcpy(string, aString, static_cast<uint8_t>(prefixLengthStr - aString));
|
||||
string[prefixLengthStr - aString] = '\0';
|
||||
|
||||
SuccessOrExit(static_cast<Ip6::Address &>(aPrefix.mPrefix).FromString(string));
|
||||
error = ParseAsUint8(prefixLengthStr + 1, aPrefix.mLength);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
#endif // #if OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
otError ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize)
|
||||
{
|
||||
otError error;
|
||||
uint16_t readSize = aSize;
|
||||
|
||||
SuccessOrExit(error = ParseAsHexString(aString, readSize, aBuffer, kDisallowTruncate));
|
||||
VerifyOrExit(readSize == aSize, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError ParseAsHexString(const char *aString, uint16_t &aSize, uint8_t *aBuffer, HexStringParseMode aMode)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
uint8_t byte = 0;
|
||||
uint16_t readBytes = 0;
|
||||
const char *hex = aString;
|
||||
size_t hexLength = strlen(aString);
|
||||
uint8_t numChars;
|
||||
|
||||
if (aMode == kDisallowTruncate)
|
||||
{
|
||||
VerifyOrExit((hexLength + 1) / 2 <= aSize, error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
|
||||
// Handle the case where number of chars in hex string is odd.
|
||||
numChars = hexLength & 1;
|
||||
|
||||
while (*hex != '\0')
|
||||
{
|
||||
uint8_t digit;
|
||||
|
||||
SuccessOrExit(error = ParseHexDigit(*hex, digit));
|
||||
byte |= digit;
|
||||
|
||||
hex++;
|
||||
numChars++;
|
||||
|
||||
if (numChars >= 2)
|
||||
{
|
||||
numChars = 0;
|
||||
*aBuffer++ = byte;
|
||||
byte = 0;
|
||||
readBytes++;
|
||||
|
||||
if (readBytes == aSize)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
byte <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
aSize = readBytes;
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
} // namespace CmdLineParser
|
||||
} // namespace Utils
|
||||
} // namespace ot
|
||||
|
||||
@@ -35,10 +35,13 @@
|
||||
#define PARSE_CMD_LINE_HPP_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <openthread/error.h>
|
||||
#include <openthread/ip6.h>
|
||||
|
||||
namespace ot {
|
||||
namespace Utils {
|
||||
namespace CmdLineParser {
|
||||
|
||||
/**
|
||||
* @addtogroup utils-parse-cmd-line
|
||||
@@ -50,32 +53,242 @@ namespace Utils {
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements the command line parser.
|
||||
* This enumeration type represents the parse mode value used as a parameter in `ParseAsHexString()`.
|
||||
*
|
||||
*/
|
||||
class CmdLineParser
|
||||
enum HexStringParseMode : uint8_t
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This function parses the command line.
|
||||
*
|
||||
* Note: this method may change the input @p aString, it will put a '\0' by the end of each argument,
|
||||
* and @p aArgs will point to the arguments in the input @p aString. Backslash ('\') can be used
|
||||
* to escape separators (' ', '\t', '\r', '\n') and the backslash itself.
|
||||
*
|
||||
* @param[in] aString A null-terminated input string.
|
||||
* @param[out] aArgsLength The argument counter of the command line.
|
||||
* @param[out] aArgs The argument vector of the command line.
|
||||
* @param[in] aArgsLengthMax The maximum argument counter.
|
||||
*
|
||||
*/
|
||||
static otError ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax);
|
||||
kDisallowTruncate, // Disallow truncation of hex string.
|
||||
kAllowTruncate, // Allow truncation of hex string.
|
||||
};
|
||||
|
||||
/**
|
||||
* This function parses a given command line string and breaks it into an argument list.
|
||||
*
|
||||
* Note: this method may change the input @p aCommandString, it will put a '\0' by the end of each argument,
|
||||
* and @p aArgs will point to the arguments in the input @p aCommandString. Backslash ('\') can be used
|
||||
* to escape separators (' ', '\t', '\r', '\n') and the backslash itself.
|
||||
*
|
||||
* @param[in] aCommandString A null-terminated input string.
|
||||
* @param[out] aArgsLength The argument counter of the command line.
|
||||
* @param[out] aArgs The argument vector of the command line.
|
||||
* @param[in] aArgsLengthMax The maximum argument counter.
|
||||
*
|
||||
*/
|
||||
otError ParseCmd(char *aCommandString, uint8_t &aArgsLength, char *aArgs[], uint8_t aArgsLengthMax);
|
||||
|
||||
/**
|
||||
* This function parses a string as a `uint8_t` value.
|
||||
*
|
||||
* The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix).
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aUint8 A reference to an `uint8_t` variable to output the parsed value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
|
||||
*
|
||||
*/
|
||||
otError ParseAsUint8(const char *aString, uint8_t &aUint8);
|
||||
|
||||
/**
|
||||
* This function parses a string as a `uint16_t` value.
|
||||
*
|
||||
* The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix).
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aUint16 A reference to an `uint16_t` variable to output the parsed value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
|
||||
*
|
||||
*/
|
||||
otError ParseAsUint16(const char *aString, uint16_t &aUint16);
|
||||
|
||||
/**
|
||||
* This function parses a string as a `uint32_t` value.
|
||||
*
|
||||
* The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix).
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aUint32 A reference to an `uint32_t` variable to output the parsed value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
|
||||
*
|
||||
*/
|
||||
otError ParseAsUint32(const char *aString, uint32_t &aUint32);
|
||||
|
||||
/**
|
||||
* This function parses a string as a `uint64_t` value.
|
||||
*
|
||||
* The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix).
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aUint64 A reference to an `uint64_t` variable to output the parsed value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
|
||||
*
|
||||
*/
|
||||
otError ParseAsUint64(const char *aString, uint64_t &aUint64);
|
||||
|
||||
/**
|
||||
* This function parses a string as a `int8_t` value.
|
||||
*
|
||||
* The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). The string can start with
|
||||
* `+`/`-` sign.
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aInt8 A reference to an `int8_t` variable to output the parsed value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
|
||||
*
|
||||
*/
|
||||
otError ParseAsInt8(const char *aString, int8_t &aInt8);
|
||||
|
||||
/**
|
||||
* This function parses a string as a `int16_t` value.
|
||||
*
|
||||
* The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). The string can start with
|
||||
* `+`/`-` sign.
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aInt16 A reference to an `int16_t` variable to output the parsed value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
|
||||
*
|
||||
*/
|
||||
otError ParseAsInt16(const char *aString, int16_t &aInt16);
|
||||
|
||||
/**
|
||||
* This function parses a string as a `int32_t` value.
|
||||
*
|
||||
* The number in string is parsed as decimal or hex format (if contains `0x` or `0X` prefix). The string can start with
|
||||
* `+`/`-` sign.
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aInt32 A reference to an `int32_t` variable to output the parsed value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid number (e.g., value out of range).
|
||||
*
|
||||
*/
|
||||
otError ParseAsInt32(const char *aString, int32_t &aInt32);
|
||||
|
||||
/**
|
||||
* This function parses a string as a `bool` value.
|
||||
*
|
||||
* Zero value is treated as `false, non-zero value as `true`.
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aBool A reference to a `bool` variable to output the parsed value.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid number.
|
||||
*
|
||||
*/
|
||||
otError ParseAsBool(const char *aString, bool &aBool);
|
||||
|
||||
#if OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
/**
|
||||
* This function parses a string as an IPv6 address.
|
||||
*
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aAddress A reference to an `otIp6Address` to output the parsed IPv6 address.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid IPv6 address.
|
||||
*
|
||||
*/
|
||||
inline otError ParseAsIp6Address(const char *aString, otIp6Address &aAddress)
|
||||
{
|
||||
return otIp6AddressFromString(aString, &aAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function parses a string as an IPv6 prefix.
|
||||
*
|
||||
* The string is parsed as `{IPv6Address}/{PrefixLength}`.
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aPrefix A reference to an `otIp6Prefix` to output the parsed IPv6 prefix.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid IPv6 prefix
|
||||
*
|
||||
*/
|
||||
otError ParseAsIp6Prefix(const char *aString, otIp6Prefix &aPrefix);
|
||||
#endif // OPENTHREAD_FTD || OPENTHREAD_MTD
|
||||
|
||||
/**
|
||||
* This function parses a hex string into a byte array of fixed expected size.
|
||||
*
|
||||
* This function returns `OT_ERROR_NONE` only when the hex string contains exactly @p aSize bytes (after parsing). If
|
||||
* there are fewer or more bytes in hex string that @p aSize, the parsed bytes (up to @p aSize) are copied into the
|
||||
* `aBuffer` and `OT_ERROR_INVALID_ARGS` is returned.
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence.
|
||||
* @param[in] aSize The expected size of byte sequence (number of bytes after parsing).
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid hex bytes and/or not @p aSize bytes.
|
||||
*
|
||||
*/
|
||||
otError ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize);
|
||||
|
||||
/**
|
||||
* This template function parses a hex string into a a given fixed size array.
|
||||
*
|
||||
* This function returns `OT_ERROR_NONE` only when the hex string contains exactly @p kBufferSize bytes (after parsing).
|
||||
* If there are fewer or more bytes in hex string that @p kBufferSize, the parsed bytes (up to @p kBufferSize) are
|
||||
* copied into the `aBuffer` and `OT_ERROR_INVALID_ARGS` is returned.
|
||||
*
|
||||
* @tparam kBufferSize The byte array size (number of bytes).
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[out] aBuffer A reference to a byte array to output the parsed byte sequence.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid hex bytes and/or not @p aSize bytes.
|
||||
*
|
||||
*/
|
||||
template <uint16_t kBufferSize> static otError ParseAsHexString(const char *aString, uint8_t (&aBuffer)[kBufferSize])
|
||||
{
|
||||
return ParseAsHexString(aString, aBuffer, kBufferSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function parses a hex string into a byte array.
|
||||
*
|
||||
* If @p aMode disallows truncation (`kDisallowTruncate`), this function verifies that parses hex string bytes fit in
|
||||
* @p aBuffer with its given size in @aSize. Otherwise when @p aMode allows truncation, extra bytes after @p aSize bytes
|
||||
* are ignored.
|
||||
*
|
||||
* @param[in] aString The string to parse.
|
||||
* @param[inout] aSize On entry indicates the number of bytes in @p aBuffer (max size of @p aBuffer).
|
||||
* On exit provides number of bytes parsed and copied into @p aBuffer
|
||||
* @param[out] aBuffer A pointer to a buffer to output the parsed byte sequence.
|
||||
* @param[in] aMode Indicates parsing mode whether to allow truncation or not.
|
||||
*
|
||||
* @retval OT_ERROR_NONE The string was parsed successfully.
|
||||
* @retval OT_ERROR_INVALID_ARGS The string does not contain valid format or too many bytes (if truncation not allowed)
|
||||
*
|
||||
*/
|
||||
otError ParseAsHexString(const char * aString,
|
||||
uint16_t & aSize,
|
||||
uint8_t * aBuffer,
|
||||
HexStringParseMode aMode = kDisallowTruncate);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace CmdLineParser
|
||||
} // namespace Utils
|
||||
} // namespace ot
|
||||
|
||||
|
||||
@@ -139,6 +139,28 @@ target_link_libraries(test-child-table
|
||||
|
||||
add_test(NAME test-child-table COMMAND test-child-table)
|
||||
|
||||
add_executable(test-cmd-line-parser
|
||||
${COMMON_SOURCES}
|
||||
test_cmd_line_parser.cpp
|
||||
)
|
||||
|
||||
target_include_directories(test-cmd-line-parser
|
||||
PRIVATE
|
||||
${COMMON_INCLUDES}
|
||||
)
|
||||
|
||||
target_compile_options(test-cmd-line-parser
|
||||
PRIVATE
|
||||
${COMMON_COMPILE_OPTIONS}
|
||||
)
|
||||
|
||||
target_link_libraries(test-cmd-line-parser
|
||||
PRIVATE
|
||||
${COMMON_LIBS}
|
||||
)
|
||||
|
||||
add_test(NAME test-cmd-line-parser COMMAND test-cmd-line-parser)
|
||||
|
||||
add_executable(test-flash
|
||||
${COMMON_SOURCES}
|
||||
test_flash.cpp
|
||||
@@ -608,6 +630,7 @@ set_target_properties(
|
||||
test-checksum
|
||||
test-child
|
||||
test-child-table
|
||||
test-cmd-line-parser
|
||||
test-flash
|
||||
test-heap
|
||||
test-hmac-sha256
|
||||
|
||||
@@ -110,6 +110,7 @@ check_PROGRAMS += \
|
||||
test-checksum \
|
||||
test-child \
|
||||
test-child-table \
|
||||
test-cmd-line-parser \
|
||||
test-flash \
|
||||
test-heap \
|
||||
test-hmac-sha256 \
|
||||
@@ -183,6 +184,9 @@ test_child_SOURCES = $(COMMON_SOURCES) test_child.cpp
|
||||
test_child_table_LDADD = $(COMMON_LDADD)
|
||||
test_child_table_SOURCES = $(COMMON_SOURCES) test_child_table.cpp
|
||||
|
||||
test_cmd_line_parser_LDADD = $(COMMON_LDADD)
|
||||
test_cmd_line_parser_SOURCES = $(COMMON_SOURCES) test_cmd_line_parser.cpp
|
||||
|
||||
test_flash_LDADD = $(COMMON_LDADD)
|
||||
test_flash_SOURCES = $(COMMON_SOURCES) test_flash.cpp
|
||||
|
||||
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Copyright (c) 2020, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "test_platform.h"
|
||||
|
||||
#include <openthread/config.h>
|
||||
|
||||
#include "common/instance.hpp"
|
||||
#include "utils/parse_cmdline.hpp"
|
||||
|
||||
#include "test_util.h"
|
||||
|
||||
using ot::Utils::CmdLineParser::ParseAsBool;
|
||||
using ot::Utils::CmdLineParser::ParseAsHexString;
|
||||
using ot::Utils::CmdLineParser::ParseAsInt16;
|
||||
using ot::Utils::CmdLineParser::ParseAsInt32;
|
||||
using ot::Utils::CmdLineParser::ParseAsInt8;
|
||||
using ot::Utils::CmdLineParser::ParseAsIp6Address;
|
||||
using ot::Utils::CmdLineParser::ParseAsIp6Prefix;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint16;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint32;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint64;
|
||||
using ot::Utils::CmdLineParser::ParseAsUint8;
|
||||
|
||||
template <typename ValueType> struct TestCase
|
||||
{
|
||||
const char *mString;
|
||||
otError mError;
|
||||
ValueType mValue;
|
||||
};
|
||||
|
||||
template <typename ValueType, otError (&Parser)(const char *aString, ValueType &aValue)>
|
||||
void VerifyParser(const TestCase<ValueType> *aTestCases, const char *aParserName, const char *aPrintFormat)
|
||||
{
|
||||
const TestCase<ValueType> *testCase = aTestCases;
|
||||
ValueType value;
|
||||
otError error;
|
||||
|
||||
printf("----------------------------------------------------------\n");
|
||||
|
||||
while (true)
|
||||
{
|
||||
printf("%s(\"%s\") -> ", aParserName, testCase->mString);
|
||||
|
||||
if (testCase->mError != OT_ERROR_NONE)
|
||||
{
|
||||
printf("error:%s", otThreadErrorToString(testCase->mError));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(aPrintFormat, testCase->mValue);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
error = Parser(testCase->mString, value);
|
||||
|
||||
VerifyOrQuit(error == testCase->mError, "Parser did not return the expected error");
|
||||
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
VerifyOrQuit(value == testCase->mValue, "Parser failed");
|
||||
}
|
||||
|
||||
if (testCase->mString[0] == '\0')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
testCase++;
|
||||
}
|
||||
}
|
||||
|
||||
void TestParsingInts(void)
|
||||
{
|
||||
TestCase<bool> kBoolTestCases[] = {
|
||||
{"0", OT_ERROR_NONE, false}, // Zero as false value
|
||||
{"1", OT_ERROR_NONE, true}, // Non-zero as true value
|
||||
{"0x0", OT_ERROR_NONE, false}, // Zero as false value
|
||||
{"0x1", OT_ERROR_NONE, true}, // Non-zero (in hex) as true value
|
||||
{"10", OT_ERROR_NONE, true}, // Non-zero as true value
|
||||
{"a", OT_ERROR_INVALID_ARGS, false}, // Error case: Incorrect char
|
||||
{"-1", OT_ERROR_INVALID_ARGS, false}, // Error case: Negative value
|
||||
{"", OT_ERROR_INVALID_ARGS, false}, // Empty string indicate end of the list
|
||||
};
|
||||
|
||||
TestCase<uint8_t> kUint8TestCases[] = {
|
||||
{"0", OT_ERROR_NONE, 0},
|
||||
{"1", OT_ERROR_NONE, 1},
|
||||
{"74", OT_ERROR_NONE, 74},
|
||||
{"255", OT_ERROR_NONE, 255}, // Max `uint8` value (decimal format)
|
||||
{"0xa", OT_ERROR_NONE, 0xa},
|
||||
{"0x04", OT_ERROR_NONE, 4},
|
||||
{"0x7e", OT_ERROR_NONE, 0x7e},
|
||||
{"0xcd", OT_ERROR_NONE, 0xcd},
|
||||
{"0x0", OT_ERROR_NONE, 0},
|
||||
{"0xff", OT_ERROR_NONE, 0xff}, // Max `uint8` value (hex format)
|
||||
{"0x0000ff", OT_ERROR_NONE, 0xff}, // Hex format (extra zeros)
|
||||
{"0xB", OT_ERROR_NONE, 0xb},
|
||||
{"0X04", OT_ERROR_NONE, 4},
|
||||
{"0X7E", OT_ERROR_NONE, 0x7e},
|
||||
{"0XCD", OT_ERROR_NONE, 0xcd},
|
||||
{"0X0", OT_ERROR_NONE, 0},
|
||||
{"0XFF", OT_ERROR_NONE, 0xff},
|
||||
{"00", OT_ERROR_NONE, 0},
|
||||
{"-5", OT_ERROR_INVALID_ARGS, 0}, // Error case: Negative value.
|
||||
{"0y", OT_ERROR_INVALID_ARGS, 0}, // Error case: Incorrect prefix.
|
||||
{"0x7g", OT_ERROR_INVALID_ARGS, 0}, // Error case: Bad hex char.
|
||||
{"0xaaa", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out or range.
|
||||
{"256", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max value + 1)
|
||||
{"12e", OT_ERROR_INVALID_ARGS, 0}, // Error case: Extra char.
|
||||
{"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list
|
||||
};
|
||||
|
||||
TestCase<uint16_t> kUint16TestCases[] = {
|
||||
{"0", OT_ERROR_NONE, 0},
|
||||
{"1245", OT_ERROR_NONE, 1245},
|
||||
{"0xa", OT_ERROR_NONE, 0xa},
|
||||
{"0xab7d", OT_ERROR_NONE, 0xab7d},
|
||||
{"0X1AE", OT_ERROR_NONE, 0x1ae},
|
||||
{"0X7E", OT_ERROR_NONE, 0x7e},
|
||||
{"65535", OT_ERROR_NONE, 65535}, // Max `uint16` value (decimal format)
|
||||
{"0xffff", OT_ERROR_NONE, 0xffff}, // Max `uint16` value (hex format)
|
||||
{"-1", OT_ERROR_INVALID_ARGS, 0}, // Error case: Negative value
|
||||
{"0y", OT_ERROR_INVALID_ARGS, 0}, // Error case: Incorrect prefix
|
||||
{"0xq", OT_ERROR_INVALID_ARGS, 0}, // Error case: Bad hex char.
|
||||
{"0x12345", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range.
|
||||
{"65536", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max value + 1)
|
||||
{"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list
|
||||
};
|
||||
|
||||
TestCase<uint32_t> kUint32TestCases[] = {
|
||||
{"0", OT_ERROR_NONE, 0},
|
||||
{"1234567", OT_ERROR_NONE, 1234567},
|
||||
{"0xc", OT_ERROR_NONE, 0xc},
|
||||
{"0x01234567", OT_ERROR_NONE, 0x1234567},
|
||||
{"0XABCDEF09", OT_ERROR_NONE, 0xabcdef09},
|
||||
{"0X54321", OT_ERROR_NONE, 0x54321},
|
||||
{"4294967295", OT_ERROR_NONE, 4294967295}, // Max `uint32` value (decimal format)
|
||||
{"0xffffffff", OT_ERROR_NONE, 0xffffffff}, // Max `uint32` value (hex format)
|
||||
{"-1", OT_ERROR_INVALID_ARGS, 0},
|
||||
{"0y", OT_ERROR_INVALID_ARGS, 0},
|
||||
{"0x1234zz", OT_ERROR_INVALID_ARGS, 0}, // Error case: Bad hex char
|
||||
{"0x123456789", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range
|
||||
{"4294967296", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max value + 1)
|
||||
{"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list.
|
||||
};
|
||||
|
||||
TestCase<uint64_t> kUint64TestCases[] = {
|
||||
{"0", OT_ERROR_NONE, 0},
|
||||
{"123456789087654321", OT_ERROR_NONE, 123456789087654321},
|
||||
{"0xb", OT_ERROR_NONE, 0xb},
|
||||
{"0x1234567890acbdef", OT_ERROR_NONE, 0x1234567890acbdef},
|
||||
{"0XFEDCBA9876543210", OT_ERROR_NONE, 0xfedcba9876543210},
|
||||
{"0xffffffffffffffff", OT_ERROR_NONE, 0xffffffffffffffff}, // Max `uint64` value (hex format)
|
||||
{"18446744073709551615", OT_ERROR_NONE, 18446744073709551615ull}, // Max `uint64` value (decimal format)
|
||||
{"-1", OT_ERROR_INVALID_ARGS, 0},
|
||||
{"0x1234567890acbdef0", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range
|
||||
{"18446744073709551616", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out or range (max value + 1)
|
||||
{"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list.
|
||||
};
|
||||
|
||||
TestCase<int8_t> kInt8TestCases[] = {
|
||||
{"0", OT_ERROR_NONE, 0},
|
||||
{"-1", OT_ERROR_NONE, -1},
|
||||
{"+74", OT_ERROR_NONE, 74},
|
||||
{"-0x12", OT_ERROR_NONE, -0x12},
|
||||
{"-0XB", OT_ERROR_NONE, -11},
|
||||
{"127", OT_ERROR_NONE, 127}, // Max `int8` value
|
||||
{"-128", OT_ERROR_NONE, -128}, // Min `int8` value
|
||||
{"128", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max value + 1)
|
||||
{"-129", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min value - 1)
|
||||
{"--1", OT_ERROR_INVALID_ARGS, 0}, // Error case: Extra sign
|
||||
{"+-2", OT_ERROR_INVALID_ARGS, 0}, // Error case: Extra sign
|
||||
{"++1", OT_ERROR_INVALID_ARGS, 0}, // Error case: Extra sign
|
||||
{"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list.
|
||||
};
|
||||
|
||||
TestCase<int16_t> kInt16TestCases[] = {
|
||||
{"-1", OT_ERROR_NONE, -1},
|
||||
{"+0x1234", OT_ERROR_NONE, 0x1234},
|
||||
{"-0X6E8", OT_ERROR_NONE, -0x6E8},
|
||||
{"32767", OT_ERROR_NONE, 32767}, // Max `int16` value
|
||||
{"0X7FFF", OT_ERROR_NONE, 0x7fff}, // Max `int16` value (hex value)
|
||||
{"-32768", OT_ERROR_NONE, -32768}, // Min `int16` value
|
||||
{"-0x8000", OT_ERROR_NONE, -0x8000}, // Min `int16` value (hex value)
|
||||
{"32768", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max + 1)
|
||||
{"0X8000", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max + 1)
|
||||
{"-32769", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min - 1)
|
||||
{"-0x8001", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min - 1)
|
||||
{"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list.
|
||||
};
|
||||
|
||||
TestCase<int32_t> kInt32TestCases[] = {
|
||||
{"-256", OT_ERROR_NONE, -256},
|
||||
{"+0x12345678", OT_ERROR_NONE, 0x12345678},
|
||||
{"-0X6677aB", OT_ERROR_NONE, -0X6677aB},
|
||||
{"2147483647", OT_ERROR_NONE, 2147483647},
|
||||
{"0x7fffFFFF", OT_ERROR_NONE, 0x7fffffff}, // Max `int32` value
|
||||
{"-2147483648", OT_ERROR_NONE, -2147483648}, // Min `int32` value
|
||||
{"2147483648", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max + 1)
|
||||
{"0X80000000", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (max + 1)
|
||||
{"-2147483649", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min - 1)
|
||||
{"-0x80000001", OT_ERROR_INVALID_ARGS, 0}, // Error case: Out of range (min - 1)
|
||||
{"", OT_ERROR_INVALID_ARGS, 0} // Empty string indicates end of the list
|
||||
};
|
||||
|
||||
VerifyParser<bool, ParseAsBool>(kBoolTestCases, "ParseAsBool", "%d");
|
||||
VerifyParser<uint8_t, ParseAsUint8>(kUint8TestCases, "ParseAsUint8", "0x%02x");
|
||||
VerifyParser<uint16_t, ParseAsUint16>(kUint16TestCases, "ParseAsUint16", "0x%04x");
|
||||
VerifyParser<uint32_t, ParseAsUint32>(kUint32TestCases, "ParseAsUint32", "0x%08x");
|
||||
VerifyParser<uint64_t, ParseAsUint64>(kUint64TestCases, "ParseAsUint64", "0x%016llx");
|
||||
VerifyParser<int8_t, ParseAsInt8>(kInt8TestCases, "ParseAsInt8", "%d");
|
||||
VerifyParser<int16_t, ParseAsInt16>(kInt16TestCases, "ParseAsInt16", "%d");
|
||||
VerifyParser<int32_t, ParseAsInt32>(kInt32TestCases, "ParseAsInt32", "%d");
|
||||
}
|
||||
|
||||
void TestParsingHexStrings(void)
|
||||
{
|
||||
const char kHexString[] = "DeadBeefCafeBabe";
|
||||
const uint8_t kParsedArray[] = {0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe};
|
||||
|
||||
uint8_t buffer[sizeof(kParsedArray)];
|
||||
uint8_t buf3[3];
|
||||
uint16_t len;
|
||||
|
||||
// Verify `ParseAsHexString(const char *aString, uint8_t *aBuffer, uint16_t aSize)`
|
||||
|
||||
buffer[0] = 0xff;
|
||||
SuccessOrQuit(ParseAsHexString("0", buffer, 1), "ParseAsHexString() failed");
|
||||
VerifyOrQuit(buffer[0] == 0, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
buffer[0] = 0;
|
||||
SuccessOrQuit(ParseAsHexString("7e", buffer, 1), "ParseAsHexString() failed");
|
||||
VerifyOrQuit(buffer[0] == 0x7e, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
VerifyOrQuit(ParseAsHexString("123", buffer, 1) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input");
|
||||
SuccessOrQuit(ParseAsHexString("123", buffer, 2), "ParseAsHexString() failed");
|
||||
VerifyOrQuit(buffer[0] == 1 && buffer[1] == 0x23, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
VerifyOrQuit(ParseAsHexString("123x", buffer, 2) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input");
|
||||
VerifyOrQuit(ParseAsHexString(" 123", buffer, 2) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input");
|
||||
|
||||
// Verify `ParseAsHexString<kMaxSize>()`
|
||||
|
||||
VerifyOrQuit(ParseAsHexString("1122", buf3) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input");
|
||||
VerifyOrQuit(ParseAsHexString("1122334", buf3) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input");
|
||||
VerifyOrQuit(ParseAsHexString("11223344", buf3) != OT_ERROR_NONE, "ParseAsHexString() passed with bad input");
|
||||
SuccessOrQuit(ParseAsHexString("abbade", buf3), "ParseAsHexString() failed");
|
||||
VerifyOrQuit(buf3[0] == 0xab && buf3[1] == 0xba && buf3[2] == 0xde, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
SuccessOrQuit(ParseAsHexString(kHexString, buffer), "ParseAsHexString failed");
|
||||
VerifyOrQuit(memcmp(buffer, kParsedArray, sizeof(buffer)) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
// Verify truncation
|
||||
|
||||
len = sizeof(buffer);
|
||||
|
||||
SuccessOrQuit(ParseAsHexString(kHexString, len, buffer), "ParseAsHexString failed");
|
||||
VerifyOrQuit(len == sizeof(kParsedArray), "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, kParsedArray, len) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
SuccessOrQuit(ParseAsHexString(kHexString + 1, len, buffer), "ParseAsHexString failed");
|
||||
VerifyOrQuit(len == sizeof(kParsedArray), "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer + 1, kParsedArray + 1, len - 1) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(buffer[0] = 0xe, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
SuccessOrQuit(ParseAsHexString(kHexString + 2, len, buffer), "ParseAsHexString failed");
|
||||
VerifyOrQuit(len == sizeof(kParsedArray) - 1, "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, kParsedArray + 1, len) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
|
||||
len = sizeof(buffer) - 1;
|
||||
VerifyOrQuit(ParseAsHexString(kHexString, len, buffer, ot::Utils::CmdLineParser::kDisallowTruncate) !=
|
||||
OT_ERROR_NONE,
|
||||
"ParseAsHexString passed with bad input");
|
||||
len = sizeof(buffer) - 1;
|
||||
SuccessOrQuit(ParseAsHexString(kHexString, len, buffer, ot::Utils::CmdLineParser::kAllowTruncate),
|
||||
"ParseAsHexString failed");
|
||||
VerifyOrQuit(len == sizeof(buffer) - 1, "ParseAsHexString() parsed incorrectly");
|
||||
VerifyOrQuit(memcmp(buffer, kParsedArray, len) == 0, "ParseAsHexString() parsed incorrectly");
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
TestParsingInts();
|
||||
TestParsingHexStrings();
|
||||
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user