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 : namespace chip { 28 : namespace app { 29 : 30 : struct CommandPathRegistryEntry 31 : { 32 : ConcreteCommandPath requestPath = ConcreteCommandPath(0, 0, 0); 33 : Optional<uint16_t> ref; 34 : }; 35 : 36 : class CommandPathRegistry 37 : { 38 : public: 39 16 : virtual ~CommandPathRegistry() = default; 40 : 41 : virtual Optional<CommandPathRegistryEntry> Find(const ConcreteCommandPath & requestPath) const = 0; 42 : virtual Optional<CommandPathRegistryEntry> GetFirstEntry() const = 0; 43 : virtual CHIP_ERROR Add(const ConcreteCommandPath & requestPath, const Optional<uint16_t> & ref) = 0; 44 : virtual size_t Count() const = 0; 45 : virtual size_t MaxSize() const = 0; 46 : }; 47 : 48 : /** 49 : * @class BasicCommandPathRegistry 50 : * 51 : * @brief Allows looking up CommandRef using the requested ConcreteCommandPath. 52 : * 53 : * While there are faster implementations, right now batch commands are capped at a low number due to 54 : * message size constraints. All commands need to be contained within a single InvokeRequest. In 55 : * practice this is usually less than 60 commands (but could be much more with TCP transports or 56 : * newer transports). 57 : */ 58 : template <size_t N> 59 : class BasicCommandPathRegistry : public CommandPathRegistry 60 : { 61 : public: 62 22 : Optional<CommandPathRegistryEntry> Find(const ConcreteCommandPath & requestPath) const override 63 : { 64 22 : for (size_t i = 0; i < mCount; i++) 65 : { 66 22 : if (mTable[i].requestPath == requestPath) 67 : { 68 22 : return MakeOptional(mTable[i]); 69 : } 70 : } 71 0 : return NullOptional; 72 : } 73 : 74 0 : Optional<CommandPathRegistryEntry> GetFirstEntry() const override 75 : { 76 0 : if (mCount > 0) 77 : { 78 0 : return MakeOptional(mTable[0]); 79 : } 80 0 : return NullOptional; 81 : } 82 : 83 15 : CHIP_ERROR Add(const ConcreteCommandPath & requestPath, const Optional<uint16_t> & ref) override 84 : { 85 15 : if (mCount >= N) 86 : { 87 0 : return CHIP_ERROR_NO_MEMORY; 88 : } 89 15 : for (size_t i = 0; i < mCount; i++) 90 : { 91 0 : if (mTable[i].requestPath == requestPath) 92 : { 93 0 : return CHIP_ERROR_DUPLICATE_KEY_ID; 94 : } 95 : // No need to check if either has value. This is because if there is more than 96 : // 1 entry in the table expectation is to have all entirely unique ref values 97 : // so duplicate optional would mean we would want to error out. 98 0 : if (mTable[i].ref == ref) 99 : { 100 0 : return CHIP_ERROR_DUPLICATE_KEY_ID; 101 : } 102 : } 103 : 104 15 : mTable[mCount] = CommandPathRegistryEntry{ requestPath, ref }; 105 15 : mCount++; 106 15 : return CHIP_NO_ERROR; 107 : } 108 : 109 0 : virtual size_t Count() const override { return mCount; } 110 0 : virtual size_t MaxSize() const override { return N; } 111 : 112 : private: 113 : size_t mCount = 0; 114 : CommandPathRegistryEntry mTable[N]; 115 : }; 116 : 117 : } // namespace app 118 : } // namespace chip