/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "resource_table.h" #include #include "cmd_parser.h" #include "file_manager.h" #include "resource_util.h" #include "securec.h" namespace OHOS { namespace Global { namespace Restool { using namespace std; ResourceTable::ResourceTable() { auto &parser =CmdParser::GetInstance(); auto &packageParser = parser.GetCmdParser(); indexFilePath_ = filesystem::path(packageParser.GetOutput()).append(RESOURCE_INDEX_FILE).string(); } ResourceTable::~ResourceTable() { } uint32_t ResourceTable::CreateResourceTable() { FileManager &fileManager = FileManager::GetInstance(); auto &allResource = fileManager.GetResources(); map> configs; for (const auto &item : allResource) { for (const auto &resourceItem : item.second) { if (resourceItem.GetResType() == ResType::ID) { break; } TableData tableData; tableData.id = item.first; tableData.resourceItem = resourceItem; configs[resourceItem.GetLimitKey()].push_back(tableData); } } if (SaveToResouorceIndex(configs) != RESTOOL_SUCCESS) { return RESTOOL_ERROR; } return RESTOOL_SUCCESS; } //below private uint32_t ResourceTable::SaveToResouorceIndex(const map> &configs) const { uint32_t pos = 0; IndexHeader indexHeader; if (!InitIndexHeader(indexHeader, configs.size())) { return RESTOOL_ERROR; } pos += sizeof(IndexHeader); map limitKeyConfigs; map idSets; if (!Prepare(configs, limitKeyConfigs, idSets, pos)) { return RESTOOL_ERROR; } ofstream out(indexFilePath_, ofstream::out | ofstream::binary); if (!out.is_open()) { cerr << "Error: open fail " << indexFilePath_ << endl; return RESTOOL_ERROR; } if (!SaveRecordItem(configs, out, idSets, pos)) { return RESTOOL_ERROR; } indexHeader.fileSize = pos; SaveHeader(indexHeader, out); SaveLimitKeyConfigs(limitKeyConfigs, out); SaveIdSets(idSets, out); return RESTOOL_SUCCESS; } bool ResourceTable::InitIndexHeader(IndexHeader &indexHeader, uint32_t count) const { if (memcpy_s(indexHeader.version, VERSION_MAX_LEN, RESTOOL_VERSION, VERSION_MAX_LEN) != EOK) { cerr << "Error: InitIndexHeader memcpy_s fail." << endl; return false; } indexHeader.limitKeyConfigSize = count; return true; } bool ResourceTable::Prepare(const map> &configs, map &limitKeyConfigs, map &idSets, uint32_t &pos) const { for (const auto &config : configs) { LimitKeyConfig limitKeyConfig; const auto &keyParams = config.second.at(0).resourceItem.GetKeyParam(); limitKeyConfig.keyCount = keyParams.size(); pos += sizeof(limitKeyConfig.keyTag) + sizeof(limitKeyConfig.offset) + sizeof(limitKeyConfig.keyCount); for (const auto &keyParam : keyParams) { limitKeyConfig.data.push_back(static_cast(keyParam.keyType)); limitKeyConfig.data.push_back(static_cast(keyParam.value)); pos += sizeof(KeyParam); } limitKeyConfigs.emplace(config.first, limitKeyConfig); } for (const auto &config : configs) { auto limitKeyConfig = limitKeyConfigs.find(config.first); if (limitKeyConfig == limitKeyConfigs.end()) { cerr << "Error: limit key config don't find '" << config.first << "'" << endl; return false; } limitKeyConfig->second.offset = pos; IdSet idSet; idSet.idCount = config.second.size(); pos += sizeof(idSet.idTag) + sizeof(idSet.idCount); for (const auto &tableData : config.second) { idSet.data.emplace(tableData.id, 0); pos += sizeof(uint32_t) + sizeof(uint32_t); } idSets.emplace(config.first, idSet); } return true; } bool ResourceTable::SaveRecordItem(const map> &configs, ofstream &out, map &idSets, uint32_t &pos) const { out.seekp(pos); for (const auto &config : configs) { auto idSet = idSets.find(config.first); if (idSet == idSets.end()) { cerr << "Error: id set don't find '" << config.first << "'" << endl; return false; } for (const auto &tableData : config.second) { if (idSet->second.data.find(tableData.id) == idSet->second.data.end()) { cerr << "Error: resource table don't find id '" << tableData.id << "'" << endl; return false; } idSet->second.data[tableData.id] = pos; RecordItem recordItem; recordItem.id = tableData.id; recordItem.resType = static_cast(tableData.resourceItem.GetResType()); vector contents; string value(reinterpret_cast(tableData.resourceItem.GetData()), tableData.resourceItem.GetDataLength()); contents.push_back(value); string name = ResourceUtil::GetIdName(tableData.resourceItem.GetName(), tableData.resourceItem.GetResType()); contents.push_back(name); string data = ResourceUtil::ComposeStrings(contents, true); recordItem.size = sizeof(RecordItem) + data.length() - sizeof(uint32_t); pos += recordItem.size + sizeof(uint32_t); out.write(reinterpret_cast(&recordItem.size), sizeof(uint32_t)); out.write(reinterpret_cast(&recordItem.resType), sizeof(uint32_t)); out.write(reinterpret_cast(&recordItem.id), sizeof(uint32_t)); out.write(reinterpret_cast(data.c_str()), data.length()); } } return true; } void ResourceTable::SaveHeader(const IndexHeader &indexHeader, std::ofstream &out) const { out.seekp(0); out.write(reinterpret_cast(&indexHeader.version), VERSION_MAX_LEN); out.write(reinterpret_cast(&indexHeader.fileSize), sizeof(uint32_t)); out.write(reinterpret_cast(&indexHeader.limitKeyConfigSize), sizeof(uint32_t)); } void ResourceTable::SaveLimitKeyConfigs(const map &limitKeyConfigs, ofstream &out) const { for (const auto &iter : limitKeyConfigs) { out.write(reinterpret_cast(iter.second.keyTag), TAG_LEN); out.write(reinterpret_cast(&iter.second.offset), sizeof(uint32_t)); out.write(reinterpret_cast(&iter.second.keyCount), sizeof(uint32_t)); for (const auto &value : iter.second.data) { out.write(reinterpret_cast(&value), sizeof(int32_t)); } } } void ResourceTable::SaveIdSets(const map &idSets, ofstream &out) const { for (const auto &iter : idSets) { out.write(reinterpret_cast(iter.second.idTag), TAG_LEN); out.write(reinterpret_cast(&iter.second.idCount), sizeof(uint32_t)); for (const auto &keyValue : iter.second.data) { out.write(reinterpret_cast(&keyValue.first), sizeof(uint32_t)); out.write(reinterpret_cast(&keyValue.second), sizeof(uint32_t)); } } } } } }