1 /*
2  * Copyright (c) 2022 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 "datashare_template.h"
17 
18 namespace OHOS {
19 namespace DataShare {
~PublishedDataItem()20 PublishedDataItem::~PublishedDataItem()
21 {
22     Clear();
23 }
24 
PublishedDataItem(const std::string & key,int64_t subscriberId,DataType value)25 PublishedDataItem::PublishedDataItem(const std::string &key, int64_t subscriberId, DataType value)
26     : key_(key), subscriberId_(subscriberId)
27 {
28     Set(value);
29 }
30 
PublishedDataItem(PublishedDataItem && item)31 PublishedDataItem::PublishedDataItem(PublishedDataItem &&item)
32 {
33     key_ = std::move(item.key_);
34     subscriberId_ = std::move(item.subscriberId_);
35     value_ = std::move(item.value_);
36     if (item.IsAshmem()) {
37         item.MoveOutAshmem();
38     }
39 }
40 
operator =(PublishedDataItem && item)41 PublishedDataItem &PublishedDataItem::operator=(PublishedDataItem &&item)
42 {
43     key_ = std::move(item.key_);
44     subscriberId_ = std::move(item.subscriberId_);
45     value_ = std::move(item.value_);
46     if (item.IsAshmem()) {
47         item.MoveOutAshmem();
48     }
49     return *this;
50 }
51 
MoveOutAshmem()52 sptr<Ashmem> PublishedDataItem::MoveOutAshmem()
53 {
54     if (IsAshmem()) {
55         AshmemNode &node = std::get<AshmemNode>(value_);
56         if (!node.isManaged) {
57             return nullptr;
58         }
59         node.isManaged = false;
60         return std::move(node.ashmem);
61     }
62     return nullptr;
63 }
64 
IsAshmem() const65 bool PublishedDataItem::IsAshmem() const
66 {
67     return value_.index() == 0;
68 }
69 
IsString() const70 bool PublishedDataItem::IsString() const
71 {
72     return value_.index() == 1;
73 }
74 
Set(DataType & value)75 void PublishedDataItem::Set(DataType &value)
76 {
77     Clear();
78     if (value.index() == 0) {
79         std::vector<uint8_t> &vecValue = std::get<std::vector<uint8_t>>(value);
80         auto size = vecValue.size();
81         sptr<Ashmem> mem = Ashmem::CreateAshmem((key_ + std::to_string(subscriberId_)).c_str(), size);
82         if (mem == nullptr) {
83             return;
84         }
85         if (!mem->MapReadAndWriteAshmem()) {
86             mem->CloseAshmem();
87             return;
88         }
89         if (!mem->WriteToAshmem(vecValue.data(), size, 0)) {
90             mem->UnmapAshmem();
91             mem->CloseAshmem();
92             return;
93         }
94         AshmemNode node = { mem, true };
95         value_ = std::move(node);
96     } else {
97         value_ = std::move(std::get<std::string>(value));
98     }
99 }
100 
GetData() const101 PublishedDataItem::DataType PublishedDataItem::GetData() const
102 {
103     if (IsAshmem()) {
104         const AshmemNode &node = std::get<AshmemNode>(value_);
105         if (node.ashmem != nullptr) {
106             node.ashmem->MapReadOnlyAshmem();
107             uint8_t *data = (uint8_t *)node.ashmem->ReadFromAshmem(node.ashmem->GetAshmemSize(), 0);
108             if (data == nullptr) {
109                 return std::vector<uint8_t>();
110             }
111             return std::vector<uint8_t>(data, data + node.ashmem->GetAshmemSize());
112         }
113         return std::vector<uint8_t>();
114     } else {
115         return std::get<std::string>(value_);
116     }
117 }
118 
SetAshmem(sptr<Ashmem> ashmem,bool isManaged)119 void PublishedDataItem::SetAshmem(sptr<Ashmem> ashmem, bool isManaged)
120 {
121     AshmemNode node = { ashmem, isManaged };
122     value_ = std::move(node);
123 }
124 
Clear()125 void PublishedDataItem::Clear()
126 {
127     AshmemNode *node = std::get_if<AshmemNode>(&value_);
128     if (node != nullptr) {
129         if (node->isManaged && node->ashmem != nullptr) {
130             node->ashmem->UnmapAshmem();
131             node->ashmem->CloseAshmem();
132         }
133         value_ = "";
134     }
135 }
136 } // namespace DataShare
137 } // namespace OHOS