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