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/data-model-provider/MetadataTypes.h>
20 : #include <data-model-providers/codedriven/endpoint/EndpointInterface.h>
21 : #include <lib/core/CHIPError.h>
22 : #include <lib/support/CodeUtils.h>
23 :
24 : namespace chip {
25 : namespace app {
26 :
27 : /**
28 : * @brief Represents a registration entry for an EndpointInterface within the EndpointInterfaceRegistry.
29 : *
30 : * This struct acts as a node in a singly-linked list used by the EndpointInterfaceRegistry.
31 : * It contains a pointer to the actual EndpointInterface and a pointer to the next
32 : * registration in the list.
33 : *
34 : * Callers are responsible for ensuring that both this registration object and the
35 : * EndpointInterface it points to outlive their registration with the EndpointInterfaceRegistry.
36 : */
37 : struct EndpointInterfaceRegistration
38 : {
39 : EndpointInterface * const endpointInterface;
40 : DataModel::EndpointEntry endpointEntry;
41 : EndpointInterfaceRegistration * next;
42 :
43 155 : EndpointInterfaceRegistration(EndpointInterface & interface, DataModel::EndpointEntry entry,
44 155 : EndpointInterfaceRegistration * next_item = nullptr) :
45 155 : endpointInterface(&interface),
46 155 : endpointEntry(entry), next(next_item)
47 155 : {}
48 : EndpointInterfaceRegistration(EndpointInterfaceRegistration && other) = default;
49 :
50 : EndpointInterfaceRegistration(const EndpointInterfaceRegistration & other) = delete;
51 : EndpointInterfaceRegistration & operator=(const EndpointInterfaceRegistration & other) = delete;
52 :
53 38 : DataModel::EndpointEntry GetEndpointEntry() const { return endpointEntry; }
54 : };
55 :
56 : /**
57 : * @brief Manages a collection of EndpointInterface instances.
58 : *
59 : * The EndpointInterfaceRegistry can be used to discover and interact programmatically
60 : * with Matter endpoints. It maintains a linked list of EndpointInterfaceRegistration
61 : * objects.
62 : *
63 : * Responsibilities:
64 : * - Allows registration and unregistration of endpoints.
65 : * - Provides a way to retrieve a specific endpoint by its EndpointId.
66 : * - Offers an iterator to traverse all registered endpoints.
67 : *
68 : * Lifetime Management:
69 : * - The registry stores raw pointers to EndpointInterface and EndpointInterfaceRegistration objects.
70 : * - It does NOT take ownership of these objects.
71 : * - Callers MUST ensure that any registered EndpointInterface and its corresponding
72 : * EndpointInterfaceRegistration object outlive the EndpointInterfaceRegistry or are unregistered
73 : * before being destroyed.
74 : */
75 : class EndpointInterfaceRegistry
76 : {
77 : public:
78 : class Iterator
79 : {
80 : public:
81 213 : explicit Iterator(EndpointInterfaceRegistration * registration) : mCurrent(registration) {}
82 :
83 12 : Iterator & operator++()
84 : {
85 12 : mCurrent = (mCurrent ? mCurrent->next : nullptr);
86 12 : return *this;
87 : }
88 1 : bool operator==(const Iterator & other) const { return mCurrent == other.mCurrent; }
89 101 : bool operator!=(const Iterator & other) const { return mCurrent != other.mCurrent; }
90 12 : EndpointInterfaceRegistration & operator*() { return *mCurrent; }
91 33 : EndpointInterfaceRegistration * operator->() { return mCurrent; }
92 :
93 : private:
94 : EndpointInterfaceRegistration * mCurrent;
95 : };
96 :
97 : /**
98 : * @brief Registers an endpoint.
99 : *
100 : * The provided `entry` (EndpointInterfaceRegistration) must not already be part of another list
101 : * (i.e., `entry.next` must be nullptr). The EndpointInterface within the entry must
102 : * be valid and have a valid EndpointId.
103 : *
104 : * @param entry The EndpointInterfaceRegistration containing the provider to register.
105 : * The lifetime of this object must be managed by the caller.
106 : * @return CHIP_NO_ERROR on success.
107 : * CHIP_ERROR_INVALID_ARGUMENT if entry.next is not nullptr,
108 : * entry.endpointInterface is nullptr,
109 : * or the endpoint ID is kInvalidEndpointId.
110 : * CHIP_ERROR_DUPLICATE_KEY_ID if an endpoint with the same ID is already registered.
111 : */
112 : CHIP_ERROR Register(EndpointInterfaceRegistration & entry);
113 :
114 : /**
115 : * @brief Unregisters an endpoint with the given EndpointId.
116 : *
117 : * @note This method does not guarantee that iterators will remain valid after this call.
118 : * If you are iterating over the registry, you should NOT call this method.
119 : *
120 : * @param endpointId The ID of the endpoint to unregister.
121 : * @return CHIP_NO_ERROR on success.
122 : * CHIP_ERROR_NOT_FOUND if no endpoint with the given ID is registered.
123 : * CHIP_ERROR_INVALID_ARGUMENT if endpointId is kInvalidEndpointId.
124 : */
125 : CHIP_ERROR Unregister(EndpointId endpointId);
126 :
127 : /** @return A pointer to the EndpointInterface for the given endpointId, or nullptr if not found. */
128 : EndpointInterface * Get(EndpointId endpointId);
129 123 : Iterator begin() { return Iterator(mRegistrations); }
130 90 : Iterator end() { return Iterator(nullptr); }
131 :
132 : private:
133 : EndpointInterfaceRegistration * mRegistrations = nullptr;
134 : EndpointInterface * mCachedInterface = nullptr;
135 : EndpointId mCachedEndpointId = kInvalidEndpointId;
136 : };
137 :
138 : } // namespace app
139 : } // namespace chip
|