Matter SDK Coverage Report
Current view: top level - app - AttributeAccessInterfaceRegistry.cpp (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 98.0 % 50 49
Test Date: 2025-01-17 19:00:11 Functions: 100.0 % 9 9

            Line data    Source code
       1              : /**
       2              :  *    Copyright (c) 2024 Project CHIP Authors
       3              :  *
       4              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       5              :  *    you may not use this file except in compliance with the License.
       6              :  *    You may obtain a copy of the License at
       7              :  *
       8              :  *        http://www.apache.org/licenses/LICENSE-2.0
       9              :  *
      10              :  *    Unless required by applicable law or agreed to in writing, software
      11              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      12              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13              :  *    See the License for the specific language governing permissions and
      14              :  *    limitations under the License.
      15              :  */
      16              : #include "app/AttributeAccessInterface.h"
      17              : #include <app/AttributeAccessInterfaceRegistry.h>
      18              : 
      19              : #include <app/AttributeAccessInterfaceCache.h>
      20              : 
      21              : namespace {
      22              : 
      23              : using chip::app::AttributeAccessInterface;
      24              : 
      25              : // shouldUnregister returns true if the given AttributeAccessInterface should be
      26              : // unregistered.
      27              : template <typename F>
      28           31 : void UnregisterMatchingAttributeAccessInterfaces(F shouldUnregister, AttributeAccessInterface *& list_head)
      29              : {
      30           31 :     AttributeAccessInterface * prev = nullptr;
      31           31 :     AttributeAccessInterface * cur  = list_head;
      32           54 :     while (cur)
      33              :     {
      34           23 :         AttributeAccessInterface * next = cur->GetNext();
      35           23 :         if (shouldUnregister(cur))
      36              :         {
      37              :             // Remove it from the list
      38            8 :             if (prev)
      39              :             {
      40            0 :                 prev->SetNext(next);
      41              :             }
      42              :             else
      43              :             {
      44            8 :                 list_head = next;
      45              :             }
      46              : 
      47            8 :             cur->SetNext(nullptr);
      48              : 
      49              :             // Do not change prev in this case.
      50              :         }
      51              :         else
      52              :         {
      53           15 :             prev = cur;
      54              :         }
      55           23 :         cur = next;
      56              :     }
      57           31 : }
      58              : 
      59              : } // namespace
      60              : 
      61              : namespace chip {
      62              : namespace app {
      63              : 
      64         5244 : AttributeAccessInterfaceRegistry & AttributeAccessInterfaceRegistry::Instance()
      65              : {
      66         5244 :     static AttributeAccessInterfaceRegistry instance;
      67         5244 :     return instance;
      68              : }
      69              : 
      70            8 : void AttributeAccessInterfaceRegistry::Unregister(AttributeAccessInterface * attrOverride)
      71              : {
      72            8 :     mAttributeAccessInterfaceCache.Invalidate();
      73            8 :     UnregisterMatchingAttributeAccessInterfaces([attrOverride](AttributeAccessInterface * entry) { return entry == attrOverride; },
      74            8 :                                                 mAttributeAccessOverrides);
      75            8 : }
      76              : 
      77           23 : void AttributeAccessInterfaceRegistry::UnregisterAllForEndpoint(EndpointId endpointId)
      78              : {
      79           23 :     mAttributeAccessInterfaceCache.Invalidate();
      80           23 :     UnregisterMatchingAttributeAccessInterfaces(
      81           38 :         [endpointId](AttributeAccessInterface * entry) { return entry->MatchesEndpoint(endpointId); }, mAttributeAccessOverrides);
      82           23 : }
      83              : 
      84           15 : bool AttributeAccessInterfaceRegistry::Register(AttributeAccessInterface * attrOverride)
      85              : {
      86           15 :     mAttributeAccessInterfaceCache.Invalidate();
      87           15 :     for (auto * cur = mAttributeAccessOverrides; cur; cur = cur->GetNext())
      88              :     {
      89            4 :         if (cur->Matches(*attrOverride))
      90              :         {
      91            4 :             ChipLogError(InteractionModel, "Duplicate attribute override registration failed");
      92            4 :             return false;
      93              :         }
      94              :     }
      95           11 :     attrOverride->SetNext(mAttributeAccessOverrides);
      96           11 :     mAttributeAccessOverrides = attrOverride;
      97           11 :     return true;
      98              : }
      99              : 
     100         5198 : AttributeAccessInterface * AttributeAccessInterfaceRegistry::Get(EndpointId endpointId, ClusterId clusterId)
     101              : {
     102              :     using CacheResult = AttributeAccessInterfaceCache::CacheResult;
     103              : 
     104         5198 :     AttributeAccessInterface * cached = nullptr;
     105         5198 :     CacheResult result                = mAttributeAccessInterfaceCache.Get(endpointId, clusterId, &cached);
     106         5198 :     switch (result)
     107              :     {
     108          179 :     case CacheResult::kDefinitelyUnused:
     109          179 :         return nullptr;
     110         4989 :     case CacheResult::kDefinitelyUsed:
     111         4989 :         return cached;
     112           30 :     case CacheResult::kCacheMiss:
     113              :     default:
     114              :         // Did not cache yet, search set of AAI registered, and cache if found.
     115           30 :         for (app::AttributeAccessInterface * cur = mAttributeAccessOverrides; cur; cur = cur->GetNext())
     116              :         {
     117           25 :             if (cur->Matches(endpointId, clusterId))
     118              :             {
     119           25 :                 mAttributeAccessInterfaceCache.MarkUsed(endpointId, clusterId, cur);
     120           25 :                 return cur;
     121              :             }
     122              :         }
     123              : 
     124              :         // Did not find AAI registered: mark as definitely not using.
     125            5 :         mAttributeAccessInterfaceCache.MarkUnused(endpointId, clusterId);
     126              :     }
     127              : 
     128            5 :     return nullptr;
     129              : }
     130              : 
     131              : } // namespace app
     132              : } // namespace chip
        

Generated by: LCOV version 2.0-1