|
18 | 18 |
|
19 | 19 | #pragma once
|
20 | 20 |
|
21 |
| -#include <app/AttributePathParams.h> |
22 | 21 | #include <app/util/basic-types.h>
|
23 | 22 | #include <assert.h>
|
24 | 23 | #include <lib/core/Optional.h>
|
25 | 24 |
|
26 | 25 | namespace chip {
|
27 | 26 | namespace app {
|
28 |
| -static constexpr AttributeId kRootAttributeId = 0xFFFFFFFF; |
29 | 27 |
|
| 28 | +/** |
| 29 | + * ClusterInfo is the representation of an attribute path or an event path used by ReadHandler, ReadClient, WriteHandler, |
| 30 | + * Report::Engine etc, it uses some invalid values for representing the wildcard values for its fields and contains a mpNext field |
| 31 | + * so it can be used as a linked list. |
| 32 | + */ |
| 33 | +// TODO: The cluster info should be separated into AttributeInfo and EventInfo. |
| 34 | +// Note: The change will happen after #11171 with a better linked list. |
30 | 35 | struct ClusterInfo
|
31 | 36 | {
|
32 |
| - enum class Flags : uint8_t |
33 |
| - { |
34 |
| - kFieldIdValid = 0x01, |
35 |
| - kListIndexValid = 0x02, |
36 |
| - kEventIdValid = 0x03, |
37 |
| - }; |
38 |
| - |
| 37 | +private: |
| 38 | + // Endpoint Id is a uint16 number, and should between 0 and 0xFFFE |
| 39 | + static constexpr EndpointId kInvalidEndpointId = 0xFFFF; |
| 40 | + // The ClusterId, AttributeId and EventId are MEIs, |
| 41 | + // 0xFFFF is not a valid manufacturer code, thus 0xFFFF'FFFF is not a valid MEI |
| 42 | + static constexpr ClusterId kInvalidClusterId = 0xFFFF'FFFF; |
| 43 | + static constexpr AttributeId kInvalidAttributeId = 0xFFFF'FFFF; |
| 44 | + static constexpr EventId kInvalidEventId = 0xFFFF'FFFF; |
| 45 | + // ListIndex is a uint16 number, thus 0xFFFF is not a valid list index. |
| 46 | + static constexpr ListIndex kInvalidListIndex = 0xFFFF; |
| 47 | + |
| 48 | +public: |
39 | 49 | bool IsAttributePathSupersetOf(const ClusterInfo & other) const
|
40 | 50 | {
|
41 |
| - if ((other.mEndpointId != mEndpointId) || (other.mClusterId != mClusterId)) |
42 |
| - { |
43 |
| - return false; |
44 |
| - } |
45 |
| - |
46 |
| - Optional<AttributeId> myFieldId = |
47 |
| - mFlags.Has(Flags::kFieldIdValid) ? Optional<AttributeId>::Value(mFieldId) : Optional<AttributeId>::Missing(); |
48 |
| - |
49 |
| - Optional<AttributeId> otherFieldId = other.mFlags.Has(Flags::kFieldIdValid) ? Optional<AttributeId>::Value(other.mFieldId) |
50 |
| - : Optional<AttributeId>::Missing(); |
51 |
| - |
52 |
| - Optional<ListIndex> myListIndex = |
53 |
| - mFlags.Has(Flags::kListIndexValid) ? Optional<ListIndex>::Value(mListIndex) : Optional<ListIndex>::Missing(); |
| 51 | + VerifyOrReturnError(HasWildcardEndpointId() || mEndpointId == other.mEndpointId, false); |
| 52 | + VerifyOrReturnError(HasWildcardClusterId() || mClusterId == other.mClusterId, false); |
| 53 | + VerifyOrReturnError(HasWildcardAttributeId() || mFieldId == other.mFieldId, false); |
| 54 | + VerifyOrReturnError(HasWildcardListIndex() || mListIndex == other.mListIndex, false); |
54 | 55 |
|
55 |
| - Optional<ListIndex> otherListIndex = other.mFlags.Has(Flags::kListIndexValid) ? Optional<ListIndex>::Value(other.mListIndex) |
56 |
| - : Optional<ListIndex>::Missing(); |
57 |
| - |
58 |
| - // If list index exists, field index must exist |
59 |
| - // Field 0xFFFFFFF (any) & listindex set is invalid |
60 |
| - assert(!(myListIndex.HasValue() && !myFieldId.HasValue())); |
61 |
| - assert(!(otherListIndex.HasValue() && !otherFieldId.HasValue())); |
62 |
| - assert(!(myFieldId == Optional<AttributeId>::Value(kRootAttributeId) && myListIndex.HasValue())); |
63 |
| - assert(!(otherFieldId == Optional<AttributeId>::Value(kRootAttributeId) && otherListIndex.HasValue())); |
64 |
| - |
65 |
| - if (myFieldId == Optional<AttributeId>::Value(kRootAttributeId)) |
66 |
| - { |
67 |
| - return true; |
68 |
| - } |
69 |
| - |
70 |
| - if (myFieldId != otherFieldId) |
71 |
| - { |
72 |
| - return false; |
73 |
| - } |
| 56 | + return true; |
| 57 | + } |
74 | 58 |
|
75 |
| - // We only support top layer for attribute representation, either FieldId or FieldId + ListIndex |
76 |
| - // Combination: if myFieldId == otherFieldId, ListIndex cannot exist without FieldId |
77 |
| - // 1. myListIndex and otherListIndex both missing or both exactly the same, then current is superset of other |
78 |
| - // 2. myListIndex is missing, no matter if otherListIndex is missing or not, then current is superset of other |
79 |
| - if (myListIndex == otherListIndex) |
80 |
| - { |
81 |
| - // either both missing or both exactly the same |
82 |
| - return true; |
83 |
| - } |
| 59 | + bool HasWildcard() const { return HasWildcardEndpointId() || HasWildcardClusterId() || HasWildcardAttributeId(); } |
84 | 60 |
|
85 |
| - if (!myListIndex.HasValue()) |
86 |
| - { |
87 |
| - // difference is ok only if myListIndex is missing |
88 |
| - return true; |
89 |
| - } |
| 61 | + /** |
| 62 | + * Check that the path meets some basic constraints of an attribute path: If list index is not wildcard, then field id must not |
| 63 | + * be wildcard. This does not verify that the attribute being targeted is actually of list type when the list index is not |
| 64 | + * wildcard. |
| 65 | + */ |
| 66 | + bool IsValidAttributePath() const { return HasWildcardListIndex() || !HasWildcardAttributeId(); } |
90 | 67 |
|
91 |
| - return false; |
92 |
| - } |
| 68 | + inline bool HasWildcardNodeId() const { return mNodeId == kUndefinedNodeId; } |
| 69 | + inline bool HasWildcardEndpointId() const { return mEndpointId == kInvalidEndpointId; } |
| 70 | + inline bool HasWildcardClusterId() const { return mClusterId == kInvalidClusterId; } |
| 71 | + inline bool HasWildcardAttributeId() const { return mFieldId == kInvalidAttributeId; } |
| 72 | + inline bool HasWildcardListIndex() const { return mListIndex == kInvalidListIndex; } |
| 73 | + inline bool HasWildcardEventId() const { return mEventId == kInvalidEventId; } |
93 | 74 |
|
94 | 75 | ClusterInfo() {}
|
95 |
| - NodeId mNodeId = 0; |
96 |
| - ClusterId mClusterId = 0; |
97 |
| - ListIndex mListIndex = 0; |
98 |
| - AttributeId mFieldId = 0; |
99 |
| - EndpointId mEndpointId = 0; |
100 |
| - BitFlags<Flags> mFlags; |
101 |
| - ClusterInfo * mpNext = nullptr; |
102 |
| - EventId mEventId = 0; |
103 |
| - /* For better structure alignment |
104 |
| - * Above ordering is by bit-size to ensure least amount of memory alignment padding. |
105 |
| - * Changing order to something more natural (e.g. clusterid before nodeid) will result |
| 76 | + /* |
| 77 | + * For better structure alignment |
| 78 | + * Below ordering is by bit-size to ensure least amount of memory alignment padding. |
| 79 | + * Changing order to something more natural (e.g. endpoint id before cluster id) will result |
106 | 80 | * in extra memory alignment padding.
|
107 |
| - * uint64 mNodeId |
108 |
| - * uint16_t mClusterId |
109 |
| - * uint16_t mListIndex |
110 |
| - * uint8_t FieldId |
111 |
| - * uint8_t EndpointId |
112 |
| - * uint8_t mDirty |
113 |
| - * uint8_t mType |
114 |
| - * uint32_t mpNext |
115 |
| - * uint16_t EventId |
116 |
| - * padding 2 bytes |
117 | 81 | */
|
| 82 | + NodeId mNodeId = kUndefinedNodeId; // uint64 |
| 83 | + ClusterInfo * mpNext = nullptr; // pointer width (32/64 bits) |
| 84 | + ClusterId mClusterId = kInvalidClusterId; // uint32 |
| 85 | + AttributeId mFieldId = kInvalidAttributeId; // uint32 |
| 86 | + EventId mEventId = kInvalidEventId; // uint32 |
| 87 | + ListIndex mListIndex = kInvalidListIndex; // uint16 |
| 88 | + EndpointId mEndpointId = kInvalidEndpointId; // uint16 |
118 | 89 | };
|
119 | 90 | } // namespace app
|
120 | 91 | } // namespace chip
|
0 commit comments