• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param : 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