@@ -83,8 +83,103 @@ class DecodableListBase
83
83
}
84
84
85
85
protected:
86
+ class Iterator
87
+ {
88
+ public:
89
+ Iterator (const TLV::TLVReader & reader)
90
+ {
91
+ mStatus = CHIP_NO_ERROR;
92
+ mReader .Init (reader);
93
+ }
94
+
95
+ bool Next ()
96
+ {
97
+ if (mReader .GetContainerType () == TLV::kTLVType_NotSpecified )
98
+ {
99
+ return false ;
100
+ }
101
+
102
+ if (mStatus == CHIP_NO_ERROR)
103
+ {
104
+ mStatus = mReader .Next ();
105
+ }
106
+
107
+ return (mStatus == CHIP_NO_ERROR);
108
+ }
109
+
110
+ /*
111
+ * Returns the result of all previous operations on this iterator.
112
+ *
113
+ * Notably, if the end-of-list was encountered in a previous call to Next,
114
+ * the status returned shall be CHIP_NO_ERROR.
115
+ */
116
+ CHIP_ERROR GetStatus () const
117
+ {
118
+ if (mStatus == CHIP_END_OF_TLV)
119
+ {
120
+ return CHIP_NO_ERROR;
121
+ }
122
+
123
+ return mStatus ;
124
+ }
125
+
126
+ protected:
127
+ CHIP_ERROR mStatus ;
128
+ TLV::TLVReader mReader ;
129
+ };
130
+
86
131
TLV::TLVReader mReader ;
87
- chip::Optional<FabricIndex> mFabricIndex ;
132
+ };
133
+
134
+ template <bool IsFabricScoped>
135
+ class FabricIndexListMemberMixin
136
+ {
137
+ };
138
+
139
+ template <>
140
+ class FabricIndexListMemberMixin <true >
141
+ {
142
+ public:
143
+ void SetFabricIndex (FabricIndex fabricIndex) { mFabricIndex .SetValue (fabricIndex); }
144
+
145
+ protected:
146
+ Optional<FabricIndex> mFabricIndex ;
147
+ };
148
+
149
+ template <bool IsFabricScoped>
150
+ class FabricIndexIteratorMemberMixin
151
+ {
152
+ };
153
+
154
+ template <>
155
+ class FabricIndexIteratorMemberMixin <true >
156
+ {
157
+ public:
158
+ FabricIndexIteratorMemberMixin (const Optional<FabricIndex> & fabricindex) : mFabricIndex (fabricindex) {}
159
+
160
+ protected:
161
+ const Optional<FabricIndex> mFabricIndex ;
162
+ };
163
+
164
+ template <bool IsFabricScoped>
165
+ class DecodableMaybeFabricScopedList : public DecodableListBase , public FabricIndexListMemberMixin <IsFabricScoped>
166
+ {
167
+ public:
168
+ static constexpr bool kIsFabricScoped = IsFabricScoped;
169
+
170
+ protected:
171
+ class Iterator : public DecodableListBase ::Iterator, public FabricIndexIteratorMemberMixin<IsFabricScoped>
172
+ {
173
+ public:
174
+ template <bool IsActuallyFabricScoped = IsFabricScoped, std::enable_if_t <IsActuallyFabricScoped, bool > = true >
175
+ Iterator (const TLV::TLVReader & reader, const Optional<FabricIndex> & fabricIndex) :
176
+ DecodableListBase::Iterator (reader), FabricIndexIteratorMemberMixin<IsFabricScoped>(fabricIndex)
177
+ {}
178
+
179
+ template <bool IsActuallyFabricScoped = IsFabricScoped, std::enable_if_t <!IsActuallyFabricScoped, bool > = true >
180
+ Iterator (const TLV::TLVReader & reader) : DecodableListBase::Iterator(reader)
181
+ {}
182
+ };
88
183
};
89
184
90
185
} // namespace detail
@@ -109,21 +204,15 @@ class DecodableListBase
109
204
*
110
205
*/
111
206
template <typename T>
112
- class DecodableList : public detail ::DecodableListBase
207
+ class DecodableList : public detail ::DecodableMaybeFabricScopedList<DataModel::IsFabricScoped<T>::value>
113
208
{
114
209
public:
115
210
DecodableList () {}
116
211
117
- static constexpr bool kIsFabricScoped = DataModel::IsFabricScoped<T>::value;
118
-
119
- template <typename T0 = T, std::enable_if_t <DataModel::IsFabricScoped<T0>::value, bool > = true >
120
- void SetFabricIndex (FabricIndex fabricIndex)
212
+ class Iterator : public detail ::DecodableMaybeFabricScopedList<DataModel::IsFabricScoped<T>::value>::Iterator
121
213
{
122
- mFabricIndex .SetValue (fabricIndex);
123
- }
214
+ using IteratorBase = typename detail::DecodableMaybeFabricScopedList<DataModel::IsFabricScoped<T>::value>::Iterator;
124
215
125
- class Iterator
126
- {
127
216
public:
128
217
/*
129
218
* Initialize the iterator with a reference to a reader.
@@ -133,11 +222,13 @@ class DecodableList : public detail::DecodableListBase
133
222
* have a `kTLVType_NotSpecified` container type if there is
134
223
* no list.
135
224
*/
136
- Iterator (const TLV::TLVReader & reader, Optional<FabricIndex> fabricIndex) : mFabricIndex (fabricIndex)
137
- {
138
- mStatus = CHIP_NO_ERROR;
139
- mReader .Init (reader);
140
- }
225
+ template <typename T0 = T, std::enable_if_t <DataModel::IsFabricScoped<T0>::value, bool > = true >
226
+ Iterator (const TLV::TLVReader & reader, Optional<FabricIndex> fabricIndex) : IteratorBase(reader, fabricIndex)
227
+ {}
228
+
229
+ template <typename T0 = T, std::enable_if_t <!DataModel::IsFabricScoped<T0>::value, bool > = true >
230
+ Iterator (const TLV::TLVReader & reader) : IteratorBase(reader)
231
+ {}
141
232
142
233
/*
143
234
* Increments the iterator to point to the next list element
@@ -157,17 +248,17 @@ class DecodableList : public detail::DecodableListBase
157
248
template <typename T0 = T, std::enable_if_t <!DataModel::IsFabricScoped<T0>::value, bool > = true >
158
249
bool Next ()
159
250
{
160
- return DoNext ();
251
+ return IteratorBase::Next () && DecodeValue ();
161
252
}
162
253
163
254
template <typename T0 = T, std::enable_if_t <DataModel::IsFabricScoped<T0>::value, bool > = true >
164
255
bool Next ()
165
256
{
166
- bool hasNext = DoNext ();
257
+ bool hasNext = IteratorBase::Next () && DecodeValue ();
167
258
168
- if (hasNext && mFabricIndex .HasValue ())
259
+ if (hasNext && this -> mFabricIndex .HasValue ())
169
260
{
170
- mValue .SetFabricIndex (mFabricIndex .Value ());
261
+ mValue .SetFabricIndex (this -> mFabricIndex .Value ());
171
262
}
172
263
173
264
return hasNext;
@@ -179,36 +270,10 @@ class DecodableList : public detail::DecodableListBase
179
270
*/
180
271
const T & GetValue () const { return mValue ; }
181
272
182
- /*
183
- * Returns the result of all previous operations on this iterator.
184
- *
185
- * Notably, if the end-of-list was encountered in a previous call to Next,
186
- * the status returned shall be CHIP_NO_ERROR.
187
- */
188
- CHIP_ERROR GetStatus () const
189
- {
190
- if (mStatus == CHIP_END_OF_TLV)
191
- {
192
- return CHIP_NO_ERROR;
193
- }
194
-
195
- return mStatus ;
196
- }
197
-
198
273
private:
199
- bool DoNext ()
274
+ bool DecodeValue ()
200
275
{
201
- if (mReader .GetContainerType () == TLV::kTLVType_NotSpecified )
202
- {
203
- return false ;
204
- }
205
-
206
- if (mStatus == CHIP_NO_ERROR)
207
- {
208
- mStatus = mReader .Next ();
209
- }
210
-
211
- if (mStatus == CHIP_NO_ERROR)
276
+ if (this ->mStatus == CHIP_NO_ERROR)
212
277
{
213
278
//
214
279
// Re-construct mValue to reset its state back to cluster object defaults.
@@ -218,22 +283,29 @@ class DecodableList : public detail::DecodableListBase
218
283
// data from previous decode attempts will continue to linger and give
219
284
// an incorrect view of the state as seen from a client.
220
285
//
221
- mValue = T ();
222
- mStatus = DataModel::Decode (mReader , mValue );
286
+ mValue = T ();
287
+ this -> mStatus = DataModel::Decode (this -> mReader , mValue );
223
288
}
224
289
225
- return (mStatus == CHIP_NO_ERROR);
290
+ return (this -> mStatus == CHIP_NO_ERROR);
226
291
}
227
292
228
293
T mValue ;
229
- CHIP_ERROR mStatus ;
230
- TLV::TLVReader mReader ;
231
- // TODO: Consider some setup where this field does not exist when T
232
- // is not a fabric scoped struct.
233
- const Optional<FabricIndex> mFabricIndex ;
234
294
};
235
295
236
- Iterator begin () const { return Iterator (mReader , mFabricIndex ); }
296
+ // Need this->mReader and this->mFabricIndex for the name lookup to realize
297
+ // those can be found in our superclasses.
298
+ template <typename T0 = T, std::enable_if_t <DataModel::IsFabricScoped<T0>::value, bool > = true >
299
+ Iterator begin () const
300
+ {
301
+ return Iterator (this ->mReader , this ->mFabricIndex );
302
+ }
303
+
304
+ template <typename T0 = T, std::enable_if_t <!DataModel::IsFabricScoped<T0>::value, bool > = true >
305
+ Iterator begin () const
306
+ {
307
+ return Iterator (this ->mReader );
308
+ }
237
309
};
238
310
239
311
} // namespace DataModel
0 commit comments