@@ -240,64 +240,72 @@ void Instance::HandleSelectAreasCmd(HandlerContext & ctx, const Commands::Select
240
240
}
241
241
}
242
242
243
+ uint32_t selectedAreasBuffer[kMaxNumSelectedAreas ];
244
+ auto selectedAreasSpan = Span<uint32_t >(selectedAreasBuffer, kMaxNumSelectedAreas );
245
+ uint32_t numberOfSelectedAreas = 0 ;
246
+
247
+ // Closure for checking if an area ID exists in the selectedAreasSpan
248
+ auto areaAlreadyExists = [&numberOfSelectedAreas, &selectedAreasSpan](uint32_t areaId) {
249
+ for (uint32_t i = 0 ; i < numberOfSelectedAreas; i++)
250
+ {
251
+ if (areaId == selectedAreasSpan[i])
252
+ {
253
+ return true ;
254
+ }
255
+ }
256
+ return false ;
257
+ };
258
+
243
259
// if number of selected locations in parameter matches number in attribute - the locations *might* be the same
244
260
bool matchesCurrentSelectedAreas = (numberOfAreas == mDelegate ->GetNumberOfSelectedAreas ());
245
261
262
+ // do as much parameter validation as we can
246
263
if (numberOfAreas != 0 )
247
264
{
248
- // do as much parameter validation as we can
265
+ uint32_t ignoredIndex = 0 ;
266
+ uint32_t oldSelectedArea;
267
+ auto iAreaIter = req.newAreas .begin ();
268
+ while (iAreaIter.Next ())
249
269
{
250
- uint32_t ignoredIndex = 0 ;
251
- uint32_t oldSelectedArea;
252
- uint32_t i = 0 ;
253
- auto iAreaIter = req.newAreas .begin ();
254
- while (iAreaIter.Next ())
255
- {
256
- uint32_t aSelectedArea = iAreaIter.GetValue ();
270
+ uint32_t selectedArea = iAreaIter.GetValue ();
257
271
258
- // each item in this list SHALL match the AreaID field of an entry on the SupportedAreas attribute's list
259
- // If the Status field is set to UnsupportedArea, the StatusText field SHALL be an empty string.
260
- if (!IsSupportedArea (aSelectedArea))
261
- {
262
- exitResponse (SelectAreasStatus::kUnsupportedArea , " " _span);
263
- return ;
264
- }
272
+ // If aSelectedArea is already in selectedAreasSpan skip
273
+ if (areaAlreadyExists (selectedArea))
274
+ {
275
+ continue ;
276
+ }
265
277
266
- // Checking for duplicate locations.
267
- uint32_t j = 0 ;
268
- auto jAreaIter = req.newAreas .begin ();
269
- while (j < i)
270
- {
271
- jAreaIter.Next (); // Since j < i and i is valid, we can safely call Next() without checking the return value.
272
- if (jAreaIter.GetValue () == aSelectedArea)
273
- {
274
- exitResponse (SelectAreasStatus::kDuplicatedAreas , " " _span);
275
- return ;
276
- }
277
- j += 1 ;
278
- }
278
+ // each item in this list SHALL match the AreaID field of an entry on the SupportedAreas attribute's list
279
+ // If the Status field is set to UnsupportedArea, the StatusText field SHALL be an empty string.
280
+ if (!IsSupportedArea (selectedArea))
281
+ {
282
+ exitResponse (SelectAreasStatus::kUnsupportedArea , " " _span);
283
+ return ;
284
+ }
279
285
280
- // check to see if parameter list and attribute still match
281
- if (matchesCurrentSelectedAreas)
286
+ // check to see if parameter list and attribute still match
287
+ if (matchesCurrentSelectedAreas)
288
+ {
289
+ if (!mDelegate ->GetSelectedAreaByIndex (ignoredIndex, oldSelectedArea) || (selectedArea != oldSelectedArea))
282
290
{
283
- if (!mDelegate ->GetSelectedAreaByIndex (ignoredIndex, oldSelectedArea) || (aSelectedArea != oldSelectedArea))
284
- {
285
- matchesCurrentSelectedAreas = false ;
286
- }
291
+ matchesCurrentSelectedAreas = false ;
287
292
}
288
-
289
- i += 1 ;
290
293
}
291
294
292
- // after iterating with Next through DecodableType - check for failure
293
- if (CHIP_NO_ERROR != iAreaIter.GetStatus ())
294
- {
295
- ctx.mCommandHandler .AddStatus (ctx.mRequestPath , Status::InvalidCommand);
296
- return ;
297
- }
295
+ selectedAreasSpan[numberOfSelectedAreas] = selectedArea;
296
+ numberOfSelectedAreas += 1 ;
297
+ }
298
+
299
+ // after iterating with Next through DecodableType - check for failure
300
+ if (CHIP_NO_ERROR != iAreaIter.GetStatus ())
301
+ {
302
+ ctx.mCommandHandler .AddStatus (ctx.mRequestPath , Status::InvalidCommand);
303
+ return ;
298
304
}
299
305
}
300
306
307
+ selectedAreasSpan.reduce_size (numberOfSelectedAreas);
308
+
301
309
// If the newAreas field is the same as the value of the SelectedAreas attribute
302
310
// the SelectAreasResponse command SHALL have the Status field set to Success and
303
311
// the StatusText field MAY be supplied with a human-readable string or include an empty string.
@@ -327,7 +335,7 @@ void Instance::HandleSelectAreasCmd(HandlerContext & ctx, const Commands::Select
327
335
// ask the device to handle SelectAreas Command
328
336
// (note - locationStatusText to be filled out by delegated function for kInvalidInMode and InvalidSet)
329
337
auto locationStatus = SelectAreasStatus::kSuccess ;
330
- if (!mDelegate ->IsValidSelectAreasSet (req , locationStatus, delegateStatusText))
338
+ if (!mDelegate ->IsValidSelectAreasSet (selectedAreasSpan , locationStatus, delegateStatusText))
331
339
{
332
340
exitResponse (locationStatus, delegateStatusText);
333
341
return ;
@@ -342,11 +350,10 @@ void Instance::HandleSelectAreasCmd(HandlerContext & ctx, const Commands::Select
342
350
343
351
if (numberOfAreas != 0 )
344
352
{
345
- auto locationIter = req.newAreas .begin ();
346
353
uint32_t ignored;
347
- while (locationIter. Next () )
354
+ for ( uint32_t areaId : selectedAreasSpan )
348
355
{
349
- mDelegate ->AddSelectedArea (locationIter. GetValue () , ignored);
356
+ mDelegate ->AddSelectedArea (areaId , ignored);
350
357
}
351
358
}
352
359
0 commit comments