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 : EndpointInterfaceRegistration * next;
41 :
42 112 : constexpr EndpointInterfaceRegistration(EndpointInterface & interface, EndpointInterfaceRegistration * next_item = nullptr) :
43 112 : endpointInterface(&interface), next(next_item)
44 112 : {}
45 : EndpointInterfaceRegistration(EndpointInterfaceRegistration && other) = default;
46 :
47 : EndpointInterfaceRegistration(const EndpointInterfaceRegistration & other) = delete;
48 : EndpointInterfaceRegistration & operator=(const EndpointInterfaceRegistration & other) = delete;
49 : };
50 :
51 : /**
52 : * @brief Manages a collection of EndpointInterface instances.
53 : *
54 : * The EndpointInterfaceRegistry can be used to discover and interact programmatically
55 : * with Matter endpoints. It maintains a linked list of EndpointInterfaceRegistration
56 : * objects.
57 : *
58 : * Responsibilities:
59 : * - Allows registration and unregistration of endpoints.
60 : * - Provides a way to retrieve a specific endpoint by its EndpointId.
61 : * - Offers an iterator to traverse all registered endpoints.
62 : *
63 : * Lifetime Management:
64 : * - The registry stores raw pointers to EndpointInterface and EndpointInterfaceRegistration objects.
65 : * - It does NOT take ownership of these objects.
66 : * - Callers MUST ensure that any registered EndpointInterface and its corresponding
67 : * EndpointInterfaceRegistration object outlive the EndpointInterfaceRegistry or are unregistered
68 : * before being destroyed.
69 : */
70 : class EndpointInterfaceRegistry
71 : {
72 : public:
73 : class Iterator
74 : {
75 : public:
76 4 : explicit Iterator(EndpointInterfaceRegistration * registration) : mCurrent(registration) {}
77 :
78 2 : Iterator & operator++()
79 : {
80 2 : mCurrent = (mCurrent ? mCurrent->next : nullptr);
81 2 : return *this;
82 : }
83 1 : bool operator==(const Iterator & other) const { return mCurrent == other.mCurrent; }
84 3 : bool operator!=(const Iterator & other) const { return mCurrent != other.mCurrent; }
85 2 : EndpointInterface * operator*() { return mCurrent->endpointInterface; }
86 : EndpointInterface * operator->() { return mCurrent->endpointInterface; }
87 :
88 : private:
89 : EndpointInterfaceRegistration * mCurrent;
90 : };
91 :
92 : /**
93 : * @brief Registers an endpoint.
94 : *
95 : * The provided `entry` (EndpointInterfaceRegistration) must not already be part of another list
96 : * (i.e., `entry.next` must be nullptr). The EndpointInterface within the entry must
97 : * be valid and have a valid EndpointId.
98 : *
99 : * @param entry The EndpointInterfaceRegistration containing the provider to register.
100 : * The lifetime of this object must be managed by the caller.
101 : * @return CHIP_NO_ERROR on success.
102 : * CHIP_ERROR_INVALID_ARGUMENT if entry.next is not nullptr,
103 : * entry.endpointInterface is nullptr,
104 : * or the endpoint ID is kInvalidEndpointId.
105 : * CHIP_ERROR_DUPLICATE_KEY_ID if an endpoint with the same ID is already registered.
106 : */
107 : CHIP_ERROR Register(EndpointInterfaceRegistration & entry);
108 :
109 : /**
110 : * @brief Unregisters an endpoint with the given EndpointId.
111 : *
112 : * @note This method does not guarantee that iterators will remain valid after this call.
113 : * If you are iterating over the registry, you should NOT call this method.
114 : *
115 : * @param endpointId The ID of the endpoint to unregister.
116 : * @return CHIP_NO_ERROR on success. It is not considered an error to
117 : * unregister a provider that is not found.
118 : * CHIP_ERROR_INVALID_ARGUMENT if endpointId is kInvalidEndpointId.
119 : */
120 : CHIP_ERROR Unregister(EndpointId endpointId);
121 :
122 : /** @return A pointer to the EndpointInterface for the given endpointId, or nullptr if not found. */
123 : EndpointInterface * Get(EndpointId endpointId);
124 2 : Iterator begin() { return Iterator(mRegistrations); }
125 2 : Iterator end() { return Iterator(nullptr); }
126 :
127 : private:
128 : EndpointInterfaceRegistration * mRegistrations = nullptr;
129 : EndpointInterface * mCachedInterface = nullptr;
130 : EndpointId mCachedEndpointId = kInvalidEndpointId;
131 : };
132 :
133 : } // namespace app
134 : } // namespace chip
|