[cli] add OutputUint64() for 64-bit integer value in decimal format (#8354)

This commit also adds a helper `Uint64ToString()` method to convert a
`uint64_t` to decimal format string. The new methods allow us to
output `uint64_t` values without needing to cast to `unsigned long
long` and/or use of `%llu` (which may not be provided by certain
embedded libraries).
This commit is contained in:
Abtin Keshavarzian
2022-11-07 09:35:27 +01:00
committed by GitHub
parent ba826ffb2a
commit 727002e9fe
6 changed files with 149 additions and 40 deletions
+58 -34
View File
@@ -876,45 +876,47 @@ template <> otError Interpreter::Process<Cmd("nat64")>(Arg aArgs[])
otNat64InitAddressMappingIterator(GetInstancePtr(), &iterator);
while (otNat64GetNextAddressMapping(GetInstancePtr(), &iterator, &mapping) == OT_ERROR_NONE)
{
char ip4AddressString[OT_IP4_ADDRESS_STRING_SIZE];
char ip6AddressString[OT_IP6_PREFIX_STRING_SIZE];
char ip4AddressString[OT_IP4_ADDRESS_STRING_SIZE];
char ip6AddressString[OT_IP6_PREFIX_STRING_SIZE];
Uint64StringBuffer u64StringBuffer;
otIp6AddressToString(&mapping.mIp6, ip6AddressString, sizeof(ip6AddressString));
otIp4AddressToString(&mapping.mIp4, ip4AddressString, sizeof(ip4AddressString));
OutputFormat("| %016llx ", mapping.mId);
OutputFormat("| %08lx%08lx ", ToUlong(static_cast<uint32_t>(mapping.mId >> 32)),
ToUlong(static_cast<uint32_t>(mapping.mId & 0xffffffff)));
OutputFormat("| %40s ", ip6AddressString);
OutputFormat("| %16s ", ip4AddressString);
OutputFormat("| %5llus ", mapping.mRemainingTimeMs / 1000);
OutputFormat("| %8llu ", mapping.mCounters.mTotal.m4To6Packets);
OutputFormat("| %12llu ", mapping.mCounters.mTotal.m4To6Bytes);
OutputFormat("| %8llu ", mapping.mCounters.mTotal.m6To4Packets);
OutputFormat("| %12llu ", mapping.mCounters.mTotal.m6To4Bytes);
OutputFormat("| %5lus ", ToUlong(mapping.mRemainingTimeMs / 1000));
OutputFormat("| %8s ", Uint64ToString(mapping.mCounters.mTotal.m4To6Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(mapping.mCounters.mTotal.m4To6Bytes, u64StringBuffer));
OutputFormat("| %8s ", Uint64ToString(mapping.mCounters.mTotal.m6To4Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(mapping.mCounters.mTotal.m6To4Bytes, u64StringBuffer));
OutputLine("|");
OutputFormat("| %016s ", "");
OutputFormat("| %68s ", "TCP");
OutputFormat("| %8llu ", mapping.mCounters.mTcp.m4To6Packets);
OutputFormat("| %12llu ", mapping.mCounters.mTcp.m4To6Bytes);
OutputFormat("| %8llu ", mapping.mCounters.mTcp.m6To4Packets);
OutputFormat("| %12llu ", mapping.mCounters.mTcp.m6To4Bytes);
OutputFormat("| %8s ", Uint64ToString(mapping.mCounters.mTcp.m4To6Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(mapping.mCounters.mTcp.m4To6Bytes, u64StringBuffer));
OutputFormat("| %8s ", Uint64ToString(mapping.mCounters.mTcp.m6To4Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(mapping.mCounters.mTcp.m6To4Bytes, u64StringBuffer));
OutputLine("|");
OutputFormat("| %016s ", "");
OutputFormat("| %68s ", "UDP");
OutputFormat("| %8llu ", mapping.mCounters.mUdp.m4To6Packets);
OutputFormat("| %12llu ", mapping.mCounters.mUdp.m4To6Bytes);
OutputFormat("| %8llu ", mapping.mCounters.mUdp.m6To4Packets);
OutputFormat("| %12llu ", mapping.mCounters.mUdp.m6To4Bytes);
OutputFormat("| %8s ", Uint64ToString(mapping.mCounters.mUdp.m4To6Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(mapping.mCounters.mUdp.m4To6Bytes, u64StringBuffer));
OutputFormat("| %8s ", Uint64ToString(mapping.mCounters.mUdp.m6To4Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(mapping.mCounters.mUdp.m6To4Bytes, u64StringBuffer));
OutputLine("|");
OutputFormat("| %016s ", "");
OutputFormat("| %68s ", "ICMP");
OutputFormat("| %8llu ", mapping.mCounters.mIcmp.m4To6Packets);
OutputFormat("| %12llu ", mapping.mCounters.mIcmp.m4To6Bytes);
OutputFormat("| %8llu ", mapping.mCounters.mIcmp.m6To4Packets);
OutputFormat("| %12llu ", mapping.mCounters.mIcmp.m6To4Bytes);
OutputFormat("| %8s ", Uint64ToString(mapping.mCounters.mIcmp.m4To6Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(mapping.mCounters.mIcmp.m4To6Bytes, u64StringBuffer));
OutputFormat("| %8s ", Uint64ToString(mapping.mCounters.mIcmp.m6To4Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(mapping.mCounters.mIcmp.m6To4Bytes, u64StringBuffer));
OutputLine("|");
}
}
@@ -979,6 +981,7 @@ template <> otError Interpreter::Process<Cmd("nat64")>(Arg aArgs[])
otNat64ProtocolCounters counters;
otNat64ErrorCounters errorCounters;
Uint64StringBuffer u64StringBuffer;
OutputTableHeader(kNat64CounterTableHeader, kNat64CounterTableHeaderColumns);
OutputTableHeader(kNat64CounterTableSubHeader, kNat64CounterTableSubHeaderColumns);
@@ -986,20 +989,36 @@ template <> otError Interpreter::Process<Cmd("nat64")>(Arg aArgs[])
otNat64GetCounters(GetInstancePtr(), &counters);
otNat64GetErrorCounters(GetInstancePtr(), &errorCounters);
OutputLine("| %13s | %8llu | %12llu | %8llu | %12llu |", "Total", counters.mTotal.m4To6Packets,
counters.mTotal.m4To6Bytes, counters.mTotal.m6To4Packets, counters.mTotal.m6To4Bytes);
OutputLine("| %13s | %8llu | %12llu | %8llu | %12llu |", "TCP", counters.mTcp.m4To6Packets,
counters.mTcp.m4To6Bytes, counters.mTcp.m6To4Packets, counters.mTcp.m6To4Bytes);
OutputLine("| %13s | %8llu | %12llu | %8llu | %12llu |", "UDP", counters.mUdp.m4To6Packets,
counters.mUdp.m4To6Bytes, counters.mUdp.m6To4Packets, counters.mUdp.m6To4Bytes);
OutputLine("| %13s | %8llu | %12llu | %8llu | %12llu |", "ICMP", counters.mIcmp.m4To6Packets,
counters.mIcmp.m4To6Bytes, counters.mIcmp.m6To4Packets, counters.mIcmp.m6To4Bytes);
OutputFormat("| %13s ", "Total");
OutputFormat("| %8s ", Uint64ToString(counters.mTotal.m4To6Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(counters.mTotal.m4To6Bytes, u64StringBuffer));
OutputFormat("| %8s ", Uint64ToString(counters.mTotal.m6To4Packets, u64StringBuffer));
OutputLine("| %12s |", Uint64ToString(counters.mTotal.m6To4Bytes, u64StringBuffer));
OutputFormat("| %13s ", "TCP");
OutputFormat("| %8s ", Uint64ToString(counters.mTcp.m4To6Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(counters.mTcp.m4To6Bytes, u64StringBuffer));
OutputFormat("| %8s ", Uint64ToString(counters.mTcp.m6To4Packets, u64StringBuffer));
OutputLine("| %12s |", Uint64ToString(counters.mTcp.m6To4Bytes, u64StringBuffer));
OutputFormat("| %13s ", "UDP");
OutputFormat("| %8s ", Uint64ToString(counters.mUdp.m4To6Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(counters.mUdp.m4To6Bytes, u64StringBuffer));
OutputFormat("| %8s ", Uint64ToString(counters.mUdp.m6To4Packets, u64StringBuffer));
OutputLine("| %12s |", Uint64ToString(counters.mUdp.m6To4Bytes, u64StringBuffer));
OutputFormat("| %13s ", "ICMP");
OutputFormat("| %8s ", Uint64ToString(counters.mIcmp.m4To6Packets, u64StringBuffer));
OutputFormat("| %12s ", Uint64ToString(counters.mIcmp.m4To6Bytes, u64StringBuffer));
OutputFormat("| %8s ", Uint64ToString(counters.mIcmp.m6To4Packets, u64StringBuffer));
OutputLine("| %12s |", Uint64ToString(counters.mIcmp.m6To4Bytes, u64StringBuffer));
OutputTableHeader(kNat64CounterTableErrorSubHeader, kNat64CounterTableErrorSubHeaderColumns);
for (uint8_t i = 0; i < OT_NAT64_DROP_REASON_COUNT; i++)
{
OutputLine("| %13s | %23llu | %23llu |", kNat64CounterErrorType[i], errorCounters.mCount4To6[i],
errorCounters.mCount6To4[i]);
OutputFormat("| %13s | %23s ", kNat64CounterErrorType[i],
Uint64ToString(errorCounters.mCount4To6[i], u64StringBuffer));
OutputLine("| %23s |", Uint64ToString(errorCounters.mCount6To4[i], u64StringBuffer));
}
}
#endif // OPENTHREAD_CONFIG_NAT64_TRANSLATOR_ENABLE
@@ -2652,9 +2671,12 @@ template <> otError Interpreter::Process<Cmd("counters")>(Arg aArgs[])
for (const MleTimeCounterName &counter : kTimeCounterNames)
{
OutputLine("Time %s Milli: %lu", counter.mName, mleCounters->*counter.mValuePtr);
OutputFormat("Time %s Milli: ", counter.mName);
OutputUint64Line(mleCounters->*counter.mValuePtr);
}
OutputLine("Time Tracked Milli: %lu", mleCounters->mTrackedTime);
OutputFormat("Time Tracked Milli: ");
OutputUint64Line(mleCounters->mTrackedTime);
}
#endif
}
@@ -5076,7 +5098,9 @@ template <> otError Interpreter::Process<Cmd("networktime")>(Arg aArgs[])
networkTimeStatus = otNetworkTimeGet(GetInstancePtr(), &time);
OutputFormat("Network Time: %luus", time);
OutputFormat("Network Time: ");
OutputUint64(time);
OutputFormat("us");
switch (networkTimeStatus)
{
@@ -6336,7 +6360,7 @@ template <> otError Interpreter::Process<Cmd("uptime")>(Arg aArgs[])
}
else if (aArgs[0] == "ms")
{
OutputLine("%lu", otInstanceGetUptime(GetInstancePtr()));
OutputUint64Line(otInstanceGetUptime(GetInstancePtr()));
}
else
{
+3 -1
View File
@@ -117,7 +117,9 @@ template <> otError Commissioner::Process<Cmd("joiner")>(Arg aArgs[])
break;
case OT_JOINER_INFO_TYPE_DISCERNER:
OutputFormat("| 0x%016llx/%2u", static_cast<unsigned long long>(joinerInfo.mSharedId.mDiscerner.mValue),
OutputFormat("| 0x%08lx%08lx/%2u",
static_cast<unsigned long>(joinerInfo.mSharedId.mDiscerner.mValue >> 32),
static_cast<unsigned long>(joinerInfo.mSharedId.mDiscerner.mValue & 0xffffffff),
joinerInfo.mSharedId.mDiscerner.mLength);
break;
}
+6 -4
View File
@@ -51,12 +51,14 @@ otError Dataset::Print(otOperationalDataset &aDataset)
{
if (aDataset.mComponents.mIsPendingTimestampPresent)
{
OutputLine("Pending Timestamp: %lu", aDataset.mPendingTimestamp.mSeconds);
OutputFormat("Pending Timestamp: ");
OutputUint64Line(aDataset.mPendingTimestamp.mSeconds);
}
if (aDataset.mComponents.mIsActiveTimestampPresent)
{
OutputLine("Active Timestamp: %lu", aDataset.mActiveTimestamp.mSeconds);
OutputFormat("Active Timestamp: ");
OutputUint64Line(aDataset.mActiveTimestamp.mSeconds);
}
if (aDataset.mComponents.mIsChannelPresent)
@@ -264,7 +266,7 @@ template <> otError Dataset::Process<Cmd("activetimestamp")>(Arg aArgs[])
{
if (sDataset.mComponents.mIsActiveTimestampPresent)
{
OutputLine("%lu", sDataset.mActiveTimestamp.mSeconds);
OutputUint64Line(sDataset.mActiveTimestamp.mSeconds);
}
}
else
@@ -666,7 +668,7 @@ template <> otError Dataset::Process<Cmd("pendingtimestamp")>(Arg aArgs[])
{
if (sDataset.mComponents.mIsPendingTimestampPresent)
{
OutputLine("%lu", sDataset.mPendingTimestamp.mSeconds);
OutputUint64Line(sDataset.mPendingTimestamp.mSeconds);
}
}
else
+10 -1
View File
@@ -62,7 +62,16 @@ template <> otError Joiner::Process<Cmd("discerner")>(Arg aArgs[])
VerifyOrExit(discerner != nullptr, error = OT_ERROR_NOT_FOUND);
OutputLine("0x%llx/%u", static_cast<unsigned long long>(discerner->mValue), discerner->mLength);
if (discerner->mValue <= 0xffffffff)
{
OutputLine("0x%lx/%u", static_cast<unsigned long>(discerner->mValue & 0xffffffff), discerner->mLength);
}
else
{
OutputLine("0x%lx%08lx/%u", static_cast<unsigned long>(discerner->mValue >> 32),
static_cast<unsigned long>(discerner->mValue & 0xffffffff), discerner->mLength);
}
error = OT_ERROR_NONE;
}
else
+34
View File
@@ -127,6 +127,40 @@ void Output::OutputBytesLine(const uint8_t *aBytes, uint16_t aLength)
OutputLine("");
}
const char *Output::Uint64ToString(uint64_t aUint64, Uint64StringBuffer &aBuffer)
{
char *cur = &aBuffer.mChars[Uint64StringBuffer::kSize - 1];
*cur = '\0';
if (aUint64 == 0)
{
*(--cur) = '0';
}
else
{
for (; aUint64 != 0; aUint64 /= 10)
{
*(--cur) = static_cast<char>('0' + static_cast<uint8_t>(aUint64 % 10));
}
}
return cur;
}
void Output::OutputUint64(uint64_t aUint64)
{
Uint64StringBuffer buffer;
OutputFormat("%s", Uint64ToString(aUint64, buffer));
}
void Output::OutputUint64Line(uint64_t aUint64)
{
OutputUint64(aUint64);
OutputLine("");
}
void Output::OutputEnabledDisabledStatus(bool aEnabled)
{
OutputLine(aEnabled ? "Enabled" : "Disabled");
+38
View File
@@ -202,6 +202,28 @@ public:
*/
otInstance *GetInstancePtr(void) { return mInstance; }
/**
* This structure represents a buffer which is sued when converting a `uint64` value to string in decimal format.
*
*/
struct Uint64StringBuffer
{
static constexpr uint16_t kSize = 21; ///< Size of a buffer
char mChars[kSize]; ///< Char array (do not access the array directly).
};
/**
* This static method converts a `uint64_t` value to a decimal format string.
*
* @param[in] aUint64 The `uint64_t` value to convert.
* @param[in] aBuffer A buffer to allocate the string from.
*
* @returns A pointer to the start of the string (null-terminated) representation of @p aUint64.
*
*/
static const char *Uint64ToString(uint64_t aUint64, Uint64StringBuffer &aBuffer);
/**
* This method delivers a formatted output string to the CLI console.
*
@@ -312,6 +334,22 @@ public:
*/
void OutputExtAddressLine(const otExtAddress &aExtAddress) { OutputBytesLine(aExtAddress.m8); }
/**
* This method outputs a `uint64_t` value in decimal format.
*
* @param[in] aUint64 The `uint64_t` value to output.
*
*/
void OutputUint64(uint64_t aUint64);
/**
* This method outputs a `uint64_t` value in decimal format and at the end it also outputs newline "\r\n".
*
* @param[in] aUint64 The `uint64_t` value to output.
*
*/
void OutputUint64Line(uint64_t aUint64);
/**
* This method outputs "Enabled" or "Disabled" status to the CLI console (it also appends newline "\r\n").
*