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/server-cluster/ServerClusterInterfaceRegistry.h>
20 :
21 : namespace chip {
22 : namespace app {
23 :
24 : /// This class specializes ServerClusterInterfaceRegistry to register ServerClusterInterface references
25 : /// that are limited to a single endpoint. In other words, GetPaths() must return path(s) in the same
26 : /// endpoint.
27 : /// The assumption that every ServerClusterInterface registered is limited to a single endpoint
28 : /// allows us to provide additional helper methods such as `ClustersOnEndpoint()` and `UnregisterAllFromEndpoint()`.
29 : class SingleEndpointServerClusterRegistry : public ServerClusterInterfaceRegistry
30 : {
31 : public:
32 : /// represents an iterable list of clusters
33 : class ClustersList
34 : {
35 : public:
36 : class Iterator
37 : {
38 : public:
39 35960 : Iterator(ServerClusterRegistration * interface, EndpointId endpoint) : mEndpointId(endpoint), mRegistration(interface)
40 : {
41 35960 : if (mRegistration != nullptr)
42 : {
43 16 : mSpan = interface->serverClusterInterface->GetPaths();
44 : }
45 35960 : AdvanceUntilMatchingEndpoint();
46 35960 : }
47 :
48 208 : Iterator & operator++()
49 : {
50 208 : if (!mSpan.empty())
51 : {
52 208 : mSpan = mSpan.SubSpan(1);
53 : }
54 208 : AdvanceUntilMatchingEndpoint();
55 208 : return *this;
56 : }
57 2 : bool operator==(const Iterator & other) const { return mRegistration == other.mRegistration; }
58 18184 : bool operator!=(const Iterator & other) const { return mRegistration != other.mRegistration; }
59 208 : ClusterId operator*() { return mSpan.begin()->mClusterId; }
60 :
61 : private:
62 : const EndpointId mEndpointId;
63 : ServerClusterRegistration * mRegistration;
64 : Span<const ConcreteClusterPath> mSpan;
65 :
66 36168 : void AdvanceUntilMatchingEndpoint()
67 : {
68 40373 : while (mRegistration != nullptr)
69 : {
70 4413 : if (mSpan.empty())
71 : {
72 2205 : mRegistration = mRegistration->next;
73 2205 : if (mRegistration != nullptr)
74 : {
75 2189 : mSpan = mRegistration->serverClusterInterface->GetPaths();
76 : }
77 2205 : continue;
78 : }
79 2208 : if (mSpan.begin()->mEndpointId == mEndpointId)
80 : {
81 208 : return;
82 : }
83 :
84 : // need to keep searching
85 2000 : mSpan = mSpan.SubSpan(1);
86 : }
87 : }
88 : };
89 :
90 17978 : constexpr ClustersList(ServerClusterRegistration * start, EndpointId endpointId) : mEndpointId(endpointId), mStart(start) {}
91 17978 : Iterator begin() { return { mStart, mEndpointId }; }
92 17982 : Iterator end() { return { nullptr, mEndpointId }; }
93 :
94 : private:
95 : const EndpointId mEndpointId;
96 : ServerClusterRegistration * mStart;
97 : };
98 :
99 180 : ~SingleEndpointServerClusterRegistry() = default;
100 :
101 : /// Add the given entry to the registry.
102 : /// NOTE the requirement of entries to be part of the same endpoint.
103 : ///
104 : /// Requirements:
105 : /// - entry MUST NOT be part of any other registration
106 : /// - paths MUST be part of the same endpoint
107 : ///
108 : /// - LIFETIME of entry must outlive the Registry (or entry must be unregistered)
109 : ///
110 : /// There can be only a single registration for a given `endpointId/clusterId` path.
111 : [[nodiscard]] CHIP_ERROR Register(ServerClusterRegistration & entry);
112 :
113 : /// Provides a list of clusters that are registered for the given endpoint.
114 : ///
115 : /// ClustersList points inside the internal registrations of the registry, so
116 : /// the list is only valid as long as the registry is not modified.
117 : ClustersList ClustersOnEndpoint(EndpointId endpointId);
118 :
119 : /// Unregister all registrations for the given endpoint.
120 : void UnregisterAllFromEndpoint(EndpointId endpointId);
121 : };
122 :
123 : } // namespace app
124 : } // namespace chip
|