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 #define LOG_TAG "DataHandler"
16
17 #include "data_handler.h"
18 #include "log_print.h"
19 #include "tlv_util.h"
20
21 namespace OHOS::UDMF {
22 constexpr const char *UD_KEY_SEPARATOR = "/";
23 constexpr const char *UD_KEY_ENTRY_SEPARATOR = "#";
24 constexpr const char *UD_KEY_PROPERTIES_SEPARATOR = "#properties";
25
MarshalToEntries(const UnifiedData & unifiedData,std::vector<Entry> & entries)26 Status DataHandler::MarshalToEntries(const UnifiedData &unifiedData, std::vector<Entry> &entries)
27 {
28 std::string unifiedKey = unifiedData.GetRuntime()->key.GetUnifiedKey();
29 std::vector<uint8_t> runtimeBytes;
30 auto runtimeTlv = TLVObject(runtimeBytes);
31 if (!TLVUtil::Writing(*unifiedData.GetRuntime(), runtimeTlv, TAG::TAG_RUNTIME)) {
32 ZLOGE("Runtime info marshalling failed:%{public}s", unifiedKey.c_str());
33 return E_WRITE_PARCEL_ERROR;
34 }
35 std::vector<uint8_t> udKeyBytes = { unifiedKey.begin(), unifiedKey.end() };
36 Entry entry = { udKeyBytes, runtimeBytes };
37 entries.emplace_back(entry);
38 std::string propsKey = unifiedData.GetRuntime()->key.GetKeyCommonPrefix() + UD_KEY_PROPERTIES_SEPARATOR;
39 std::vector<uint8_t> propsBytes;
40 auto propsTlv = TLVObject(propsBytes);
41 if (!TLVUtil::Writing(*unifiedData.GetProperties(), propsTlv, TAG::TAG_PROPERTIES)) {
42 ZLOGE("Properties info marshalling failed:%{public}s", propsKey.c_str());
43 return E_WRITE_PARCEL_ERROR;
44 }
45 std::vector<uint8_t> propsKeyBytes = { propsKey.begin(), propsKey.end() };
46 Entry propsEntry = { propsKeyBytes, propsBytes };
47 entries.emplace_back(std::move(propsEntry));
48 return BuildEntries(unifiedData.GetRecords(), unifiedKey, entries);
49 }
50
UnmarshalEntries(const std::string & key,const std::vector<Entry> & entries,UnifiedData & unifiedData)51 Status DataHandler::UnmarshalEntries(const std::string &key, const std::vector<Entry> &entries,
52 UnifiedData &unifiedData)
53 {
54 std::map<std::string, std::shared_ptr<UnifiedRecord>> records;
55 std::map<std::string, std::map<std::string, ValueType>> innerEntries;
56 auto status = UnmarshalEntryItem(unifiedData, entries, key, records, innerEntries);
57 if (status != E_OK) {
58 ZLOGE("UnmarshalEntryItem failed.");
59 return status;
60 }
61 for (auto &[entryKey, entryValue] : innerEntries) {
62 auto idx = entryKey.rfind(UD_KEY_ENTRY_SEPARATOR);
63 std::string recordKey = entryKey.substr(0, idx);
64 std::string entryUtdId = entryKey.substr(idx + 1);
65 if (records.find(recordKey) != records.end() && entryValue.find(entryUtdId) != entryValue.end()) {
66 records[recordKey]->AddEntry(entryUtdId, std::move(entryValue[entryUtdId]));
67 }
68 }
69 return E_OK;
70 }
71
UnmarshalEntryItem(UnifiedData & unifiedData,const std::vector<Entry> & entries,const std::string & key,std::map<std::string,std::shared_ptr<UnifiedRecord>> & records,std::map<std::string,std::map<std::string,ValueType>> & innerEntries)72 Status DataHandler::UnmarshalEntryItem(UnifiedData &unifiedData, const std::vector<Entry> &entries,
73 const std::string &key, std::map<std::string, std::shared_ptr<UnifiedRecord>> &records,
74 std::map<std::string, std::map<std::string, ValueType>> &innerEntries)
75 {
76 for (const auto &entry : entries) {
77 std::string keyStr = { entry.key.begin(), entry.key.end() };
78 auto data = TLVObject(const_cast<std::vector<uint8_t> &>(entry.value));
79 if (keyStr == key) {
80 Runtime runtime;
81 if (!TLVUtil::ReadTlv(runtime, data, TAG::TAG_RUNTIME)) {
82 ZLOGE("Unmarshall runtime info failed.");
83 return E_READ_PARCEL_ERROR;
84 }
85 unifiedData.SetRuntime(runtime);
86 continue;
87 }
88 auto isStartWithKey = keyStr.find(key) == 0;
89 std::string propsKey = UnifiedKey(key).GetKeyCommonPrefix() + UD_KEY_PROPERTIES_SEPARATOR;
90 if (!isStartWithKey && (keyStr == propsKey)) {
91 std::shared_ptr<UnifiedDataProperties> properties;
92 if (!TLVUtil::ReadTlv(properties, data, TAG::TAG_PROPERTIES)) {
93 ZLOGE("Unmarshall unified properties failed.");
94 return E_READ_PARCEL_ERROR;
95 }
96 unifiedData.SetProperties(std::move(properties));
97 continue;
98 }
99 auto isEntryItem = keyStr.rfind(UD_KEY_ENTRY_SEPARATOR) != std::string::npos;
100 if (isStartWithKey && !isEntryItem) {
101 std::shared_ptr<UnifiedRecord> record;
102 if (!TLVUtil::ReadTlv(record, data, TAG::TAG_UNIFIED_RECORD)) {
103 ZLOGE("Unmarshall unified record failed.");
104 return E_READ_PARCEL_ERROR;
105 }
106 unifiedData.AddRecord(record);
107 records.emplace(keyStr, record);
108 continue;
109 }
110 if (isStartWithKey && isEntryItem) {
111 std::shared_ptr<std::map<std::string, ValueType>> entryRead =
112 std::make_shared<std::map<std::string, ValueType>>();
113 if (!TLVUtil::ReadTlv(entryRead, data, TAG::TAG_INNER_ENTRIES)) {
114 ZLOGE("Unmarshall inner entry failed.");
115 return E_READ_PARCEL_ERROR;
116 }
117 innerEntries.emplace(keyStr, std::move(*entryRead));
118 }
119 }
120 return E_OK;
121 }
122
BuildEntries(const std::vector<std::shared_ptr<UnifiedRecord>> & records,const std::string & unifiedKey,std::vector<Entry> & entries)123 Status DataHandler::BuildEntries(const std::vector<std::shared_ptr<UnifiedRecord>> &records,
124 const std::string &unifiedKey, std::vector<Entry> &entries)
125 {
126 for (const auto &record : records) {
127 std::string recordKey = unifiedKey + UD_KEY_SEPARATOR + record->GetUid();
128 auto recordEntries = record->GetInnerEntries();
129 for (auto &recordEntry : *recordEntries) {
130 std::string key = recordKey + UD_KEY_ENTRY_SEPARATOR + recordEntry.first;
131 std::vector<uint8_t> entryBytes;
132 auto entryTlv = TLVObject(entryBytes);
133 const std::shared_ptr<std::map<std::string, ValueType>> entryMap =
134 std::make_shared<std::map<std::string, ValueType>>();
135 entryMap->insert_or_assign(recordEntry.first, recordEntry.second);
136 if (!TLVUtil::Writing(entryMap, entryTlv, TAG::TAG_INNER_ENTRIES)) {
137 ZLOGI("Marshall inner entry failed.");
138 return E_WRITE_PARCEL_ERROR;
139 }
140 std::vector<uint8_t> keyBytes = { key.begin(), key.end() };
141 Entry entry = { keyBytes, entryBytes };
142 entries.emplace_back(entry);
143 }
144 recordEntries->clear();
145 std::vector<uint8_t> recordBytes;
146 auto recordTlv = TLVObject(recordBytes);
147 if (!TLVUtil::Writing(record, recordTlv, TAG::TAG_UNIFIED_RECORD)) {
148 ZLOGI("Marshall unified record failed.");
149 return E_WRITE_PARCEL_ERROR;
150 }
151 std::vector<uint8_t> keyBytes = { recordKey.begin(), recordKey.end() };
152 Entry entry = { keyBytes, recordBytes };
153 entries.emplace_back(entry);
154 }
155 return E_OK;
156 }
157 } // namespace UDMF::OHOS