Skip to content

Commit

Permalink
Refactor TLV tags to use enums, re-implemented scene handler and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
lpbeliveau-silabs authored and pull[bot] committed Jan 18, 2024
1 parent efbc3c5 commit 1145652
Show file tree
Hide file tree
Showing 9 changed files with 1,117 additions and 377 deletions.
1 change: 1 addition & 0 deletions src/app/clusters/scenes/ExtensionFieldsSets.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class ExtensionFieldsSets
virtual CHIP_ERROR Deserialize(TLV::TLVReader & reader) = 0;
virtual void Clear() = 0;
virtual bool IsEmpty() const = 0;
virtual uint8_t GetFieldNum() const = 0;
};
} // namespace scenes
} // namespace chip
33 changes: 15 additions & 18 deletions src/app/clusters/scenes/ExtensionFieldsSetsImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ ExtensionFieldsSetsImpl::ExtensionFieldsSetsImpl() : ExtensionFieldsSets() {}
CHIP_ERROR ExtensionFieldsSetsImpl::Serialize(TLV::TLVWriter & writer) const
{
TLV::TLVType container;
ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(1), TLV::kTLVType_Structure, container));
ReturnErrorOnFailure(writer.Put(TagFieldNum(), static_cast<uint8_t>(this->mFieldNum)));
ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(kTagEFSArrayContainer), TLV::kTLVType_Structure, container));
ReturnErrorOnFailure(writer.Put(TLV::ContextTag(kTagEFSFieldNum), static_cast<uint8_t>(this->mFieldNum)));
if (!this->IsEmpty())
{
for (uint8_t i = 0; i < kMaxClusterPerScenes; i++)
for (uint8_t i = 0; i < this->mFieldNum; i++)
{
if (!this->mEFS[i].IsEmpty())
{
Expand All @@ -44,10 +44,10 @@ CHIP_ERROR ExtensionFieldsSetsImpl::Serialize(TLV::TLVWriter & writer) const
CHIP_ERROR ExtensionFieldsSetsImpl::Deserialize(TLV::TLVReader & reader)
{
TLV::TLVType container;
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::ContextTag(1)));
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::ContextTag(kTagEFSArrayContainer)));
ReturnErrorOnFailure(reader.EnterContainer(container));

ReturnErrorOnFailure(reader.Next(TagFieldNum()));
ReturnErrorOnFailure(reader.Next(TLV::ContextTag(kTagEFSFieldNum)));
ReturnErrorOnFailure(reader.Get(this->mFieldNum));

if (!this->IsEmpty())
Expand All @@ -73,11 +73,6 @@ void ExtensionFieldsSetsImpl::Clear()
this->mFieldNum = 0;
}

bool ExtensionFieldsSetsImpl::IsEmpty() const
{
return (this->mFieldNum == 0);
}

