• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "resource_table.h"
17 #include <cJSON.h>
18 #include <cstdint>
19 #include "cmd/cmd_parser.h"
20 #include "file_entry.h"
21 #include "file_manager.h"
22 #include "resource_util.h"
23 #include "securec.h"
24 
25 namespace OHOS {
26 namespace Global {
27 namespace Restool {
28 using namespace std;
ResourceTable()29 ResourceTable::ResourceTable()
30 {
31     auto &parser = CmdParser::GetInstance();
32     auto &packageParser = parser.GetPackageParser();
33     if (!packageParser.GetIdDefinedOutput().empty()) {
34         idDefinedPath_ = FileEntry::FilePath(packageParser.GetIdDefinedOutput()).Append(ID_DEFINED_FILE).GetPath();
35     }
36     indexFilePath_ = FileEntry::FilePath(packageParser.GetOutput()).Append(RESOURCE_INDEX_FILE).GetPath();
37 }
38 
~ResourceTable()39 ResourceTable::~ResourceTable()
40 {
41 }
42 
CreateResourceTable()43 uint32_t ResourceTable::CreateResourceTable()
44 {
45     FileManager &fileManager = FileManager::GetInstance();
46     auto &allResource = fileManager.GetResources();
47     map<string, vector<TableData>> configs;
48     for (const auto &item : allResource) {
49         for (const auto &resourceItem : item.second) {
50             if (resourceItem.GetResType() == ResType::ID) {
51                 break;
52             }
53             TableData tableData;
54             tableData.id = item.first;
55             tableData.resourceItem = resourceItem;
56             configs[resourceItem.GetLimitKey()].push_back(tableData);
57         }
58     }
59 
60     if (SaveToResouorceIndex(configs) != RESTOOL_SUCCESS) {
61         return RESTOOL_ERROR;
62     }
63 
64     if (!idDefinedPath_.empty()) {
65         if (CreateIdDefined(allResource) != RESTOOL_SUCCESS) {
66             return RESTOOL_ERROR;
67         }
68     }
69     return RESTOOL_SUCCESS;
70 }
71 
CreateResourceTable(const map<int64_t,vector<shared_ptr<ResourceItem>>> & items)72 uint32_t ResourceTable::CreateResourceTable(const map<int64_t, vector<shared_ptr<ResourceItem>>> &items)
73 {
74     map<string, vector<TableData>> configs;
75     map<int64_t, vector<ResourceItem>> allResource;
76     for (const auto &item : items) {
77         vector<ResourceItem> resourceItems;
78         for (const auto &resourceItemPtr : item.second) {
79             if (resourceItemPtr->GetResType() == ResType::ID) {
80                 break;
81             }
82             TableData tableData;
83             tableData.id = item.first;
84             tableData.resourceItem = *resourceItemPtr;
85             resourceItems.push_back(*resourceItemPtr);
86             configs[resourceItemPtr->GetLimitKey()].push_back(tableData);
87         }
88         allResource.emplace(item.first, resourceItems);
89     }
90 
91     if (SaveToResouorceIndex(configs) != RESTOOL_SUCCESS) {
92         return RESTOOL_ERROR;
93     }
94 
95     if (!idDefinedPath_.empty()) {
96         if (CreateIdDefined(allResource) != RESTOOL_SUCCESS) {
97             return RESTOOL_ERROR;
98         }
99     }
100     return RESTOOL_SUCCESS;
101 }
102 
LoadResTable(const string path,map<int64_t,vector<ResourceItem>> & resInfos)103 uint32_t ResourceTable::LoadResTable(const string path, map<int64_t, vector<ResourceItem>> &resInfos)
104 {
105     ifstream in(path, ios::binary);
106     if (!in.is_open()) {
107         PrintError(GetError(ERR_CODE_OPEN_FILE_ERROR).FormatCause(path.c_str(), strerror(errno)));
108         return RESTOOL_ERROR;
109     }
110 
111     in.seekg(0, ios::end);
112     int64_t length = in.tellg();
113     if (length <= 0) {
114         in.close();
115         PrintError(GetError(ERR_CODE_READ_FILE_ERROR).FormatCause(path.c_str(), "file is empty"));
116         return RESTOOL_ERROR;
117     }
118     in.seekg(0, ios::beg);
119     uint32_t errorCode = LoadResTable(in, resInfos);
120     in.close();
121     return errorCode;
122 }
123 
LoadResTable(basic_istream<char> & in,map<int64_t,vector<ResourceItem>> & resInfos)124 uint32_t ResourceTable::LoadResTable(basic_istream<char> &in, map<int64_t, vector<ResourceItem>> &resInfos)
125 {
126     if (!in) {
127         std::string msg = "file stream bad, state code: " + std::to_string(in.rdstate());
128         PrintError(GetError(ERR_CODE_READ_FILE_ERROR).FormatCause(in.rdstate(), msg.c_str()));
129         return RESTOOL_ERROR;
130     }
131     in.seekg(0, ios::end);
132     int64_t length = in.tellg();
133     in.seekg(0, ios::beg);
134     uint64_t pos = 0;
135     IndexHeader indexHeader;
136     if (!ReadFileHeader(in, indexHeader, pos, static_cast<uint64_t>(length))) {
137         return RESTOOL_ERROR;
138     }
139 
140     map<int64_t, vector<KeyParam>> limitKeys;
141     if (!ReadLimitKeys(in, limitKeys, indexHeader.limitKeyConfigSize, pos, static_cast<uint64_t>(length))) {
142         return RESTOOL_ERROR;
143     }
144 
145     map<int64_t, pair<int64_t, int64_t>> datas;
146     if (!ReadIdTables(in, datas, indexHeader.limitKeyConfigSize, pos, static_cast<uint64_t>(length))) {
147         return RESTOOL_ERROR;
148     }
149 
150     while (in.tellg() < length) {
151         RecordItem record;
152         if (!ReadDataRecordPrepare(in, record, pos, static_cast<uint64_t>(length)) ||
153             !ReadDataRecordStart(in, record, limitKeys, datas, resInfos)) {
154             return RESTOOL_ERROR;
155         }
156     }
157     return RESTOOL_SUCCESS;
158 }
159 
CreateIdDefined(const map<int64_t,vector<ResourceItem>> & allResource) const160 uint32_t ResourceTable::CreateIdDefined(const map<int64_t, vector<ResourceItem>> &allResource) const
161 {
162     cJSON *root = cJSON_CreateObject();
163     cJSON *recordArray = cJSON_CreateArray();
164     if (recordArray == nullptr) {
165         PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("failed to create cJSON object for record array")
166             .SetPosition(idDefinedPath_));
167         cJSON_Delete(root);
168         return RESTOOL_ERROR;
169     }
170     cJSON_AddItemToObject(root, "record", recordArray);
171     for (const auto &pairPtr : allResource) {
172         if (pairPtr.second.empty()) {
173             PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("resource item vector is empty")
174                 .SetPosition(idDefinedPath_));
175             cJSON_Delete(root);
176             return RESTOOL_ERROR;
177         }
178         cJSON *jsonItem = cJSON_CreateObject();
179         if (jsonItem == nullptr) {
180             PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("failed to create cJSON object for resource item")
181                 .SetPosition(idDefinedPath_));
182             cJSON_Delete(root);
183             return RESTOOL_ERROR;
184         }
185         ResourceItem item = pairPtr.second.front();
186         ResType resType = item.GetResType();
187         string type = ResourceUtil::ResTypeToString(resType);
188         string name = item.GetName();
189         int64_t id = pairPtr.first;
190         if (type.empty()) {
191             string errMsg = "name = ";
192             errMsg.append(name);
193             errMsg.append("invalid restype, type must in ").append(ResourceUtil::GetAllRestypeString());
194             PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause(errMsg.c_str()).SetPosition(idDefinedPath_));
195             cJSON_Delete(jsonItem);
196             cJSON_Delete(root);
197             return RESTOOL_ERROR;
198         }
199         cJSON_AddStringToObject(jsonItem, "type", type.c_str());
200         cJSON_AddStringToObject(jsonItem, "name", ResourceUtil::GetIdName(name, resType).c_str());
201         cJSON_AddStringToObject(jsonItem, "id", ResourceUtil::DecToHexStr(id).c_str());
202         cJSON_AddItemToArray(recordArray, jsonItem);
203     }
204     if (!ResourceUtil::SaveToJsonFile(idDefinedPath_, root)) {
205         cJSON_Delete(root);
206         return RESTOOL_ERROR;
207     }
208     cJSON_Delete(root);
209     return RESTOOL_SUCCESS;
210 }
211 
212 // below private
SaveToResouorceIndex(const map<string,vector<TableData>> & configs) const213 uint32_t ResourceTable::SaveToResouorceIndex(const map<string, vector<TableData>> &configs) const
214 {
215     uint32_t pos = 0;
216     IndexHeader indexHeader;
217     if (!InitIndexHeader(indexHeader, configs.size())) {
218         return RESTOOL_ERROR;
219     }
220     pos += sizeof(IndexHeader);
221 
222     map<string, LimitKeyConfig> limitKeyConfigs;
223     map<string, IdSet> idSets;
224     if (!Prepare(configs, limitKeyConfigs, idSets, pos)) {
225         return RESTOOL_ERROR;
226     }
227 
228     ofstream out(indexFilePath_, ofstream::out | ofstream::binary);
229     if (!out.is_open()) {
230         PrintError(GetError(ERR_CODE_OPEN_FILE_ERROR).FormatCause(indexFilePath_.c_str(), strerror(errno)));
231         return RESTOOL_ERROR;
232     }
233 
234     ostringstream outStreamData;
235     if (!SaveRecordItem(configs, outStreamData, idSets, pos)) {
236         return RESTOOL_ERROR;
237     }
238 
239     ostringstream outStreamHeader;
240     indexHeader.fileSize = pos;
241     SaveHeader(indexHeader, outStreamHeader);
242     SaveLimitKeyConfigs(limitKeyConfigs, outStreamHeader);
243     SaveIdSets(idSets, outStreamHeader);
244     out << outStreamHeader.str();
245     out << outStreamData.str();
246     return RESTOOL_SUCCESS;
247 }
248 
InitIndexHeader(IndexHeader & indexHeader,uint32_t count) const249 bool ResourceTable::InitIndexHeader(IndexHeader &indexHeader, uint32_t count) const
250 {
251     if (memcpy_s(indexHeader.version, VERSION_MAX_LEN, RESTOOL_VERSION, VERSION_MAX_LEN) != EOK) {
252         PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("memcpy error when init index header"));
253         return false;
254     }
255     indexHeader.limitKeyConfigSize = count;
256     return true;
257 }
258 
Prepare(const map<string,vector<TableData>> & configs,map<string,LimitKeyConfig> & limitKeyConfigs,map<string,IdSet> & idSets,uint32_t & pos) const259 bool ResourceTable::Prepare(const map<string, vector<TableData>> &configs,
260                             map<string, LimitKeyConfig> &limitKeyConfigs,
261                             map<string, IdSet> &idSets, uint32_t &pos) const
262 {
263     for (const auto &config : configs) {
264         LimitKeyConfig limitKeyConfig;
265         const auto &keyParams = config.second.at(0).resourceItem.GetKeyParam();
266         limitKeyConfig.keyCount = keyParams.size();
267         pos += sizeof(limitKeyConfig.keyTag) + sizeof(limitKeyConfig.offset) + sizeof(limitKeyConfig.keyCount);
268         for (const auto &keyParam : keyParams) {
269             limitKeyConfig.data.push_back(static_cast<int32_t>(keyParam.keyType));
270             limitKeyConfig.data.push_back(static_cast<int32_t>(keyParam.value));
271             pos += sizeof(KeyParam);
272         }
273         limitKeyConfigs.emplace(config.first, limitKeyConfig);
274     }
275 
276     for (const auto &config : configs) {
277         auto limitKeyConfig = limitKeyConfigs.find(config.first);
278         if (limitKeyConfig == limitKeyConfigs.end()) {
279             PrintError(GetError(ERR_CODE_INVALID_LIMIT_KEY).FormatCause(config.first.c_str()));
280             return false;
281         }
282         limitKeyConfig->second.offset = pos;
283 
284         IdSet idSet;
285         idSet.idCount = config.second.size();
286         pos += sizeof(idSet.idTag) + sizeof(idSet.idCount);
287         for (const auto &tableData : config.second) {
288             idSet.data.emplace(tableData.id, 0);
289             pos += sizeof(uint32_t) + sizeof(uint32_t);
290         }
291         idSets.emplace(config.first, idSet);
292     }
293     return true;
294 }
295 
SaveRecordItem(const map<string,vector<TableData>> & configs,ostringstream & out,map<string,IdSet> & idSets,uint32_t & pos) const296 bool ResourceTable::SaveRecordItem(const map<string, vector<TableData>> &configs,
297                                    ostringstream &out, map<string, IdSet> &idSets, uint32_t &pos) const
298 {
299     for (const auto &config : configs) {
300         auto idSet = idSets.find(config.first);
301         if (idSet == idSets.end()) {
302             PrintError(GetError(ERR_CODE_INVALID_LIMIT_KEY).FormatCause(config.first.c_str()));
303             return false;
304         }
305 
306         for (const auto &tableData : config.second) {
307             if (idSet->second.data.find(tableData.id) == idSet->second.data.end()) {
308                 string resType = ResourceUtil::ResTypeToString(tableData.resourceItem.GetResType());
309                 string name = tableData.resourceItem.GetName();
310                 PrintError(GetError(ERR_CODE_RESOURCE_ID_NOT_DEFINED).FormatCause(name.c_str(), resType.c_str()));
311                 return false;
312             }
313             idSet->second.data[tableData.id] = pos;
314             RecordItem recordItem;
315             recordItem.id = tableData.id;
316             recordItem.resType = static_cast<int32_t>(tableData.resourceItem.GetResType());
317             vector<string> contents;
318             string value(reinterpret_cast<const char *>(tableData.resourceItem.GetData()),
319                 tableData.resourceItem.GetDataLength());
320             contents.push_back(value);
321             string name = ResourceUtil::GetIdName(tableData.resourceItem.GetName(),
322                 tableData.resourceItem.GetResType());
323             contents.push_back(name);
324             string data = ResourceUtil::ComposeStrings(contents, true);
325             recordItem.size = sizeof(RecordItem) + data.length() - sizeof(uint32_t);
326             pos += recordItem.size + sizeof(uint32_t);
327 
328             out.write(reinterpret_cast<const char *>(&recordItem.size), sizeof(uint32_t));
329             out.write(reinterpret_cast<const char *>(&recordItem.resType), sizeof(uint32_t));
330             out.write(reinterpret_cast<const char *>(&recordItem.id), sizeof(uint32_t));
331             out.write(reinterpret_cast<const char *>(data.c_str()), data.length());
332         }
333     }
334     return true;
335 }
336 
SaveHeader(const IndexHeader & indexHeader,ostringstream & out) const337 void ResourceTable::SaveHeader(const IndexHeader &indexHeader, ostringstream &out) const
338 {
339     out.write(reinterpret_cast<const char *>(&indexHeader.version), VERSION_MAX_LEN);
340     out.write(reinterpret_cast<const char *>(&indexHeader.fileSize), sizeof(uint32_t));
341     out.write(reinterpret_cast<const char *>(&indexHeader.limitKeyConfigSize), sizeof(uint32_t));
342 }
343 
SaveLimitKeyConfigs(const map<string,LimitKeyConfig> & limitKeyConfigs,ostringstream & out) const344 void ResourceTable::SaveLimitKeyConfigs(const map<string, LimitKeyConfig> &limitKeyConfigs, ostringstream &out) const
345 {
346     for (const auto &iter : limitKeyConfigs) {
347         out.write(reinterpret_cast<const char *>(iter.second.keyTag), TAG_LEN);
348         out.write(reinterpret_cast<const char *>(&iter.second.offset), sizeof(uint32_t));
349         out.write(reinterpret_cast<const char *>(&iter.second.keyCount), sizeof(uint32_t));
350         for (const auto &value : iter.second.data) {
351             out.write(reinterpret_cast<const char *>(&value), sizeof(int32_t));
352         }
353     }
354 }
355 
SaveIdSets(const map<string,IdSet> & idSets,ostringstream & out) const356 void ResourceTable::SaveIdSets(const map<string, IdSet> &idSets, ostringstream &out) const
357 {
358     for (const auto &iter : idSets) {
359         out.write(reinterpret_cast<const char *>(iter.second.idTag), TAG_LEN);
360         out.write(reinterpret_cast<const char *>(&iter.second.idCount), sizeof(uint32_t));
361         for (const auto &keyValue : iter.second.data) {
362             out.write(reinterpret_cast<const char *>(&keyValue.first), sizeof(uint32_t));
363             out.write(reinterpret_cast<const char *>(&keyValue.second), sizeof(uint32_t));
364         }
365     }
366 }
367 
ReadFileHeader(basic_istream<char> & in,IndexHeader & indexHeader,uint64_t & pos,uint64_t length)368 bool ResourceTable::ReadFileHeader(basic_istream<char> &in, IndexHeader &indexHeader, uint64_t &pos, uint64_t length)
369 {
370     pos += sizeof(indexHeader);
371     if (pos > length) {
372         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("header length error"));
373         return false;
374     }
375     in.read(reinterpret_cast<char *>(indexHeader.version), VERSION_MAX_LEN);
376     in.read(reinterpret_cast<char *>(&indexHeader.fileSize), INT_TO_BYTES);
377     in.read(reinterpret_cast<char *>(&indexHeader.limitKeyConfigSize), INT_TO_BYTES);
378     return true;
379 }
380 
ReadLimitKeys(basic_istream<char> & in,map<int64_t,vector<KeyParam>> & limitKeys,uint32_t count,uint64_t & pos,uint64_t length)381 bool ResourceTable::ReadLimitKeys(basic_istream<char> &in, map<int64_t, vector<KeyParam>> &limitKeys,
382                                   uint32_t count, uint64_t &pos, uint64_t length)
383 {
384     for (uint32_t i = 0; i< count; i++) {
385         pos = pos + TAG_LEN + INT_TO_BYTES + INT_TO_BYTES;
386         if (pos > length) {
387             PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("KEYS length error"));
388             return false;
389         }
390         LimitKeyConfig limitKey;
391         in.read(reinterpret_cast<char *>(limitKey.keyTag), TAG_LEN);
392         string keyTag(reinterpret_cast<const char *>(limitKey.keyTag), TAG_LEN);
393         if (keyTag != "KEYS") {
394             PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX)
395                 .FormatCause(string("invalid key tag = " + keyTag).c_str()));
396             return false;
397         }
398         in.read(reinterpret_cast<char *>(&limitKey.offset), INT_TO_BYTES);
399         in.read(reinterpret_cast<char *>(&limitKey.keyCount), INT_TO_BYTES);
400 
401         vector<KeyParam> keyParams;
402         for (uint32_t j = 0; j < limitKey.keyCount; j++) {
403             pos = pos + INT_TO_BYTES + INT_TO_BYTES;
404             if (pos > length) {
405                 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("keyParams length error"));
406                 return false;
407             }
408             KeyParam keyParam;
409             in.read(reinterpret_cast<char *>(&keyParam.keyType), INT_TO_BYTES);
410             in.read(reinterpret_cast<char *>(&keyParam.value), INT_TO_BYTES);
411             keyParams.push_back(keyParam);
412         }
413         limitKeys[limitKey.offset] = keyParams;
414     }
415     return true;
416 }
417 
ReadIdTables(basic_istream<char> & in,std::map<int64_t,std::pair<int64_t,int64_t>> & datas,uint32_t count,uint64_t & pos,uint64_t length)418 bool ResourceTable::ReadIdTables(basic_istream<char> &in, std::map<int64_t, std::pair<int64_t, int64_t>> &datas,
419                                  uint32_t count, uint64_t &pos, uint64_t length)
420 {
421     for (uint32_t i = 0; i< count; i++) {
422         pos = pos + TAG_LEN + INT_TO_BYTES;
423         if (pos > length) {
424             PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("IDSS length error"));
425             return false;
426         }
427         IdSet idss;
428         int64_t offset = in.tellg();
429         in.read(reinterpret_cast<char *>(idss.idTag), TAG_LEN);
430         string idTag(reinterpret_cast<const char *>(idss.idTag), TAG_LEN);
431         if (idTag != "IDSS") {
432             PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX)
433                 .FormatCause(string("invalid id tag = " + idTag).c_str()));
434             return false;
435         }
436         in.read(reinterpret_cast<char *>(&idss.idCount), INT_TO_BYTES);
437 
438         for (uint32_t j = 0; j < idss.idCount; j++) {
439             pos = pos + INT_TO_BYTES + INT_TO_BYTES;
440             if (pos > length) {
441                 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("id data length error"));
442                 return false;
443             }
444             IdData data;
445             in.read(reinterpret_cast<char *>(&data.id), INT_TO_BYTES);
446             in.read(reinterpret_cast<char *>(&data.dataOffset), INT_TO_BYTES);
447             datas[data.dataOffset] = make_pair(data.id, offset);
448         }
449     }
450     return true;
451 }
452 
ReadDataRecordPrepare(basic_istream<char> & in,RecordItem & record,uint64_t & pos,uint64_t length)453 bool ResourceTable::ReadDataRecordPrepare(basic_istream<char> &in, RecordItem &record, uint64_t &pos, uint64_t length)
454 {
455     pos = pos + INT_TO_BYTES;
456     if (pos > length) {
457         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("data record length error"));
458         return false;
459     }
460     in.read(reinterpret_cast<char *>(&record.size), INT_TO_BYTES);
461     pos = pos + record.size;
462     if (pos > length) {
463         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("record.size length error"));
464         return false;
465     }
466     in.read(reinterpret_cast<char *>(&record.resType), INT_TO_BYTES);
467     in.read(reinterpret_cast<char *>(&record.id), INT_TO_BYTES);
468     return true;
469 }
470 
ReadDataRecordStart(basic_istream<char> & in,RecordItem & record,const map<int64_t,vector<KeyParam>> & limitKeys,const map<int64_t,pair<int64_t,int64_t>> & datas,map<int64_t,vector<ResourceItem>> & resInfos)471 bool ResourceTable::ReadDataRecordStart(basic_istream<char> &in, RecordItem &record,
472                                         const map<int64_t, vector<KeyParam>> &limitKeys,
473                                         const map<int64_t, pair<int64_t, int64_t>> &datas,
474                                         map<int64_t, vector<ResourceItem>> &resInfos)
475 {
476     int64_t offset = in.tellg();
477     offset = offset - INT_TO_BYTES - INT_TO_BYTES - INT_TO_BYTES;
478     uint16_t value_size = 0;
479     in.read(reinterpret_cast<char *>(&value_size), sizeof(uint16_t));
480     if (value_size + sizeof(uint16_t) > record.size) {
481         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("value size error"));
482         return false;
483     }
484     int8_t values[value_size];
485     in.read(reinterpret_cast<char *>(&values), value_size);
486 
487     uint16_t name_size = 0;
488     in.read(reinterpret_cast<char *>(&name_size), sizeof(uint16_t));
489     if (value_size + sizeof(uint16_t) + name_size + sizeof(uint16_t) > record.size) {
490         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("name size error"));
491         return false;
492     }
493     int8_t name[name_size];
494     in.read(reinterpret_cast<char *>(name), name_size);
495     string filename(reinterpret_cast<char *>(name));
496 
497     auto idTableOffset = datas.find(offset);
498     if (idTableOffset == datas.end()) {
499         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("invalid id offset"));
500         return false;
501     }
502 
503     if (idTableOffset->second.first != record.id) {
504         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("invalid id"));
505         return false;
506     }
507 
508     if (limitKeys.find(idTableOffset->second.second) == limitKeys.end()) {
509         PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("invalid limit key offset"));
510         return false;
511     }
512 
513     const vector<KeyParam> &keyparams = limitKeys.find(datas.find(offset)->second.second)->second;
514     ResourceItem resourceitem(filename, keyparams, g_resTypeMap.find(record.resType)->second);
515     resourceitem.SetLimitKey(ResourceUtil::PaserKeyParam(keyparams));
516     resourceitem.SetData(values, value_size);
517     resourceitem.MarkCoverable();
518     resInfos[record.id].push_back(resourceitem);
519     return true;
520 }
521 
522 }
523 }
524 }
525