• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 #include "PropertyTools/property_data.h"
17 
18 #include <algorithm>
19 
20 #include <base/containers/allocator.h>
21 #include <core/log.h>
22 #include <core/property/intf_property_api.h>
23 
24 using namespace CORE_NS;
25 using BASE_NS::array_view;
26 using BASE_NS::FNV1aHash;
27 using BASE_NS::string;
28 using BASE_NS::string_view;
29 using BASE_NS::vector;
30 
31 namespace {
32 PropertyData::PropertyOffset FindProperty(
33     array_view<const Property> properties, const string_view name, const uintptr_t baseOffset);
34 
FindPropertyMember(const Property & property,const string_view name,const uintptr_t baseOffset)35 PropertyData::PropertyOffset FindPropertyMember(
36     const Property& property, const string_view name, const uintptr_t baseOffset)
37 {
38     PropertyData::PropertyOffset ret = FindProperty(property.metaData.memberProperties, name, baseOffset);
39     if (ret) {
40         ret.offset += property.offset;
41     }
42     return ret;
43 }
44 
FindProperty(array_view<const Property> properties,const string_view name,const uintptr_t baseOffset)45 PropertyData::PropertyOffset FindProperty(
46     array_view<const Property> properties, const string_view name, const uintptr_t baseOffset)
47 {
48     PropertyData::PropertyOffset ret { nullptr, 0U, 0U };
49     // trim down to name without array index or member variable.
50     constexpr string_view delimiters = ".[";
51     const auto delimPos = name.find_first_of(delimiters);
52     auto property = std::find_if(properties.begin(), properties.end(),
53         [baseName = name.substr(0, delimPos)](const Property& p) { return p.name == baseName; });
54     if (property != properties.end()) {
55         // if we have only a name we are done
56         if (delimPos == string_view::npos) {
57             ret.property = &*property;
58             ret.offset += property->offset;
59             ret.index = std::distance(properties.begin(), property);
60         } else if (name[delimPos] == '[') {
61             // there needs to be more than two characters after [ to be a valid array index. the propery must also be an
62             // array.
63             if ((name.size() - delimPos > 2) && property->metaData.containerMethods) { // 2: 2 chs on right of '['
64                 const char* start = name.substr(delimPos + 1).data();
65                 char* end;
66                 const unsigned long index = strtoul(start, &end, 10); // 10: base
67                 if (end && *end == ']') {
68                     // probably managed to convert an array index
69                     size_t size = property->type.isArray
70                                       ? property->count
71                                       : property->metaData.containerMethods->size(property->offset + baseOffset);
72                     if (index < size) {
73                         const auto arrayPos = static_cast<size_t>(end - name.data()) + 1;
74                         if (arrayPos < name.size() && name[arrayPos] == '.') {
75                             ret = FindPropertyMember(
76                                 property->metaData.containerMethods->property, name.substr(arrayPos + 1), baseOffset);
77                         } else {
78                             ret.property = &property->metaData.containerMethods->property;
79                             ret.index = index;
80                         }
81 
82                         if (property->type.isArray) {
83                             ret.offset += property->offset + index * property->metaData.containerMethods->property.size;
84                         } else {
85                             ret.offset +=
86                                 property->metaData.containerMethods->get(property->offset + baseOffset, index) -
87                                 baseOffset;
88                         }
89                     }
90                 }
91             }
92         } else {
93             ret = FindPropertyMember(*property, name.substr(delimPos + 1), baseOffset);
94         }
95     }
96     return ret;
97 }
98 } // namespace
99 
PropertyData()100 PropertyData::PropertyData()
101 {
102     Reset();
103 }
104 
WLock(IPropertyHandle & aHandle)105 bool PropertyData::WLock(IPropertyHandle& aHandle) // no-copy direct-access (Locks the datahandle);
106 {
107     CORE_ASSERT(dataHandle_ == nullptr);
108     CORE_ASSERT(dataHandleW_ == nullptr);
109     dataHandleW_ = &aHandle;
110     dataHandle_ = dataHandleW_;
111     owner_ = dataHandleW_->Owner();
112     size_ = dataHandleW_->Size();
113     dataW_ = static_cast<uint8_t*>(dataHandleW_->WLock());
114     data_ = dataW_;
115     return true;
116 }
117 
WLock(IPropertyHandle & data,const string_view propertyPath)118 PropertyData::PropertyOffset PropertyData::WLock(IPropertyHandle& data, const string_view propertyPath)
119 {
120     if (WLock(data)) {
121         const uintptr_t baseOffset = reinterpret_cast<uintptr_t>(dataW_);
122         if (auto po = FindProperty(Owner()->MetaData(), propertyPath, baseOffset); po) {
123             return po;
124         }
125     }
126     WUnlock(data);
127     return { 0, 0 };
128 }
129 
WUnlock(const IPropertyHandle & aHandle)130 bool PropertyData::WUnlock(const IPropertyHandle& aHandle) // (releases the datahandle lock, and removes ref)
131 {
132     CORE_ASSERT(dataHandleW_);
133     CORE_ASSERT(dataHandleW_ == dataHandle_);
134     CORE_ASSERT(dataHandleW_ == &aHandle);
135     if (dataHandleW_ == &aHandle) {
136         if (dataHandleW_) {
137             dataHandleW_->WUnlock();
138             Reset();
139         }
140         return true;
141     }
142     return false;
143 }
144 
RLock(const IPropertyHandle & aHandle)145 bool PropertyData::RLock(const IPropertyHandle& aHandle) // no-copy direct-access (Locks the datahandle);
146 {
147     CORE_ASSERT(dataHandle_ == nullptr);
148     CORE_ASSERT(dataHandleW_ == nullptr);
149     dataHandleW_ = nullptr;
150     dataHandle_ = &aHandle;
151     owner_ = dataHandle_->Owner();
152     size_ = dataHandle_->Size();
153     data_ = dataHandle_->RLock();
154     dataW_ = nullptr;
155     return true;
156 }
157 
RLock(const IPropertyHandle & data,const string_view propertyPath)158 PropertyData::PropertyOffset PropertyData::RLock(const IPropertyHandle& data, const string_view propertyPath)
159 {
160     if (RLock(data)) {
161         const uintptr_t baseOffset = reinterpret_cast<uintptr_t>(data_);
162         if (auto po = FindProperty(Owner()->MetaData(), propertyPath, baseOffset); po) {
163             return po;
164         }
165     }
166     RUnlock(data);
167     return { 0, 0 };
168 }
169 
RUnlock(const IPropertyHandle & aHandle)170 bool PropertyData::RUnlock(const IPropertyHandle& aHandle) // (releases the datahandle lock, and removes ref)
171 {
172     CORE_ASSERT(dataHandle_);
173     CORE_ASSERT(dataHandleW_ == nullptr);
174     CORE_ASSERT(dataHandle_ == &aHandle);
175     if (dataHandle_ == &aHandle) {
176         if (dataHandle_) {
177             dataHandle_->RUnlock();
178             Reset();
179         }
180         return true;
181     }
182     return false;
183 }
184 
FindProperty(const array_view<const Property> properties,const string_view propertyPath,const uintptr_t baseOffset)185 PropertyData::PropertyOffset PropertyData::FindProperty(
186     const array_view<const Property> properties, const string_view propertyPath, const uintptr_t baseOffset)
187 {
188     PropertyData::PropertyOffset offset = ::FindProperty(properties, propertyPath, baseOffset);
189     if (offset) {
190         offset.offset += baseOffset;
191     }
192     return offset;
193 }
194 
~PropertyData()195 PropertyData::~PropertyData()
196 {
197     if (dataHandleW_) {
198         WUnlock(*dataHandleW_);
199     }
200     if (dataHandle_) {
201         RUnlock(*dataHandle_);
202     }
203 }
204 
Reset()205 void PropertyData::Reset()
206 {
207     size_ = 0;
208     data_ = nullptr;
209     dataW_ = nullptr;
210     owner_ = nullptr;
211     dataHandle_ = nullptr;
212     dataHandleW_ = nullptr;
213 }
214 
MetaData() const215 array_view<const Property> PropertyData::MetaData() const
216 {
217     if (owner_) {
218         return owner_->MetaData();
219     }
220     return {};
221 }
222 
MetaData(size_t index) const223 const Property* PropertyData::MetaData(size_t index) const
224 {
225     if (owner_) {
226         const auto& meta = owner_->MetaData();
227         if (index < meta.size()) {
228             return &meta[index];
229         }
230     }
231     return nullptr;
232 }
233 
Get(size_t index)234 PropertyValue PropertyData::Get(size_t index)
235 {
236     if (owner_) {
237         const auto& props_ = owner_->MetaData();
238         if (index < props_.size() && dataW_) {
239             const auto& meta = props_[index];
240             return PropertyValue(
241                 &meta, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dataW_) + meta.offset), meta.count);
242         }
243     }
244     return PropertyValue();
245 }
246 
Get(size_t index) const247 PropertyValue PropertyData::Get(size_t index) const
248 {
249     if (owner_) {
250         const auto& props_ = owner_->MetaData();
251         if (index < props_.size()) {
252             const auto& meta = props_[index];
253             return PropertyValue(
254                 &meta, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(data_) + meta.offset), meta.count);
255         }
256     }
257     return PropertyValue();
258 }
259 
PropertyCount() const260 size_t PropertyData::PropertyCount() const
261 {
262     if (owner_) {
263         const auto& props_ = owner_->MetaData();
264         return props_.size();
265     }
266     return 0;
267 }
268 
Get(const string_view name)269 PropertyValue PropertyData::Get(const string_view name)
270 {
271     if (owner_) {
272         const auto& props_ = owner_->MetaData();
273         if (!props_.empty() && dataW_) {
274             const auto nameHash = FNV1aHash(name.data(), name.size());
275             for (const auto& meta : props_) {
276                 if (meta.hash == nameHash && meta.name == name) {
277                     return PropertyValue(
278                         &meta, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dataW_) + meta.offset), meta.count);
279                 }
280             }
281         }
282     }
283     return PropertyValue();
284 }
285 
Get(const string_view name) const286 PropertyValue PropertyData::Get(const string_view name) const
287 {
288     if (owner_) {
289         const auto& props_ = owner_->MetaData();
290         if (!props_.empty()) {
291             const auto nameHash = FNV1aHash(name.data(), name.size());
292             for (const auto& meta : props_) {
293                 if (meta.hash == nameHash && meta.name == name) {
294                     return PropertyValue(
295                         &meta, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(data_) + meta.offset), meta.count);
296                 }
297             }
298         }
299     }
300     return PropertyValue();
301 }
302 
operator [](size_t index)303 PropertyValue PropertyData::operator[](size_t index)
304 {
305     return Get(index);
306 }
307 
operator [](size_t index) const308 PropertyValue PropertyData::operator[](size_t index) const
309 {
310     return Get(index);
311 }
312 
operator [](const string_view & name)313 PropertyValue PropertyData::operator[](const string_view& name)
314 {
315     return Get(name);
316 }
317 
operator [](const string_view & name) const318 PropertyValue PropertyData::operator[](const string_view& name) const
319 {
320     return Get(name);
321 }
322 
Owner() const323 const IPropertyApi* PropertyData::Owner() const
324 {
325     return owner_;
326 }
327 
Size() const328 size_t PropertyData::Size() const
329 {
330     return size_;
331 }
332 
RLock() const333 const void* PropertyData::RLock() const
334 {
335     return data_;
336 }
337 
WLock()338 void* PropertyData::WLock()
339 {
340     return dataW_;
341 }
342 
RUnlock() const343 void PropertyData::RUnlock() const {}
344 
WUnlock()345 void PropertyData::WUnlock() {}
346