1
2 /*
3 * Copyright (c) 2024 Huawei Device Co., Ltd.
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
17 #include "unified_record_impl.h"
18
19 #include <cstdlib>
20 #include <iomanip>
21 #include <map>
22 #include <string>
23 #include <variant>
24 #include <vector>
25
26 #include "ffi_remote_data.h"
27 #include "securec.h"
28 #include "unified_record_ffi.h"
29
30 #include "application_defined_record.h"
31 #include "audio.h"
32 #include "folder.h"
33 #include "html.h"
34 #include "image.h"
35 #include "link.h"
36 #include "pixel_map_impl.h"
37 #include "pixel_map.h"
38 #include "plain_text.h"
39 #include "system_defined_appitem.h"
40 #include "system_defined_form.h"
41 #include "system_defined_pixelmap.h"
42 #include "utils.h"
43 #include "video.h"
44
45 using namespace OHOS::FFI;
46 using namespace OHOS::UDMF;
47
48 namespace OHOS {
49 namespace UDMF {
VectorToByteArray(std::vector<uint8_t> bytes)50 static CArrUI8 VectorToByteArray(std::vector<uint8_t> bytes)
51 {
52 if (bytes.size() == 0) {
53 return CArrUI8 {};
54 }
55 uint8_t *head = static_cast<uint8_t*>(malloc(bytes.size() * sizeof(uint8_t)));
56 if (head == nullptr) {
57 return CArrUI8 {};
58 }
59 for (size_t i = 0; i < bytes.size(); i++) {
60 head[i] = bytes[i];
61 }
62 CArrUI8 byteArray = {head, bytes.size()};
63 return byteArray;
64 }
65
ValueType2CJValueType(ValueType value)66 CJValueType CUnifiedRecord::ValueType2CJValueType(ValueType value)
67 {
68 CJValueType cjvalue;
69 if (std::holds_alternative<std::monostate>(value)) {
70 cjvalue.tag = UNDEFINED;
71 } else if (std::holds_alternative<nullptr_t>(value)) {
72 cjvalue.tag = NULLTAG;
73 } else if (auto p = std::get_if<int32_t>(&value)) {
74 cjvalue.integer32 = *p;
75 cjvalue.tag = INTEGER32;
76 } else if (auto p = std::get_if<int64_t>(&value)) {
77 cjvalue.integer64 = *p;
78 cjvalue.tag = INTEGER64;
79 } else if (auto p = std::get_if<double>(&value)) {
80 cjvalue.dou = *p;
81 cjvalue.tag = DOUBLE;
82 } else if (auto p = std::get_if<bool>(&value)) {
83 cjvalue.boolean = *p;
84 cjvalue.tag = BOOLEAN;
85 } else if (auto p = std::get_if<std::string>(&value)) {
86 cjvalue.string = Utils::MallocCString(*p);
87 cjvalue.tag = STRING;
88 } else if (auto p = std::get_if<std::vector<uint8_t>>(&value)) {
89 cjvalue.byteArray = VectorToByteArray(*p);
90 cjvalue.tag = BYTEARRAY;
91 } else if (auto p = std::get_if<std::shared_ptr<OHOS::Media::PixelMap>>(&value)) {
92 cjvalue.pixelMapId = this->pixelMapId_;
93 cjvalue.tag = PIXELMAP;
94 }
95
96 return cjvalue;
97 }
98
CJValueType2ValueType(CJValueType cjvalue)99 ValueType CUnifiedRecord::CJValueType2ValueType(CJValueType cjvalue)
100 {
101 ValueType value;
102 switch (cjvalue.tag) {
103 case INTEGER32:
104 value = cjvalue.integer32;
105 break;
106 case INTEGER64:
107 value = cjvalue.integer64;
108 break;
109 case DOUBLE:
110 value = cjvalue.dou;
111 break;
112 case BOOLEAN:
113 value = cjvalue.boolean;
114 break;
115 case STRING:
116 value = cjvalue.string;
117 break;
118 case BYTEARRAY: {
119 std::vector<uint8_t> bytes = std::vector<uint8_t>();
120 for (int64_t i = 0; i < cjvalue.byteArray.size; i++) {
121 bytes.push_back(cjvalue.byteArray.head[i]);
122 }
123 value = bytes;
124 break;
125 }
126
127 case PIXELMAP: {
128 auto instance = FFIData::GetData<OHOS::Media::PixelMapImpl>(cjvalue.pixelMapId);
129 if (instance == nullptr) {
130 value = -1;
131 break;
132 }
133 value = instance->GetRealPixelMap();
134 break;
135 }
136
137 case NULLTAG: {
138 value = nullptr;
139 break;
140 }
141
142 case UNDEFINED: {
143 value = std::monostate();
144 break;
145 }
146
147 default:
148 value = -1;
149 break;
150 }
151
152 return value;
153 }
154
CUnifiedRecord()155 CUnifiedRecord::CUnifiedRecord()
156 {
157 unifiedRecord_ = std::make_shared<UnifiedRecord>();
158 }
159
CUnifiedRecord(const char * type)160 CUnifiedRecord::CUnifiedRecord(const char *type)
161 {
162 UDType utdType = APPLICATION_DEFINED_RECORD;
163 if (UtdUtils::IsValidUtdId(type)) {
164 utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type));
165 }
166 static const std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>()>> constructors = {
167 {TEXT, []() { return std::make_shared<Text>(); }},
168 {PLAIN_TEXT, []() { return std::make_shared<PlainText>(); }},
169 {HTML, []() { return std::make_shared<Html>(); }},
170 {HYPERLINK, []() { return std::make_shared<Link>(); }},
171 {FILE, []() { return std::make_shared<File>(); }},
172 {IMAGE, []() { return std::make_shared<Image>(); }},
173 {VIDEO, []() { return std::make_shared<Video>(); }},
174 {AUDIO, []() { return std::make_shared<Audio>(); }},
175 {FOLDER, []() { return std::make_shared<Folder>(); }},
176 {SYSTEM_DEFINED_RECORD, []()
177 { return std::make_shared<SystemDefinedRecord>(); }},
178 {SYSTEM_DEFINED_APP_ITEM, []()
179 { return std::make_shared<SystemDefinedAppItem>(); }},
180 {SYSTEM_DEFINED_FORM, []()
181 { return std::make_shared<SystemDefinedForm>(); }},
182 {SYSTEM_DEFINED_PIXEL_MAP, []()
183 { return std::make_shared<SystemDefinedPixelMap>(); }},
184 {APPLICATION_DEFINED_RECORD, []()
185 { return std::make_shared<ApplicationDefinedRecord>(); }},
186 };
187 auto constructor = constructors.find(utdType);
188 if (constructor == constructors.end()) {
189 unifiedRecord_ = std::make_shared<UnifiedRecord>(utdType);
190 return;
191 }
192 unifiedRecord_ = constructor->second();
193 }
194
CUnifiedRecord(const char * type,CJValueType cjvalue)195 CUnifiedRecord::CUnifiedRecord(const char *type, CJValueType cjvalue)
196 {
197 UDType utdType = APPLICATION_DEFINED_RECORD;
198 if (UtdUtils::IsValidUtdId(type)) {
199 utdType = static_cast<UDType>(UtdUtils::GetUtdEnumFromUtdId(type));
200 }
201 ValueType value = CJValueType2ValueType(cjvalue);
202 if (cjvalue.tag == PIXELMAP) {
203 this->pixelMapId_ = cjvalue.pixelMapId;
204 }
205 static const std::map<UDType, std::function<std::shared_ptr<UnifiedRecord>(UDType, ValueType)>> constructors = {
206 {TEXT, [](UDType type, ValueType value) { return std::make_shared<Text>(type, value); }},
207 {PLAIN_TEXT, [](UDType type, ValueType value) { return std::make_shared<PlainText>(type, value); }},
208 {HTML, [](UDType type, ValueType value) { return std::make_shared<Html>(type, value); }},
209 {HYPERLINK, [](UDType type, ValueType value) { return std::make_shared<Link>(type, value); }},
210 {FILE, [](UDType type, ValueType value) { return std::make_shared<File>(type, value); }},
211 {IMAGE, [](UDType type, ValueType value) { return std::make_shared<Image>(type, value); }},
212 {VIDEO, [](UDType type, ValueType value) { return std::make_shared<Video>(type, value); }},
213 {AUDIO, [](UDType type, ValueType value) { return std::make_shared<Audio>(type, value); }},
214 {FOLDER, [](UDType type, ValueType value) { return std::make_shared<Folder>(type, value); }},
215 {SYSTEM_DEFINED_RECORD, [](UDType type, ValueType value)
216 { return std::make_shared<SystemDefinedRecord>(type, value); }},
217 {SYSTEM_DEFINED_APP_ITEM, [](UDType type, ValueType value)
218 { return std::make_shared<SystemDefinedAppItem>(type, value); }},
219 {SYSTEM_DEFINED_FORM, [](UDType type, ValueType value)
220 { return std::make_shared<SystemDefinedForm>(type, value); }},
221 {SYSTEM_DEFINED_PIXEL_MAP, [](UDType type, ValueType value)
222 { return std::make_shared<SystemDefinedPixelMap>(type, value); }},
223 {APPLICATION_DEFINED_RECORD, [](UDType type, ValueType value)
224 { return std::make_shared<ApplicationDefinedRecord>(type, value); }},
225 };
226 auto constructor = constructors.find(utdType);
227 if (constructor == constructors.end()) {
228 unifiedRecord_ = std::make_shared<UnifiedRecord>(utdType, value);
229 return;
230 }
231 unifiedRecord_ = constructor->second(utdType, value);
232 }
233
GetType()234 char *CUnifiedRecord::GetType()
235 {
236 std::string ret = UtdUtils::GetUtdIdFromUtdEnum(this->unifiedRecord_->GetType());
237 return Utils::MallocCString(ret);
238 }
239
GetValue()240 CJValueType CUnifiedRecord::GetValue()
241 {
242 ValueType value = this->unifiedRecord_->GetValue();
243 CJValueType cjvalue = ValueType2CJValueType(value);
244 return cjvalue;
245 }
246
GetUnifiedRecord() const247 const std::shared_ptr<UDMF::UnifiedRecord> &CUnifiedRecord::GetUnifiedRecord() const
248 {
249 return unifiedRecord_;
250 }
251
GetFileUri()252 char *CUnifiedRecord::GetFileUri()
253 {
254 std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_);
255 std::string res = resFile->GetUri();
256 return Utils::MallocCString(res);
257 }
258
SetFileUri(const char * uri)259 void CUnifiedRecord::SetFileUri(const char *uri)
260 {
261 std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_);
262 resFile->SetUri(uri);
263 }
264
GetFileDetails()265 CRecord CUnifiedRecord::GetFileDetails()
266 {
267 CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } };
268 std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_);
269 OHOS::UDMF::UDDetails resDetails = resFile->GetDetails();
270 std::map<std::string, std::string> params;
271 for (auto it : resDetails) {
272 if (std::holds_alternative<std::string>(it.second)) {
273 const std::string &strValue = std::get<std::string>(it.second);
274 params.emplace(it.first, strValue);
275 }
276 }
277 char **keysHead = static_cast<char**>(malloc(sizeof(char*) * params.size()));
278 if (keysHead == nullptr) {
279 return ret;
280 }
281 char **valuesHead = static_cast<char**>(malloc(sizeof(char*) * params.size()));
282 if (valuesHead == nullptr) {
283 free(keysHead);
284 return ret;
285 }
286 int64_t i = 0;
287 for (auto ¶m : params) {
288 keysHead[i] = CreateCStringFromString(param.first);
289 valuesHead[i] = CreateCStringFromString(param.second);
290 i++;
291 }
292 ret.keys.size = static_cast<int64_t>(params.size());
293 ret.keys.head = keysHead;
294 ret.values.size = static_cast<int64_t>(params.size());
295 ret.values.head = valuesHead;
296 return ret;
297 }
298
SetFileDetails(const std::map<std::string,std::string> & details)299 void CUnifiedRecord::SetFileDetails(const std::map<std::string, std::string> &details)
300 {
301 std::shared_ptr<UDMF::File> resFile = std::reinterpret_pointer_cast<UDMF::File>(this->unifiedRecord_);
302 OHOS::UDMF::UDDetails udDetails;
303 for (auto ¶m : details) {
304 udDetails[param.first] = param.second;
305 }
306 resFile->SetDetails(udDetails);
307 }
308
GetImageUri()309 char *CUnifiedRecord::GetImageUri()
310 {
311 std::shared_ptr<UDMF::Image> resImage = std::reinterpret_pointer_cast<UDMF::Image>(this->unifiedRecord_);
312 std::string res = resImage->GetUri();
313 return Utils::MallocCString(res);
314 }
315
SetImageUri(const char * uri)316 void CUnifiedRecord::SetImageUri(const char *uri)
317 {
318 std::shared_ptr<UDMF::Image> resImage = std::reinterpret_pointer_cast<UDMF::Image>(this->unifiedRecord_);
319 resImage->SetUri(uri);
320 }
321
GetVideoUri()322 char *CUnifiedRecord::GetVideoUri()
323 {
324 std::shared_ptr<UDMF::Video> resVideo = std::reinterpret_pointer_cast<UDMF::Video>(this->unifiedRecord_);
325 std::string res = resVideo->GetUri();
326 return Utils::MallocCString(res);
327 }
328
SetVideoUri(const char * uri)329 void CUnifiedRecord::SetVideoUri(const char *uri)
330 {
331 std::shared_ptr<UDMF::Video> resVideo = std::reinterpret_pointer_cast<UDMF::Video>(this->unifiedRecord_);
332 resVideo->SetUri(uri);
333 }
334
GetTextDetails()335 CRecord CUnifiedRecord::GetTextDetails()
336 {
337 CRecord ret = { .keys = { .head = nullptr, .size = 0 }, .values = { .head = nullptr, .size = 0 } };
338 std::shared_ptr<UDMF::Text> resText = std::reinterpret_pointer_cast<UDMF::Text>(this->unifiedRecord_);
339 OHOS::UDMF::UDDetails resDetails = resText->GetDetails();
340 std::map<std::string, std::string> params;
341 for (auto it : resDetails) {
342 if (std::holds_alternative<std::string>(it.second)) {
343 const std::string &strValue = std::get<std::string>(it.second);
344 params.emplace(it.first, strValue);
345 }
346 }
347 char **keysHead = static_cast<char**>(malloc(sizeof(char*) * params.size()));
348 if (keysHead == nullptr) {
349 return ret;
350 }
351 char **valuesHead = static_cast<char**>(malloc(sizeof(char*) * params.size()));
352 if (valuesHead == nullptr) {
353 free(keysHead);
354 return ret;
355 }
356 int64_t i = 0;
357 for (auto ¶m : params) {
358 keysHead[i] = CreateCStringFromString(param.first);
359 valuesHead[i] = CreateCStringFromString(param.second);
360 i++;
361 }
362 ret.keys.size = static_cast<int64_t>(params.size());
363 ret.keys.head = keysHead;
364 ret.values.size = static_cast<int64_t>(params.size());
365 ret.values.head = valuesHead;
366 return ret;
367 }
368
SetTextDetails(const std::map<std::string,std::string> & details)369 void CUnifiedRecord::SetTextDetails(const std::map<std::string, std::string> &details)
370 {
371 std::shared_ptr<UDMF::Text> resText = std::reinterpret_pointer_cast<UDMF::Text>(this->unifiedRecord_);
372 OHOS::UDMF::UDDetails udDetails;
373 for (auto ¶m : details) {
374 udDetails[param.first] = param.second;
375 }
376 resText->SetDetails(udDetails);
377 }
378
GetHyperLinkUrl()379 char *CUnifiedRecord::GetHyperLinkUrl()
380 {
381 std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_);
382 std::string res = resLink->GetUrl();
383 return Utils::MallocCString(res);
384 }
385
SetHyperLinkUrl(const char * url)386 void CUnifiedRecord::SetHyperLinkUrl(const char *url)
387 {
388 std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_);
389 resLink->SetUrl(url);
390 }
391
GetHyperLinkDescription()392 char *CUnifiedRecord::GetHyperLinkDescription()
393 {
394 std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_);
395 std::string res = resLink->GetDescription();
396 return Utils::MallocCString(res);
397 }
398
SetHyperLinkDescription(const char * description)399 void CUnifiedRecord::SetHyperLinkDescription(const char *description)
400 {
401 std::shared_ptr<UDMF::Link> resLink = std::reinterpret_pointer_cast<UDMF::Link>(this->unifiedRecord_);
402 resLink->SetDescription(description);
403 }
404
GetPlainTextContent()405 char *CUnifiedRecord::GetPlainTextContent()
406 {
407 std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_);
408 std::string res = resText->GetContent();
409 return Utils::MallocCString(res);
410 }
411
SetPlainTextContent(const char * text)412 void CUnifiedRecord::SetPlainTextContent(const char *text)
413 {
414 std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_);
415 resText->SetContent(text);
416 }
417
GetPlainTextAbstract()418 char *CUnifiedRecord::GetPlainTextAbstract()
419 {
420 std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_);
421 std::string res = resText->GetAbstract();
422 return Utils::MallocCString(res);
423 }
424
SetPlainTextAbstract(const char * abstr)425 void CUnifiedRecord::SetPlainTextAbstract(const char *abstr)
426 {
427 std::shared_ptr<UDMF::PlainText> resText = std::reinterpret_pointer_cast<UDMF::PlainText>(this->unifiedRecord_);
428 resText->SetAbstract(abstr);
429 }
430
CreateCStringFromString(const std::string & source)431 char *CreateCStringFromString(const std::string &source)
432 {
433 if (source.size() == 0) {
434 return nullptr;
435 }
436 size_t length = source.size() + 1;
437 auto res = static_cast<char*>(malloc(length));
438 if (res == nullptr) {
439 return nullptr;
440 }
441 if (strcpy_s(res, length, source.c_str()) != 0) {
442 free(res);
443 return nullptr;
444 }
445 return res;
446 }
447 } // namespace UDMF
448 } // namespace OHOS
449