Skip to content

Commit

Permalink
[tlv] Encapsulate Tag encoding
Browse files Browse the repository at this point in the history
Make the internal representation of Tag private so that
it is easier and safer to change it.

Signed-off-by: Damian Krolik <[email protected]>
  • Loading branch information
Damian-Nordic committed Dec 23, 2022
1 parent 26bd9d6 commit 3eb17b4
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 72 deletions.
6 changes: 3 additions & 3 deletions src/lib/core/CHIPTLVReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,7 @@ CHIP_ERROR TLVReader::VerifyElement()
}
else
{
if (mElemTag == UnknownImplicitTag)
if (mElemTag == UnknownImplicitTag())
return CHIP_ERROR_UNKNOWN_IMPLICIT_TLV_TAG;
switch (mContainerType)
{
Expand Down Expand Up @@ -806,11 +806,11 @@ Tag TLVReader::ReadTag(TLVTagControl tagControl, const uint8_t *& p) const
return CommonTag(LittleEndian::Read32(p));
case TLVTagControl::ImplicitProfile_2Bytes:
if (ImplicitProfileId == kProfileIdNotSpecified)
return UnknownImplicitTag;
return UnknownImplicitTag();
return ProfileTag(ImplicitProfileId, LittleEndian::Read16(p));
case TLVTagControl::ImplicitProfile_4Bytes:
if (ImplicitProfileId == kProfileIdNotSpecified)
return UnknownImplicitTag;
return UnknownImplicitTag();
return ProfileTag(ImplicitProfileId, LittleEndian::Read32(p));
case TLVTagControl::FullyQualified_6Bytes:
vendorId = LittleEndian::Read16(p);
Expand Down
125 changes: 71 additions & 54 deletions src/lib/core/CHIPTLVTags.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,40 @@
namespace chip {
namespace TLV {

struct Tag
class Tag
{
explicit constexpr Tag(uint64_t val) : mVal(val) {}
Tag() {}
public:
Tag() = default;

constexpr bool operator==(const Tag & other) const { return mVal == other.mVal; }
constexpr bool operator!=(const Tag & other) const { return mVal != other.mVal; }

private:
explicit constexpr Tag(uint64_t val) : mVal(val) {}

friend constexpr Tag ProfileTag(uint32_t profileId, uint32_t tagNum);
friend constexpr Tag ProfileTag(uint16_t vendorId, uint16_t profileNum, uint32_t tagNum);
friend constexpr Tag ContextTag(uint8_t tagNum);
friend constexpr Tag CommonTag(uint32_t tagNum);
friend constexpr Tag AnonymousTag();
friend constexpr Tag UnknownImplicitTag();

friend constexpr uint32_t ProfileIdFromTag(Tag tag);
friend constexpr uint16_t VendorIdFromTag(Tag tag);
friend constexpr uint16_t ProfileNumFromTag(Tag tag);
friend constexpr uint32_t TagNumFromTag(Tag tag);

friend constexpr bool IsProfileTag(Tag tag);
friend constexpr bool IsContextTag(Tag tag);
friend constexpr bool IsSpecialTag(Tag tag);

static constexpr uint32_t kProfileIdShift = 32;
static constexpr uint32_t kVendorIdShift = 48;
static constexpr uint32_t kProfileNumShift = 32;
static constexpr uint32_t kSpecialTagProfileId = 0xFFFFFFFF;
static constexpr uint32_t kAnonymousTagNum = 0xFFFFFFFF;
static constexpr uint32_t kContextTagMaxNum = UINT8_MAX;

uint64_t mVal;
};

Expand All @@ -50,20 +78,6 @@ enum TLVCommonProfiles
kCommonProfileId = 0
};

// TODO: Move to private namespace
enum TLVTagFields
{
kProfileIdMask = 0xFFFFFFFF00000000ULL,
kProfileNumMask = 0x0000FFFF00000000ULL,
kVendorIdMask = 0xFFFF000000000000ULL,
kProfileIdShift = 32,
kVendorIdShift = 48,
kProfileNumShift = 32,
kTagNumMask = 0x00000000FFFFFFFFULL,
kSpecialTagMarker = 0xFFFFFFFF00000000ULL,
kContextTagMaxNum = UINT8_MAX
};

// TODO: Move to private namespace
enum class TLVTagControl : uint8_t
{
Expand Down Expand Up @@ -99,9 +113,9 @@ enum
* @param[in] tagNum The profile-specific tag number assigned to the tag.
* @return A 64-bit integer representing the tag.
*/
inline constexpr Tag ProfileTag(uint32_t profileId, uint32_t tagNum)
constexpr Tag ProfileTag(uint32_t profileId, uint32_t tagNum)
{
return Tag(((static_cast<uint64_t>(profileId)) << kProfileIdShift) | tagNum);
return Tag((static_cast<uint64_t>(profileId) << Tag::kProfileIdShift) | tagNum);
}

/**
Expand All @@ -112,10 +126,10 @@ inline constexpr Tag ProfileTag(uint32_t profileId, uint32_t tagNum)
* @param[in] tagNum The profile-specific tag number assigned to the tag.
* @return A 64-bit integer representing the tag.
*/
inline constexpr Tag ProfileTag(uint16_t vendorId, uint16_t profileNum, uint32_t tagNum)
constexpr Tag ProfileTag(uint16_t vendorId, uint16_t profileNum, uint32_t tagNum)
{
return Tag(((static_cast<uint64_t>(vendorId)) << kVendorIdShift) | ((static_cast<uint64_t>(profileNum)) << kProfileNumShift) |
tagNum);
return Tag((static_cast<uint64_t>(vendorId) << Tag::kVendorIdShift) |
(static_cast<uint64_t>(profileNum) << Tag::kProfileNumShift) | tagNum);
}

/**
Expand All @@ -124,9 +138,9 @@ inline constexpr Tag ProfileTag(uint16_t vendorId, uint16_t profileNum, uint32_t
* @param[in] tagNum The context-specific tag number assigned to the tag.
* @return A 64-bit integer representing the tag.
*/
inline constexpr Tag ContextTag(uint8_t tagNum)
constexpr Tag ContextTag(uint8_t tagNum)
{
return Tag(kSpecialTagMarker | tagNum);
return ProfileTag(Tag::kSpecialTagProfileId, tagNum);
}

/**
Expand All @@ -135,20 +149,23 @@ inline constexpr Tag ContextTag(uint8_t tagNum)
* @param[in] tagNum The common profile tag number assigned to the tag.
* @return A 64-bit integer representing the tag.
*/
inline constexpr Tag CommonTag(uint32_t tagNum)
constexpr Tag CommonTag(uint32_t tagNum)
{
return ProfileTag(kCommonProfileId, tagNum);
}

/**
* A value signifying a TLV element that has no tag (i.e. an anonymous element).
*/
inline constexpr Tag AnonymousTag()
constexpr Tag AnonymousTag()
{
return Tag(kSpecialTagMarker | 0x00000000FFFFFFFFULL);
return ProfileTag(Tag::kSpecialTagProfileId, Tag::kAnonymousTagNum);
}

constexpr Tag UnknownImplicitTag()
{
return ProfileTag(Tag::kSpecialTagProfileId, 0xFFFFFFFE);
}
// TODO: Move to private namespace
static constexpr Tag UnknownImplicitTag(kSpecialTagMarker | 0x00000000FFFFFFFEULL);

/**
* Returns the profile id from a TLV tag
Expand All @@ -158,9 +175,22 @@ static constexpr Tag UnknownImplicitTag(kSpecialTagMarker | 0x00000000FFFFFFFEUL
* @param[in] tag The API representation of a profile-specific TLV tag.
* @return The profile id.
*/
inline constexpr uint32_t ProfileIdFromTag(Tag tag)
constexpr uint32_t ProfileIdFromTag(Tag tag)
{
return static_cast<uint32_t>((tag.mVal & kProfileIdMask) >> kProfileIdShift);
return static_cast<uint32_t>(tag.mVal >> Tag::kProfileIdShift);
}

/**
* Returns the vendor id from a TLV tag
*
* @note The behavior of this function is undefined if the supplied tag is not a profile-specific tag.
*
* @param[in] tag The API representation of a profile-specific TLV tag.
* @return The associated vendor id.
*/
constexpr uint16_t VendorIdFromTag(Tag tag)
{
return static_cast<uint16_t>(tag.mVal >> Tag::kVendorIdShift);
}

/**
Expand All @@ -171,9 +201,9 @@ inline constexpr uint32_t ProfileIdFromTag(Tag tag)
* @param[in] tag The API representation of a profile-specific TLV tag.
* @return The associated profile number.
*/
inline constexpr uint16_t ProfileNumFromTag(Tag tag)
constexpr uint16_t ProfileNumFromTag(Tag tag)
{
return static_cast<uint16_t>((tag.mVal & kProfileNumMask) >> kProfileNumShift);
return static_cast<uint16_t>(tag.mVal >> Tag::kProfileNumShift);
}

/**
Expand All @@ -187,44 +217,31 @@ inline constexpr uint16_t ProfileNumFromTag(Tag tag)
* @param[in] tag The API representation of a profile-specific or context-specific TLV tag.
* @return The associated tag number.
*/
inline constexpr uint32_t TagNumFromTag(Tag tag)
{
return static_cast<uint32_t>(tag.mVal & kTagNumMask);
}

/**
* Returns the vendor id from a TLV tag
*
* @note The behavior of this function is undefined if the supplied tag is not a profile-specific tag.
*
* @param[in] tag The API representation of a profile-specific TLV tag.
* @return The associated vendor id.
*/
inline constexpr uint16_t VendorIdFromTag(Tag tag)
constexpr uint32_t TagNumFromTag(Tag tag)
{
return static_cast<uint16_t>((tag.mVal & kVendorIdMask) >> kVendorIdShift);
return static_cast<uint32_t>(tag.mVal);
}

/**
* Returns true of the supplied tag is a profile-specific tag.
*/
inline constexpr bool IsProfileTag(Tag tag)
constexpr bool IsProfileTag(Tag tag)
{
return (tag.mVal & kProfileIdMask) != kSpecialTagMarker;
return ProfileIdFromTag(tag) != Tag::kSpecialTagProfileId;
}

/**
* Returns true if the supplied tag is a context-specific tag.
*/
inline constexpr bool IsContextTag(Tag tag)
constexpr bool IsContextTag(Tag tag)
{
return (tag.mVal & kProfileIdMask) == kSpecialTagMarker && TagNumFromTag(tag) <= kContextTagMaxNum;
return ProfileIdFromTag(tag) == Tag::kSpecialTagProfileId && TagNumFromTag(tag) <= Tag::kContextTagMaxNum;
}

// TODO: move to private namespace
inline constexpr bool IsSpecialTag(Tag tag)
constexpr bool IsSpecialTag(Tag tag)
{
return (tag.mVal & kProfileIdMask) == kSpecialTagMarker;
return ProfileIdFromTag(tag) == Tag::kSpecialTagProfileId;
}

} // namespace TLV
Expand Down
27 changes: 12 additions & 15 deletions src/lib/core/CHIPTLVWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -629,24 +629,21 @@ CHIP_ERROR TLVWriter::WriteElementHead(TLVElementType elemType, Tag tag, uint64_
else
p = stagingBuf;

if (IsSpecialTag(tag))
if (IsContextTag(tag))
{
if (tagNum <= kContextTagMaxNum)
{
if (mContainerType != kTLVType_Structure && mContainerType != kTLVType_List)
return CHIP_ERROR_INVALID_TLV_TAG;
if (mContainerType != kTLVType_Structure && mContainerType != kTLVType_List)
return CHIP_ERROR_INVALID_TLV_TAG;

Write8(p, TLVTagControl::ContextSpecific | elemType);
Write8(p, static_cast<uint8_t>(tagNum));
}
else
{
if (elemType != TLVElementType::EndOfContainer && mContainerType != kTLVType_NotSpecified &&
mContainerType != kTLVType_Array && mContainerType != kTLVType_List)
return CHIP_ERROR_INVALID_TLV_TAG;
Write8(p, TLVTagControl::ContextSpecific | elemType);
Write8(p, static_cast<uint8_t>(tagNum));
}
else if (IsSpecialTag(tag))
{
if (elemType != TLVElementType::EndOfContainer && mContainerType != kTLVType_NotSpecified &&
mContainerType != kTLVType_Array && mContainerType != kTLVType_List)
return CHIP_ERROR_INVALID_TLV_TAG;

Write8(p, TLVTagControl::Anonymous | elemType);
}
Write8(p, TLVTagControl::Anonymous | elemType);
}
else
{
Expand Down

0 comments on commit 3eb17b4

Please sign in to comment.