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 #include "render_data_store_pod.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 
21 #include <base/containers/array_view.h>
22 #include <render/namespace.h>
23 
24 #include "util/log.h"
25 
26 using namespace BASE_NS;
27 
RENDER_BEGIN_NAMESPACE()28 RENDER_BEGIN_NAMESPACE()
29 RenderDataStorePod::RenderDataStorePod(const string_view name) : name_(name) {}
30 
CreatePod(const string_view tpName,const string_view name,const array_view<const uint8_t> srcData)31 void RenderDataStorePod::CreatePod(
32     const string_view tpName, const string_view name, const array_view<const uint8_t> srcData)
33 {
34     if (srcData.empty()) {
35         PLUGIN_LOG_W("Zero size pod is not created (name: %s)", tpName.data());
36         return;
37     }
38     bool contains = false;
39     {
40         const auto lock = std::lock_guard(mutex_);
41 
42         contains = nameToDataOffset_.contains(name);
43         if (!contains) {
44             const size_t prevByteSize = dataStore_.size();
45             const size_t newByteSize = prevByteSize + srcData.size();
46             dataStore_.resize(newByteSize);
47             uint8_t* dst = &dataStore_[prevByteSize];
48             if (!CloneData(dst, dataStore_.size() - prevByteSize, srcData.data(), srcData.size())) {
49                 PLUGIN_LOG_E("Copying of RenderDataStorePod Data failed.");
50             }
51 
52             auto& typeNameRef = typeNameToPodNames_[tpName];
53             nameToDataOffset_[name] = { static_cast<uint32_t>(prevByteSize), static_cast<uint32_t>(srcData.size()) };
54             typeNameRef.emplace_back(name);
55         }
56     } // end of lock
57 
58     // already created, set data
59     if (contains) {
60         PLUGIN_LOG_I("updating already created pod: %s", name.data());
61         Set(name, srcData);
62     }
63 }
64 
DestroyPod(const string_view typeName,const string_view name)65 void RenderDataStorePod::DestroyPod(const string_view typeName, const string_view name)
66 {
67     const auto lock = std::lock_guard(mutex_);
68 
69     if (const auto iter = nameToDataOffset_.find(name); iter != nameToDataOffset_.end()) {
70         const auto offsetToData = iter->second;
71         PLUGIN_ASSERT(offsetToData.index + offsetToData.byteSize <= static_cast<uint32_t>(dataStore_.size()));
72         const auto first = dataStore_.cbegin() + static_cast<int32_t>(offsetToData.index);
73         const auto last = first + static_cast<int32_t>(offsetToData.byteSize);
74         dataStore_.erase(first, last);
75         nameToDataOffset_.erase(iter);
76         // move the index of pods after the destroyed pod by the size of the pod
77         for (auto& nameToOffset : nameToDataOffset_) {
78             if (nameToOffset.second.index > offsetToData.index) {
79                 nameToOffset.second.index -= offsetToData.byteSize;
80             }
81         }
82         if (auto tpIter = typeNameToPodNames_.find(typeName); tpIter != typeNameToPodNames_.end()) {
83             for (auto nameIter = tpIter->second.cbegin(); nameIter != tpIter->second.cend(); ++nameIter) {
84                 if (*nameIter == name) {
85                     tpIter->second.erase(nameIter);
86                     break;
87                 }
88             }
89         }
90     } else {
91         PLUGIN_LOG_I("pod not found: %s", name.data());
92     }
93 }
94 
Set(const string_view name,const array_view<const uint8_t> srcData)95 void RenderDataStorePod::Set(const string_view name, const array_view<const uint8_t> srcData)
96 {
97     const auto lock = std::lock_guard(mutex_);
98 
99     const auto iter = nameToDataOffset_.find(name);
100     if (iter != nameToDataOffset_.cend()) {
101         const uint32_t index = iter->second.index;
102         const uint32_t byteSize = iter->second.byteSize;
103         PLUGIN_ASSERT(index + byteSize <= static_cast<uint32_t>(dataStore_.size()));
104         PLUGIN_ASSERT(srcData.size() <= byteSize);
105 
106         const uint32_t maxByteSize = std::min(byteSize, static_cast<uint32_t>(srcData.size()));
107 
108         uint8_t* dst = &dataStore_[index];
109         if (!CloneData(dst, dataStore_.size() - index, srcData.data(), maxByteSize)) {
110             PLUGIN_LOG_E("Copying of RenderDataStorePod Data failed.");
111         }
112     } else {
113         PLUGIN_LOG_E("render data store pod: %s not created", name.data());
114     }
115 }
116 
Get(const string_view name) const117 array_view<const uint8_t> RenderDataStorePod::Get(const string_view name) const
118 {
119     const auto lock = std::lock_guard(mutex_);
120 
121     array_view<const uint8_t> view;
122     const auto iter = nameToDataOffset_.find(name);
123     if (iter != nameToDataOffset_.cend()) {
124         const uint32_t index = iter->second.index;
125         const uint32_t byteSize = iter->second.byteSize;
126         PLUGIN_ASSERT(index + byteSize <= static_cast<uint32_t>(dataStore_.size()));
127 
128         const uint8_t* data = &dataStore_[index];
129         view = array_view<const uint8_t>(data, byteSize);
130     }
131     return view;
132 }
133 
GetPodNames(const string_view tpName) const134 array_view<const string> RenderDataStorePod::GetPodNames(const string_view tpName) const
135 {
136     const auto lock = std::lock_guard(mutex_);
137 
138     const auto iter = typeNameToPodNames_.find(tpName);
139     if (iter != typeNameToPodNames_.cend()) {
140         return array_view<const string>(iter->second.data(), iter->second.size());
141     } else {
142         PLUGIN_LOG_I("render data store pod type (%s), not found", tpName.data());
143         return {};
144     }
145 }
146 
147 // for plugin / factory interface
Create(IRenderContext &,char const * name)148 IRenderDataStore* RenderDataStorePod::Create(IRenderContext&, char const* name)
149 {
150     // engine not used
151     return new RenderDataStorePod(name);
152 }
153 
Destroy(IRenderDataStore * aInstance)154 void RenderDataStorePod::Destroy(IRenderDataStore* aInstance)
155 {
156     delete static_cast<RenderDataStorePod*>(aInstance);
157 }
158 RENDER_END_NAMESPACE()
159