mirror of
https://github.com/espressif/openthread.git
synced 2026-08-20 01:19:51 +00:00
[message] new helper methods to compare bytes in a message (#6068)
This commit adds new helper `Compare` methods in `Message` class to compare the bytes from the message (at a given offset) with a byte array or bytes from a (template) object or bytes read from another message. This commit also updates the message unit test to cover the behavior of the newly added methods.
This commit is contained in:
@@ -525,6 +525,48 @@ otError Message::Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const
|
||||
return (ReadBytes(aOffset, aBuf, aLength) == aLength) ? OT_ERROR_NONE : OT_ERROR_PARSE;
|
||||
}
|
||||
|
||||
bool Message::CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength) const
|
||||
{
|
||||
uint16_t bytesToCompare = aLength;
|
||||
const uint8_t *bufPtr = reinterpret_cast<const uint8_t *>(aBuf);
|
||||
Chunk chunk;
|
||||
|
||||
GetFirstChunk(aOffset, aLength, chunk);
|
||||
|
||||
while (chunk.GetLength() > 0)
|
||||
{
|
||||
VerifyOrExit(memcmp(bufPtr, chunk.GetData(), chunk.GetLength()) == 0);
|
||||
bufPtr += chunk.GetLength();
|
||||
bytesToCompare -= chunk.GetLength();
|
||||
GetNextChunk(aLength, chunk);
|
||||
}
|
||||
|
||||
exit:
|
||||
return (bytesToCompare == 0);
|
||||
}
|
||||
|
||||
bool Message::CompareBytes(uint16_t aOffset,
|
||||
const Message &aOtherMessage,
|
||||
uint16_t aOtherOffset,
|
||||
uint16_t aLength) const
|
||||
{
|
||||
uint16_t bytesToCompare = aLength;
|
||||
Chunk chunk;
|
||||
|
||||
GetFirstChunk(aOffset, aLength, chunk);
|
||||
|
||||
while (chunk.GetLength() > 0)
|
||||
{
|
||||
VerifyOrExit(aOtherMessage.CompareBytes(aOtherOffset, chunk.GetData(), chunk.GetLength()));
|
||||
aOtherOffset += chunk.GetLength();
|
||||
bytesToCompare -= chunk.GetLength();
|
||||
GetNextChunk(aLength, chunk);
|
||||
}
|
||||
|
||||
exit:
|
||||
return (bytesToCompare == 0);
|
||||
}
|
||||
|
||||
void Message::WriteBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength)
|
||||
{
|
||||
const uint8_t *bufPtr = reinterpret_cast<const uint8_t *>(aBuf);
|
||||
|
||||
@@ -710,6 +710,60 @@ public:
|
||||
return Read(aOffset, &aObject, sizeof(ObjectType));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method compares the bytes in the message at a given offset with a given byte array.
|
||||
*
|
||||
* If there are fewer bytes available in the message than the requested @p aLength, the comparison is treated as
|
||||
* failure (returns FALSE).
|
||||
*
|
||||
* @param[in] aOffset Byte offset within the message to read from for the comparison.
|
||||
* @param[in] aBuf A pointer to a data buffer to compare with the bytes from message.
|
||||
* @param[in] aLength Number of bytes in @p aBuf.
|
||||
*
|
||||
* @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes from @p aBuf,
|
||||
* FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength) const;
|
||||
|
||||
/**
|
||||
* This method compares the bytes in the message at a given offset with bytes read from another message.
|
||||
*
|
||||
* If either message has fewer bytes available than the requested @p aLength, the comparison is treated as failure
|
||||
* (returns FALSE).
|
||||
*
|
||||
* @param[in] aOffset Byte offset within the message to read from for the comparison.
|
||||
* @param[in] aOtherMessage The other message to compare with.
|
||||
* @param[in] aOtherOffset Byte offset within @p aOtherMessage to read from for the comparison.
|
||||
* @param[in] aLength Number of bytes to compare.
|
||||
*
|
||||
* @returns TRUE if there are enough bytes available in both messages and they all match. FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
bool CompareBytes(uint16_t aOffset, const Message &aOtherMessage, uint16_t aOtherOffset, uint16_t aLength) const;
|
||||
|
||||
/**
|
||||
* This method compares the bytes in the message at a given offset with an object.
|
||||
*
|
||||
* The bytes in the message are compared with the bytes in @p aObject. If there are fewer bytes available in the
|
||||
* message than the requested object size, it is treated as failed comparison (returns FALSE).
|
||||
*
|
||||
* @tparam ObjectType The object type to compare with the bytes in message.
|
||||
*
|
||||
* @param[in] aOffset Byte offset within the message to read from for the comparison.
|
||||
* @param[in] aObject A reference to the object to compare with the message bytes.
|
||||
*
|
||||
* @returns TRUE if there are enough bytes available in @p aMessage and they match the bytes in @p aObject,
|
||||
* FALSE otherwise.
|
||||
*
|
||||
*/
|
||||
template <typename ObjectType> bool Compare(uint16_t aOffset, const ObjectType &aObject) const
|
||||
{
|
||||
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
|
||||
|
||||
return CompareBytes(aOffset, &aObject, sizeof(ObjectType));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method writes bytes to the message.
|
||||
*
|
||||
|
||||
@@ -67,6 +67,8 @@ void TestMessage(void)
|
||||
message->WriteBytes(0, writeBuffer, kMaxSize);
|
||||
SuccessOrQuit(message->Read(0, readBuffer, kMaxSize), "Message::Read failed");
|
||||
VerifyOrQuit(memcmp(writeBuffer, readBuffer, kMaxSize) == 0, "Message compare failed");
|
||||
VerifyOrQuit(message->CompareBytes(0, readBuffer, kMaxSize), "Message::CompareBytes failed");
|
||||
VerifyOrQuit(message->Compare(0, readBuffer), "Message::Compare failed");
|
||||
VerifyOrQuit(message->GetLength() == kMaxSize, "Message::GetLength failed");
|
||||
|
||||
for (uint16_t offset = 0; offset < kMaxSize; offset++)
|
||||
@@ -82,11 +84,30 @@ void TestMessage(void)
|
||||
|
||||
SuccessOrQuit(message->Read(0, readBuffer, kMaxSize), "Message::Read failed");
|
||||
VerifyOrQuit(memcmp(writeBuffer, readBuffer, kMaxSize) == 0, "Message compare failed");
|
||||
VerifyOrQuit(message->Compare(0, writeBuffer), "Message::Compare() failed");
|
||||
|
||||
memset(readBuffer, 0, sizeof(readBuffer));
|
||||
SuccessOrQuit(message->Read(offset, readBuffer, length), "Message::Read failed");
|
||||
VerifyOrQuit(memcmp(readBuffer, &writeBuffer[offset], length) == 0, "Message compare failed");
|
||||
VerifyOrQuit(memcmp(&readBuffer[length], zeroBuffer, kMaxSize - length) == 0, "Message read after length");
|
||||
|
||||
VerifyOrQuit(message->CompareBytes(offset, &writeBuffer[offset], length), "Message::CompareBytes() failed");
|
||||
|
||||
if (length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Change the first byte, and then last byte, and verify that
|
||||
// `CompareBytes()` correctly fails.
|
||||
|
||||
writeBuffer[offset]++;
|
||||
VerifyOrQuit(!message->CompareBytes(offset, &writeBuffer[offset], length), "CompareBytes() failed");
|
||||
writeBuffer[offset]--;
|
||||
|
||||
writeBuffer[offset + length - 1]++;
|
||||
VerifyOrQuit(!message->CompareBytes(offset, &writeBuffer[offset], length), "CompareBytes() failed");
|
||||
writeBuffer[offset + length - 1]--;
|
||||
}
|
||||
|
||||
// Verify `ReadBytes()` behavior when requested read length goes beyond available bytes in the message.
|
||||
@@ -97,10 +118,14 @@ void TestMessage(void)
|
||||
|
||||
memset(readBuffer, 0, sizeof(readBuffer));
|
||||
readLength = message->ReadBytes(offset, readBuffer, length);
|
||||
VerifyOrQuit(readLength <= length, "Message::ReadBytes() returned longer length");
|
||||
|
||||
VerifyOrQuit(readLength < length, "Message::ReadBytes() returned longer length");
|
||||
VerifyOrQuit(readLength == kMaxSize - offset, "Message::Read failed");
|
||||
VerifyOrQuit(memcmp(readBuffer, &writeBuffer[offset], readLength) == 0, "Message compare failed");
|
||||
VerifyOrQuit(memcmp(&readBuffer[readLength], zeroBuffer, kMaxSize - readLength) == 0, "read after length");
|
||||
|
||||
VerifyOrQuit(!message->CompareBytes(offset, readBuffer, length), "Message::CompareBytes failed");
|
||||
VerifyOrQuit(message->CompareBytes(offset, readBuffer, readLength), "Message::CompareBytes failed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +165,11 @@ void TestMessage(void)
|
||||
VerifyOrQuit(
|
||||
memcmp(&readBuffer[dstOffset + bytesCopied], zeroBuffer, kMaxSize - bytesCopied - dstOffset) == 0,
|
||||
"read after length");
|
||||
|
||||
VerifyOrQuit(message->CompareBytes(srcOffset, *message2, dstOffset, bytesCopied),
|
||||
"Message::CompareBytes with two messages failed");
|
||||
VerifyOrQuit(message2->CompareBytes(dstOffset, *message, srcOffset, bytesCopied),
|
||||
"Message::CompareBytes with two messages failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user