/// @brief Inserts a field Set set into the array of extension field Set sets for a scene entry.
/// If the same ID is present in the EFS array, it will overwrite it.
/// @param fieldSet field set to be inserted
Expand All @@ -87,6 +82,9 @@ CHIP_ERROR ExtensionFieldsSetsImpl::InsertFieldSet(ExtensionFieldsSet & fieldSet
CHIP_ERROR err = CHIP_ERROR_NO_MEMORY;
uint8_t idPosition = kInvalidPosition;
uint8_t firstEmptyPosition = kInvalidPosition;

VerifyOrReturnError(fieldSet.mID != kInvalidClusterId, CHIP_ERROR_INVALID_ARGUMENT);

for (uint8_t i = 0; i < kMaxClusterPerScenes; i++)
{
if (this->mEFS[i].mID == fieldSet.mID)
Expand All @@ -104,12 +102,12 @@ CHIP_ERROR ExtensionFieldsSetsImpl::InsertFieldSet(ExtensionFieldsSet & fieldSet
// if found, replace at found position, otherwise at insert first free position, otherwise return error
if (idPosition < kMaxClusterPerScenes)
{
ReturnErrorOnFailure(this->mEFS[idPosition] = fieldSet);
err = CHIP_NO_ERROR;
this->mEFS[idPosition] = fieldSet;
err = CHIP_NO_ERROR;
}
else if (firstEmptyPosition < kMaxClusterPerScenes)
{
ReturnErrorOnFailure(this->mEFS[firstEmptyPosition] = fieldSet);
this->mEFS[firstEmptyPosition] = fieldSet;
this->mFieldNum++;
err = CHIP_NO_ERROR;
}
Expand All @@ -119,23 +117,22 @@ CHIP_ERROR ExtensionFieldsSetsImpl::InsertFieldSet(ExtensionFieldsSet & fieldSet

CHIP_ERROR ExtensionFieldsSetsImpl::GetFieldSetAtPosition(ExtensionFieldsSet & fieldSet, uint8_t position)
{
if (position < this->mFieldNum)
{
ReturnErrorOnFailure(fieldSet = this->mEFS[position]);
}
VerifyOrReturnError(position < this->mFieldNum, CHIP_ERROR_BUFFER_TOO_SMALL);

fieldSet = this->mEFS[position];

return CHIP_NO_ERROR;
}

CHIP_ERROR ExtensionFieldsSetsImpl::RemoveFieldAtPosition(uint8_t position)
{

VerifyOrReturnError(position < kMaxClusterPerScenes, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnValue(!this->IsEmpty() && !this->mEFS[position].IsEmpty(), CHIP_NO_ERROR);

uint8_t next = position + 1;
uint8_t moveNum = kMaxClusterPerScenes - next;

// TODO: Implement general array management methods
// Compress array after removal
memmove(&this->mEFS[position], &this->mEFS[next], sizeof(ExtensionFieldsSet) * moveNum);

Expand Down
61 changes: 31 additions & 30 deletions src/app/clusters/scenes/ExtensionFieldsSetsImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,47 +23,64 @@
namespace chip {
namespace scenes {

enum EFSTLVTag
{
kTagEFSArrayContainer = 1,
kTagEFSFieldNum = 1,
kTagEFSContainer,
kTagEFSClusterID,
kTagEFS,
};

using clusterId = chip::ClusterId;

struct ExtensionFieldsSet
{
static constexpr TLV::Tag TagClusterId() { return TLV::ContextTag(1); }
static constexpr TLV::Tag TagEFS() { return TLV::ContextTag(2); }
clusterId mID = kInvalidClusterId;
uint8_t mBytesBuffer[kMaxFieldsPerCluster] = { 0 };
uint8_t mUsedBytes = 0;

ExtensionFieldsSet() = default;
ExtensionFieldsSet(clusterId cmID, uint8_t * data, uint8_t dataSize) : mID(cmID), mUsedBytes(dataSize)
ExtensionFieldsSet(clusterId cmID, const uint8_t * data, uint8_t dataSize) : mID(cmID), mUsedBytes(dataSize)
{
if (dataSize <= kMaxFieldsPerCluster)
{
memcpy(mBytesBuffer, data, mUsedBytes);
}
}

ExtensionFieldsSet(clusterId cmID, ByteSpan bytes) : mID(cmID), mUsedBytes(static_cast<uint8_t>(bytes.size()))
{
if (bytes.size() <= kMaxFieldsPerCluster)
{
memcpy(mBytesBuffer, bytes.data(), bytes.size());
}
}

~ExtensionFieldsSet() = default;

CHIP_ERROR Serialize(TLV::TLVWriter & writer) const
{
TLV::TLVType container;
ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(1), TLV::kTLVType_Structure, container));
ReturnErrorOnFailure(writer.StartContainer(TLV::ContextTag(kTagEFSContainer), TLV::kTLVType_Structure, container));

ReturnErrorOnFailure(writer.Put(TagClusterId(), static_cast<uint16_t>(this->mID)));
ReturnErrorOnFailure(writer.PutBytes(TagEFS(), mBytesBuffer, mUsedBytes));
ReturnErrorOnFailure(writer.Put(TLV::ContextTag(kTagEFSClusterID), static_cast<uint16_t>(this->mID)));
ReturnErrorOnFailure(writer.PutBytes(TLV::ContextTag(kTagEFS), mBytesBuffer, mUsedBytes));

return writer.EndContainer(container);
}

CHIP_ERROR Deserialize(TLV::TLVReader & reader)
{
ByteSpan buffer;
TLV::TLVType container;
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::ContextTag(1)));
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::ContextTag(kTagEFSContainer)));
ReturnErrorOnFailure(reader.EnterContainer(container));

ReturnErrorOnFailure(reader.Next(TagClusterId()));
ReturnErrorOnFailure(reader.Next(TLV::ContextTag(kTagEFSClusterID)));
ReturnErrorOnFailure(reader.Get(this->mID));

ReturnErrorOnFailure(reader.Next(TagEFS()));
ReturnErrorOnFailure(reader.Next(TLV::ContextTag(kTagEFS)));
ReturnErrorOnFailure(reader.Get(buffer));
VerifyOrReturnError(buffer.size() <= kMaxFieldsPerCluster, CHIP_ERROR_BUFFER_TOO_SMALL);
this->mUsedBytes = static_cast<uint8_t>(buffer.size());
Expand All @@ -86,22 +103,6 @@ struct ExtensionFieldsSet
return (this->mID == other.mID && !memcmp(this->mBytesBuffer, other.mBytesBuffer, this->mUsedBytes) &&
this->mUsedBytes == other.mUsedBytes);
}

CHIP_ERROR operator=(const ExtensionFieldsSet & other)
{
if (other.mUsedBytes <= kMaxFieldsPerCluster)
{
memcpy(this->mBytesBuffer, other.mBytesBuffer, other.mUsedBytes);
}
else
{
return CHIP_ERROR_BUFFER_TOO_SMALL;
}
this->mID = other.mID;
this->mUsedBytes = other.mUsedBytes;

return CHIP_NO_ERROR;
}
};

class ExtensionFieldsSetsImpl : public ExtensionFieldsSets
Expand All @@ -114,7 +115,8 @@ class ExtensionFieldsSetsImpl : public ExtensionFieldsSets
CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override;
CHIP_ERROR Deserialize(TLV::TLVReader & reader) override;
void Clear() override;
bool IsEmpty() const override;
bool IsEmpty() const override { return (this->mFieldNum == 0); }
uint8_t GetFieldNum() const override { return this->mFieldNum; };

// implementation
CHIP_ERROR InsertFieldSet(ExtensionFieldsSet & field);
Expand All @@ -133,19 +135,18 @@ class ExtensionFieldsSetsImpl : public ExtensionFieldsSets
return true;
}

CHIP_ERROR operator=(const ExtensionFieldsSetsImpl & other)
ExtensionFieldsSetsImpl & operator=(const ExtensionFieldsSetsImpl & other)
{
for (uint8_t i = 0; i < kMaxClusterPerScenes; i++)
{
ReturnErrorOnFailure(this->mEFS[i] = other.mEFS[i]);
this->mEFS[i] = other.mEFS[i];
}
mFieldNum = other.mFieldNum;

return CHIP_NO_ERROR;
return *this;
}

protected:
static constexpr TLV::Tag TagFieldNum() { return TLV::ContextTag(1); }
ExtensionFieldsSet mEFS[kMaxClusterPerScenes];
uint8_t mFieldNum = 0;
};
Expand Down
Loading

0 comments on commit 1145652

Please sign in to comment.