Line data Source code
1 : /*
2 : * Copyright (c) 2025 Project CHIP Authors
3 : *
4 : * Licensed under the Apache License, Version 2.0 (the "License");
5 : * you may not use this file except in compliance with the License.
6 : * You may obtain a copy of the License at
7 : *
8 : * http://www.apache.org/licenses/LICENSE-2.0
9 : *
10 : * Unless required by applicable law or agreed to in writing, software
11 : * distributed under the License is distributed on an "AS IS" BASIS,
12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 : * See the License for the specific language governing permissions and
14 : * limitations under the License.
15 : */
16 : #pragma once
17 :
18 : #include <app/AttributeValueDecoder.h>
19 : #include <app/ConcreteAttributePath.h>
20 : #include <app/data-model-provider/ActionReturnStatus.h>
21 : #include <app/persistence/AttributePersistenceProvider.h>
22 : #include <app/persistence/String.h>
23 :
24 : #include <type_traits>
25 :
26 : namespace chip::app {
27 :
28 : /// Provides functionality for handling attribute persistence via
29 : /// an AttributePersistenceProvider.
30 : ///
31 : /// AttributePersistenceProvider works with raw bytes, however attributes
32 : /// have known (strong) types and their load/decode logic is often
33 : /// similar and reusable. This class implements the logic of handling
34 : /// such attributes, so that it can be reused across cluster implementations.
35 : class AttributePersistence
36 : {
37 : public:
38 4 : AttributePersistence(AttributePersistenceProvider & provider) : mProvider(provider) {}
39 :
40 : /// Loads a native-endianness stored value of type `T` into `value` from the persistence provider.
41 : ///
42 : /// If load fails, `false` is returned and data is filled with `valueOnLoadFailure`.
43 : ///
44 : /// Error reason for load failure is logged (or nothing logged in case "Value not found" is the
45 : /// reason for the load failure).
46 : template <typename T, typename std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
47 6 : bool LoadNativeEndianValue(const ConcreteAttributePath & path, T & value, const T & valueOnLoadFailure)
48 : {
49 6 : return InternalRawLoadNativeEndianValue(path, &value, &valueOnLoadFailure, sizeof(T));
50 : }
51 :
52 : /// Performs all the steps of:
53 : /// - decode the given raw data
54 : /// - write to storage
55 : template <typename T, typename std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
56 1 : CHIP_ERROR DecodeAndStoreNativeEndianValue(const ConcreteAttributePath & path, AttributeValueDecoder & decoder, T & value)
57 : {
58 1 : ReturnErrorOnFailure(decoder.Decode(value));
59 1 : return mProvider.WriteValue(path, { reinterpret_cast<const uint8_t *>(&value), sizeof(value) });
60 : }
61 :
62 : /// Load the given string from concrete storage.
63 : ///
64 : /// NOTE: `value` is take as an internal short string to avoid the templates that Storage::String
65 : /// implies, however callers are generally expected to pass in a `Storage::String` value and
66 : /// not use internal classes directly.
67 : ///
68 : /// Returns true on success, false on failure. On failure the string is reset to empty.
69 : bool LoadString(const ConcreteAttributePath & path, Storage::Internal::ShortString & value);
70 :
71 : /// Store the given string in persistent storage.
72 : ///
73 : /// NOTE: `value` is take as an internal short string to avoid the templates that Storage::String
74 : /// implies, however callers are generally expected to pass in a `Storage::String` value and
75 : /// not use internal classes directly.
76 : CHIP_ERROR StoreString(const ConcreteAttributePath & path, const Storage::Internal::ShortString & value);
77 :
78 : private:
79 : AttributePersistenceProvider & mProvider;
80 :
81 : /// Loads a raw value of size `size` into the memory pointed to by `data`.
82 : /// If load fails, `false` is returned and data is filled with `valueOnLoadFailure`.
83 : ///
84 : /// Error reason for load failure is logged (or nothing logged in case "Value not found" is the
85 : /// reason for the load failure).
86 : bool InternalRawLoadNativeEndianValue(const ConcreteAttributePath & path, void * data, const void * valueOnLoadFailure,
87 : size_t size);
88 : };
89 :
90 : } // namespace chip::app
|