From 3ee92c974bdbca2add52a1f820c9bef45a6f751c Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Mon, 26 Feb 2018 13:54:13 -0800 Subject: [PATCH] [mac] add method ToString() to Mac::ChannelMask (#2578) --- src/core/mac/mac.cpp | 55 +++++++++++++++++++++++++++++++++++ src/core/mac/mac.hpp | 19 ++++++++++++ tests/unit/test_mac_frame.cpp | 14 +++++++-- 3 files changed, 86 insertions(+), 2 deletions(-) diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 6f76af093..72aa7fc74 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -35,6 +35,7 @@ #include "mac.hpp" +#include #include "utils/wrap_string.h" #include "common/code_utils.hpp" @@ -93,6 +94,60 @@ exit: return error; } +const char *ChannelMask::ToString(char *aBuffer, uint16_t aSize) const +{ + uint8_t channel = kChannelIteratorFirst; + bool addComma = false; + char * bufPtr = aBuffer; + size_t bufLen = aSize; + int len; + otError error; + + len = snprintf(bufPtr, bufLen, "{"); + VerifyOrExit((len >= 0) && (static_cast(len) < bufLen)); + bufPtr += len; + bufLen -= static_cast(len); + + error = GetNextChannel(channel); + + while (error == OT_ERROR_NONE) + { + uint8_t rangeStart = channel; + uint8_t rangeEnd = channel; + + while ((error = GetNextChannel(channel)) == OT_ERROR_NONE) + { + if (channel != rangeEnd + 1) + { + break; + } + + rangeEnd = channel; + } + + len = snprintf(bufPtr, bufLen, "%s%d", addComma ? ", " : " ", rangeStart); + VerifyOrExit((len >= 0) && (static_cast(len) < bufLen)); + bufPtr += len; + bufLen -= static_cast(len); + + addComma = true; + + if (rangeStart < rangeEnd) + { + len = snprintf(bufPtr, bufLen, "%s%d", rangeEnd == rangeStart + 1 ? ", " : "-", rangeEnd); + VerifyOrExit((len >= 0) && (static_cast(len) < bufLen)); + bufPtr += len; + bufLen -= static_cast(len); + } + } + + len = snprintf(bufPtr, bufLen, " }"); + VerifyOrExit((len >= 0) && (static_cast(len) < bufLen)); + +exit: + return aBuffer; +} + Mac::Mac(Instance &aInstance) : InstanceLocator(aInstance) , mOperation(kOperationIdle) diff --git a/src/core/mac/mac.hpp b/src/core/mac/mac.hpp index 66c68583f..ce0328701 100644 --- a/src/core/mac/mac.hpp +++ b/src/core/mac/mac.hpp @@ -113,6 +113,7 @@ public: enum { kChannelIteratorFirst = 0xff, ///< Value to pass in `GetNextChannel()` to get the first channel in the mask. + kInfoStringSize = 45, ///< Recommended buffer size to use with `ToString()`. }; /** @@ -223,6 +224,24 @@ public: */ otError GetNextChannel(uint8_t &aChannel) const; + /** + * This method converts the channel mask into a human-readable NULL-terminated string. + * + * Examples of possible output: + * - empty mask -> "{ }" + * - all channels -> "{ 11-26 }" + * - single channel -> "{ 20 }" + * - multiple ranges -> "{ 11, 14-17, 20-22, 24, 25 }" + * - no range -> "{ 14, 21, 26 }" + * + * @param[out] aBuffer A pointer to a char buffer to output the string. + * @param[in] aSize Size of the buffer (number of bytes). + * + * @returns A pointer to the @p aBuffer. + * + */ + const char *ToString(char *aBuffer, uint16_t aSize) const; + private: #if (OT_RADIO_CHANNEL_MIN >= 32) || (OT_RADIO_CHANNEL_MAX >= 32) #error `OT_RADIO_CHANNEL_MAX` or `OT_RADIO_CHANNEL_MIN` are larger than 32. `ChannelMask` uses 32 bit mask. diff --git a/tests/unit/test_mac_frame.cpp b/tests/unit/test_mac_frame.cpp index 1fd162eff..9d8b3e47d 100644 --- a/tests/unit/test_mac_frame.cpp +++ b/tests/unit/test_mac_frame.cpp @@ -125,20 +125,24 @@ void VerifyChannelMaskContent(const Mac::ChannelMask &aMask, uint8_t *aChannels, void TestMacChannelMask(void) { uint8_t all_channels[] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}; - uint8_t channels1[] = {11, 14, 15, 20, 21, 26}; - uint8_t channels2[] = {14, 21, 25}; + uint8_t channels1[] = {11, 14, 15, 16, 17, 20, 21, 22, 24, 25}; + uint8_t channels2[] = {14, 21, 26}; uint8_t channels3[] = {14, 21}; uint8_t channles4[] = {20}; Mac::ChannelMask mask1; Mac::ChannelMask mask2(OT_RADIO_SUPPORTED_CHANNELS); + char stringBuffer[Mac::ChannelMask::kInfoStringSize]; + printf("Testing Mac::ChannelMask\n"); VerifyOrQuit(mask1.IsEmpty(), "ChannelMask.IsEmpty failed\n"); + printf("empty = %s\n", mask1.ToString(stringBuffer, sizeof(stringBuffer))); VerifyOrQuit(!mask2.IsEmpty(), "ChannelMask.IsEmpty failed\n"); VerifyOrQuit(mask2.GetMask() == OT_RADIO_SUPPORTED_CHANNELS, "ChannelMask.GetMask() failed\n"); + printf("all_channels = %s\n", mask2.ToString(stringBuffer, sizeof(stringBuffer))); mask1.SetMask(OT_RADIO_SUPPORTED_CHANNELS); VerifyOrQuit(!mask1.IsEmpty(), "ChannelMask.IsEmpty failed\n"); @@ -162,6 +166,8 @@ void TestMacChannelMask(void) mask1.AddChannel(channels1[index]); } + printf("channels1 = %s\n", mask1.ToString(stringBuffer, sizeof(stringBuffer))); + VerifyOrQuit(!mask1.IsEmpty(), "ChannelMask.IsEmpty failed\n"); VerifyChannelMaskContent(mask1, channels1, sizeof(channels1)); @@ -172,6 +178,8 @@ void TestMacChannelMask(void) mask2.AddChannel(channels2[index]); } + printf("channels2 = %s\n", mask2.ToString(stringBuffer, sizeof(stringBuffer))); + VerifyOrQuit(!mask2.IsEmpty(), "ChannelMask.IsEmpty failed\n"); VerifyChannelMaskContent(mask2, channels2, sizeof(channels2)); @@ -181,6 +189,8 @@ void TestMacChannelMask(void) mask2.Clear(); mask2.AddChannel(channles4[0]); VerifyChannelMaskContent(mask2, channles4, sizeof(channles4)); + + printf("channels4 = %s\n", mask2.ToString(stringBuffer, sizeof(stringBuffer))); } } // namespace ot