1 /*
2 * Copyright (c) 2021-2025 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
18 #include <algorithm>
19 #include <cJSON.h>
20 #include <cstdint>
21 #include "cmd/cmd_parser.h"
22 #include "file_entry.h"
23 #include "file_manager.h"
24 #include "resource_util.h"
25 #include "securec.h"
26
27 namespace OHOS {
28 namespace Global {
29 namespace Restool {
30 using namespace std;
ResourceTable(bool isNewModule)31 ResourceTable::ResourceTable(bool isNewModule)
32 {
33 auto &parser = CmdParser::GetInstance();
34 auto &packageParser = parser.GetPackageParser();
35 if (!packageParser.GetIdDefinedOutput().empty()) {
36 idDefinedPath_ = FileEntry::FilePath(packageParser.GetIdDefinedOutput()).Append(ID_DEFINED_FILE).GetPath();
37 }
38 indexFilePath_ = FileEntry::FilePath(packageParser.GetOutput()).Append(RESOURCE_INDEX_FILE).GetPath();
39 newResIndex_ = isNewModule;
40 }
41
~ResourceTable()42 ResourceTable::~ResourceTable()
43 {
44 }
45
CreateResourceTable()46 uint32_t ResourceTable::CreateResourceTable()
47 {
48 FileManager &fileManager = FileManager::GetInstance();
49 auto &allResource = fileManager.GetResources();
50 map<string, vector<TableData>> configs;
51 for (const auto &item : allResource) {
52 for (const auto &resourceItem : item.second) {
53 if (resourceItem.GetResType() == ResType::ID) {
54 break;
55 }
56 TableData tableData;
57 tableData.id = item.first;
58 tableData.resourceItem = resourceItem;
59 configs[resourceItem.GetLimitKey()].push_back(tableData);
60 }
61 }
62
63 if (!newResIndex_) {
64 if (SaveToResouorceIndex(configs) != RESTOOL_SUCCESS) {
65 return RESTOOL_ERROR;
66 }
67 } else {
68 if (SaveToNewResouorceIndex(configs) != RESTOOL_SUCCESS) {
69 return RESTOOL_ERROR;
70 }
71 }
72
73 if (!idDefinedPath_.empty()) {
74 if (CreateIdDefined(allResource) != RESTOOL_SUCCESS) {
75 return RESTOOL_ERROR;
76 }
77 }
78 return RESTOOL_SUCCESS;
79 }
80
CreateResourceTable(const map<int64_t,vector<shared_ptr<ResourceItem>>> & items)81 uint32_t ResourceTable::CreateResourceTable(const map<int64_t, vector<shared_ptr<ResourceItem>>> &items)
82 {
83 map<string, vector<TableData>> configs;
84 map<int64_t, vector<ResourceItem>> allResource;
85 for (const auto &item : items) {
86 vector<ResourceItem> resourceItems;
87 for (const auto &resourceItemPtr : item.second) {
88 if (resourceItemPtr->GetResType() == ResType::ID) {
89 break;
90 }
91 TableData tableData;
92 tableData.id = item.first;
93 tableData.resourceItem = *resourceItemPtr;
94 resourceItems.push_back(*resourceItemPtr);
95 configs[resourceItemPtr->GetLimitKey()].push_back(tableData);
96 }
97 allResource.emplace(item.first, resourceItems);
98 }
99
100 if (!newResIndex_) {
101 if (SaveToResouorceIndex(configs) != RESTOOL_SUCCESS) {
102 return RESTOOL_ERROR;
103 }
104 } else {
105 if (SaveToNewResouorceIndex(configs) != RESTOOL_SUCCESS) {
106 return RESTOOL_ERROR;
107 }
108 }
109
110 if (!idDefinedPath_.empty()) {
111 if (CreateIdDefined(allResource) != RESTOOL_SUCCESS) {
112 return RESTOOL_ERROR;
113 }
114 }
115 return RESTOOL_SUCCESS;
116 }
117
LoadResTable(const string path,map<int64_t,vector<ResourceItem>> & resInfos)118 uint32_t ResourceTable::LoadResTable(const string path, map<int64_t, vector<ResourceItem>> &resInfos)
119 {
120 ifstream in(path, ios::binary);
121 if (!in.is_open()) {
122 PrintError(GetError(ERR_CODE_OPEN_FILE_ERROR).FormatCause(path.c_str(), strerror(errno)));
123 return RESTOOL_ERROR;
124 }
125
126 in.seekg(0, ios::end);
127 int64_t length = in.tellg();
128 if (length <= 0) {
129 in.close();
130 PrintError(GetError(ERR_CODE_READ_FILE_ERROR).FormatCause(path.c_str(), "file is empty"));
131 return RESTOOL_ERROR;
132 }
133 in.seekg(0, ios::beg);
134 uint32_t errorCode = LoadResTable(in, resInfos);
135 in.close();
136 return errorCode;
137 }
138
LoadResTable(basic_istream<char> & in,map<int64_t,vector<ResourceItem>> & resInfos)139 uint32_t ResourceTable::LoadResTable(basic_istream<char> &in, map<int64_t, vector<ResourceItem>> &resInfos)
140 {
141 if (!in) {
142 std::string msg = "file stream bad, state code: " + std::to_string(in.rdstate());
143 PrintError(GetError(ERR_CODE_READ_FILE_ERROR).FormatCause(in.rdstate(), msg.c_str()));
144 return RESTOOL_ERROR;
145 }
146 in.seekg(0, ios::end);
147 int64_t length = in.tellg();
148 in.seekg(0, ios::beg);
149 uint64_t pos = 0;
150 IndexHeader indexHeader;
151 if (!ReadFileHeader(in, indexHeader, pos, static_cast<uint64_t>(length))) {
152 return RESTOOL_ERROR;
153 }
154
155 if (IsNewModule(indexHeader)) {
156 return LoadNewResTable(in, resInfos);
157 }
158
159 map<int64_t, vector<KeyParam>> limitKeys;
160 if (!ReadLimitKeys(in, limitKeys, indexHeader.limitKeyConfigSize, pos, static_cast<uint64_t>(length))) {
161 return RESTOOL_ERROR;
162 }
163
164 map<int64_t, pair<int64_t, int64_t>> datas;
165 if (!ReadIdTables(in, datas, indexHeader.limitKeyConfigSize, pos, static_cast<uint64_t>(length))) {
166 return RESTOOL_ERROR;
167 }
168
169 while (in.tellg() < length) {
170 RecordItem record;
171 if (!ReadDataRecordPrepare(in, record, pos, static_cast<uint64_t>(length)) ||
172 !ReadDataRecordStart(in, record, limitKeys, datas, resInfos)) {
173 return RESTOOL_ERROR;
174 }
175 }
176 return RESTOOL_SUCCESS;
177 }
178
CreateIdDefined(const map<int64_t,vector<ResourceItem>> & allResource) const179 uint32_t ResourceTable::CreateIdDefined(const map<int64_t, vector<ResourceItem>> &allResource) const
180 {
181 cJSON *root = cJSON_CreateObject();
182 cJSON *recordArray = cJSON_CreateArray();
183 if (recordArray == nullptr) {
184 PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("failed to create cJSON object for record array")
185 .SetPosition(idDefinedPath_));
186 cJSON_Delete(root);
187 return RESTOOL_ERROR;
188 }
189 cJSON_AddItemToObject(root, "record", recordArray);
190 for (const auto &pairPtr : allResource) {
191 if (pairPtr.second.empty()) {
192 PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("resource item vector is empty")
193 .SetPosition(idDefinedPath_));
194 cJSON_Delete(root);
195 return RESTOOL_ERROR;
196 }
197 cJSON *jsonItem = cJSON_CreateObject();
198 if (jsonItem == nullptr) {
199 PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("failed to create cJSON object for resource item")
200 .SetPosition(idDefinedPath_));
201 cJSON_Delete(root);
202 return RESTOOL_ERROR;
203 }
204 ResourceItem item = pairPtr.second.front();
205 ResType resType = item.GetResType();
206 string type = ResourceUtil::ResTypeToString(resType);
207 string name = item.GetName();
208 int64_t id = pairPtr.first;
209 if (type.empty()) {
210 string errMsg = "name = ";
211 errMsg.append(name);
212 errMsg.append("invalid restype, type must in ").append(ResourceUtil::GetAllRestypeString());
213 PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause(errMsg.c_str()).SetPosition(idDefinedPath_));
214 cJSON_Delete(jsonItem);
215 cJSON_Delete(root);
216 return RESTOOL_ERROR;
217 }
218 cJSON_AddStringToObject(jsonItem, "type", type.c_str());
219 cJSON_AddStringToObject(jsonItem, "name", ResourceUtil::GetIdName(name, resType).c_str());
220 cJSON_AddStringToObject(jsonItem, "id", ResourceUtil::DecToHexStr(id).c_str());
221 cJSON_AddItemToArray(recordArray, jsonItem);
222 }
223 if (!ResourceUtil::SaveToJsonFile(idDefinedPath_, root)) {
224 cJSON_Delete(root);
225 return RESTOOL_ERROR;
226 }
227 cJSON_Delete(root);
228 return RESTOOL_SUCCESS;
229 }
230
231 // below private
SaveToResouorceIndex(const map<string,vector<TableData>> & configs) const232 uint32_t ResourceTable::SaveToResouorceIndex(const map<string, vector<TableData>> &configs) const
233 {
234 uint32_t pos = 0;
235 IndexHeader indexHeader;
236 if (!InitIndexHeader(indexHeader, configs.size())) {
237 return RESTOOL_ERROR;
238 }
239 pos += sizeof(IndexHeader);
240
241 map<string, LimitKeyConfig> limitKeyConfigs;
242 map<string, IdSet> idSets;
243 if (!Prepare(configs, limitKeyConfigs, idSets, pos)) {
244 return RESTOOL_ERROR;
245 }
246
247 ofstream out(indexFilePath_, ofstream::out | ofstream::binary);
248 if (!out.is_open()) {
249 PrintError(GetError(ERR_CODE_OPEN_FILE_ERROR).FormatCause(indexFilePath_.c_str(), strerror(errno)));
250 return RESTOOL_ERROR;
251 }
252
253 ostringstream outStreamData;
254 if (!SaveRecordItem(configs, outStreamData, idSets, pos)) {
255 return RESTOOL_ERROR;
256 }
257
258 ostringstream outStreamHeader;
259 indexHeader.fileSize = pos;
260 SaveHeader(indexHeader, outStreamHeader);
261 SaveLimitKeyConfigs(limitKeyConfigs, outStreamHeader);
262 SaveIdSets(idSets, outStreamHeader);
263 out << outStreamHeader.str();
264 out << outStreamData.str();
265 return RESTOOL_SUCCESS;
266 }
267
InitHeader(IndexHeaderV2 & indexHeader,IdSetHeader & idSetHeader,DataHeader & dataHeader,uint32_t count)268 bool ResourceTable::InitHeader(IndexHeaderV2 &indexHeader, IdSetHeader &idSetHeader,
269 DataHeader &dataHeader, uint32_t count)
270 {
271 std::string restoolVersion = RESTOOLV2_NAME + RESTOOL_VERSION;
272 if (memcpy_s(indexHeader.version, VERSION_MAX_LEN, restoolVersion.data(), restoolVersion.length()) != EOK) {
273 PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("memcpy error when init index header"));
274 return false;
275 }
276
277 indexHeader.keyCount = count;
278 indexHeader.length = IndexHeaderV2::INDEX_HEADER_LEN;
279 indexHeader.keyConfigs.reserve(indexHeader.keyCount);
280 idSetHeader.length = IdSetHeader::ID_SET_HEADER_LEN;
281 dataHeader.length = DataHeader::DATA_HEADER_LEN;
282 return true;
283 }
284
PrepareKeyConfig(IndexHeaderV2 & indexHeader,const uint32_t configId,const string & config,const vector<TableData> & data)285 void ResourceTable::PrepareKeyConfig(IndexHeaderV2 &indexHeader, const uint32_t configId,
286 const string &config, const vector<TableData> &data)
287 {
288 const vector<KeyParam> &keyParams = data[0].resourceItem.GetKeyParam();
289 KeyConfig keyConfig;
290 keyConfig.configId = configId;
291 keyConfig.keyCount = keyParams.size();
292 keyConfig.configs.reserve(keyConfig.keyCount);
293 indexHeader.length += KeyConfig::KEY_CONFIG_HEADER_LEN;
294 for (const auto ¶m : keyParams) {
295 keyConfig.configs.push_back(param);
296 indexHeader.length += KeyParam::KEY_PARAM_LEN;
297 }
298 indexHeader.keyConfigs[config] = keyConfig;
299 }
300
PrepareResIndex(IdSetHeader & idSetHeader,const TableData & tableData)301 void ResourceTable::PrepareResIndex(IdSetHeader &idSetHeader, const TableData &tableData)
302 {
303 ResType resType = tableData.resourceItem.GetResType();
304 if (idSetHeader.resTypes.find(resType) == idSetHeader.resTypes.end()) {
305 ResTypeHeader resTypeHeader;
306 resTypeHeader.resType = resType;
307 resTypeHeader.length = ResTypeHeader::RES_TYPE_HEADER_LEN;
308 idSetHeader.resTypes[resTypeHeader.resType] = resTypeHeader;
309 idSetHeader.typeCount++;
310 idSetHeader.length += ResTypeHeader::RES_TYPE_HEADER_LEN;
311 }
312 if (idSetHeader.resTypes[resType].resIndexs.find(tableData.id) != idSetHeader.resTypes[resType].resIndexs.end()) {
313 return;
314 }
315
316 ResIndex resIndex;
317 resIndex.resId = tableData.id;
318 resIndex.name = ResourceUtil::GetIdName(tableData.resourceItem.GetName(), resType);
319 resIndex.length = resIndex.name.length();
320 idSetHeader.resTypes[resType].resIndexs[tableData.id] = resIndex;
321 idSetHeader.resTypes[resType].length += ResIndex::RES_INDEX_LEN + resIndex.length;
322 idSetHeader.resTypes[resType].count++;
323 idSetHeader.length += ResIndex::RES_INDEX_LEN + resIndex.length;
324 }
325
PrepareResInfo(DataHeader & dataHeader,const uint32_t resId,const uint32_t configId,const uint32_t dataPoolLen)326 void ResourceTable::PrepareResInfo(DataHeader &dataHeader, const uint32_t resId,
327 const uint32_t configId, const uint32_t dataPoolLen)
328 {
329 if (dataHeader.resInfos.find(resId) == dataHeader.resInfos.end()) {
330 ResInfo resInfo;
331 resInfo.resId = resId;
332 resInfo.length = ResInfo::RES_INFO_LEN;
333 dataHeader.resInfos[resInfo.resId] = resInfo;
334 dataHeader.length += ResInfo::RES_INFO_LEN;
335 dataHeader.idCount++;
336 }
337 dataHeader.resInfos[resId].dataOffset[configId] = dataPoolLen;
338 dataHeader.resInfos[resId].length += ResInfo::DATA_OFFSET_LEN;
339 dataHeader.resInfos[resId].valueCount++;
340 dataHeader.length += ResInfo::DATA_OFFSET_LEN;
341 }
342
WriteDataPool(ostringstream & dataPool,const ResourceItem & resourceItem,uint32_t & dataPoolLen)343 void ResourceTable::WriteDataPool(ostringstream &dataPool, const ResourceItem &resourceItem, uint32_t &dataPoolLen)
344 {
345 uint32_t length = resourceItem.GetDataLength();
346 const int8_t *data = resourceItem.GetData();
347 dataPool.write(reinterpret_cast<const char *>(&length), sizeof(uint16_t));
348 dataPool.write(reinterpret_cast<const char *>(data), length);
349 dataPoolLen += sizeof(uint16_t) + length;
350 }
351
WriteResInfo(ostringstream & dataBlock,const DataHeader & idSetHeader,const uint32_t dataBlockOffset,unordered_map<uint32_t,uint32_t> & idOffsetMap)352 void ResourceTable::WriteResInfo(ostringstream &dataBlock, const DataHeader &idSetHeader,
353 const uint32_t dataBlockOffset, unordered_map<uint32_t, uint32_t> &idOffsetMap)
354 {
355 uint32_t offset = dataBlockOffset;
356 dataBlock.write(reinterpret_cast<const char *>(idSetHeader.idTag), TAG_LEN);
357 dataBlock.write(reinterpret_cast<const char *>(&idSetHeader.length), sizeof(uint32_t));
358 dataBlock.write(reinterpret_cast<const char *>(&idSetHeader.idCount), sizeof(uint32_t));
359 offset += DataHeader::DATA_HEADER_LEN;
360 for (const auto &resInfo : idSetHeader.resInfos) {
361 idOffsetMap[resInfo.second.resId] = offset;
362 dataBlock.write(reinterpret_cast<const char *>(&resInfo.second.resId), sizeof(uint32_t));
363 dataBlock.write(reinterpret_cast<const char *>(&resInfo.second.length), sizeof(uint32_t));
364 dataBlock.write(reinterpret_cast<const char *>(&resInfo.second.valueCount), sizeof(uint32_t));
365 offset += ResInfo::RES_INFO_LEN;
366 for (const auto &dataOffset : resInfo.second.dataOffset) {
367 uint32_t configId = dataOffset.first;
368 uint32_t realOffset = dataOffset.second + idSetHeader.length + dataBlockOffset;
369 dataBlock.write(reinterpret_cast<const char *>(&configId), sizeof(uint32_t));
370 dataBlock.write(reinterpret_cast<const char *>(&realOffset), sizeof(uint32_t));
371 offset += ResInfo::DATA_OFFSET_LEN;
372 }
373 }
374 }
375
WriteIdSet(ostringstream & idSetBlock,const IdSetHeader & idSetHeader,const unordered_map<uint32_t,uint32_t> & idOffsetMap)376 void ResourceTable::WriteIdSet(ostringstream &idSetBlock, const IdSetHeader &idSetHeader,
377 const unordered_map<uint32_t, uint32_t> &idOffsetMap)
378 {
379 idSetBlock.write(reinterpret_cast<const char *>(idSetHeader.idTag), TAG_LEN);
380 idSetBlock.write(reinterpret_cast<const char *>(&idSetHeader.length), sizeof(uint32_t));
381 idSetBlock.write(reinterpret_cast<const char *>(&idSetHeader.typeCount), sizeof(uint32_t));
382 idSetBlock.write(reinterpret_cast<const char *>(&idSetHeader.idCount), sizeof(uint32_t));
383 for (const auto &resType : idSetHeader.resTypes) {
384 idSetBlock.write(reinterpret_cast<const char *>(&resType.second.resType), sizeof(uint32_t));
385 idSetBlock.write(reinterpret_cast<const char *>(&resType.second.length), sizeof(uint32_t));
386 idSetBlock.write(reinterpret_cast<const char *>(&resType.second.count), sizeof(uint32_t));
387 for (const auto &resIndex : resType.second.resIndexs) {
388 uint32_t realOffset = idOffsetMap.find(resIndex.second.resId)->second;
389 idSetBlock.write(reinterpret_cast<const char *>(&resIndex.second.resId), sizeof(uint32_t));
390 idSetBlock.write(reinterpret_cast<const char *>(&realOffset), sizeof(uint32_t));
391 idSetBlock.write(reinterpret_cast<const char *>(&resIndex.second.length), sizeof(uint32_t));
392 idSetBlock.write(reinterpret_cast<const char *>(
393 resIndex.second.name.c_str()), resIndex.second.length);
394 }
395 }
396 }
397
WriteResHeader(ostringstream & resHeaderBlock,const IndexHeaderV2 & indexHeader)398 void ResourceTable::WriteResHeader(ostringstream &resHeaderBlock, const IndexHeaderV2 &indexHeader)
399 {
400 resHeaderBlock.write(reinterpret_cast<const char *>(indexHeader.version), VERSION_MAX_LEN);
401 resHeaderBlock.write(reinterpret_cast<const char *>(&indexHeader.length), sizeof(uint32_t));
402 resHeaderBlock.write(reinterpret_cast<const char *>(&indexHeader.keyCount), sizeof(uint32_t));
403 resHeaderBlock.write(reinterpret_cast<const char *>(&indexHeader.dataBlockOffset), sizeof(uint32_t));
404 for (const auto &keyConfig : indexHeader.keyConfigs) {
405 resHeaderBlock.write(reinterpret_cast<const char *>(keyConfig.second.keyTag), TAG_LEN);
406 resHeaderBlock.write(reinterpret_cast<const char *>(&keyConfig.second.configId), sizeof(uint32_t));
407 resHeaderBlock.write(reinterpret_cast<const char *>(&keyConfig.second.keyCount), sizeof(uint32_t));
408 for (const auto &config : keyConfig.second.configs) {
409 resHeaderBlock.write(reinterpret_cast<const char *>(&config.keyType), sizeof(int32_t));
410 resHeaderBlock.write(reinterpret_cast<const char *>(&config.value), sizeof(int32_t));
411 }
412 }
413 }
414
WriteToIndex(const IndexHeaderV2 & indexHeader,const IdSetHeader & idSetHeader,const DataHeader & dataHeader,const ostringstream & dataPool,ofstream & out)415 void ResourceTable::WriteToIndex(const IndexHeaderV2 &indexHeader, const IdSetHeader &idSetHeader,
416 const DataHeader &dataHeader, const ostringstream &dataPool, ofstream &out)
417 {
418 ostringstream dataBlock;
419 unordered_map<uint32_t, uint32_t> idOffsetMap;
420 WriteResInfo(dataBlock, dataHeader, indexHeader.dataBlockOffset, idOffsetMap);
421
422 ostringstream idSetBlock;
423 WriteIdSet(idSetBlock, idSetHeader, idOffsetMap);
424
425 ostringstream resHeaderBlock;
426 WriteResHeader(resHeaderBlock, indexHeader);
427
428 out << resHeaderBlock.str();
429 out << idSetBlock.str();
430 out << dataBlock.str();
431 out << dataPool.str();
432 }
433
SaveToNewResouorceIndex(const map<string,vector<TableData>> & configs) const434 uint32_t ResourceTable::SaveToNewResouorceIndex(const map<string, vector<TableData>> &configs) const
435 {
436 IndexHeaderV2 indexHeader;
437 IdSetHeader idSetHeader;
438 DataHeader dataHeader;
439
440 if (!InitHeader(indexHeader, idSetHeader, dataHeader, configs.size())) {
441 return false;
442 }
443
444 ostringstream dataPool;
445 uint32_t dataPoolLen = 0;
446 uint32_t configId = 0;
447 for (const auto &config : configs) {
448 PrepareKeyConfig(indexHeader, configId, config.first, config.second);
449 for (const auto &tableData : config.second) {
450 PrepareResIndex(idSetHeader, tableData);
451 PrepareResInfo(dataHeader, tableData.id, configId, dataPoolLen);
452 WriteDataPool(dataPool, tableData.resourceItem, dataPoolLen);
453 }
454 configId++;
455 }
456 idSetHeader.idCount = dataHeader.idCount;
457 indexHeader.dataBlockOffset = indexHeader.length + idSetHeader.length;
458 indexHeader.length += idSetHeader.length + dataHeader.length + dataPoolLen;
459
460 ofstream out(indexFilePath_, ofstream::out | ofstream::binary);
461 if (!out.is_open()) {
462 PrintError(GetError(ERR_CODE_OPEN_FILE_ERROR).FormatCause(indexFilePath_.c_str(), strerror(errno)));
463 return RESTOOL_ERROR;
464 }
465 WriteToIndex(indexHeader, idSetHeader, dataHeader, dataPool, out);
466 return RESTOOL_SUCCESS;
467 }
468
InitIndexHeader(IndexHeader & indexHeader,uint32_t count) const469 bool ResourceTable::InitIndexHeader(IndexHeader &indexHeader, uint32_t count) const
470 {
471 std::string restoolVersion = RESTOOL_NAME + RESTOOL_VERSION;
472 if (memcpy_s(indexHeader.version, VERSION_MAX_LEN, restoolVersion.data(), restoolVersion.length()) != EOK) {
473 PrintError(GetError(ERR_CODE_UNDEFINED_ERROR).FormatCause("memcpy error when init index header"));
474 return false;
475 }
476 indexHeader.limitKeyConfigSize = count;
477 return true;
478 }
479
Prepare(const map<string,vector<TableData>> & configs,map<string,LimitKeyConfig> & limitKeyConfigs,map<string,IdSet> & idSets,uint32_t & pos) const480 bool ResourceTable::Prepare(const map<string, vector<TableData>> &configs,
481 map<string, LimitKeyConfig> &limitKeyConfigs,
482 map<string, IdSet> &idSets, uint32_t &pos) const
483 {
484 for (const auto &config : configs) {
485 LimitKeyConfig limitKeyConfig;
486 const auto &keyParams = config.second.at(0).resourceItem.GetKeyParam();
487 limitKeyConfig.keyCount = keyParams.size();
488 pos += sizeof(limitKeyConfig.keyTag) + sizeof(limitKeyConfig.offset) + sizeof(limitKeyConfig.keyCount);
489 for (const auto &keyParam : keyParams) {
490 limitKeyConfig.data.push_back(static_cast<int32_t>(keyParam.keyType));
491 limitKeyConfig.data.push_back(static_cast<int32_t>(keyParam.value));
492 pos += sizeof(KeyParam);
493 }
494 limitKeyConfigs.emplace(config.first, limitKeyConfig);
495 }
496
497 for (const auto &config : configs) {
498 auto limitKeyConfig = limitKeyConfigs.find(config.first);
499 if (limitKeyConfig == limitKeyConfigs.end()) {
500 PrintError(GetError(ERR_CODE_INVALID_LIMIT_KEY).FormatCause(config.first.c_str()));
501 return false;
502 }
503 limitKeyConfig->second.offset = pos;
504
505 IdSet idSet;
506 idSet.idCount = config.second.size();
507 pos += sizeof(idSet.idTag) + sizeof(idSet.idCount);
508 for (const auto &tableData : config.second) {
509 idSet.data.emplace(tableData.id, 0);
510 pos += sizeof(uint32_t) + sizeof(uint32_t);
511 }
512 idSets.emplace(config.first, idSet);
513 }
514 return true;
515 }
516
SaveRecordItem(const map<string,vector<TableData>> & configs,ostringstream & out,map<string,IdSet> & idSets,uint32_t & pos) const517 bool ResourceTable::SaveRecordItem(const map<string, vector<TableData>> &configs,
518 ostringstream &out, map<string, IdSet> &idSets, uint32_t &pos) const
519 {
520 for (const auto &config : configs) {
521 auto idSet = idSets.find(config.first);
522 if (idSet == idSets.end()) {
523 PrintError(GetError(ERR_CODE_INVALID_LIMIT_KEY).FormatCause(config.first.c_str()));
524 return false;
525 }
526
527 for (const auto &tableData : config.second) {
528 if (idSet->second.data.find(tableData.id) == idSet->second.data.end()) {
529 string resType = ResourceUtil::ResTypeToString(tableData.resourceItem.GetResType());
530 string name = tableData.resourceItem.GetName();
531 PrintError(GetError(ERR_CODE_RESOURCE_ID_NOT_DEFINED).FormatCause(name.c_str(), resType.c_str()));
532 return false;
533 }
534 idSet->second.data[tableData.id] = pos;
535 RecordItem recordItem;
536 recordItem.id = tableData.id;
537 recordItem.resType = static_cast<int32_t>(tableData.resourceItem.GetResType());
538 vector<string> contents;
539 string value(reinterpret_cast<const char *>(tableData.resourceItem.GetData()),
540 tableData.resourceItem.GetDataLength());
541 contents.push_back(value);
542 string name = ResourceUtil::GetIdName(tableData.resourceItem.GetName(),
543 tableData.resourceItem.GetResType());
544 contents.push_back(name);
545 string data = ResourceUtil::ComposeStrings(contents, true);
546 recordItem.size = sizeof(RecordItem) + data.length() - sizeof(uint32_t);
547 pos += recordItem.size + sizeof(uint32_t);
548
549 out.write(reinterpret_cast<const char *>(&recordItem.size), sizeof(uint32_t));
550 out.write(reinterpret_cast<const char *>(&recordItem.resType), sizeof(uint32_t));
551 out.write(reinterpret_cast<const char *>(&recordItem.id), sizeof(uint32_t));
552 out.write(reinterpret_cast<const char *>(data.c_str()), data.length());
553 }
554 }
555 return true;
556 }
557
SaveHeader(const IndexHeader & indexHeader,ostringstream & out) const558 void ResourceTable::SaveHeader(const IndexHeader &indexHeader, ostringstream &out) const
559 {
560 out.write(reinterpret_cast<const char *>(&indexHeader.version), VERSION_MAX_LEN);
561 out.write(reinterpret_cast<const char *>(&indexHeader.fileSize), sizeof(uint32_t));
562 out.write(reinterpret_cast<const char *>(&indexHeader.limitKeyConfigSize), sizeof(uint32_t));
563 }
564
SaveLimitKeyConfigs(const map<string,LimitKeyConfig> & limitKeyConfigs,ostringstream & out) const565 void ResourceTable::SaveLimitKeyConfigs(const map<string, LimitKeyConfig> &limitKeyConfigs, ostringstream &out) const
566 {
567 for (const auto &iter : limitKeyConfigs) {
568 out.write(reinterpret_cast<const char *>(iter.second.keyTag), TAG_LEN);
569 out.write(reinterpret_cast<const char *>(&iter.second.offset), sizeof(uint32_t));
570 out.write(reinterpret_cast<const char *>(&iter.second.keyCount), sizeof(uint32_t));
571 for (const auto &value : iter.second.data) {
572 out.write(reinterpret_cast<const char *>(&value), sizeof(int32_t));
573 }
574 }
575 }
576
SaveIdSets(const map<string,IdSet> & idSets,ostringstream & out) const577 void ResourceTable::SaveIdSets(const map<string, IdSet> &idSets, ostringstream &out) const
578 {
579 for (const auto &iter : idSets) {
580 out.write(reinterpret_cast<const char *>(iter.second.idTag), TAG_LEN);
581 out.write(reinterpret_cast<const char *>(&iter.second.idCount), sizeof(uint32_t));
582 for (const auto &keyValue : iter.second.data) {
583 out.write(reinterpret_cast<const char *>(&keyValue.first), sizeof(uint32_t));
584 out.write(reinterpret_cast<const char *>(&keyValue.second), sizeof(uint32_t));
585 }
586 }
587 }
588
ReadFileHeader(basic_istream<char> & in,IndexHeader & indexHeader,uint64_t & pos,uint64_t length)589 bool ResourceTable::ReadFileHeader(basic_istream<char> &in, IndexHeader &indexHeader, uint64_t &pos, uint64_t length)
590 {
591 pos += sizeof(indexHeader);
592 if (pos > length) {
593 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("header length error"));
594 return false;
595 }
596 in.read(reinterpret_cast<char *>(indexHeader.version), VERSION_MAX_LEN);
597 in.read(reinterpret_cast<char *>(&indexHeader.fileSize), sizeof(uint32_t));
598 in.read(reinterpret_cast<char *>(&indexHeader.limitKeyConfigSize), sizeof(uint32_t));
599 return true;
600 }
601
ReadLimitKeys(basic_istream<char> & in,map<int64_t,vector<KeyParam>> & limitKeys,uint32_t count,uint64_t & pos,uint64_t length)602 bool ResourceTable::ReadLimitKeys(basic_istream<char> &in, map<int64_t, vector<KeyParam>> &limitKeys,
603 uint32_t count, uint64_t &pos, uint64_t length)
604 {
605 for (uint32_t i = 0; i< count; i++) {
606 pos = pos + TAG_LEN + sizeof(uint32_t) + sizeof(uint32_t);
607 if (pos > length) {
608 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("KEYS length error"));
609 return false;
610 }
611 LimitKeyConfig limitKey;
612 in.read(reinterpret_cast<char *>(limitKey.keyTag), TAG_LEN);
613 string keyTag(reinterpret_cast<const char *>(limitKey.keyTag), TAG_LEN);
614 if (keyTag != "KEYS") {
615 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX)
616 .FormatCause(string("invalid key tag = " + keyTag).c_str()));
617 return false;
618 }
619 in.read(reinterpret_cast<char *>(&limitKey.offset), sizeof(uint32_t));
620 in.read(reinterpret_cast<char *>(&limitKey.keyCount), sizeof(uint32_t));
621
622 vector<KeyParam> keyParams;
623 for (uint32_t j = 0; j < limitKey.keyCount; j++) {
624 pos = pos + sizeof(uint32_t) + sizeof(uint32_t);
625 if (pos > length) {
626 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("keyParams length error"));
627 return false;
628 }
629 KeyParam keyParam;
630 in.read(reinterpret_cast<char *>(&keyParam.keyType), sizeof(uint32_t));
631 in.read(reinterpret_cast<char *>(&keyParam.value), sizeof(uint32_t));
632 keyParams.push_back(keyParam);
633 }
634 limitKeys[limitKey.offset] = keyParams;
635 }
636 return true;
637 }
638
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)639 bool ResourceTable::ReadIdTables(basic_istream<char> &in, std::map<int64_t, std::pair<int64_t, int64_t>> &datas,
640 uint32_t count, uint64_t &pos, uint64_t length)
641 {
642 for (uint32_t i = 0; i< count; i++) {
643 pos = pos + TAG_LEN + sizeof(uint32_t);
644 if (pos > length) {
645 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("IDSS length error"));
646 return false;
647 }
648 IdSet idss;
649 int64_t offset = in.tellg();
650 in.read(reinterpret_cast<char *>(idss.idTag), TAG_LEN);
651 string idTag(reinterpret_cast<const char *>(idss.idTag), TAG_LEN);
652 if (idTag != "IDSS") {
653 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX)
654 .FormatCause(string("invalid id tag = " + idTag).c_str()));
655 return false;
656 }
657 in.read(reinterpret_cast<char *>(&idss.idCount), sizeof(uint32_t));
658
659 for (uint32_t j = 0; j < idss.idCount; j++) {
660 pos = pos + sizeof(uint32_t) + sizeof(uint32_t);
661 if (pos > length) {
662 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("id data length error"));
663 return false;
664 }
665 IdData data;
666 in.read(reinterpret_cast<char *>(&data.id), sizeof(uint32_t));
667 in.read(reinterpret_cast<char *>(&data.dataOffset), sizeof(uint32_t));
668 datas[data.dataOffset] = make_pair(data.id, offset);
669 }
670 }
671 return true;
672 }
673
ReadDataRecordPrepare(basic_istream<char> & in,RecordItem & record,uint64_t & pos,uint64_t length)674 bool ResourceTable::ReadDataRecordPrepare(basic_istream<char> &in, RecordItem &record, uint64_t &pos, uint64_t length)
675 {
676 pos = pos + sizeof(uint32_t);
677 if (pos > length) {
678 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("data record length error"));
679 return false;
680 }
681 in.read(reinterpret_cast<char *>(&record.size), sizeof(uint32_t));
682 pos = pos + record.size;
683 if (pos > length) {
684 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("record.size length error"));
685 return false;
686 }
687 in.read(reinterpret_cast<char *>(&record.resType), sizeof(uint32_t));
688 in.read(reinterpret_cast<char *>(&record.id), sizeof(uint32_t));
689 return true;
690 }
691
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)692 bool ResourceTable::ReadDataRecordStart(basic_istream<char> &in, RecordItem &record,
693 const map<int64_t, vector<KeyParam>> &limitKeys,
694 const map<int64_t, pair<int64_t, int64_t>> &datas,
695 map<int64_t, vector<ResourceItem>> &resInfos)
696 {
697 int64_t offset = in.tellg();
698 offset = offset - sizeof(uint32_t) - sizeof(uint32_t) - sizeof(uint32_t);
699 uint16_t value_size = 0;
700 in.read(reinterpret_cast<char *>(&value_size), sizeof(uint16_t));
701 if (value_size + sizeof(uint16_t) > record.size) {
702 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("value size error"));
703 return false;
704 }
705 int8_t values[value_size];
706 in.read(reinterpret_cast<char *>(&values), value_size);
707
708 uint16_t name_size = 0;
709 in.read(reinterpret_cast<char *>(&name_size), sizeof(uint16_t));
710 if (value_size + sizeof(uint16_t) + name_size + sizeof(uint16_t) > record.size) {
711 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("name size error"));
712 return false;
713 }
714 int8_t name[name_size];
715 in.read(reinterpret_cast<char *>(name), name_size);
716 string filename(reinterpret_cast<char *>(name));
717
718 auto idTableOffset = datas.find(offset);
719 if (idTableOffset == datas.end()) {
720 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("invalid id offset"));
721 return false;
722 }
723
724 if (idTableOffset->second.first != record.id) {
725 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("invalid id"));
726 return false;
727 }
728
729 if (limitKeys.find(idTableOffset->second.second) == limitKeys.end()) {
730 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("invalid limit key offset"));
731 return false;
732 }
733
734 const vector<KeyParam> &keyparams = limitKeys.find(datas.find(offset)->second.second)->second;
735 ResourceItem resourceitem(filename, keyparams, g_resTypeMap.find(record.resType)->second);
736 resourceitem.SetLimitKey(ResourceUtil::PaserKeyParam(keyparams));
737 resourceitem.SetData(values, value_size);
738 resourceitem.MarkCoverable();
739 resInfos[record.id].push_back(resourceitem);
740 return true;
741 }
742
IsNewModule(const IndexHeader & indexHeader)743 bool ResourceTable::IsNewModule(const IndexHeader &indexHeader)
744 {
745 string version = string(reinterpret_cast<const char *>(indexHeader.version), VERSION_MAX_LEN);
746 if (version.substr(0, version.find(" ")) == "Restool") {
747 return false;
748 }
749 return true;
750 }
751
LoadNewResTable(basic_istream<char> & in,map<int64_t,vector<ResourceItem>> & resInfos)752 uint32_t ResourceTable::LoadNewResTable(basic_istream<char> &in, map<int64_t, vector<ResourceItem>> &resInfos)
753 {
754 if (!in) {
755 std::string msg = "file stream bad, state code: " + std::to_string(in.rdstate());
756 PrintError(GetError(ERR_CODE_READ_FILE_ERROR).FormatCause(in.rdstate(), msg.c_str()));
757 return RESTOOL_ERROR;
758 }
759 in.seekg(0, ios::end);
760 int64_t length = in.tellg();
761 in.seekg(0, ios::beg);
762 uint64_t pos = 0;
763 IndexHeaderV2 indexHeader;
764 if (!ReadNewFileHeader(in, indexHeader, pos, static_cast<uint64_t>(length))) {
765 return RESTOOL_ERROR;
766 }
767 IdSetHeader idSetHeader;
768 if (!ReadIdSetHeader(in, idSetHeader, pos, static_cast<uint64_t>(length))) {
769 return RESTOOL_ERROR;
770 }
771 for (const auto &resType : idSetHeader.resTypes) {
772 for (const auto &resId : resType.second.resIndexs) {
773 ReadResources(in, resId.second, resType.second, indexHeader, static_cast<uint64_t>(length), resInfos);
774 }
775 }
776 return RESTOOL_SUCCESS;
777 }
778
ReadNewFileHeader(basic_istream<char> & in,IndexHeaderV2 & indexHeader,uint64_t & pos,uint64_t length)779 bool ResourceTable::ReadNewFileHeader(basic_istream<char> &in, IndexHeaderV2 &indexHeader,
780 uint64_t &pos, uint64_t length)
781 {
782 pos += IndexHeaderV2::INDEX_HEADER_LEN;
783 if (pos > length) {
784 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("header length error"));
785 return false;
786 }
787 in.read(reinterpret_cast<char *>(indexHeader.version), VERSION_MAX_LEN);
788 in.read(reinterpret_cast<char *>(&indexHeader.length), sizeof(uint32_t));
789 in.read(reinterpret_cast<char *>(&indexHeader.keyCount), sizeof(uint32_t));
790 in.read(reinterpret_cast<char *>(&indexHeader.dataBlockOffset), sizeof(uint32_t));
791
792 for (uint32_t key = 0; key < indexHeader.keyCount; key++) {
793 pos += KeyConfig::KEY_CONFIG_HEADER_LEN;
794 if (pos > length) {
795 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("KeyConfig header length error"));
796 return false;
797 }
798 KeyConfig keyConfig;
799 in.read(reinterpret_cast<char *>(keyConfig.keyTag), TAG_LEN);
800 in.read(reinterpret_cast<char *>(&keyConfig.configId), sizeof(uint32_t));
801 in.read(reinterpret_cast<char *>(&keyConfig.keyCount), sizeof(uint32_t));
802
803 for (uint32_t keyType = 0; keyType < keyConfig.keyCount; keyType++) {
804 pos += KeyParam::KEY_PARAM_LEN;
805 if (pos > length) {
806 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("KeyParam length error"));
807 return false;
808 }
809 KeyParam keyParam;
810 in.read(reinterpret_cast<char *>(&keyParam.keyType), sizeof(uint32_t));
811 in.read(reinterpret_cast<char *>(&keyParam.value), sizeof(uint32_t));
812 keyConfig.configs.push_back(keyParam);
813 }
814 indexHeader.idKeyConfigs[keyConfig.configId] = keyConfig;
815 }
816 return true;
817 }
818
ReadIdSetHeader(basic_istream<char> & in,IdSetHeader & idSetHeader,uint64_t & pos,uint64_t length)819 bool ResourceTable::ReadIdSetHeader(basic_istream<char> &in, IdSetHeader &idSetHeader, uint64_t &pos, uint64_t length)
820 {
821 pos += IdSetHeader::ID_SET_HEADER_LEN;
822 if (pos > length) {
823 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("IdSet header length error"));
824 return false;
825 }
826 in.read(reinterpret_cast<char *>(idSetHeader.idTag), TAG_LEN);
827 in.read(reinterpret_cast<char *>(&idSetHeader.length), sizeof(uint32_t));
828 in.read(reinterpret_cast<char *>(&idSetHeader.typeCount), sizeof(uint32_t));
829 in.read(reinterpret_cast<char *>(&idSetHeader.idCount), sizeof(uint32_t));
830
831 for (uint32_t resType = 0; resType < idSetHeader.typeCount; resType++) {
832 pos += ResTypeHeader::RES_TYPE_HEADER_LEN;
833 if (pos > length) {
834 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("ResType header length error"));
835 return false;
836 }
837 ResTypeHeader resTypeHeader;
838 in.read(reinterpret_cast<char *>(&resTypeHeader.resType), sizeof(uint32_t));
839 in.read(reinterpret_cast<char *>(&resTypeHeader.length), sizeof(uint32_t));
840 in.read(reinterpret_cast<char *>(&resTypeHeader.count), sizeof(uint32_t));
841
842 for (uint32_t resId = 0; resId < resTypeHeader.count; resId++) {
843 pos += ResIndex::RES_INDEX_LEN;
844 if (pos > length) {
845 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("ResIndex length error"));
846 return false;
847 }
848 ResIndex resIndex;
849 in.read(reinterpret_cast<char *>(&resIndex.resId), sizeof(uint32_t));
850 in.read(reinterpret_cast<char *>(&resIndex.offset), sizeof(uint32_t));
851 in.read(reinterpret_cast<char *>(&resIndex.length), sizeof(uint32_t));
852 pos += resIndex.length;
853 if (pos > length) {
854 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("resource name length error"));
855 return false;
856 }
857 char *name = new char[resIndex.length + 1]();
858 in.read(name, resIndex.length);
859 resIndex.name = string(name, resIndex.length);
860 delete[] name;
861
862 resTypeHeader.resIndexs[resIndex.resId] = resIndex;
863 }
864 idSetHeader.resTypes[resTypeHeader.resType] = resTypeHeader;
865 }
866 return true;
867 }
868
ReadResources(std::basic_istream<char> & in,const ResIndex & resIndex,const ResTypeHeader & resTypeHeader,IndexHeaderV2 & indexHeader,uint64_t length,map<int64_t,vector<ResourceItem>> & resInfos)869 bool ResourceTable::ReadResources(std::basic_istream<char> &in, const ResIndex &resIndex,
870 const ResTypeHeader &resTypeHeader, IndexHeaderV2 &indexHeader, uint64_t length,
871 map<int64_t, vector<ResourceItem>> &resInfos)
872 {
873 ResInfo resInfo;
874 if (!ReadResInfo(in, resInfo, resIndex.offset, length)) {
875 return RESTOOL_ERROR;
876 }
877 uint64_t pos = resIndex.offset + ResInfo::RES_INFO_LEN;
878 for (uint32_t resConfig = 0; resConfig < resInfo.valueCount; resConfig++) {
879 uint32_t resConfigId;
880 uint32_t dataOffset;
881 if (!ReadResConfig(in, resConfigId, dataOffset, pos, length)) {
882 return RESTOOL_ERROR;
883 }
884 ResourceItem resourceItem(resIndex.name, indexHeader.idKeyConfigs[resConfigId].configs,
885 resTypeHeader.resType);
886 resourceItem.SetLimitKey(ResourceUtil::PaserKeyParam(indexHeader.idKeyConfigs[resConfigId].configs));
887 if (!ReadResourceItem(in, resourceItem, dataOffset, pos, length)) {
888 return RESTOOL_ERROR;
889 }
890 resInfos[resIndex.resId].push_back(resourceItem);
891 }
892 return true;
893 }
894
ReadResInfo(std::basic_istream<char> & in,ResInfo & resInfo,uint32_t offset,uint64_t length)895 bool ResourceTable::ReadResInfo(std::basic_istream<char> &in, ResInfo &resInfo, uint32_t offset, uint64_t length)
896 {
897 in.seekg(offset, ios::beg);
898 if (offset + ResInfo::RES_INFO_LEN > length) {
899 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("ResInfo length error"));
900 return false;
901 }
902 in.read(reinterpret_cast<char *>(&resInfo.resId), sizeof(uint32_t));
903 in.read(reinterpret_cast<char *>(&resInfo.length), sizeof(uint32_t));
904 in.read(reinterpret_cast<char *>(&resInfo.valueCount), sizeof(uint32_t));
905 return true;
906 }
907
ReadResConfig(std::basic_istream<char> & in,uint32_t & resConfigId,uint32_t & dataOffset,uint64_t & pos,uint64_t length)908 bool ResourceTable::ReadResConfig(std::basic_istream<char> &in, uint32_t &resConfigId, uint32_t &dataOffset,
909 uint64_t &pos, uint64_t length)
910 {
911 in.seekg(pos, ios::beg);
912 pos += sizeof(uint32_t) + sizeof(uint32_t);
913 if (pos > length) {
914 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("Config id length error"));
915 return false;
916 }
917 in.read(reinterpret_cast<char *>(&resConfigId), sizeof(uint32_t));
918 in.read(reinterpret_cast<char *>(&dataOffset), sizeof(uint32_t));
919 return true;
920 }
921
ReadResourceItem(std::basic_istream<char> & in,ResourceItem & resourceItem,uint32_t dataOffset,uint64_t & pos,uint64_t length)922 bool ResourceTable::ReadResourceItem(std::basic_istream<char> &in, ResourceItem &resourceItem,
923 uint32_t dataOffset, uint64_t &pos, uint64_t length)
924 {
925 if (dataOffset + sizeof(uint16_t) > length) {
926 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("resource length error"));
927 return false;
928 }
929 in.seekg(dataOffset, ios::beg);
930 uint16_t dataLen;
931 in.read(reinterpret_cast<char *>(&dataLen), sizeof(uint16_t));
932 if (dataOffset + sizeof(uint16_t) + dataLen > length) {
933 PrintError(GetError(ERR_CODE_INVALID_RESOURCE_INDEX).FormatCause("resource length error"));
934 return false;
935 }
936 int8_t data[dataLen + 1];
937 in.read(reinterpret_cast<char *>(data), dataLen);
938
939 resourceItem.SetData(data, dataLen + 1);
940 resourceItem.MarkCoverable();
941 return true;
942 }
943 }
944 }
945 }
946