Matter SDK Coverage Report
Current view: top level - data-model-providers/codegen - ServerClusterInterfaceRegistry.h (source / functions) Coverage Total Hit
Test: SHA:4cbce7f768f16e614f5a8ccb8cd93c92cbeae70d Lines: 100.0 % 25 25
Test Date: 2025-04-26 07:09:35 Functions: 100.0 % 8 8

            Line data    Source code
       1              : /*
       2              :  *    Copyright (c) 2025 Project CHIP Authors
       3              :  *    All rights reserved.
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : #pragma once
      18              : 
      19              : #include <app/ConcreteClusterPath.h>
      20              : #include <app/server-cluster/ServerClusterInterface.h>
      21              : #include <lib/core/CHIPError.h>
      22              : #include <lib/core/DataModelTypes.h>
      23              : 
      24              : #include <iterator>
      25              : 
      26              : namespace chip {
      27              : namespace app {
      28              : 
      29              : /// Represents an entry in the server cluster interface registry for
      30              : /// a specific interface.
      31              : ///
      32              : /// In practice this is a single-linked list element.
      33              : struct ServerClusterRegistration
      34              : {
      35              :     // A single-linked list of clusters registered for the given `endpointId`
      36              :     ServerClusterInterface * const serverClusterInterface;
      37              :     ServerClusterRegistration * next;
      38              : 
      39              :     constexpr ServerClusterRegistration(ServerClusterInterface & interface, ServerClusterRegistration * next_item = nullptr) :
      40              :         serverClusterInterface(&interface), next(next_item)
      41              :     {}
      42              :     ServerClusterRegistration(ServerClusterRegistration && other) = default;
      43              : 
      44              :     // we generally do not want to allow copies as those may have different "next" entries.
      45              :     ServerClusterRegistration(const ServerClusterRegistration & other)             = delete;
      46              :     ServerClusterRegistration & operator=(const ServerClusterRegistration & other) = delete;
      47              : };
      48              : 
      49              : /// Allows registering and retrieving ServerClusterInterface instances for specific cluster paths.
      50              : class ServerClusterInterfaceRegistry
      51              : {
      52              : public:
      53              :     /// represents an iterable list of clusters
      54              :     class ClustersList
      55              :     {
      56              :     public:
      57              :         class Iterator
      58              :         {
      59              :         public:
      60        33844 :             Iterator(ServerClusterRegistration * interface, EndpointId endpoint) : mEndpointId(endpoint), mRegistration(interface)
      61              :             {
      62        33844 :                 if (mRegistration != nullptr)
      63              :                 {
      64           14 :                     mSpan = interface->serverClusterInterface->GetPaths();
      65              :                 }
      66        33844 :                 AdvanceUntilMatchingEndpoint();
      67        33844 :             }
      68              : 
      69          206 :             Iterator & operator++()
      70              :             {
      71          206 :                 if (!mSpan.empty())
      72              :                 {
      73          206 :                     mSpan = mSpan.SubSpan(1);
      74              :                 }
      75          206 :                 AdvanceUntilMatchingEndpoint();
      76          206 :                 return *this;
      77              :             }
      78              :             bool operator==(const Iterator & other) const { return mRegistration == other.mRegistration; }
      79        17124 :             bool operator!=(const Iterator & other) const { return mRegistration != other.mRegistration; }
      80          206 :             ClusterId operator*() { return mSpan.begin()->mClusterId; }
      81              : 
      82              :         private:
      83              :             const EndpointId mEndpointId;
      84              :             ServerClusterRegistration * mRegistration;
      85              :             Span<const ConcreteClusterPath> mSpan;
      86              : 
      87        34050 :             void AdvanceUntilMatchingEndpoint()
      88              :             {
      89        38253 :                 while (mRegistration != nullptr)
      90              :                 {
      91         4409 :                     if (mSpan.empty())
      92              :                     {
      93         2203 :                         mRegistration = mRegistration->next;
      94         2203 :                         if (mRegistration != nullptr)
      95              :                         {
      96         2189 :                             mSpan = mRegistration->serverClusterInterface->GetPaths();
      97              :                         }
      98         2203 :                         continue;
      99              :                     }
     100         2206 :                     if (mSpan.begin()->mEndpointId == mEndpointId)
     101              :                     {
     102          206 :                         return;
     103              :                     }
     104              : 
     105              :                     // need to keep searching
     106         2000 :                     mSpan = mSpan.SubSpan(1);
     107              :                 }
     108              :             }
     109              :         };
     110              : 
     111        16920 :         constexpr ClustersList(ServerClusterRegistration * start, EndpointId endpointId) : mEndpointId(endpointId), mStart(start) {}
     112        16920 :         Iterator begin() { return { mStart, mEndpointId }; }
     113        16924 :         Iterator end() { return { nullptr, mEndpointId }; }
     114              : 
     115              :     private:
     116              :         const EndpointId mEndpointId;
     117              :         ServerClusterRegistration * mStart;
     118              :     };
     119              : 
     120              :     ~ServerClusterInterfaceRegistry();
     121              : 
     122              :     /// Add the given entry to the registry.
     123              :     /// NOTE the requirement of entries to be part of the same endpoint.
     124              :     ///
     125              :     /// Requirements:
     126              :     ///   - entry MUST NOT be part of any other registration
     127              :     ///   - paths MUST be part of the same endpoint (requirement for codegen server cluster interface implementations)
     128              :     ///   - LIFETIME of entry must outlive the Registry (or entry must be unregistered)
     129              :     ///
     130              :     /// There can be only a single registration for a given `endpointId/clusterId` path.
     131              :     [[nodiscard]] CHIP_ERROR Register(ServerClusterRegistration & entry);
     132              : 
     133              :     /// Remove an existing registration
     134              :     ///
     135              :     /// Will return CHIP_ERROR_NOT_FOUND if the given registration is not found.
     136              :     CHIP_ERROR Unregister(ServerClusterInterface *);
     137              : 
     138              :     /// Return the interface registered for the given cluster path or nullptr if one does not exist
     139              :     ServerClusterInterface * Get(const ConcreteClusterPath & path);
     140              : 
     141              :     /// Provides a list of clusters that are registered for the given endpoint.
     142              :     ///
     143              :     /// ClustersList points inside the internal registrations of the registry, so
     144              :     /// the list is only valid as long as the registry is not modified.
     145              :     ClustersList ClustersOnEndpoint(EndpointId endpointId);
     146              : 
     147              :     /// Unregister all registrations for the given endpoint.
     148              :     void UnregisterAllFromEndpoint(EndpointId endpointId);
     149              : 
     150              :     // Set up the underlying context for all clusters that are managed by this registry.
     151              :     //
     152              :     // The values within context will be copied and used.
     153              :     CHIP_ERROR SetContext(ServerClusterContext && context);
     154              : 
     155              :     // Invalidates current context.
     156              :     void ClearContext();
     157              : 
     158              : private:
     159              :     ServerClusterRegistration * mRegistrations = nullptr;
     160              : 
     161              :     // A one-element cache to speed up finding a cluster within an endpoint.
     162              :     // The endpointId specifies which endpoint the cache belongs to.
     163              :     ServerClusterInterface * mCachedInterface = nullptr;
     164              : 
     165              :     // Managing context for this registry
     166              :     std::optional<ServerClusterContext> mContext;
     167              : };
     168              : 
     169              : } // namespace app
     170              : } // namespace chip
        

Generated by: LCOV version 2.0-1