Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2023 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #pragma once
20 :
21 : #include <stddef.h>
22 :
23 : #include <app/ConcreteCommandPath.h>
24 : #include <lib/core/CHIPError.h>
25 : #include <lib/core/Optional.h>
26 :
27 : #include <optional>
28 :
29 : namespace chip {
30 : namespace app {
31 :
32 : struct CommandPathRegistryEntry
33 : {
34 : ConcreteCommandPath requestPath = ConcreteCommandPath(0, 0, 0);
35 : std::optional<uint16_t> ref;
36 : };
37 :
38 : class CommandPathRegistry
39 : {
40 : public:
41 16 : virtual ~CommandPathRegistry() = default;
42 :
43 : virtual std::optional<CommandPathRegistryEntry> Find(const ConcreteCommandPath & requestPath) const = 0;
44 : virtual std::optional<CommandPathRegistryEntry> GetFirstEntry() const = 0;
45 : virtual CHIP_ERROR Add(const ConcreteCommandPath & requestPath, const std::optional<uint16_t> & ref) = 0;
46 : virtual size_t Count() const = 0;
47 : virtual size_t MaxSize() const = 0;
48 : };
49 :
50 : /**
51 : * @class BasicCommandPathRegistry
52 : *
53 : * @brief Allows looking up CommandRef using the requested ConcreteCommandPath.
54 : *
55 : * While there are faster implementations, right now batch commands are capped at a low number due to
56 : * message size constraints. All commands need to be contained within a single InvokeRequest. In
57 : * practice this is usually less than 60 commands (but could be much more with TCP transports or
58 : * newer transports).
59 : */
60 : template <size_t N>
61 : class BasicCommandPathRegistry : public CommandPathRegistry
62 : {
63 : public:
64 48 : std::optional<CommandPathRegistryEntry> Find(const ConcreteCommandPath & requestPath) const override
65 : {
66 48 : for (size_t i = 0; i < mCount; i++)
67 : {
68 47 : if (mTable[i].requestPath == requestPath)
69 : {
70 47 : return std::make_optional(mTable[i]);
71 : }
72 : }
73 1 : return std::nullopt;
74 : }
75 :
76 0 : std::optional<CommandPathRegistryEntry> GetFirstEntry() const override
77 : {
78 0 : if (mCount > 0)
79 : {
80 0 : return std::make_optional(mTable[0]);
81 : }
82 0 : return std::nullopt;
83 : }
84 :
85 40 : CHIP_ERROR Add(const ConcreteCommandPath & requestPath, const std::optional<uint16_t> & ref) override
86 : {
87 40 : if (mCount >= N)
88 : {
89 0 : return CHIP_ERROR_NO_MEMORY;
90 : }
91 40 : for (size_t i = 0; i < mCount; i++)
92 : {
93 0 : if (mTable[i].requestPath == requestPath)
94 : {
95 0 : return CHIP_ERROR_DUPLICATE_KEY_ID;
96 : }
97 : // No need to check if either has value. This is because if there is more than
98 : // 1 entry in the table expectation is to have all entirely unique ref values
99 : // so duplicate optional would mean we would want to error out.
100 0 : if (mTable[i].ref == ref)
101 : {
102 0 : return CHIP_ERROR_DUPLICATE_KEY_ID;
103 : }
104 : }
105 :
106 40 : mTable[mCount] = CommandPathRegistryEntry{ requestPath, ref };
107 40 : mCount++;
108 40 : return CHIP_NO_ERROR;
109 : }
110 :
111 0 : virtual size_t Count() const override { return mCount; }
112 0 : virtual size_t MaxSize() const override { return N; }
113 :
114 : private:
115 : size_t mCount = 0;
116 : CommandPathRegistryEntry mTable[N];
117 : };
118 :
119 : } // namespace app
120 : } // namespace chip
|