• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef META_API_PROPERTY_ARRAY_PROPERTY_CHANGES_RECOGNIZER_H
17 #define META_API_PROPERTY_ARRAY_PROPERTY_CHANGES_RECOGNIZER_H
18 
19 #include <base/containers/unordered_map.h>
20 
21 #include <meta/base/algorithms.h>
22 #include <meta/interface/property/array_property.h>
23 
24 META_BEGIN_NAMESPACE()
25 
26 template<typename ValueType>
27 struct AddedValue {
28     ValueType value;
29     int index = 0;
30 
31     bool operator==(const AddedValue& v) const
32     {
33         return value == v.value && index == v.index;
34     }
35 };
36 
37 struct IndexChange {
38     int previousIndex = 0;
39     int newIndex = 0;
40 
41     bool operator==(const IndexChange& v) const
42     {
43         return previousIndex == v.previousIndex && newIndex == v.newIndex;
44     }
45 };
46 
47 template<typename ValueType>
48 struct ArrayChanges {
49     BASE_NS::vector<size_t> indexesRemoved;
50     BASE_NS::vector<AddedValue<ValueType>> valuesAdded;
51     BASE_NS::vector<IndexChange> positionChanged;
52 };
53 
54 /// Helper to keep track of array property changes
55 template<typename ValueType>
56 class ArrayPropertyChangesRecognizer {
57 public:
58     ArrayPropertyChangesRecognizer() = default;
59 
SetValue(const META_NS::ArrayProperty<ValueType> & arrayProperty)60     void SetValue(const META_NS::ArrayProperty<ValueType>& arrayProperty)
61     {
62         previousValues_ = arrayProperty->GetValue();
63     }
64 
Clear()65     void Clear()
66     {
67         previousValues_.clear();
68     }
69 
OnArrayPropertyChanged(const META_NS::ArrayProperty<ValueType> & arrayProperty)70     ArrayChanges<ValueType> OnArrayPropertyChanged(const META_NS::ArrayProperty<ValueType>& arrayProperty)
71     {
72         auto newValuesVector = arrayProperty->GetValue();
73         auto changes = ArrayChanges<ValueType>();
74 
75         { // check for removes
76             BASE_NS::unordered_map<ValueType, size_t> prev;
77             for (size_t oldIndex = 0; oldIndex != previousValues_.size(); ++oldIndex) {
78                 auto& v = previousValues_[oldIndex];
79                 if (auto p = FindFirstOf(newValuesVector, v, prev[v]); p != NPOS) {
80                     prev[v] = p + 1;
81                 } else {
82                     changes.indexesRemoved.push_back(static_cast<int>(oldIndex));
83                 }
84             }
85         }
86 
87         { // check for modifications and additions
88             BASE_NS::unordered_map<ValueType, size_t> prev;
89             for (size_t newIndex = 0; newIndex < newValuesVector.size(); ++newIndex) {
90                 auto& v = newValuesVector[newIndex];
91                 if (auto p = FindFirstOf(previousValues_, v, prev[v]); p != NPOS) {
92                     prev[v] = p + 1;
93                     if (p != newIndex) {
94                         changes.positionChanged.push_back({ static_cast<int>(p), static_cast<int>(newIndex) });
95                     }
96                 } else {
97                     changes.valuesAdded.push_back({ v, static_cast<int>(newIndex) });
98                 }
99             }
100         }
101 
102         previousValues_ = BASE_NS::move(newValuesVector);
103 
104         return changes;
105     }
106 
107 private:
108     BASE_NS::vector<ValueType> previousValues_;
109 };
110 
111 META_END_NAMESPACE()
112 
113 #endif
114