13920e296Sopenharmony_ci/*
23920e296Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
33920e296Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43920e296Sopenharmony_ci * you may not use this file except in compliance with the License.
53920e296Sopenharmony_ci * You may obtain a copy of the License at
63920e296Sopenharmony_ci *
73920e296Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
83920e296Sopenharmony_ci *
93920e296Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103920e296Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113920e296Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123920e296Sopenharmony_ci * See the License for the specific language governing permissions and
133920e296Sopenharmony_ci * limitations under the License.
143920e296Sopenharmony_ci */
153920e296Sopenharmony_ci
163920e296Sopenharmony_ci#include "i_resource_compiler.h"
173920e296Sopenharmony_ci#include <algorithm>
183920e296Sopenharmony_ci#include <iostream>
193920e296Sopenharmony_ci#include "file_entry.h"
203920e296Sopenharmony_ci#include "id_worker.h"
213920e296Sopenharmony_ci#include "resource_util.h"
223920e296Sopenharmony_ci#include "restool_errors.h"
233920e296Sopenharmony_ci
243920e296Sopenharmony_cinamespace OHOS {
253920e296Sopenharmony_cinamespace Global {
263920e296Sopenharmony_cinamespace Restool {
273920e296Sopenharmony_ciusing namespace std;
283920e296Sopenharmony_ciIResourceCompiler::IResourceCompiler(ResType type, const string &output)
293920e296Sopenharmony_ci    :type_(type), output_(output)
303920e296Sopenharmony_ci{
313920e296Sopenharmony_ci}
323920e296Sopenharmony_ci
333920e296Sopenharmony_ciIResourceCompiler::~IResourceCompiler()
343920e296Sopenharmony_ci{
353920e296Sopenharmony_ci    nameInfos_.clear();
363920e296Sopenharmony_ci    resourceInfos_.clear();
373920e296Sopenharmony_ci}
383920e296Sopenharmony_ci
393920e296Sopenharmony_ciuint32_t IResourceCompiler::Compile(const vector<DirectoryInfo> &directoryInfos)
403920e296Sopenharmony_ci{
413920e296Sopenharmony_ci    vector<FileInfo> fileInfos;
423920e296Sopenharmony_ci    map<string, vector<FileInfo>> setsByDirectory;
433920e296Sopenharmony_ci    for (const auto &directoryInfo : directoryInfos) {
443920e296Sopenharmony_ci        string outputFolder = GetOutputFolder(directoryInfo);
453920e296Sopenharmony_ci        FileEntry f(directoryInfo.dirPath);
463920e296Sopenharmony_ci        if (!f.Init()) {
473920e296Sopenharmony_ci            return RESTOOL_ERROR;
483920e296Sopenharmony_ci        }
493920e296Sopenharmony_ci        for (const auto &it : f.GetChilds()) {
503920e296Sopenharmony_ci            if (ResourceUtil::IsIgnoreFile(it->GetFilePath().GetFilename(), it->IsFile())) {
513920e296Sopenharmony_ci                continue;
523920e296Sopenharmony_ci            }
533920e296Sopenharmony_ci
543920e296Sopenharmony_ci            if (!it->IsFile()) {
553920e296Sopenharmony_ci                cerr << "Error: '" << it->GetFilePath().GetPath() << "' must be a file." << endl;
563920e296Sopenharmony_ci                return RESTOOL_ERROR;
573920e296Sopenharmony_ci            }
583920e296Sopenharmony_ci
593920e296Sopenharmony_ci            FileInfo fileInfo = { directoryInfo, it->GetFilePath().GetPath(), it->GetFilePath().GetFilename() };
603920e296Sopenharmony_ci            fileInfos.push_back(fileInfo);
613920e296Sopenharmony_ci            setsByDirectory[outputFolder].push_back(fileInfo);
623920e296Sopenharmony_ci        }
633920e296Sopenharmony_ci    }
643920e296Sopenharmony_ci
653920e296Sopenharmony_ci    sort(fileInfos.begin(), fileInfos.end(), [](const auto &a, const auto &b) {
663920e296Sopenharmony_ci        return a.filePath < b.filePath;
673920e296Sopenharmony_ci    });
683920e296Sopenharmony_ci    if (CompileFiles(fileInfos) != RESTOOL_SUCCESS) {
693920e296Sopenharmony_ci        return RESTOOL_ERROR;
703920e296Sopenharmony_ci    }
713920e296Sopenharmony_ci    return PostCommit();
723920e296Sopenharmony_ci}
733920e296Sopenharmony_ci
743920e296Sopenharmony_ciuint32_t IResourceCompiler::CompileFiles(const std::vector<FileInfo> &fileInfos)
753920e296Sopenharmony_ci{
763920e296Sopenharmony_ci    for (const auto &fileInfo : fileInfos) {
773920e296Sopenharmony_ci        if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
783920e296Sopenharmony_ci            return RESTOOL_ERROR;
793920e296Sopenharmony_ci        }
803920e296Sopenharmony_ci    }
813920e296Sopenharmony_ci    return RESTOOL_SUCCESS;
823920e296Sopenharmony_ci}
833920e296Sopenharmony_ci
843920e296Sopenharmony_ciconst map<int64_t, vector<ResourceItem>> &IResourceCompiler::GetResult() const
853920e296Sopenharmony_ci{
863920e296Sopenharmony_ci    return resourceInfos_;
873920e296Sopenharmony_ci}
883920e296Sopenharmony_ci
893920e296Sopenharmony_ciuint32_t IResourceCompiler::Compile(const FileInfo &fileInfo)
903920e296Sopenharmony_ci{
913920e296Sopenharmony_ci    if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
923920e296Sopenharmony_ci        return RESTOOL_ERROR;
933920e296Sopenharmony_ci    }
943920e296Sopenharmony_ci    return PostCommit();
953920e296Sopenharmony_ci}
963920e296Sopenharmony_ci
973920e296Sopenharmony_ciuint32_t IResourceCompiler::CompileForAppend(const FileInfo &fileInfo)
983920e296Sopenharmony_ci{
993920e296Sopenharmony_ci    return CompileSingleFile(fileInfo);
1003920e296Sopenharmony_ci}
1013920e296Sopenharmony_ci
1023920e296Sopenharmony_ciconst map<pair<ResType, string>, vector<ResourceItem>> &IResourceCompiler::GetResourceItems() const
1033920e296Sopenharmony_ci{
1043920e296Sopenharmony_ci    return nameInfos_;
1053920e296Sopenharmony_ci}
1063920e296Sopenharmony_ci
1073920e296Sopenharmony_civoid IResourceCompiler::SetModuleName(const string &moduleName)
1083920e296Sopenharmony_ci{
1093920e296Sopenharmony_ci    moduleName_ = moduleName;
1103920e296Sopenharmony_ci}
1113920e296Sopenharmony_ci
1123920e296Sopenharmony_ciuint32_t IResourceCompiler::CompileSingleFile(const FileInfo &fileInfo)
1133920e296Sopenharmony_ci{
1143920e296Sopenharmony_ci    return RESTOOL_SUCCESS;
1153920e296Sopenharmony_ci}
1163920e296Sopenharmony_ci
1173920e296Sopenharmony_ciuint32_t IResourceCompiler::PostCommit()
1183920e296Sopenharmony_ci{
1193920e296Sopenharmony_ci    IdWorker &idWorker = IdWorker::GetInstance();
1203920e296Sopenharmony_ci    for (const auto &nameInfo : nameInfos_) {
1213920e296Sopenharmony_ci        int64_t id = idWorker.GenerateId(nameInfo.first.first, nameInfo.first.second);
1223920e296Sopenharmony_ci        if (id < 0) {
1233920e296Sopenharmony_ci            cerr << "Error: restype='" << ResourceUtil::ResTypeToString(nameInfo.first.first) << "' name='";
1243920e296Sopenharmony_ci            cerr << nameInfo.first.second << "' id not be defined." << endl;
1253920e296Sopenharmony_ci            return RESTOOL_ERROR;
1263920e296Sopenharmony_ci        }
1273920e296Sopenharmony_ci        resourceInfos_.emplace(id, nameInfo.second);
1283920e296Sopenharmony_ci    }
1293920e296Sopenharmony_ci    return RESTOOL_SUCCESS;
1303920e296Sopenharmony_ci}
1313920e296Sopenharmony_ci
1323920e296Sopenharmony_cibool IResourceCompiler::MergeResourceItem(const ResourceItem &resourceItem)
1333920e296Sopenharmony_ci{
1343920e296Sopenharmony_ci    string idName = ResourceUtil::GetIdName(resourceItem.GetName(), resourceItem.GetResType());
1353920e296Sopenharmony_ci    if (!ResourceUtil::IsValidName(idName)) {
1363920e296Sopenharmony_ci        cerr << "Error: invalid idName '" << idName << "'."<< NEW_LINE_PATH <<  resourceItem.GetFilePath() << endl;
1373920e296Sopenharmony_ci        cerr << SOLUTIONS << endl;
1383920e296Sopenharmony_ci        cerr << SOLUTIONS_ARROW << "Modify the name '" << idName << "' to match [a-zA-Z0-9_]." << endl;
1393920e296Sopenharmony_ci        return false;
1403920e296Sopenharmony_ci    }
1413920e296Sopenharmony_ci    auto item = nameInfos_.find(make_pair(resourceItem.GetResType(), idName));
1423920e296Sopenharmony_ci    if (item == nameInfos_.end()) {
1433920e296Sopenharmony_ci        nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
1443920e296Sopenharmony_ci        return true;
1453920e296Sopenharmony_ci    }
1463920e296Sopenharmony_ci
1473920e296Sopenharmony_ci    auto ret = find_if(item->second.begin(), item->second.end(), [resourceItem](auto &iter) {
1483920e296Sopenharmony_ci        return resourceItem.GetLimitKey() == iter.GetLimitKey();
1493920e296Sopenharmony_ci    });
1503920e296Sopenharmony_ci    if (ret != item->second.end()) {
1513920e296Sopenharmony_ci        cerr << "Error: resource '" << idName << "' first declared." << NEW_LINE_PATH << ret->GetFilePath() << endl;
1523920e296Sopenharmony_ci        cerr << "but declare again." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl;
1533920e296Sopenharmony_ci        return false;
1543920e296Sopenharmony_ci    }
1553920e296Sopenharmony_ci
1563920e296Sopenharmony_ci    nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
1573920e296Sopenharmony_ci    return true;
1583920e296Sopenharmony_ci}
1593920e296Sopenharmony_ci
1603920e296Sopenharmony_cistring IResourceCompiler::GetOutputFolder(const DirectoryInfo &directoryInfo) const
1613920e296Sopenharmony_ci{
1623920e296Sopenharmony_ci    string outputFolder = FileEntry::FilePath(output_).Append(RESOURCES_DIR)
1633920e296Sopenharmony_ci        .Append(directoryInfo.limitKey).Append(directoryInfo.fileCluster).GetPath();
1643920e296Sopenharmony_ci    return outputFolder;
1653920e296Sopenharmony_ci}
1663920e296Sopenharmony_ci}
1673920e296Sopenharmony_ci}
1683920e296Sopenharmony_ci}
169